Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89a5bfa3 authored by Steve French's avatar Steve French
Browse files

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: default avatarPavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent bf3c90ee
Loading
Loading
Loading
Loading
+12 −6
Original line number Original line Diff line number Diff line
@@ -88,15 +88,21 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
	}
	}


	if (buf) {
	if (buf) {
		/* open response does not have IndexNumber field - get it */
		/* if open response does not have IndexNumber field - get it */
		rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid,
		if (smb2_data->IndexNumber == 0) {
			rc = SMB2_get_srv_num(xid, oparms->tcon,
				      fid->persistent_fid,
				      fid->volatile_fid,
				      fid->volatile_fid,
				      &smb2_data->IndexNumber);
				      &smb2_data->IndexNumber);
			if (rc) {
			if (rc) {
			/* let get_inode_info disable server inode numbers */
				/*
				 * let get_inode_info disable server inode
				 * numbers
				 */
				smb2_data->IndexNumber = 0;
				smb2_data->IndexNumber = 0;
				rc = 0;
				rc = 0;
			}
			}
		}
		move_smb2_info_to_cifs(buf, smb2_data);
		move_smb2_info_to_cifs(buf, smb2_data);
	}
	}


+4 −3
Original line number Original line Diff line number Diff line
@@ -754,11 +754,12 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
	tcon->crfid.is_valid = true;
	tcon->crfid.is_valid = true;
	kref_init(&tcon->crfid.refcount);
	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) {
	if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
		kref_get(&tcon->crfid.refcount);
		kref_get(&tcon->crfid.refcount);
		oplock = smb2_parse_lease_state(server, o_rsp,
		smb2_parse_contexts(server, o_rsp,
				&oparms.fid->epoch,
				&oparms.fid->epoch,
						oparms.fid->lease_key);
				oparms.fid->lease_key, &oplock, NULL);
	} else
	} else
		goto oshr_exit;
		goto oshr_exit;


+33 −13
Original line number Original line Diff line number Diff line
@@ -1873,10 +1873,21 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
	return buf;
	return buf;
}
}


__u8
static void
smb2_parse_lease_state(struct TCP_Server_Info *server,
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,
		       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;
	char *data_offset;
	struct create_context *cc;
	struct create_context *cc;
@@ -1884,15 +1895,24 @@ smb2_parse_lease_state(struct TCP_Server_Info *server,
	unsigned int remaining;
	unsigned int remaining;
	char *name;
	char *name;


	*oplock = 0;
	data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
	data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
	remaining = le32_to_cpu(rsp->CreateContextsLength);
	remaining = le32_to_cpu(rsp->CreateContextsLength);
	cc = (struct create_context *)data_offset;
	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)) {
	while (remaining >= sizeof(struct create_context)) {
		name = le16_to_cpu(cc->NameOffset) + (char *)cc;
		name = le16_to_cpu(cc->NameOffset) + (char *)cc;
		if (le16_to_cpu(cc->NameLength) == 4 &&
		if (le16_to_cpu(cc->NameLength) == 4 &&
		    strncmp(name, "RqLs", 4) == 0)
		    strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0)
			return server->ops->parse_lease_buf(cc, epoch,
			*oplock = server->ops->parse_lease_buf(cc, epoch,
							   lease_key);
							   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);
		next = le32_to_cpu(cc->Next);
		if (!next)
		if (!next)
@@ -1901,7 +1921,10 @@ smb2_parse_lease_state(struct TCP_Server_Info *server,
		cc = (struct create_context *)((char *)cc + next);
		cc = (struct create_context *)((char *)cc + next);
	}
	}


	return 0;
	if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
		*oplock = rsp->OplockLevel;

	return;
}
}


static int
static int
@@ -2588,12 +2611,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
		buf->DeletePending = 0;
		buf->DeletePending = 0;
	}
	}


	if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE)

		*oplock = smb2_parse_lease_state(server, rsp,
	smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
						 &oparms->fid->epoch,
			    oparms->fid->lease_key, oplock, buf);
						 oparms->fid->lease_key);
	else
		*oplock = rsp->OplockLevel;
creat_exit:
creat_exit:
	SMB2_open_free(&rqst);
	SMB2_open_free(&rqst);
	free_rsp_buf(resp_buftype, rsp);
	free_rsp_buf(resp_buftype, rsp);
+3 −1
Original line number Original line Diff line number Diff line
@@ -818,7 +818,9 @@ struct durable_reconnect_context_v2 {
} __packed;
} __packed;


/* See MS-SMB2 2.2.14.2.9 */
/* 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 DiskFileId;
	__le64 VolumeId;
	__le64 VolumeId;
	__u32  Reserved[4];
	__u32  Reserved[4];
+4 −3
Original line number Original line Diff line number Diff line
@@ -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 *,
extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
					enum securityEnum);
					enum securityEnum);
extern __u8 smb2_parse_lease_state(struct TCP_Server_Info *server,
extern void smb2_parse_contexts(struct TCP_Server_Info *server,
				struct smb2_create_rsp *rsp,
				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);
extern int smb3_encryption_required(const struct cifs_tcon *tcon);
extern int smb3_encryption_required(const struct cifs_tcon *tcon);
extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
			     struct kvec *iov, unsigned int min_buf_size);
			     struct kvec *iov, unsigned int min_buf_size);