Skip to content

Commit

Permalink
smb3: optimize open to not send query file internal info
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steve French committed Jul 18, 2019
1 parent bf3c90e commit 89a5bfa
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 26 deletions.
18 changes: 12 additions & 6 deletions fs/cifs/smb2file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
7 changes: 4 additions & 3 deletions fs/cifs/smb2ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
46 changes: 33 additions & 13 deletions fs/cifs/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1873,26 +1873,46 @@ 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;
unsigned int next;
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)
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion fs/cifs/smb2pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
7 changes: 4 additions & 3 deletions fs/cifs/smb2proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 89a5bfa

Please sign in to comment.