Now that we have the qfid context returned on open we can cut 1/3 of the traffic on open by not sending the query FILE_INTERNAL_INFORMATION -- Thanks, Steve
From e3f8b1c5dbf19a0e6ef38d09b423f68b00078a9c Mon Sep 17 00:00:00 2001 From: Steve French <stfrench@xxxxxxxxxxxxx> Date: Thu, 18 Jul 2019 02:39:05 -0500 Subject: [PATCH] smb3: optimize open to not send query file internal info We can cut one third of the traffic on open by not querying the inode number explicitly via SMB3 query_info since it is now returned on open in the qfid context. Speeds up open significantly. Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- fs/cifs/smb2file.c | 18 ++++++++++++------ fs/cifs/smb2ops.c | 5 +++-- fs/cifs/smb2pdu.c | 42 +++++++++++++++++++++++++++++++----------- fs/cifs/smb2pdu.h | 2 ++ fs/cifs/smb2proto.h | 5 +++-- 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 54bffb2a1786..e6a1fc72018f 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -88,14 +88,20 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, } if (buf) { - /* open response does not have IndexNumber field - get it */ - rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid, + /* if open response does not have IndexNumber field - get it */ + if (smb2_data->IndexNumber == 0) { + rc = SMB2_get_srv_num(xid, oparms->tcon, + fid->persistent_fid, fid->volatile_fid, &smb2_data->IndexNumber); - if (rc) { - /* let get_inode_info disable server inode numbers */ - smb2_data->IndexNumber = 0; - rc = 0; + if (rc) { + /* + * let get_inode_info disable server inode + * numbers + */ + smb2_data->IndexNumber = 0; + rc = 0; + } } move_smb2_info_to_cifs(buf, smb2_data); } diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 0cdc4e47ca87..e73486e9b94d 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -711,11 +711,12 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) tcon->crfid.is_valid = true; kref_init(&tcon->crfid.refcount); + /* BB TBD check to see if oplock level check can be removed below */ if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) { kref_get(&tcon->crfid.refcount); - oplock = smb2_parse_lease_state(server, o_rsp, + oplock = smb2_parse_contexts(server, o_rsp, &oparms.fid->epoch, - oparms.fid->lease_key); + oparms.fid->lease_key, NULL); } else goto oshr_exit; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index b352f453a6d2..a55708b75468 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1873,26 +1873,46 @@ create_reconnect_durable_buf(struct cifs_fid *fid) return buf; } +static void +parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf) +{ + struct on_disk_id *pdisk_id = (struct on_disk_id *)cc; + + cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n", + pdisk_id->DiskFileId, pdisk_id->VolumeId); + buf->IndexNumber = pdisk_id->DiskFileId; +} + __u8 -smb2_parse_lease_state(struct TCP_Server_Info *server, +smb2_parse_contexts(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, - unsigned int *epoch, char *lease_key) + unsigned int *epoch, char *lease_key, + struct smb2_file_all_info *buf) { char *data_offset; struct create_context *cc; unsigned int next; unsigned int remaining; char *name; + __u8 oplock = 0; data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); remaining = le32_to_cpu(rsp->CreateContextsLength); cc = (struct create_context *)data_offset; + + /* Initialize inode number to 0 in case no valid data in qfid context */ + if (buf) + buf->IndexNumber = 0; + while (remaining >= sizeof(struct create_context)) { name = le16_to_cpu(cc->NameOffset) + (char *)cc; if (le16_to_cpu(cc->NameLength) == 4 && - strncmp(name, "RqLs", 4) == 0) - return server->ops->parse_lease_buf(cc, epoch, - lease_key); + strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0) + oplock = server->ops->parse_lease_buf(cc, epoch, + lease_key); + else if (buf && (le16_to_cpu(cc->NameLength) == 4) && + strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0) + parse_query_id_ctxt(cc, buf); next = le32_to_cpu(cc->Next); if (!next) @@ -1901,7 +1921,7 @@ smb2_parse_lease_state(struct TCP_Server_Info *server, cc = (struct create_context *)((char *)cc + next); } - return 0; + return oplock; } static int @@ -2588,11 +2608,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, buf->DeletePending = 0; } - if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) - *oplock = smb2_parse_lease_state(server, rsp, - &oparms->fid->epoch, - oparms->fid->lease_key); - else + + *oplock = smb2_parse_contexts(server, rsp, &oparms->fid->epoch, + oparms->fid->lease_key, + buf); + if (*oplock == 0) /* no lease open context found */ *oplock = rsp->OplockLevel; creat_exit: SMB2_open_free(&rqst); diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 7e2e782f8edd..7c916adc2fbc 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -819,6 +819,8 @@ struct durable_reconnect_context_v2 { /* See MS-SMB2 2.2.14.2.9 */ struct on_disk_id { + struct create_context ccontext; + __u8 Name[8]; __le64 DiskFileId; __le64 VolumeId; __u32 Reserved[4]; diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index e4ca98cf3af3..b6b1a1bed466 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -232,9 +232,10 @@ extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *); extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, enum securityEnum); -extern __u8 smb2_parse_lease_state(struct TCP_Server_Info *server, +extern __u8 smb2_parse_contexts(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, - unsigned int *epoch, char *lease_key); + unsigned int *epoch, char *lease_key, + struct smb2_file_all_info *buf); extern int smb3_encryption_required(const struct cifs_tcon *tcon); extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, struct kvec *iov, unsigned int min_buf_size); -- 2.20.1