four smb3 fixes for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAlyky9oACgkQiiy9cAdy T1EW8Qv8D9lQlYxTDOWj5Uc8xXDfVLXCaX1SDQkA1jXjcq1d8PuFqMZLcgec19vb rIAhuojtuF8JFdIzVwq/2jwBxcnk7lb4ru2AgLFWMWBAjGfQdS329XUcGno+Llyv zIx4FGfUqrATsIfWRtUBdCML/8evrI5Miv/HRrWSqv6KlyAThUzBDeQsPrG8fs2a 7J9//9qqdiZXMdOL3sRUXBY5JuWHAPAS2TJcpTJzgpPHVoO5Hz+KtDx76XlJvypi Ol9oKVUB4AQTX/A2OqsMUCW39skQSgOW6zp4oWB1R/ctJHhMsYES5+UhAO9PXn0p uZr8VA1AVA6OOhpdvyiYGZm0UcMQZGXBPdbTUUZoaE7tsv9SIG91ayVyTWEwmpKe yaGxSRJY5eogX3H20jFXmyAFBDuC2zf5KwqhF2gnEFXpMddgczADlVc+EntxNKWT lpWHQiLgM4QckNSL88r/fu/9m0bB1Wlok/Oukh7oWWfo0wE7IOmknEGYCnjS70k+ KAmBLJBN =TvT3 -----END PGP SIGNATURE----- Merge tag '5.1-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6 Pull smb3 fixes from Steve French: "Four smb3 fixes for stable: - fix an open path where we had an unitialized structure - fix for snapshot (previous version) enumeration - allow reconnect timeout on handles to be configurable to better handle network or server crash - correctly handle lack of file_all_info structure" * tag '5.1-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: a smb2_validate_and_copy_iov failure does not mean the handle is invalid. SMB3: Allow persistent handle timeout to be configurable on mount smb3: Fix enumerating snapshots to Azure cifs: fix kref underflow in close_shroot()
This commit is contained in:
commit
145f47c738
|
@ -559,6 +559,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
|||
tcon->ses->server->echo_interval / HZ);
|
||||
if (tcon->snapshot_time)
|
||||
seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
|
||||
if (tcon->handle_timeout)
|
||||
seq_printf(s, ",handletimeout=%u", tcon->handle_timeout);
|
||||
/* convert actimeo and display it in seconds */
|
||||
seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
|
||||
|
||||
|
|
|
@ -59,6 +59,12 @@
|
|||
*/
|
||||
#define CIFS_MAX_ACTIMEO (1 << 30)
|
||||
|
||||
/*
|
||||
* Max persistent and resilient handle timeout (milliseconds).
|
||||
* Windows durable max was 960000 (16 minutes)
|
||||
*/
|
||||
#define SMB3_MAX_HANDLE_TIMEOUT 960000
|
||||
|
||||
/*
|
||||
* MAX_REQ is the maximum number of requests that WE will send
|
||||
* on one socket concurrently.
|
||||
|
@ -586,6 +592,7 @@ struct smb_vol {
|
|||
struct nls_table *local_nls;
|
||||
unsigned int echo_interval; /* echo interval in secs */
|
||||
__u64 snapshot_time; /* needed for timewarp tokens */
|
||||
__u32 handle_timeout; /* persistent and durable handle timeout in ms */
|
||||
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
|
||||
};
|
||||
|
||||
|
@ -1058,6 +1065,7 @@ struct cifs_tcon {
|
|||
__u32 vol_serial_number;
|
||||
__le64 vol_create_time;
|
||||
__u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */
|
||||
__u32 handle_timeout; /* persistent and durable handle timeout in ms */
|
||||
__u32 ss_flags; /* sector size flags */
|
||||
__u32 perf_sector_size; /* best sector size for perf */
|
||||
__u32 max_chunks;
|
||||
|
|
|
@ -103,7 +103,7 @@ enum {
|
|||
Opt_cruid, Opt_gid, Opt_file_mode,
|
||||
Opt_dirmode, Opt_port,
|
||||
Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
|
||||
Opt_echo_interval, Opt_max_credits,
|
||||
Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
|
||||
Opt_snapshot,
|
||||
|
||||
/* Mount options which take string value */
|
||||
|
@ -208,6 +208,7 @@ static const match_table_t cifs_mount_option_tokens = {
|
|||
{ Opt_rsize, "rsize=%s" },
|
||||
{ Opt_wsize, "wsize=%s" },
|
||||
{ Opt_actimeo, "actimeo=%s" },
|
||||
{ Opt_handletimeout, "handletimeout=%s" },
|
||||
{ Opt_echo_interval, "echo_interval=%s" },
|
||||
{ Opt_max_credits, "max_credits=%s" },
|
||||
{ Opt_snapshot, "snapshot=%s" },
|
||||
|
@ -1619,6 +1620,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
|||
|
||||
vol->actimeo = CIFS_DEF_ACTIMEO;
|
||||
|
||||
/* Most clients set timeout to 0, allows server to use its default */
|
||||
vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
|
||||
|
||||
/* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
|
||||
vol->ops = &smb30_operations;
|
||||
vol->vals = &smbdefault_values;
|
||||
|
@ -2017,6 +2021,18 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
|||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
case Opt_handletimeout:
|
||||
if (get_option_ul(args, &option)) {
|
||||
cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
|
||||
__func__);
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
vol->handle_timeout = option;
|
||||
if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
|
||||
cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
case Opt_echo_interval:
|
||||
if (get_option_ul(args, &option)) {
|
||||
cifs_dbg(VFS, "%s: Invalid echo interval value\n",
|
||||
|
@ -3183,6 +3199,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
|
|||
return 0;
|
||||
if (tcon->snapshot_time != volume_info->snapshot_time)
|
||||
return 0;
|
||||
if (tcon->handle_timeout != volume_info->handle_timeout)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -3297,6 +3315,16 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
|
|||
tcon->snapshot_time = volume_info->snapshot_time;
|
||||
}
|
||||
|
||||
if (volume_info->handle_timeout) {
|
||||
if (ses->server->vals->protocol_id == 0) {
|
||||
cifs_dbg(VFS,
|
||||
"Use SMB2.1 or later for handle timeout option\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out_fail;
|
||||
} else
|
||||
tcon->handle_timeout = volume_info->handle_timeout;
|
||||
}
|
||||
|
||||
tcon->ses = ses;
|
||||
if (volume_info->password) {
|
||||
tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
|
||||
|
|
|
@ -68,13 +68,15 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
|
|||
|
||||
|
||||
if (oparms->tcon->use_resilient) {
|
||||
nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */
|
||||
/* default timeout is 0, servers pick default (120 seconds) */
|
||||
nr_ioctl_req.Timeout =
|
||||
cpu_to_le32(oparms->tcon->handle_timeout);
|
||||
nr_ioctl_req.Reserved = 0;
|
||||
rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
|
||||
fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
|
||||
true /* is_fsctl */,
|
||||
(char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
|
||||
NULL, NULL /* no return info */);
|
||||
CIFSMaxBufSize, NULL, NULL /* no return info */);
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
cifs_dbg(VFS,
|
||||
"resiliency not supported by server, disabling\n");
|
||||
|
|
|
@ -581,7 +581,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
|
|||
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
|
||||
FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
|
||||
NULL /* no data input */, 0 /* no data input */,
|
||||
(char **)&out_buf, &ret_data_len);
|
||||
CIFSMaxBufSize, (char **)&out_buf, &ret_data_len);
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
cifs_dbg(FYI,
|
||||
"server does not support query network interfaces\n");
|
||||
|
@ -717,32 +717,28 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
|
|||
oparms.fid->mid = le64_to_cpu(o_rsp->sync_hdr.MessageId);
|
||||
#endif /* CIFS_DEBUG2 */
|
||||
|
||||
if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE)
|
||||
oplock = smb2_parse_lease_state(server, o_rsp,
|
||||
&oparms.fid->epoch,
|
||||
oparms.fid->lease_key);
|
||||
else
|
||||
goto oshr_exit;
|
||||
|
||||
|
||||
memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid));
|
||||
tcon->crfid.tcon = tcon;
|
||||
tcon->crfid.is_valid = true;
|
||||
kref_init(&tcon->crfid.refcount);
|
||||
kref_get(&tcon->crfid.refcount);
|
||||
|
||||
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);
|
||||
} else
|
||||
goto oshr_exit;
|
||||
|
||||
qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
|
||||
if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info))
|
||||
goto oshr_exit;
|
||||
rc = smb2_validate_and_copy_iov(
|
||||
if (!smb2_validate_and_copy_iov(
|
||||
le16_to_cpu(qi_rsp->OutputBufferOffset),
|
||||
sizeof(struct smb2_file_all_info),
|
||||
&rsp_iov[1], sizeof(struct smb2_file_all_info),
|
||||
(char *)&tcon->crfid.file_all_info);
|
||||
if (rc)
|
||||
goto oshr_exit;
|
||||
tcon->crfid.file_all_info_is_valid = 1;
|
||||
(char *)&tcon->crfid.file_all_info))
|
||||
tcon->crfid.file_all_info_is_valid = 1;
|
||||
|
||||
oshr_exit:
|
||||
mutex_unlock(&tcon->crfid.fid_mutex);
|
||||
|
@ -1299,7 +1295,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
|
||||
rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
|
||||
FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */,
|
||||
NULL, 0 /* no input */,
|
||||
NULL, 0 /* no input */, CIFSMaxBufSize,
|
||||
(char **)&res_key, &ret_data_len);
|
||||
|
||||
if (rc) {
|
||||
|
@ -1404,7 +1400,7 @@ smb2_ioctl_query_info(const unsigned int xid,
|
|||
rc = SMB2_ioctl_init(tcon, &rqst[1],
|
||||
COMPOUND_FID, COMPOUND_FID,
|
||||
qi.info_type, true, NULL,
|
||||
0);
|
||||
0, CIFSMaxBufSize);
|
||||
}
|
||||
} else if (qi.flags == PASSTHRU_QUERY_INFO) {
|
||||
memset(&qi_iov, 0, sizeof(qi_iov));
|
||||
|
@ -1532,8 +1528,8 @@ smb2_copychunk_range(const unsigned int xid,
|
|||
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
|
||||
trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
|
||||
true /* is_fsctl */, (char *)pcchunk,
|
||||
sizeof(struct copychunk_ioctl), (char **)&retbuf,
|
||||
&ret_data_len);
|
||||
sizeof(struct copychunk_ioctl), CIFSMaxBufSize,
|
||||
(char **)&retbuf, &ret_data_len);
|
||||
if (rc == 0) {
|
||||
if (ret_data_len !=
|
||||
sizeof(struct copychunk_ioctl_rsp)) {
|
||||
|
@ -1693,7 +1689,7 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
|
||||
true /* is_fctl */,
|
||||
&setsparse, 1, NULL, NULL);
|
||||
&setsparse, 1, CIFSMaxBufSize, NULL, NULL);
|
||||
if (rc) {
|
||||
tcon->broken_sparse_sup = true;
|
||||
cifs_dbg(FYI, "set sparse rc = %d\n", rc);
|
||||
|
@ -1766,7 +1762,7 @@ smb2_duplicate_extents(const unsigned int xid,
|
|||
true /* is_fsctl */,
|
||||
(char *)&dup_ext_buf,
|
||||
sizeof(struct duplicate_extents_to_file),
|
||||
NULL,
|
||||
CIFSMaxBufSize, NULL,
|
||||
&ret_data_len);
|
||||
|
||||
if (ret_data_len > 0)
|
||||
|
@ -1801,7 +1797,7 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
true /* is_fsctl */,
|
||||
(char *)&integr_info,
|
||||
sizeof(struct fsctl_set_integrity_information_req),
|
||||
NULL,
|
||||
CIFSMaxBufSize, NULL,
|
||||
&ret_data_len);
|
||||
|
||||
}
|
||||
|
@ -1809,6 +1805,8 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
/* GMT Token is @GMT-YYYY.MM.DD-HH.MM.SS Unicode which is 48 bytes + null */
|
||||
#define GMT_TOKEN_SIZE 50
|
||||
|
||||
#define MIN_SNAPSHOT_ARRAY_SIZE 16 /* See MS-SMB2 section 3.3.5.15.1 */
|
||||
|
||||
/*
|
||||
* Input buffer contains (empty) struct smb_snapshot array with size filled in
|
||||
* For output see struct SRV_SNAPSHOT_ARRAY in MS-SMB2 section 2.2.32.2
|
||||
|
@ -1820,13 +1818,29 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
char *retbuf = NULL;
|
||||
unsigned int ret_data_len = 0;
|
||||
int rc;
|
||||
u32 max_response_size;
|
||||
struct smb_snapshot_array snapshot_in;
|
||||
|
||||
if (get_user(ret_data_len, (unsigned int __user *)ioc_buf))
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Note that for snapshot queries that servers like Azure expect that
|
||||
* the first query be minimal size (and just used to get the number/size
|
||||
* of previous versions) so response size must be specified as EXACTLY
|
||||
* sizeof(struct snapshot_array) which is 16 when rounded up to multiple
|
||||
* of eight bytes.
|
||||
*/
|
||||
if (ret_data_len == 0)
|
||||
max_response_size = MIN_SNAPSHOT_ARRAY_SIZE;
|
||||
else
|
||||
max_response_size = CIFSMaxBufSize;
|
||||
|
||||
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid,
|
||||
FSCTL_SRV_ENUMERATE_SNAPSHOTS,
|
||||
true /* is_fsctl */,
|
||||
NULL, 0 /* no input data */,
|
||||
NULL, 0 /* no input data */, max_response_size,
|
||||
(char **)&retbuf,
|
||||
&ret_data_len);
|
||||
cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
|
||||
|
@ -2304,7 +2318,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
|
|||
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
|
||||
FSCTL_DFS_GET_REFERRALS,
|
||||
true /* is_fsctl */,
|
||||
(char *)dfs_req, dfs_req_size,
|
||||
(char *)dfs_req, dfs_req_size, CIFSMaxBufSize,
|
||||
(char **)&dfs_rsp, &dfs_rsp_size);
|
||||
} while (rc == -EAGAIN);
|
||||
|
||||
|
@ -2658,7 +2672,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
|
|||
rc = SMB2_ioctl_init(tcon, &rqst[num++], cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
|
||||
true /* is_fctl */, (char *)&fsctl_buf,
|
||||
sizeof(struct file_zero_data_information));
|
||||
sizeof(struct file_zero_data_information),
|
||||
CIFSMaxBufSize);
|
||||
if (rc)
|
||||
goto zero_range_exit;
|
||||
|
||||
|
@ -2735,7 +2750,8 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
|
|||
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
|
||||
true /* is_fctl */, (char *)&fsctl_buf,
|
||||
sizeof(struct file_zero_data_information), NULL, NULL);
|
||||
sizeof(struct file_zero_data_information),
|
||||
CIFSMaxBufSize, NULL, NULL);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -1002,7 +1002,8 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
|
|||
|
||||
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
|
||||
FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
|
||||
(char *)pneg_inbuf, inbuflen, (char **)&pneg_rsp, &rsplen);
|
||||
(char *)pneg_inbuf, inbuflen, CIFSMaxBufSize,
|
||||
(char **)&pneg_rsp, &rsplen);
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
/*
|
||||
* Old Windows versions or Netapp SMB server can return
|
||||
|
@ -1858,8 +1859,9 @@ add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
|
|||
}
|
||||
|
||||
static struct create_durable_v2 *
|
||||
create_durable_v2_buf(struct cifs_fid *pfid)
|
||||
create_durable_v2_buf(struct cifs_open_parms *oparms)
|
||||
{
|
||||
struct cifs_fid *pfid = oparms->fid;
|
||||
struct create_durable_v2 *buf;
|
||||
|
||||
buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL);
|
||||
|
@ -1873,7 +1875,14 @@ create_durable_v2_buf(struct cifs_fid *pfid)
|
|||
(struct create_durable_v2, Name));
|
||||
buf->ccontext.NameLength = cpu_to_le16(4);
|
||||
|
||||
buf->dcontext.Timeout = 0; /* Should this be configurable by workload */
|
||||
/*
|
||||
* NB: Handle timeout defaults to 0, which allows server to choose
|
||||
* (most servers default to 120 seconds) and most clients default to 0.
|
||||
* This can be overridden at mount ("handletimeout=") if the user wants
|
||||
* a different persistent (or resilient) handle timeout for all opens
|
||||
* opens on a particular SMB3 mount.
|
||||
*/
|
||||
buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
|
||||
buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
|
||||
generate_random_uuid(buf->dcontext.CreateGuid);
|
||||
memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
|
||||
|
@ -1926,7 +1935,7 @@ add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
|
|||
struct smb2_create_req *req = iov[0].iov_base;
|
||||
unsigned int num = *num_iovec;
|
||||
|
||||
iov[num].iov_base = create_durable_v2_buf(oparms->fid);
|
||||
iov[num].iov_base = create_durable_v2_buf(oparms);
|
||||
if (iov[num].iov_base == NULL)
|
||||
return -ENOMEM;
|
||||
iov[num].iov_len = sizeof(struct create_durable_v2);
|
||||
|
@ -2478,7 +2487,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
|||
int
|
||||
SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
|
||||
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
||||
bool is_fsctl, char *in_data, u32 indatalen)
|
||||
bool is_fsctl, char *in_data, u32 indatalen,
|
||||
__u32 max_response_size)
|
||||
{
|
||||
struct smb2_ioctl_req *req;
|
||||
struct kvec *iov = rqst->rq_iov;
|
||||
|
@ -2520,16 +2530,21 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
|
|||
req->OutputCount = 0; /* MBZ */
|
||||
|
||||
/*
|
||||
* Could increase MaxOutputResponse, but that would require more
|
||||
* than one credit. Windows typically sets this smaller, but for some
|
||||
* In most cases max_response_size is set to 16K (CIFSMaxBufSize)
|
||||
* We Could increase default MaxOutputResponse, but that could require
|
||||
* more credits. Windows typically sets this smaller, but for some
|
||||
* ioctls it may be useful to allow server to send more. No point
|
||||
* limiting what the server can send as long as fits in one credit
|
||||
* Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE
|
||||
* (by default, note that it can be overridden to make max larger)
|
||||
* in responses (except for read responses which can be bigger.
|
||||
* We may want to bump this limit up
|
||||
* We can not handle more than CIFS_MAX_BUF_SIZE yet but may want
|
||||
* to increase this limit up in the future.
|
||||
* Note that for snapshot queries that servers like Azure expect that
|
||||
* the first query be minimal size (and just used to get the number/size
|
||||
* of previous versions) so response size must be specified as EXACTLY
|
||||
* sizeof(struct snapshot_array) which is 16 when rounded up to multiple
|
||||
* of eight bytes. Currently that is the only case where we set max
|
||||
* response size smaller.
|
||||
*/
|
||||
req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize);
|
||||
req->MaxOutputResponse = cpu_to_le32(max_response_size);
|
||||
|
||||
if (is_fsctl)
|
||||
req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
|
||||
|
@ -2550,13 +2565,14 @@ SMB2_ioctl_free(struct smb_rqst *rqst)
|
|||
cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SMB2 IOCTL is used for both IOCTLs and FSCTLs
|
||||
*/
|
||||
int
|
||||
SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
||||
u64 volatile_fid, u32 opcode, bool is_fsctl,
|
||||
char *in_data, u32 indatalen,
|
||||
char *in_data, u32 indatalen, u32 max_out_data_len,
|
||||
char **out_data, u32 *plen /* returned data len */)
|
||||
{
|
||||
struct smb_rqst rqst;
|
||||
|
@ -2593,8 +2609,8 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|||
rqst.rq_iov = iov;
|
||||
rqst.rq_nvec = SMB2_IOCTL_IOV_SIZE;
|
||||
|
||||
rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid,
|
||||
opcode, is_fsctl, in_data, indatalen);
|
||||
rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid, opcode,
|
||||
is_fsctl, in_data, indatalen, max_out_data_len);
|
||||
if (rc)
|
||||
goto ioctl_exit;
|
||||
|
||||
|
@ -2672,7 +2688,8 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
|
||||
FSCTL_SET_COMPRESSION, true /* is_fsctl */,
|
||||
(char *)&fsctl_input /* data input */,
|
||||
2 /* in data len */, &ret_data /* out data */, NULL);
|
||||
2 /* in data len */, CIFSMaxBufSize /* max out data */,
|
||||
&ret_data /* out data */, NULL);
|
||||
|
||||
cifs_dbg(FYI, "set compression rc %d\n", rc);
|
||||
|
||||
|
|
|
@ -142,11 +142,12 @@ extern int SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
|
|||
extern void SMB2_open_free(struct smb_rqst *rqst);
|
||||
extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
||||
bool is_fsctl, char *in_data, u32 indatalen,
|
||||
bool is_fsctl, char *in_data, u32 indatalen, u32 maxoutlen,
|
||||
char **out_data, u32 *plen /* returned data len */);
|
||||
extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
|
||||
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
||||
bool is_fsctl, char *in_data, u32 indatalen);
|
||||
bool is_fsctl, char *in_data, u32 indatalen,
|
||||
__u32 max_response_size);
|
||||
extern void SMB2_ioctl_free(struct smb_rqst *rqst);
|
||||
extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_file_id, u64 volatile_file_id);
|
||||
|
|
Loading…
Reference in New Issue