Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull SMB3 updates from Steve French: "A collection of SMB3 patches adding some reliability features (persistent and resilient handles) and improving SMB3 copy offload. I will have some additional patches for SMB3 encryption and SMB3.1.1 signing (important security features), and also for improving SMB3 persistent handle reconnection (setting ChannelSequence number e.g.) that I am still working on but wanted to get this set in since they can stand alone" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: Allow copy offload (CopyChunk) across shares Add resilienthandles mount parm [SMB3] Send durable handle v2 contexts when use of persistent handles required [SMB3] Display persistenthandles in /proc/mounts for SMB3 shares if enabled [SMB3] Enable checking for continuous availability and persistent handle support [SMB3] Add parsing for new mount option controlling persistent handles Allow duplicate extents in SMB3 not just SMB3.1.1
This commit is contained in:
commit
f3996e6ac6
@ -454,6 +454,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
||||
seq_puts(s, ",nocase");
|
||||
if (tcon->retry)
|
||||
seq_puts(s, ",hard");
|
||||
if (tcon->use_persistent)
|
||||
seq_puts(s, ",persistenthandles");
|
||||
else if (tcon->use_resilient)
|
||||
seq_puts(s, ",resilienthandles");
|
||||
if (tcon->unix_ext)
|
||||
seq_puts(s, ",unix");
|
||||
else
|
||||
@ -921,9 +925,7 @@ const struct file_operations cifs_file_ops = {
|
||||
.mmap = cifs_file_mmap,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.llseek = cifs_llseek,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
@ -939,9 +941,7 @@ const struct file_operations cifs_file_strict_ops = {
|
||||
.mmap = cifs_file_strict_mmap,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.llseek = cifs_llseek,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
@ -957,9 +957,7 @@ const struct file_operations cifs_file_direct_ops = {
|
||||
.flush = cifs_flush,
|
||||
.mmap = cifs_file_mmap,
|
||||
.splice_read = generic_file_splice_read,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.llseek = cifs_llseek,
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
@ -975,9 +973,7 @@ const struct file_operations cifs_file_nobrl_ops = {
|
||||
.mmap = cifs_file_mmap,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.llseek = cifs_llseek,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
@ -992,9 +988,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
|
||||
.mmap = cifs_file_strict_mmap,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.llseek = cifs_llseek,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
@ -1009,9 +1003,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
|
||||
.flush = cifs_flush,
|
||||
.mmap = cifs_file_mmap,
|
||||
.splice_read = generic_file_splice_read,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.llseek = cifs_llseek,
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
|
@ -493,7 +493,10 @@ struct smb_vol {
|
||||
bool mfsymlinks:1; /* use Minshall+French Symlinks */
|
||||
bool multiuser:1;
|
||||
bool rwpidforward:1; /* pid forward for read/write operations */
|
||||
bool nosharesock;
|
||||
bool nosharesock:1;
|
||||
bool persistent:1;
|
||||
bool nopersistent:1;
|
||||
bool resilient:1; /* noresilient not required since not fored for CA */
|
||||
unsigned int rsize;
|
||||
unsigned int wsize;
|
||||
bool sockopt_tcp_nodelay:1;
|
||||
@ -895,6 +898,8 @@ struct cifs_tcon {
|
||||
bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
|
||||
bool broken_sparse_sup; /* if server or share does not support sparse */
|
||||
bool need_reconnect:1; /* connection reset, tid now invalid */
|
||||
bool use_resilient:1; /* use resilient instead of durable handles */
|
||||
bool use_persistent:1; /* use persistent instead of durable handles */
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
bool print:1; /* set if connection to printer share */
|
||||
bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */
|
||||
@ -1015,6 +1020,7 @@ struct cifs_fid {
|
||||
__u64 persistent_fid; /* persist file id for smb2 */
|
||||
__u64 volatile_fid; /* volatile file id for smb2 */
|
||||
__u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */
|
||||
__u8 create_guid[16];
|
||||
#endif
|
||||
struct cifs_pending_open *pending_open;
|
||||
unsigned int epoch;
|
||||
|
@ -87,6 +87,8 @@ enum {
|
||||
Opt_sign, Opt_seal, Opt_noac,
|
||||
Opt_fsc, Opt_mfsymlinks,
|
||||
Opt_multiuser, Opt_sloppy, Opt_nosharesock,
|
||||
Opt_persistent, Opt_nopersistent,
|
||||
Opt_resilient, Opt_noresilient,
|
||||
|
||||
/* Mount options which take numeric value */
|
||||
Opt_backupuid, Opt_backupgid, Opt_uid,
|
||||
@ -169,6 +171,10 @@ static const match_table_t cifs_mount_option_tokens = {
|
||||
{ Opt_multiuser, "multiuser" },
|
||||
{ Opt_sloppy, "sloppy" },
|
||||
{ Opt_nosharesock, "nosharesock" },
|
||||
{ Opt_persistent, "persistenthandles"},
|
||||
{ Opt_nopersistent, "nopersistenthandles"},
|
||||
{ Opt_resilient, "resilienthandles"},
|
||||
{ Opt_noresilient, "noresilienthandles"},
|
||||
|
||||
{ Opt_backupuid, "backupuid=%s" },
|
||||
{ Opt_backupgid, "backupgid=%s" },
|
||||
@ -1497,6 +1503,33 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||
case Opt_nosharesock:
|
||||
vol->nosharesock = true;
|
||||
break;
|
||||
case Opt_nopersistent:
|
||||
vol->nopersistent = true;
|
||||
if (vol->persistent) {
|
||||
cifs_dbg(VFS,
|
||||
"persistenthandles mount options conflict\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
case Opt_persistent:
|
||||
vol->persistent = true;
|
||||
if ((vol->nopersistent) || (vol->resilient)) {
|
||||
cifs_dbg(VFS,
|
||||
"persistenthandles mount options conflict\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
case Opt_resilient:
|
||||
vol->resilient = true;
|
||||
if (vol->persistent) {
|
||||
cifs_dbg(VFS,
|
||||
"persistenthandles mount options conflict\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
case Opt_noresilient:
|
||||
vol->resilient = false; /* already the default */
|
||||
break;
|
||||
|
||||
/* Numeric Values */
|
||||
case Opt_backupuid:
|
||||
@ -2655,6 +2688,42 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
|
||||
cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
|
||||
}
|
||||
tcon->seal = volume_info->seal;
|
||||
tcon->use_persistent = false;
|
||||
/* check if SMB2 or later, CIFS does not support persistent handles */
|
||||
if (volume_info->persistent) {
|
||||
if (ses->server->vals->protocol_id == 0) {
|
||||
cifs_dbg(VFS,
|
||||
"SMB3 or later required for persistent handles\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out_fail;
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
} else if (ses->server->capabilities &
|
||||
SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
|
||||
tcon->use_persistent = true;
|
||||
else /* persistent handles requested but not supported */ {
|
||||
cifs_dbg(VFS,
|
||||
"Persistent handles not supported on share\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out_fail;
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
}
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
} else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
|
||||
&& (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
|
||||
&& (volume_info->nopersistent == false)) {
|
||||
cifs_dbg(FYI, "enabling persistent handles\n");
|
||||
tcon->use_persistent = true;
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
} else if (volume_info->resilient) {
|
||||
if (ses->server->vals->protocol_id == 0) {
|
||||
cifs_dbg(VFS,
|
||||
"SMB2.1 or later required for resilient handles\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out_fail;
|
||||
}
|
||||
tcon->use_resilient = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can have only one retry value for a connection to a share so for
|
||||
* resources mounted more than once to the same server share the last
|
||||
@ -3503,6 +3572,15 @@ try_mount_again:
|
||||
goto mount_fail_check;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
if ((volume_info->persistent == true) && ((ses->server->capabilities &
|
||||
SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
|
||||
cifs_dbg(VFS, "persistent handles not supported by server\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
goto mount_fail_check;
|
||||
}
|
||||
#endif /* CONFIG_CIFS_SMB2*/
|
||||
|
||||
/* search for existing tcon to this server share */
|
||||
tcon = cifs_get_tcon(ses, volume_info);
|
||||
if (IS_ERR(tcon)) {
|
||||
|
@ -85,9 +85,14 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file,
|
||||
src_tcon = tlink_tcon(smb_file_src->tlink);
|
||||
target_tcon = tlink_tcon(smb_file_target->tlink);
|
||||
|
||||
/* check if source and target are on same tree connection */
|
||||
if (src_tcon != target_tcon) {
|
||||
cifs_dbg(VFS, "file copy src and target on different volume\n");
|
||||
/* check source and target on same server (or volume if dup_extents) */
|
||||
if (dup_extents && (src_tcon != target_tcon)) {
|
||||
cifs_dbg(VFS, "source and target of copy not on same share\n");
|
||||
goto out_fput;
|
||||
}
|
||||
|
||||
if (!dup_extents && (src_tcon->ses != target_tcon->ses)) {
|
||||
cifs_dbg(VFS, "source and target of copy not on same server\n");
|
||||
goto out_fput;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
|
||||
struct smb2_file_all_info *smb2_data = NULL;
|
||||
__u8 smb2_oplock[17];
|
||||
struct cifs_fid *fid = oparms->fid;
|
||||
struct network_resiliency_req nr_ioctl_req;
|
||||
|
||||
smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb);
|
||||
if (smb2_path == NULL) {
|
||||
@ -67,6 +68,24 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
||||
if (oparms->tcon->use_resilient) {
|
||||
nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */
|
||||
nr_ioctl_req.Reserved = 0;
|
||||
rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
|
||||
fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY, true,
|
||||
(char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
|
||||
NULL, NULL /* no return info */);
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
cifs_dbg(VFS,
|
||||
"resiliency not supported by server, disabling\n");
|
||||
oparms->tcon->use_resilient = false;
|
||||
} else if (rc)
|
||||
cifs_dbg(FYI, "error %d setting resiliency\n", rc);
|
||||
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
/* open response does not have IndexNumber field - get it */
|
||||
rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid,
|
||||
|
@ -810,7 +810,6 @@ smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
cfile->fid.volatile_fid, cfile->pid, &eof, false);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_SMB311
|
||||
static int
|
||||
smb2_duplicate_extents(const unsigned int xid,
|
||||
struct cifsFileInfo *srcfile,
|
||||
@ -854,8 +853,6 @@ smb2_duplicate_extents(const unsigned int xid,
|
||||
duplicate_extents_out:
|
||||
return rc;
|
||||
}
|
||||
#endif /* CONFIG_CIFS_SMB311 */
|
||||
|
||||
|
||||
static int
|
||||
smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
@ -1703,6 +1700,7 @@ struct smb_version_operations smb30_operations = {
|
||||
.create_lease_buf = smb3_create_lease_buf,
|
||||
.parse_lease_buf = smb3_parse_lease_buf,
|
||||
.clone_range = smb2_clone_range,
|
||||
.duplicate_extents = smb2_duplicate_extents,
|
||||
.validate_negotiate = smb3_validate_negotiate,
|
||||
.wp_retry_size = smb2_wp_retry_size,
|
||||
.dir_needs_close = smb2_dir_needs_close,
|
||||
@ -1840,7 +1838,7 @@ struct smb_version_values smb21_values = {
|
||||
struct smb_version_values smb30_values = {
|
||||
.version_string = SMB30_VERSION_STRING,
|
||||
.protocol_id = SMB30_PROT_ID,
|
||||
.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
|
||||
.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES,
|
||||
.large_lock_type = 0,
|
||||
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
|
||||
@ -1860,7 +1858,7 @@ struct smb_version_values smb30_values = {
|
||||
struct smb_version_values smb302_values = {
|
||||
.version_string = SMB302_VERSION_STRING,
|
||||
.protocol_id = SMB302_PROT_ID,
|
||||
.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
|
||||
.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES,
|
||||
.large_lock_type = 0,
|
||||
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
|
||||
@ -1881,7 +1879,7 @@ struct smb_version_values smb302_values = {
|
||||
struct smb_version_values smb311_values = {
|
||||
.version_string = SMB311_VERSION_STRING,
|
||||
.protocol_id = SMB311_PROT_ID,
|
||||
.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
|
||||
.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES,
|
||||
.large_lock_type = 0,
|
||||
.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
|
||||
|
@ -1151,13 +1151,130 @@ add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct create_durable_v2 *
|
||||
create_durable_v2_buf(struct cifs_fid *pfid)
|
||||
{
|
||||
struct create_durable_v2 *buf;
|
||||
|
||||
buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
buf->ccontext.DataOffset = cpu_to_le16(offsetof
|
||||
(struct create_durable_v2, dcontext));
|
||||
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2));
|
||||
buf->ccontext.NameOffset = cpu_to_le16(offsetof
|
||||
(struct create_durable_v2, Name));
|
||||
buf->ccontext.NameLength = cpu_to_le16(4);
|
||||
|
||||
buf->dcontext.Timeout = 0; /* Should this be configurable by workload */
|
||||
buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
|
||||
get_random_bytes(buf->dcontext.CreateGuid, 16);
|
||||
memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
|
||||
|
||||
/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
|
||||
buf->Name[0] = 'D';
|
||||
buf->Name[1] = 'H';
|
||||
buf->Name[2] = '2';
|
||||
buf->Name[3] = 'Q';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static struct create_durable_handle_reconnect_v2 *
|
||||
create_reconnect_durable_v2_buf(struct cifs_fid *fid)
|
||||
{
|
||||
struct create_durable_handle_reconnect_v2 *buf;
|
||||
|
||||
buf = kzalloc(sizeof(struct create_durable_handle_reconnect_v2),
|
||||
GFP_KERNEL);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
buf->ccontext.DataOffset =
|
||||
cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
|
||||
dcontext));
|
||||
buf->ccontext.DataLength =
|
||||
cpu_to_le32(sizeof(struct durable_reconnect_context_v2));
|
||||
buf->ccontext.NameOffset =
|
||||
cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
|
||||
Name));
|
||||
buf->ccontext.NameLength = cpu_to_le16(4);
|
||||
|
||||
buf->dcontext.Fid.PersistentFileId = fid->persistent_fid;
|
||||
buf->dcontext.Fid.VolatileFileId = fid->volatile_fid;
|
||||
buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
|
||||
memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16);
|
||||
|
||||
/* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */
|
||||
buf->Name[0] = 'D';
|
||||
buf->Name[1] = 'H';
|
||||
buf->Name[2] = '2';
|
||||
buf->Name[3] = 'C';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
add_durable_context(struct kvec *iov, unsigned int *num_iovec,
|
||||
add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
|
||||
struct cifs_open_parms *oparms)
|
||||
{
|
||||
struct smb2_create_req *req = iov[0].iov_base;
|
||||
unsigned int num = *num_iovec;
|
||||
|
||||
iov[num].iov_base = create_durable_v2_buf(oparms->fid);
|
||||
if (iov[num].iov_base == NULL)
|
||||
return -ENOMEM;
|
||||
iov[num].iov_len = sizeof(struct create_durable_v2);
|
||||
if (!req->CreateContextsOffset)
|
||||
req->CreateContextsOffset =
|
||||
cpu_to_le32(sizeof(struct smb2_create_req) - 4 +
|
||||
iov[1].iov_len);
|
||||
le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2));
|
||||
inc_rfc1001_len(&req->hdr, sizeof(struct create_durable_v2));
|
||||
*num_iovec = num + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
|
||||
struct cifs_open_parms *oparms)
|
||||
{
|
||||
struct smb2_create_req *req = iov[0].iov_base;
|
||||
unsigned int num = *num_iovec;
|
||||
|
||||
/* indicate that we don't need to relock the file */
|
||||
oparms->reconnect = false;
|
||||
|
||||
iov[num].iov_base = create_reconnect_durable_v2_buf(oparms->fid);
|
||||
if (iov[num].iov_base == NULL)
|
||||
return -ENOMEM;
|
||||
iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2);
|
||||
if (!req->CreateContextsOffset)
|
||||
req->CreateContextsOffset =
|
||||
cpu_to_le32(sizeof(struct smb2_create_req) - 4 +
|
||||
iov[1].iov_len);
|
||||
le32_add_cpu(&req->CreateContextsLength,
|
||||
sizeof(struct create_durable_handle_reconnect_v2));
|
||||
inc_rfc1001_len(&req->hdr,
|
||||
sizeof(struct create_durable_handle_reconnect_v2));
|
||||
*num_iovec = num + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
add_durable_context(struct kvec *iov, unsigned int *num_iovec,
|
||||
struct cifs_open_parms *oparms, bool use_persistent)
|
||||
{
|
||||
struct smb2_create_req *req = iov[0].iov_base;
|
||||
unsigned int num = *num_iovec;
|
||||
|
||||
if (use_persistent) {
|
||||
if (oparms->reconnect)
|
||||
return add_durable_reconnect_v2_context(iov, num_iovec,
|
||||
oparms);
|
||||
else
|
||||
return add_durable_v2_context(iov, num_iovec, oparms);
|
||||
}
|
||||
|
||||
if (oparms->reconnect) {
|
||||
iov[num].iov_base = create_reconnect_durable_buf(oparms->fid);
|
||||
/* indicate that we don't need to relock the file */
|
||||
@ -1275,7 +1392,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
ccontext->Next =
|
||||
cpu_to_le32(server->vals->create_lease_size);
|
||||
}
|
||||
rc = add_durable_context(iov, &num_iovecs, oparms);
|
||||
|
||||
rc = add_durable_context(iov, &num_iovecs, oparms,
|
||||
tcon->use_persistent);
|
||||
if (rc) {
|
||||
cifs_small_buf_release(req);
|
||||
kfree(copy_path);
|
||||
|
@ -590,6 +590,44 @@ struct create_durable {
|
||||
} Data;
|
||||
} __packed;
|
||||
|
||||
/* See MS-SMB2 2.2.13.2.11 */
|
||||
/* Flags */
|
||||
#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002
|
||||
struct durable_context_v2 {
|
||||
__le32 Timeout;
|
||||
__le32 Flags;
|
||||
__u64 Reserved;
|
||||
__u8 CreateGuid[16];
|
||||
} __packed;
|
||||
|
||||
struct create_durable_v2 {
|
||||
struct create_context ccontext;
|
||||
__u8 Name[8];
|
||||
struct durable_context_v2 dcontext;
|
||||
} __packed;
|
||||
|
||||
/* See MS-SMB2 2.2.13.2.12 */
|
||||
struct durable_reconnect_context_v2 {
|
||||
struct {
|
||||
__u64 PersistentFileId;
|
||||
__u64 VolatileFileId;
|
||||
} Fid;
|
||||
__u8 CreateGuid[16];
|
||||
__le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
|
||||
} __packed;
|
||||
|
||||
/* See MS-SMB2 2.2.14.2.12 */
|
||||
struct durable_reconnect_context_v2_rsp {
|
||||
__le32 Timeout;
|
||||
__le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
|
||||
} __packed;
|
||||
|
||||
struct create_durable_handle_reconnect_v2 {
|
||||
struct create_context ccontext;
|
||||
__u8 Name[8];
|
||||
struct durable_reconnect_context_v2 dcontext;
|
||||
} __packed;
|
||||
|
||||
#define COPY_CHUNK_RES_KEY_SIZE 24
|
||||
struct resume_key_req {
|
||||
char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];
|
||||
@ -643,6 +681,13 @@ struct fsctl_get_integrity_information_rsp {
|
||||
/* Integrity flags for above */
|
||||
#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
|
||||
|
||||
/* See MS-SMB2 2.2.31.3 */
|
||||
struct network_resiliency_req {
|
||||
__le32 Timeout;
|
||||
__le32 Reserved;
|
||||
} __packed;
|
||||
/* There is no buffer for the response ie no struct network_resiliency_rsp */
|
||||
|
||||
|
||||
struct validate_negotiate_info_req {
|
||||
__le32 Capabilities;
|
||||
|
@ -90,7 +90,7 @@
|
||||
#define FSCTL_SRV_ENUMERATE_SNAPSHOTS 0x00144064
|
||||
/* Retrieve an opaque file reference for server-side data movement ie copy */
|
||||
#define FSCTL_SRV_REQUEST_RESUME_KEY 0x00140078
|
||||
#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4 /* BB add struct */
|
||||
#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4
|
||||
#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
|
||||
#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
|
||||
#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
|
||||
|
Loading…
Reference in New Issue
Block a user