Linux CIFS filesystem development
 help / color / mirror / Atom feed
* [PATCH 1/4] Add parsing for new mount option controlling persistent handles
@ 2015-10-03 23:53 Steve French
       [not found] ` <1443916442-42466-1-git-send-email-smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 5+ messages in thread
From: Steve French @ 2015-10-03 23:53 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Steve French, Steve French

"nopersistenthandles" and "persistenthandles" mount options added.
The former will not request persistent handles on open even when
SMB3 negotiated and Continuous Availability share.  The latter
will request persistent handles (as long as server notes the
capability in protocol negotiation) even if share is not Continuous
Availability share.

Signed-off-by: Steve French <steve.french-7I+n7zu2hftEKMMhf/gKZA@public.gmane.org>
---
 fs/cifs/cifsglob.h |  4 +++-
 fs/cifs/connect.c  | 19 +++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a79e484..221ccfa 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -493,7 +493,9 @@ 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;
 	unsigned int rsize;
 	unsigned int wsize;
 	bool sockopt_tcp_nodelay:1;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 011f4d8..a16f2f0 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -87,6 +87,7 @@ enum {
 	Opt_sign, Opt_seal, Opt_noac,
 	Opt_fsc, Opt_mfsymlinks,
 	Opt_multiuser, Opt_sloppy, Opt_nosharesock,
+	Opt_persistent, Opt_nopersistent,
 
 	/* Mount options which take numeric value */
 	Opt_backupuid, Opt_backupgid, Opt_uid,
@@ -169,6 +170,8 @@ 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_backupuid, "backupuid=%s" },
 	{ Opt_backupgid, "backupgid=%s" },
@@ -1497,6 +1500,22 @@ 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) {
+				cifs_dbg(VFS,
+				  "persistenthandles mount options conflict\n");
+				goto cifs_parse_mount_err;
+			}
+			break;
 
 		/* Numeric Values */
 		case Opt_backupuid:
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] Enable checking for continuous availability and persistent handle support
       [not found] ` <1443916442-42466-1-git-send-email-smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2015-10-03 23:54   ` Steve French
  2015-10-03 23:54   ` [PATCH 3/4] Display persistenthandles in /proc/mounts for SMB3 shares if enabled Steve French
  2015-10-03 23:54   ` [PATCH 4/4] [SMB3] Send durable handle v2 contexts when use of persistent handles required Steve French
  2 siblings, 0 replies; 5+ messages in thread
From: Steve French @ 2015-10-03 23:54 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Steve French, Steve French

Validate "persistenthandles" and "nopersistenthandles" mount options against
the support the server claims in negotiate and tree connect SMB3 responses.

Signed-off-by: Steve French <steve.french-7I+n7zu2hftEKMMhf/gKZA@public.gmane.org>
---
 fs/cifs/cifsglob.h |  1 +
 fs/cifs/connect.c  | 30 ++++++++++++++++++++++++++++++
 fs/cifs/smb2ops.c  |  6 +++---
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 221ccfa..51353bb 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -901,6 +901,7 @@ 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_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 */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index a16f2f0..9e44532 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2673,6 +2673,30 @@ 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;
+		} 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;
+		}
+	} 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;
+	}
+
 	/*
 	 * 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
@@ -3521,6 +3545,12 @@ try_mount_again:
 		goto mount_fail_check;
 	}
 
+	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;
+	}
 	/* search for existing tcon to this server share */
 	tcon = cifs_get_tcon(ses, volume_info);
 	if (IS_ERR(tcon)) {
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index a464008..3c7b6d6 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1843,7 +1843,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 | SMB2_GLOBAL_CAP_ENCRYPTION,
+	.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES,
 	.large_lock_type = 0,
 	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
 	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
@@ -1863,7 +1863,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,
@@ -1884,7 +1884,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,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] Display persistenthandles in /proc/mounts for SMB3 shares if enabled
       [not found] ` <1443916442-42466-1-git-send-email-smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2015-10-03 23:54   ` [PATCH 2/4] Enable checking for continuous availability and persistent handle support Steve French
@ 2015-10-03 23:54   ` Steve French
  2015-10-03 23:54   ` [PATCH 4/4] [SMB3] Send durable handle v2 contexts when use of persistent handles required Steve French
  2 siblings, 0 replies; 5+ messages in thread
From: Steve French @ 2015-10-03 23:54 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Steve French, Steve French

Signed-off-by: Steve French <steve.french-7I+n7zu2hftEKMMhf/gKZA@public.gmane.org>
---
 fs/cifs/cifsfs.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e739950..13302e9 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -454,6 +454,8 @@ 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");
 	if (tcon->unix_ext)
 		seq_puts(s, ",unix");
 	else
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] [SMB3] Send durable handle v2 contexts when use of persistent handles required
       [not found] ` <1443916442-42466-1-git-send-email-smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2015-10-03 23:54   ` [PATCH 2/4] Enable checking for continuous availability and persistent handle support Steve French
  2015-10-03 23:54   ` [PATCH 3/4] Display persistenthandles in /proc/mounts for SMB3 shares if enabled Steve French
