diff options
author | Steve French <stfrench@microsoft.com> | 2019-07-18 18:22:18 -0400 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-07-18 18:44:13 -0400 |
commit | 89a5bfa350faf87156acda4d7c457808bfecaa0e (patch) | |
tree | 9560165181bb65a6966bd21681ea9b777517447c /fs/cifs | |
parent | bf3c90ee1efe4dd3417d2129f9f6c68a4c76de00 (diff) |
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.
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>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/smb2file.c | 18 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 7 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 46 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 4 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 7 |
5 files changed, 56 insertions, 26 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, | |||
88 | } | 88 | } |
89 | 89 | ||
90 | if (buf) { | 90 | if (buf) { |
91 | /* open response does not have IndexNumber field - get it */ | 91 | /* if open response does not have IndexNumber field - get it */ |
92 | rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid, | 92 | if (smb2_data->IndexNumber == 0) { |
93 | rc = SMB2_get_srv_num(xid, oparms->tcon, | ||
94 | fid->persistent_fid, | ||
93 | fid->volatile_fid, | 95 | fid->volatile_fid, |
94 | &smb2_data->IndexNumber); | 96 | &smb2_data->IndexNumber); |
95 | if (rc) { | 97 | if (rc) { |
96 | /* let get_inode_info disable server inode numbers */ | 98 | /* |
97 | smb2_data->IndexNumber = 0; | 99 | * let get_inode_info disable server inode |
98 | rc = 0; | 100 | * numbers |
101 | */ | ||
102 | smb2_data->IndexNumber = 0; | ||
103 | rc = 0; | ||
104 | } | ||
99 | } | 105 | } |
100 | move_smb2_info_to_cifs(buf, smb2_data); | 106 | move_smb2_info_to_cifs(buf, smb2_data); |
101 | } | 107 | } |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index fed75e1646c1..a5bc1b671c12 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -754,11 +754,12 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) | |||
754 | tcon->crfid.is_valid = true; | 754 | tcon->crfid.is_valid = true; |
755 | kref_init(&tcon->crfid.refcount); | 755 | kref_init(&tcon->crfid.refcount); |
756 | 756 | ||
757 | /* BB TBD check to see if oplock level check can be removed below */ | ||
757 | if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) { | 758 | if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) { |
758 | kref_get(&tcon->crfid.refcount); | 759 | kref_get(&tcon->crfid.refcount); |
759 | oplock = smb2_parse_lease_state(server, o_rsp, | 760 | smb2_parse_contexts(server, o_rsp, |
760 | &oparms.fid->epoch, | 761 | &oparms.fid->epoch, |
761 | oparms.fid->lease_key); | 762 | oparms.fid->lease_key, &oplock, NULL); |
762 | } else | 763 | } else |
763 | goto oshr_exit; | 764 | goto oshr_exit; |
764 | 765 | ||
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index f58e4dc3987b..c8cd7b6cdda2 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -1873,10 +1873,21 @@ create_reconnect_durable_buf(struct cifs_fid *fid) | |||
1873 | return buf; | 1873 | return buf; |
1874 | } | 1874 | } |
1875 | 1875 | ||
1876 | __u8 | 1876 | static void |
1877 | smb2_parse_lease_state(struct TCP_Server_Info *server, | 1877 | parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf) |
1878 | { | ||
1879 | struct create_on_disk_id *pdisk_id = (struct create_on_disk_id *)cc; | ||
1880 | |||
1881 | cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n", | ||
1882 | pdisk_id->DiskFileId, pdisk_id->VolumeId); | ||
1883 | buf->IndexNumber = pdisk_id->DiskFileId; | ||
1884 | } | ||
1885 | |||
1886 | void | ||
1887 | smb2_parse_contexts(struct TCP_Server_Info *server, | ||
1878 | struct smb2_create_rsp *rsp, | 1888 | struct smb2_create_rsp *rsp, |
1879 | unsigned int *epoch, char *lease_key) | 1889 | unsigned int *epoch, char *lease_key, __u8 *oplock, |
1890 | struct smb2_file_all_info *buf) | ||
1880 | { | 1891 | { |
1881 | char *data_offset; | 1892 | char *data_offset; |
1882 | struct create_context *cc; | 1893 | struct create_context *cc; |
@@ -1884,15 +1895,24 @@ smb2_parse_lease_state(struct TCP_Server_Info *server, | |||
1884 | unsigned int remaining; | 1895 | unsigned int remaining; |
1885 | char *name; | 1896 | char *name; |
1886 | 1897 | ||
1898 | *oplock = 0; | ||
1887 | data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); | 1899 | data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); |
1888 | remaining = le32_to_cpu(rsp->CreateContextsLength); | 1900 | remaining = le32_to_cpu(rsp->CreateContextsLength); |
1889 | cc = (struct create_context *)data_offset; | 1901 | cc = (struct create_context *)data_offset; |
1902 | |||
1903 | /* Initialize inode number to 0 in case no valid data in qfid context */ | ||
1904 | if (buf) | ||
1905 | buf->IndexNumber = 0; | ||
1906 | |||
1890 | while (remaining >= sizeof(struct create_context)) { | 1907 | while (remaining >= sizeof(struct create_context)) { |
1891 | name = le16_to_cpu(cc->NameOffset) + (char *)cc; | 1908 | name = le16_to_cpu(cc->NameOffset) + (char *)cc; |
1892 | if (le16_to_cpu(cc->NameLength) == 4 && | 1909 | if (le16_to_cpu(cc->NameLength) == 4 && |
1893 | strncmp(name, "RqLs", 4) == 0) | 1910 | strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0) |
1894 | return server->ops->parse_lease_buf(cc, epoch, | 1911 | *oplock = server->ops->parse_lease_buf(cc, epoch, |
1895 | lease_key); | 1912 | lease_key); |
1913 | else if (buf && (le16_to_cpu(cc->NameLength) == 4) && | ||
1914 | strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0) | ||
1915 | parse_query_id_ctxt(cc, buf); | ||
1896 | 1916 | ||
1897 | next = le32_to_cpu(cc->Next); | 1917 | next = le32_to_cpu(cc->Next); |
1898 | if (!next) | 1918 | if (!next) |
@@ -1901,7 +1921,10 @@ smb2_parse_lease_state(struct TCP_Server_Info *server, | |||
1901 | cc = (struct create_context *)((char *)cc + next); | 1921 | cc = (struct create_context *)((char *)cc + next); |
1902 | } | 1922 | } |
1903 | 1923 | ||
1904 | return 0; | 1924 | if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) |
1925 | *oplock = rsp->OplockLevel; | ||
1926 | |||
1927 | return; | ||
1905 | } | 1928 | } |
1906 | 1929 | ||
1907 | static int | 1930 | static int |
@@ -2588,12 +2611,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
2588 | buf->DeletePending = 0; | 2611 | buf->DeletePending = 0; |
2589 | } | 2612 | } |
2590 | 2613 | ||
2591 | if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) | 2614 | |
2592 | *oplock = smb2_parse_lease_state(server, rsp, | 2615 | smb2_parse_contexts(server, rsp, &oparms->fid->epoch, |
2593 | &oparms->fid->epoch, | 2616 | oparms->fid->lease_key, oplock, buf); |
2594 | oparms->fid->lease_key); | ||
2595 | else | ||
2596 | *oplock = rsp->OplockLevel; | ||
2597 | creat_exit: | 2617 | creat_exit: |
2598 | SMB2_open_free(&rqst); | 2618 | SMB2_open_free(&rqst); |
2599 | free_rsp_buf(resp_buftype, rsp); | 2619 | free_rsp_buf(resp_buftype, rsp); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 7e2e782f8edd..747de9317659 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -818,7 +818,9 @@ struct durable_reconnect_context_v2 { | |||
818 | } __packed; | 818 | } __packed; |
819 | 819 | ||
820 | /* See MS-SMB2 2.2.14.2.9 */ | 820 | /* See MS-SMB2 2.2.14.2.9 */ |
821 | struct on_disk_id { | 821 | struct create_on_disk_id { |
822 | struct create_context ccontext; | ||
823 | __u8 Name[8]; | ||
822 | __le64 DiskFileId; | 824 | __le64 DiskFileId; |
823 | __le64 VolumeId; | 825 | __le64 VolumeId; |
824 | __u32 Reserved[4]; | 826 | __u32 Reserved[4]; |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 52df125e9189..07ca72486cfa 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -228,9 +228,10 @@ extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *); | |||
228 | 228 | ||
229 | extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, | 229 | extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, |
230 | enum securityEnum); | 230 | enum securityEnum); |
231 | extern __u8 smb2_parse_lease_state(struct TCP_Server_Info *server, | 231 | extern void smb2_parse_contexts(struct TCP_Server_Info *server, |
232 | struct smb2_create_rsp *rsp, | 232 | struct smb2_create_rsp *rsp, |
233 | unsigned int *epoch, char *lease_key); | 233 | unsigned int *epoch, char *lease_key, |
234 | __u8 *oplock, struct smb2_file_all_info *buf); | ||
234 | extern int smb3_encryption_required(const struct cifs_tcon *tcon); | 235 | extern int smb3_encryption_required(const struct cifs_tcon *tcon); |
235 | extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, | 236 | extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, |
236 | struct kvec *iov, unsigned int min_buf_size); | 237 | struct kvec *iov, unsigned int min_buf_size); |