aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb2pdu.c
diff options
context:
space:
mode:
authorSteve French <stfrench@microsoft.com>2019-07-06 14:41:38 -0500
committerSteve French <stfrench@microsoft.com>2019-07-07 22:37:44 -0500
commitff2a09e9196e2f9d5edc60d1a68bc3d3649d035b (patch)
treef87106734c684c680c8dc4d8dc3165fe4dba9383 /fs/cifs/smb2pdu.c
parentsmb3: Send netname context during negotiate protocol (diff)
downloadlinux-dev-ff2a09e9196e2f9d5edc60d1a68bc3d3649d035b.tar.xz
linux-dev-ff2a09e9196e2f9d5edc60d1a68bc3d3649d035b.zip
SMB3: query inode number on open via create context
We can cut the number of roundtrips on open (may also help some rename cases as well) by returning the inode number in the SMB2 open request itself instead of querying it afterwards via a query FILE_INTERNAL_INFO. This should significantly improve the performance of posix open. Add SMB2_CREATE_QUERY_ON_DISK_ID create context request on open calls so that when server supports this we can save a roundtrip for QUERY_INFO on every open. Follow on patch will add the response processing for SMB2_CREATE_QUERY_ON_DISK_ID context and optimize smb2_open_file to avoid the extra network roundtrip on every posix open. This patch adds the context on SMB2/SMB3 open requests. Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs/smb2pdu.c')
-rw-r--r--fs/cifs/smb2pdu.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 34d5397a1989..f58e4dc3987b 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2118,6 +2118,48 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
return 0;
}
+static struct crt_query_id_ctxt *
+create_query_id_buf(void)
+{
+ struct crt_query_id_ctxt *buf;
+
+ buf = kzalloc(sizeof(struct crt_query_id_ctxt), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->ccontext.DataOffset = cpu_to_le16(0);
+ buf->ccontext.DataLength = cpu_to_le32(0);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct crt_query_id_ctxt, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_QUERY_ON_DISK_ID is "QFid" */
+ buf->Name[0] = 'Q';
+ buf->Name[1] = 'F';
+ buf->Name[2] = 'i';
+ buf->Name[3] = 'd';
+ return buf;
+}
+
+/* See MS-SMB2 2.2.13.2.9 */
+static int
+add_query_id_context(struct kvec *iov, unsigned int *num_iovec)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+
+ iov[num].iov_base = create_query_id_buf();
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = sizeof(struct crt_query_id_ctxt);
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset = cpu_to_le32(
+ sizeof(struct smb2_create_req) +
+ iov[num - 1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_query_id_ctxt));
+ *num_iovec = num + 1;
+ return 0;
+}
+
static int
alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
const char *treename, const __le16 *path)
@@ -2446,6 +2488,12 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock,
return rc;
}
+ if (n_iov > 2) {
+ struct create_context *ccontext =
+ (struct create_context *)iov[n_iov-1].iov_base;
+ ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
+ }
+ add_query_id_context(iov, &n_iov);
rqst->rq_nvec = n_iov;
return 0;