@ 2015-10-03 23:54   ` Steve French
       [not found]     ` <1443916442-42466-4-git-send-email-smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2 siblings, 1 reply; 5+ messages in thread
From: Steve French @ 2015-10-03 23:54 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA
  Cc: Steve French, Pavel Shilovsky, Steve French

CC: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
Signed-off-by: Steve French <steve.french-7I+n7zu2hftEKMMhf/gKZA@public.gmane.org>
---
 fs/cifs/cifsglob.h |   1 +
 fs/cifs/smb2pdu.c  | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 fs/cifs/smb2pdu.h  |  45 ++++++++++++++++++++
 fs/cifs/smbfsctl.h |   2 +-
 4 files changed, 168 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 51353bb..ec31a03 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1022,6 +1022,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;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index c744b57..c135046 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1148,13 +1148,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), 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 */
@@ -1272,7 +1389,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);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index b26da75..ff88d9f 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -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;
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h
index a639d0d..f996dae 100644
--- a/fs/cifs/smbfsctl.h
+++ b/fs/cifs/smbfsctl.h
@@ -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
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 4/4] [SMB3] Send durable handle v2 contexts when use of persistent handles required
       [not found]     ` <1443916442-42466-4-git-send-email-smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2015-10-04 10:33       ` Pavel Shilovsky
  0 siblings, 0 replies; 5+ messages in thread
From: Pavel Shilovsky @ 2015-10-04 10:33 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, Steve French

2015-10-04 2:54 GMT+03:00 Steve French <smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> CC: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> Signed-off-by: Steve French <steve.french-7I+n7zu2hftEKMMhf/gKZA@public.gmane.org>
> ---
>  fs/cifs/cifsglob.h |   1 +
>  fs/cifs/smb2pdu.c  | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  fs/cifs/smb2pdu.h  |  45 ++++++++++++++++++++
>  fs/cifs/smbfsctl.h |   2 +-
>  4 files changed, 168 insertions(+), 3 deletions(-)
>
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 51353bb..ec31a03 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -1022,6 +1022,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;
> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> index c744b57..c135046 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -1148,13 +1148,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), 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 */
> @@ -1272,7 +1389,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);
> diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
> index b26da75..ff88d9f 100644
> --- a/fs/cifs/smb2pdu.h
> +++ b/fs/cifs/smb2pdu.h
> @@ -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;
> diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h
> index a639d0d..f996dae 100644
> --- a/fs/cifs/smbfsctl.h
> +++ b/fs/cifs/smbfsctl.h
> @@ -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
> --
> 1.9.1

The whole series looks good to me. You can add my

Reviewed-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

tag to each of 4 patches.

-- 
Best regards,
Pavel Shilovsky.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-10-04 10:33 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-03 23:53 [PATCH 1/4] Add parsing for new mount option controlling persistent handles Steve French
     [not found] ` <1443916442-42466-1-git-send-email-smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-10-03 23:54   ` [PATCH 2/4] Enable checking for continuous availability and persistent handle support Steve French
2015-10-03 23:54   ` [PATCH 3/4] Display persistenthandles in /proc/mounts for SMB3 shares if enabled Steve French
2015-10-03 23:54   ` [PATCH 4/4] [SMB3] Send durable handle v2 contexts when use of persistent handles required Steve French
     [not found]     ` <1443916442-42466-4-git-send-email-smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-10-04 10:33       ` Pavel Shilovsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox