aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2018-12-12 09:52:44 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2018-12-12 09:52:44 +1100
commit7f2d4aa789a4df83151aaad6fc4bda49c7480da0 (patch)
treedccbd7bd6769f485e3c010b65c3a92777561d0fa
parente97b29910a6489ba54a4519127a2aedb2dfbf34c (diff)
parent1b472ce02520985ffc98855dfca16b7fd2c80be6 (diff)
downloadlinux-2.6-7f2d4aa789a4df83151aaad6fc4bda49c7480da0.tar.gz
Merge remote-tracking branch 'cifs/for-next'
-rw-r--r--fs/cifs/cifsencrypt.c2
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/inode.c2
-rw-r--r--fs/cifs/sess.c4
-rw-r--r--fs/cifs/smb2ops.c263
-rw-r--r--fs/cifs/smb2pdu.c12
-rw-r--r--fs/cifs/smb2pdu.h1
-rw-r--r--fs/cifs/smb2proto.h10
-rw-r--r--fs/cifs/transport.c8
10 files changed, 180 insertions, 126 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 85b31cfa2f3c00..ecdff344e8fea1 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -224,7 +224,7 @@ int cifs_verify_signature(struct smb_rqst *rqst,
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
struct smb_com_lock_req *pSMB =
(struct smb_com_lock_req *)cifs_pdu;
- if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
+ if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
return 0;
}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 38ab0fca49e1da..7b3b9313dcdebe 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1790,6 +1790,7 @@ extern struct smb_version_values smb3any_values;
extern struct smb_version_operations smb30_operations;
extern struct smb_version_values smb30_values;
#define SMB302_VERSION_STRING "3.02"
+#define ALT_SMB302_VERSION_STRING "3.0.2"
/*extern struct smb_version_operations smb302_operations;*/ /* not needed yet */
extern struct smb_version_values smb302_values;
#define SMB311_VERSION_STRING "3.1.1"
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 6f24f129a75135..e4a924ba6325a5 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -304,6 +304,7 @@ static const match_table_t cifs_smb_version_tokens = {
{ Smb_21, SMB21_VERSION_STRING },
{ Smb_30, SMB30_VERSION_STRING },
{ Smb_302, SMB302_VERSION_STRING },
+ { Smb_302, ALT_SMB302_VERSION_STRING },
{ Smb_311, SMB311_VERSION_STRING },
{ Smb_311, ALT_SMB311_VERSION_STRING },
{ Smb_3any, SMB3ANY_VERSION_STRING },
@@ -1827,7 +1828,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
vol->password = NULL;
break;
}
- /* Yes it is. Drop down to Opt_pass below.*/
+ /* Fallthrough - to Opt_pass below.*/
case Opt_pass:
/* Obtain the value string */
value = strchr(data, '=');
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a81a9df997c1c1..1fe9f3b01703f1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -333,7 +333,7 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
fattr->cf_mtime = timespec64_trunc(fattr->cf_mtime, sb->s_time_gran);
fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
fattr->cf_nlink = 2;
- fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
+ fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL;
}
static int
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index aa23c00367ec46..dcd49ad60c83d4 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -534,9 +534,9 @@ cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
if (global_secflags & CIFSSEC_MAY_NTLM)
return NTLM;
default:
- /* Fallthrough to attempt LANMAN authentication next */
break;
}
+ /* Fallthrough - to attempt LANMAN authentication next */
case CIFS_NEGFLAVOR_LANMAN:
switch (requested) {
case LANMAN:
@@ -1154,14 +1154,12 @@ out:
static int
_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
{
- struct smb_hdr *smb_buf;
SESSION_SETUP_ANDX *pSMB;
struct cifs_ses *ses = sess_data->ses;
__u32 capabilities;
char *bcc_ptr;
pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
- smb_buf = (struct smb_hdr *)pSMB;
capabilities = cifs_ssetup_hdr(ses, pSMB);
if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 225fec1cfa6733..888999ef76aabd 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -831,72 +831,48 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
{
int rc;
__le16 *utf16_path;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
- struct smb2_file_full_ea_info *smb2_data;
- int ea_buf_size = SMB2_MIN_EA_BUF;
+ struct kvec rsp_iov = {NULL, 0};
+ int buftype = CIFS_NO_BUFFER;
+ struct smb2_query_info_rsp *rsp;
+ struct smb2_file_full_ea_info *info = NULL;
utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
if (!utf16_path)
return -ENOMEM;
- oparms.tcon = tcon;
- oparms.desired_access = FILE_READ_EA;
- oparms.disposition = FILE_OPEN;
- if (backup_cred(cifs_sb))
- oparms.create_options = CREATE_OPEN_BACKUP_INTENT;
- else
- oparms.create_options = 0;
- oparms.fid = &fid;
- oparms.reconnect = false;
-
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
- kfree(utf16_path);
+ rc = smb2_query_info_compound(xid, tcon, utf16_path,
+ FILE_READ_EA,
+ FILE_FULL_EA_INFORMATION,
+ SMB2_O_INFO_FILE,
+ SMB2_MAX_EA_BUF,
+ &rsp_iov, &buftype, cifs_sb);
if (rc) {
- cifs_dbg(FYI, "open failed rc=%d\n", rc);
- return rc;
- }
-
- while (1) {
- smb2_data = kzalloc(ea_buf_size, GFP_KERNEL);
- if (smb2_data == NULL) {
- SMB2_close(xid, tcon, fid.persistent_fid,
- fid.volatile_fid);
- return -ENOMEM;
- }
-
- rc = SMB2_query_eas(xid, tcon, fid.persistent_fid,
- fid.volatile_fid,
- ea_buf_size, smb2_data);
-
- if (rc != -E2BIG)
- break;
-
- kfree(smb2_data);
- ea_buf_size <<= 1;
-
- if (ea_buf_size > SMB2_MAX_EA_BUF) {
- cifs_dbg(VFS, "EA size is too large\n");
- SMB2_close(xid, tcon, fid.persistent_fid,
- fid.volatile_fid);
- return -ENOMEM;
- }
+ /*
+ * If ea_name is NULL (listxattr) and there are no EAs,
+ * return 0 as it's not an error. Otherwise, the specified
+ * ea_name was not found.
+ */
+ if (!ea_name && rc == -ENODATA)
+ rc = 0;
+ goto qeas_exit;
}
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+ rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+ le32_to_cpu(rsp->OutputBufferLength),
+ &rsp_iov,
+ sizeof(struct smb2_file_full_ea_info));
+ if (rc)
+ goto qeas_exit;
- /*
- * If ea_name is NULL (listxattr) and there are no EAs, return 0 as it's
- * not an error. Otherwise, the specified ea_name was not found.
- */
- if (!rc)
- rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data,
- SMB2_MAX_EA_BUF, ea_name);
- else if (!ea_name && rc == -ENODATA)
- rc = 0;
+ info = (struct smb2_file_full_ea_info *)(
+ le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
+ rc = move_smb2_ea_to_cifs(ea_data, buf_size, info,
+ le32_to_cpu(rsp->OutputBufferLength), ea_name);
- kfree(smb2_data);
+ qeas_exit:
+ kfree(utf16_path);
+ free_rsp_buf(buftype, rsp_iov.iov_base);
return rc;
}
@@ -907,14 +883,28 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
const __u16 ea_value_len, const struct nls_table *nls_codepage,
struct cifs_sb_info *cifs_sb)
{
- int rc;
- __le16 *utf16_path;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
- struct smb2_file_full_ea_info *ea;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = ses->server;
+ __le16 *utf16_path = NULL;
int ea_name_len = strlen(ea_name);
+ int flags = 0;
int len;
+ struct smb_rqst rqst[3];
+ int resp_buftype[3];
+ struct kvec rsp_iov[3];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct cifs_open_parms oparms;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_fid fid;
+ struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
+ unsigned int size[1];
+ void *data[1];
+ struct smb2_file_full_ea_info *ea = NULL;
+ struct kvec close_iov[1];
+ int rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
if (ea_name_len > 255)
return -EINVAL;
@@ -923,6 +913,16 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
if (!utf16_path)
return -ENOMEM;
+ memset(rqst, 0, sizeof(rqst));
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+ memset(rsp_iov, 0, sizeof(rsp_iov));
+
+ /* Open */
+ memset(&open_iov, 0, sizeof(open_iov));
+ rqst[0].rq_iov = open_iov;
+ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ memset(&oparms, 0, sizeof(oparms));
oparms.tcon = tcon;
oparms.desired_access = FILE_WRITE_EA;
oparms.disposition = FILE_OPEN;
@@ -933,18 +933,22 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
- kfree(utf16_path);
- if (rc) {
- cifs_dbg(FYI, "open failed rc=%d\n", rc);
- return rc;
- }
+ rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path);
+ if (rc)
+ goto sea_exit;
+ smb2_set_next_command(ses->server, &rqst[0]);
+
+
+ /* Set Info */
+ memset(&si_iov, 0, sizeof(si_iov));
+ rqst[1].rq_iov = si_iov;
+ rqst[1].rq_nvec = 1;
len = sizeof(ea) + ea_name_len + ea_value_len + 1;
ea = kzalloc(len, GFP_KERNEL);
if (ea == NULL) {
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto sea_exit;
}
ea->ea_name_length = ea_name_len;
@@ -952,12 +956,36 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
memcpy(ea->ea_data, ea_name, ea_name_len + 1);
memcpy(ea->ea_data + ea_name_len + 1, ea_value, ea_value_len);
- rc = SMB2_set_ea(xid, tcon, fid.persistent_fid, fid.volatile_fid, ea,
- len);
- kfree(ea);
+ size[0] = len;
+ data[0] = ea;
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ rc = SMB2_set_info_init(tcon, &rqst[1], COMPOUND_FID,
+ COMPOUND_FID, current->tgid,
+ FILE_FULL_EA_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ smb2_set_next_command(server, &rqst[1]);
+ smb2_set_related(&rqst[1]);
+
+
+ /* Close */
+ memset(&close_iov, 0, sizeof(close_iov));
+ rqst[2].rq_iov = close_iov;
+ rqst[2].rq_nvec = 1;
+ rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID);
+ smb2_set_related(&rqst[2]);
+
+ rc = compound_send_recv(xid, ses, flags, 3, rqst,
+ resp_buftype, rsp_iov);
+ sea_exit:
+ kfree(ea);
+ kfree(utf16_path);
+ SMB2_open_free(&rqst[0]);
+ SMB2_set_info_free(&rqst[1]);
+ SMB2_close_free(&rqst[2]);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
return rc;
}
#endif
@@ -1778,25 +1806,29 @@ smb2_set_next_command(struct TCP_Server_Info *server, struct smb_rqst *rqst)
shdr->NextCommand = cpu_to_le32(len);
}
-static int
-smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
- struct kstatfs *buf)
+/*
+ * Passes the query info response back to the caller on success.
+ * Caller need to free this with free_rsp_buf().
+ */
+int
+smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
+ __le16 *utf16_path, u32 desired_access,
+ u32 class, u32 type, u32 output_len,
+ struct kvec *rsp, int *buftype,
+ struct cifs_sb_info *cifs_sb)
{
- struct smb2_query_info_rsp *rsp;
- struct smb2_fs_full_size_info *info = NULL;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = ses->server;
+ int flags = 0;
struct smb_rqst rqst[3];
int resp_buftype[3];
struct kvec rsp_iov[3];
struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
struct kvec qi_iov[1];
struct kvec close_iov[1];
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = ses->server;
- __le16 srch_path = 0; /* Null - open root of share */
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
struct cifs_open_parms oparms;
struct cifs_fid fid;
- int flags = 0;
int rc;
if (smb3_encryption_required(tcon))
@@ -1811,15 +1843,18 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
oparms.tcon = tcon;
- oparms.desired_access = FILE_READ_ATTRIBUTES;
+ oparms.desired_access = desired_access;
oparms.disposition = FILE_OPEN;
- oparms.create_options = 0;
+ if (cifs_sb && backup_cred(cifs_sb))
+ oparms.create_options = CREATE_OPEN_BACKUP_INTENT;
+ else
+ oparms.create_options = 0;
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &srch_path);
+ rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path);
if (rc)
- goto qfs_exit;
+ goto qic_exit;
smb2_set_next_command(server, &rqst[0]);
memset(&qi_iov, 0, sizeof(qi_iov));
@@ -1827,12 +1862,11 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
rqst[1].rq_nvec = 1;
rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, COMPOUND_FID,
- FS_FULL_SIZE_INFORMATION,
- SMB2_O_INFO_FILESYSTEM, 0,
- sizeof(struct smb2_fs_full_size_info), 0,
+ class, type, 0,
+ output_len, 0,
NULL);
if (rc)
- goto qfs_exit;
+ goto qic_exit;
smb2_set_next_command(server, &rqst[1]);
smb2_set_related(&rqst[1]);
@@ -1842,32 +1876,61 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID);
if (rc)
- goto qfs_exit;
+ goto qic_exit;
smb2_set_related(&rqst[2]);
rc = compound_send_recv(xid, ses, flags, 3, rqst,
resp_buftype, rsp_iov);
+ if (rc) {
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ goto qic_exit;
+ }
+ *rsp = rsp_iov[1];
+ *buftype = resp_buftype[1];
+
+ qic_exit:
+ SMB2_open_free(&rqst[0]);
+ SMB2_query_info_free(&rqst[1]);
+ SMB2_close_free(&rqst[2]);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+ return rc;
+}
+
+static int
+smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
+ struct kstatfs *buf)
+{
+ struct smb2_query_info_rsp *rsp;
+ struct smb2_fs_full_size_info *info = NULL;
+ __le16 utf16_path = 0; /* Null - open root of share */
+ struct kvec rsp_iov = {NULL, 0};
+ int buftype = CIFS_NO_BUFFER;
+ int rc;
+
+
+ rc = smb2_query_info_compound(xid, tcon, &utf16_path,
+ FILE_READ_ATTRIBUTES,
+ FS_FULL_SIZE_INFORMATION,
+ SMB2_O_INFO_FILESYSTEM,
+ sizeof(struct smb2_fs_full_size_info),
+ &rsp_iov, &buftype, NULL);
if (rc)
goto qfs_exit;
- rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
buf->f_type = SMB2_MAGIC_NUMBER;
info = (struct smb2_fs_full_size_info *)(
le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
le32_to_cpu(rsp->OutputBufferLength),
- &rsp_iov[1],
+ &rsp_iov,
sizeof(struct smb2_fs_full_size_info));
if (!rc)
smb2_copy_fs_info_to_kstatfs(info, buf);
qfs_exit:
- SMB2_open_free(&rqst[0]);
- SMB2_query_info_free(&rqst[1]);
- SMB2_close_free(&rqst[2]);
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+ free_rsp_buf(buftype, rsp_iov.iov_base);
return rc;
}
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 27f86537a5d11a..448031898dd43a 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2768,18 +2768,6 @@ qinf_exit:
return rc;
}
-int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- int ea_buf_size, struct smb2_file_full_ea_info *data)
-{
- return query_info(xid, tcon, persistent_fid, volatile_fid,
- FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0,
- ea_buf_size,
- sizeof(struct smb2_file_full_ea_info),
- (void **)&data,
- NULL);
-}
-
int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data)
{
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 5671d5ee7f58f6..05dea6750c33d5 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -1398,7 +1398,6 @@ struct smb2_file_link_info { /* encoding of request for level 11 */
char FileName[0]; /* Name to be assigned to new link */
} __packed; /* level 11 Set */
-#define SMB2_MIN_EA_BUF 2048
#define SMB2_MAX_EA_BUF 65536
struct smb2_file_full_ea_info { /* encoding of response for level 15 */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 9f4e9ed9ce53c2..7f351e5c3ce6ed 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -153,10 +153,6 @@ extern int SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
extern void SMB2_close_free(struct smb_rqst *rqst);
extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id);
-extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id,
- int ea_buf_size,
- struct smb2_file_full_ea_info *data);
extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id,
struct smb2_file_all_info *data);
@@ -240,4 +236,10 @@ extern void smb2_copy_fs_info_to_kstatfs(
extern int smb311_crypto_shash_allocate(struct TCP_Server_Info *server);
extern int smb311_update_preauth_hash(struct cifs_ses *ses,
struct kvec *iov, int nvec);
+extern int smb2_query_info_compound(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ __le16 *utf16_path, u32 desired_access,
+ u32 class, u32 type, u32 output_len,
+ struct kvec *rsp, int *buftype,
+ struct cifs_sb_info *cifs_sb);
#endif /* _SMB2PROTO_H */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 83ff0c25710d08..5be7302853b6c5 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -126,9 +126,11 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
if ((slow_rsp_threshold != 0) &&
time_after(now, midEntry->when_alloc + (slow_rsp_threshold * HZ)) &&
(midEntry->command != command)) {
- /* smb2slowcmd[NUMBER_OF_SMB2_COMMANDS] counts by command */
- if ((le16_to_cpu(midEntry->command) < NUMBER_OF_SMB2_COMMANDS) &&
- (le16_to_cpu(midEntry->command) >= 0))
+ /*
+ * smb2slowcmd[NUMBER_OF_SMB2_COMMANDS] counts by command
+ * NB: le16_to_cpu returns unsigned so can not be negative below
+ */
+ if (le16_to_cpu(midEntry->command) < NUMBER_OF_SMB2_COMMANDS)
cifs_stats_inc(&midEntry->server->smb2slowcmd[le16_to_cpu(midEntry->command)]);
trace_smb3_slow_rsp(le16_to_cpu(midEntry->command),