smb3: optimize open to not send query file internal info
authorSteve French <stfrench@microsoft.com>
Thu, 18 Jul 2019 22:22:18 +0000 (17:22 -0500)
committerSteve French <stfrench@microsoft.com>
Thu, 18 Jul 2019 22:44:13 +0000 (17:44 -0500)
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.

This is better in multiple ways, and
speeds up file open about 10% (more if network is slow).

Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/smb2file.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/smb2proto.h

index 54bffb2..e6a1fc7 100644 (file)
@@ -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);
        }
index fed75e1..a5bc1b6 100644 (file)
@@ -754,11 +754,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,
-                                               &oparms.fid->epoch,
-                                               oparms.fid->lease_key);
+               smb2_parse_contexts(server, o_rsp,
+                               &oparms.fid->epoch,
+                               oparms.fid->lease_key, &oplock, NULL);
        } else
                goto oshr_exit;
 
index f58e4dc..c8cd7b6 100644 (file)
@@ -1873,10 +1873,21 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
        return buf;
 }
 
-__u8
-smb2_parse_lease_state(struct TCP_Server_Info *server,
+static void
+parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf)
+{
+       struct create_on_disk_id *pdisk_id = (struct create_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;
+}
+
+void
+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, __u8 *oplock,
+                      struct smb2_file_all_info *buf)
 {
        char *data_offset;
        struct create_context *cc;
@@ -1884,15 +1895,24 @@ smb2_parse_lease_state(struct TCP_Server_Info *server,
        unsigned int remaining;
        char *name;
 
+       *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,10 @@ smb2_parse_lease_state(struct TCP_Server_Info *server,
                cc = (struct create_context *)((char *)cc + next);
        }
 
-       return 0;
+       if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
+               *oplock = rsp->OplockLevel;
+
+       return;
 }
 
 static int
@@ -2588,12 +2611,9 @@ 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 = rsp->OplockLevel;
+
+       smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
+                           oparms->fid->lease_key, oplock, buf);
 creat_exit:
        SMB2_open_free(&rqst);
        free_rsp_buf(resp_buftype, rsp);
index 7e2e782..747de93 100644 (file)
@@ -818,7 +818,9 @@ struct durable_reconnect_context_v2 {
 } __packed;
 
 /* See MS-SMB2 2.2.14.2.9 */
-struct on_disk_id {
+struct create_on_disk_id {
+       struct create_context ccontext;
+       __u8   Name[8];
        __le64 DiskFileId;
        __le64 VolumeId;
        __u32  Reserved[4];
index 52df125..07ca724 100644 (file)
@@ -228,9 +228,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,
-                                  struct smb2_create_rsp *rsp,
-                                  unsigned int *epoch, char *lease_key);
+extern void smb2_parse_contexts(struct TCP_Server_Info *server,
+                               struct smb2_create_rsp *rsp,
+                               unsigned int *epoch, char *lease_key,
+                               __u8 *oplock, 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);