diff options
author | Aurelien Aptel <aaptel@suse.com> | 2020-05-31 12:38:22 -0500 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2020-06-04 13:50:55 -0500 |
commit | 352d96f3acc6e02099f58a24d5cabce7f8ee061f (patch) | |
tree | e79c6858570c78cfc3bf7589584d421bbcd99bbf /fs/cifs | |
parent | 7c06514afd38ed7a4b83edfd39ab033c804b4cf3 (diff) |
cifs: multichannel: move channel selection above transport layer
Move the channel (TCP_Server_Info*) selection from the tranport
layer to higher in the call stack so that:
- credit handling is done with the server that will actually be used
to send.
* ->wait_mtu_credit
* ->set_credits / set_credits
* ->add_credits / add_credits
* add_credits_and_wake_if
- potential reconnection (smb2_reconnect) done when initializing a
request is checked and done with the server that will actually be
used to send.
To do this:
- remove the cifs_pick_channel() call out of compound_send_recv()
- select channel and pass it down by adding a cifs_pick_channel(ses)
call in:
- smb311_posix_mkdir
- SMB2_open
- SMB2_ioctl
- __SMB2_close
- query_info
- SMB2_change_notify
- SMB2_flush
- smb2_async_readv (if none provided in context param)
- SMB2_read (if none provided in context param)
- smb2_async_writev (if none provided in context param)
- SMB2_write (if none provided in context param)
- SMB2_query_directory
- send_set_info
- SMB2_oplock_break
- SMB311_posix_qfs_info
- SMB2_QFS_info
- SMB2_QFS_attr
- smb2_lockv
- SMB2_lease_break
- smb2_compound_op
- smb2_set_ea
- smb2_ioctl_query_info
- smb2_query_dir_first
- smb2_query_info_comound
- smb2_query_symlink
- cifs_writepages
- cifs_write_from_iter
- cifs_send_async_read
- cifs_read
- cifs_readpages
- add TCP_Server_Info *server param argument to:
- cifs_send_recv
- compound_send_recv
- SMB2_open_init
- SMB2_query_info_init
- SMB2_set_info_init
- SMB2_close_init
- SMB2_ioctl_init
- smb2_iotcl_req_init
- SMB2_query_directory_init
- SMB2_notify_init
- SMB2_flush_init
- build_qfs_info_req
- smb2_hdr_assemble
- smb2_reconnect
- fill_small_buf
- smb2_plain_req_init
- __smb2_plain_req_init
The read/write codepath is different than the rest as it is using
pages, io iterators and async calls. To deal with those we add a
server pointer in the cifs_writedata/cifs_readdata/cifs_io_parms
context struct and set it in:
- cifs_writepages (wdata)
- cifs_write_from_iter (wdata)
- cifs_readpages (rdata)
- cifs_send_async_read (rdata)
The [rw]data->server pointer is eventually copied to
cifs_io_parms->server to pass it down to SMB2_read/SMB2_write.
If SMB2_read/SMB2_write is called from a different place that doesn't
set the server field it will pick a channel.
Some places do not pick a channel and just use ses->server or
cifs_ses_server(ses). All cifs_ses_server(ses) calls are in codepaths
involving negprot/sess.setup.
- SMB2_negotiate (binding channel)
- SMB2_sess_alloc_buffer (binding channel)
- SMB2_echo (uses provided one)
- SMB2_logoff (uses master)
- SMB2_tdis (uses master)
(list not exhaustive)
Signed-off-by: Aurelien Aptel <aaptel@suse.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 32 | ||||
-rw-r--r-- | fs/cifs/link.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2inode.c | 44 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 79 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 353 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 25 | ||||
-rw-r--r-- | fs/cifs/transport.c | 14 |
9 files changed, 356 insertions, 198 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 4d261fd78fcb..c0cbbd0bbb1d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1335,6 +1335,7 @@ struct cifs_io_parms { __u64 offset; unsigned int length; struct cifs_tcon *tcon; + struct TCP_Server_Info *server; }; struct cifs_aio_ctx { @@ -1382,6 +1383,7 @@ struct cifs_readdata { struct cifs_readdata *rdata, struct iov_iter *iter); struct kvec iov[2]; + struct TCP_Server_Info *server; #ifdef CONFIG_CIFS_SMB_DIRECT struct smbd_mr *mr; #endif @@ -1408,6 +1410,7 @@ struct cifs_writedata { pid_t pid; unsigned int bytes; int result; + struct TCP_Server_Info *server; #ifdef CONFIG_CIFS_SMB_DIRECT struct smbd_mr *mr; #endif diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 9767f9b5d315..a25a46237f9f 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -98,9 +98,11 @@ extern int cifs_call_async(struct TCP_Server_Info *server, const struct cifs_credits *exist_credits); extern struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses); extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, struct smb_rqst *rqst, int *resp_buf_type, const int flags, struct kvec *resp_iov); extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, const int flags, const int num_rqst, struct smb_rqst *rqst, int *resp_buf_type, struct kvec *resp_iov); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index de130f3aa452..2ca9b387d216 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2292,8 +2292,6 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, struct address_space *mapping, struct writeback_control *wbc) { int rc; - struct TCP_Server_Info *server = - tlink_tcon(wdata->cfile->tlink)->ses->server; wdata->sync_mode = wbc->sync_mode; wdata->nr_pages = nr_pages; @@ -2305,14 +2303,15 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, wdata->bytes = ((nr_pages - 1) * PAGE_SIZE) + wdata->tailsz; wdata->pid = wdata->cfile->pid; - rc = adjust_credits(server, &wdata->credits, wdata->bytes); + rc = adjust_credits(wdata->server, &wdata->credits, wdata->bytes); if (rc) return rc; if (wdata->cfile->invalidHandle) rc = -EAGAIN; else - rc = server->ops->async_writev(wdata, cifs_writedata_release); + rc = wdata->server->ops->async_writev(wdata, + cifs_writedata_release); return rc; } @@ -2349,7 +2348,8 @@ static int cifs_writepages(struct address_space *mapping, range_whole = true; scanned = true; } - server = cifs_sb_master_tcon(cifs_sb)->ses->server; + server = cifs_pick_channel(cifs_sb_master_tcon(cifs_sb)->ses); + retry: while (!done && index <= end) { unsigned int i, nr_pages, found_pages, wsize; @@ -2403,6 +2403,7 @@ retry: wdata->credits = credits_on_stack; wdata->cfile = cfile; + wdata->server = server; cfile = NULL; if (!wdata->cfile) { @@ -2806,8 +2807,7 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, unsigned int wsize; struct cifs_credits credits; int rc; - struct TCP_Server_Info *server = - tlink_tcon(wdata->cfile->tlink)->ses->server; + struct TCP_Server_Info *server = wdata->server; do { if (wdata->cfile->invalidHandle) { @@ -2893,7 +2893,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, else pid = current->tgid; - server = tlink_tcon(open_file->tlink)->ses->server; + server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); xid = get_xid(); do { @@ -2997,6 +2997,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, wdata->nr_pages = nr_pages; wdata->offset = (__u64)offset; wdata->cfile = cifsFileInfo_get(open_file); + wdata->server = server; wdata->pid = pid; wdata->bytes = cur_len; wdata->pagesz = PAGE_SIZE; @@ -3538,8 +3539,10 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, unsigned int rsize; struct cifs_credits credits; int rc; - struct TCP_Server_Info *server = - tlink_tcon(rdata->cfile->tlink)->ses->server; + struct TCP_Server_Info *server; + + /* XXX: should we pick a new channel here? */ + server = rdata->server; do { if (rdata->cfile->invalidHandle) { @@ -3618,7 +3621,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, size_t start; struct iov_iter direct_iov = ctx->iter; - server = tlink_tcon(open_file->tlink)->ses->server; + server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) pid = open_file->pid; @@ -3702,6 +3705,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, rdata->tailsz = PAGE_SIZE; } + rdata->server = server; rdata->cfile = cifsFileInfo_get(open_file); rdata->nr_pages = npages; rdata->offset = offset; @@ -4031,7 +4035,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) } open_file = file->private_data; tcon = tlink_tcon(open_file->tlink); - server = tcon->ses->server; + server = cifs_pick_channel(tcon->ses); if (!server->ops->sync_read) { free_xid(xid); @@ -4070,6 +4074,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) io_parms.tcon = tcon; io_parms.offset = *offset; io_parms.length = current_read_size; + io_parms.server = server; rc = server->ops->sync_read(xid, &open_file->fid, &io_parms, &bytes_read, &cur_offset, &buf_type); @@ -4372,7 +4377,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, pid = current->tgid; rc = 0; - server = tlink_tcon(open_file->tlink)->ses->server; + server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n", __func__, file, mapping, num_pages); @@ -4443,6 +4448,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } rdata->cfile = cifsFileInfo_get(open_file); + rdata->server = server; rdata->mapping = mapping; rdata->offset = offset; rdata->bytes = bytes; diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 2072458e6e24..c381d2d03ef6 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -450,7 +450,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, int rc; struct cifs_fid fid; struct cifs_open_parms oparms; - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; struct kvec iov[2]; diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index fa86c78384c3..0a116fc490a9 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -74,6 +74,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; struct cifs_fid fid; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server; int num_rqst = 0; int resp_buftype[3]; struct smb2_query_info_rsp *qi_rsp = NULL; @@ -89,6 +90,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, rqst = &vars->rqst[0]; rsp_iov = &vars->rsp_iov[0]; + server = cifs_pick_channel(ses); + if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; @@ -115,7 +118,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, rqst[num_rqst].rq_iov = &vars->open_iov[0]; rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE; - rc = SMB2_open_init(tcon, &rqst[num_rqst], &oplock, &vars->oparms, + rc = SMB2_open_init(tcon, server, + &rqst[num_rqst], &oplock, &vars->oparms, utf16_path); kfree(utf16_path); if (rc) @@ -133,7 +137,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, rqst[num_rqst].rq_nvec = 1; if (cfile) - rc = SMB2_query_info_init(tcon, &rqst[num_rqst], + rc = SMB2_query_info_init(tcon, server, + &rqst[num_rqst], cfile->fid.persistent_fid, cfile->fid.volatile_fid, FILE_ALL_INFORMATION, @@ -141,10 +146,11 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 0, NULL); else { - rc = SMB2_query_info_init(tcon, &rqst[num_rqst], + rc = SMB2_query_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, - FILE_ALL_INFORMATION, + FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0, sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 0, NULL); @@ -177,7 +183,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ data[0] = &delete_pending[0]; - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_DISPOSITION_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -194,7 +201,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, size[0] = 8; /* sizeof __le64 */ data[0] = ptr; - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -213,13 +221,15 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, data[0] = ptr; if (cfile) - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], cfile->fid.persistent_fid, cfile->fid.volatile_fid, current->tgid, FILE_BASIC_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); else { - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_BASIC_INFORMATION, @@ -253,13 +263,15 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, data[1] = (__le16 *)ptr; if (cfile) - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], cfile->fid.persistent_fid, cfile->fid.volatile_fid, current->tgid, FILE_RENAME_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); else { - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_RENAME_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -289,7 +301,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, size[1] = len + 2 /* null */; data[1] = (__le16 *)ptr; - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_LINK_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -312,7 +325,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, /* Close */ rqst[num_rqst].rq_iov = &vars->close_iov[0]; rqst[num_rqst].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID, + rc = SMB2_close_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, false); smb2_set_related(&rqst[num_rqst]); if (rc) @@ -323,11 +337,13 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, if (cfile) { cifsFileInfo_put(cfile); cfile = NULL; - rc = compound_send_recv(xid, ses, flags, num_rqst - 2, + rc = compound_send_recv(xid, ses, server, + flags, num_rqst - 2, &rqst[1], &resp_buftype[1], &rsp_iov[1]); } else - rc = compound_send_recv(xid, ses, flags, num_rqst, + rc = compound_send_recv(xid, ses, server, + flags, num_rqst, rqst, resp_buftype, rsp_iov); diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 49c5c80f5d36..e97eb0050a0e 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -708,7 +708,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, oparms.fid = pfid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, &utf16_path); if (rc) goto oshr_free; smb2_set_next_command(tcon, &rqst[0]); @@ -717,7 +718,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, rqst[1].rq_iov = qi_iov; rqst[1].rq_nvec = 1; - rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, + rc = SMB2_query_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0, sizeof(struct smb2_file_all_info) + @@ -727,7 +729,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, smb2_set_related(&rqst[1]); - rc = compound_send_recv(xid, ses, flags, 2, rqst, + rc = compound_send_recv(xid, ses, server, + flags, 2, rqst, resp_buftype, rsp_iov); mutex_lock(&tcon->crfid.fid_mutex); @@ -1102,6 +1105,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb) { struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); __le16 *utf16_path = NULL; int ea_name_len = strlen(ea_name); int flags = 0; @@ -1190,7 +1194,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, oparms.fid = &fid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto sea_exit; smb2_set_next_command(tcon, &rqst[0]); @@ -1216,7 +1221,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, size[0] = len; data[0] = ea; - rc = SMB2_set_info_init(tcon, &rqst[1], COMPOUND_FID, + rc = SMB2_set_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -1228,10 +1234,12 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, 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, false); + rc = SMB2_close_init(tcon, server, + &rqst[2], COMPOUND_FID, COMPOUND_FID, false); smb2_set_related(&rqst[2]); - rc = compound_send_recv(xid, ses, flags, 3, rqst, + rc = compound_send_recv(xid, ses, server, + flags, 3, rqst, resp_buftype, rsp_iov); /* no need to bump num_remote_opens because handle immediately closed */ @@ -1473,6 +1481,7 @@ smb2_ioctl_query_info(const unsigned int xid, struct smb_rqst *rqst; struct kvec *rsp_iov; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); char __user *arg = (char __user *)p; struct smb_query_info qi; struct smb_query_info __user *pqi; @@ -1505,7 +1514,7 @@ smb2_ioctl_query_info(const unsigned int xid, return -EINVAL; } - if (!ses || !(ses->server)) { + if (!ses || !server) { kfree(vars); return -EIO; } @@ -1552,7 +1561,8 @@ smb2_ioctl_query_info(const unsigned int xid, oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL; } - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, path); if (rc) goto iqinf_exit; smb2_set_next_command(tcon, &rqst[0]); @@ -1566,7 +1576,8 @@ smb2_ioctl_query_info(const unsigned int xid, rqst[1].rq_iov = &vars->io_iov[0]; rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; - rc = SMB2_ioctl_init(tcon, &rqst[1], + rc = SMB2_ioctl_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, qi.info_type, true, buffer, qi.output_buffer_length, @@ -1585,7 +1596,8 @@ smb2_ioctl_query_info(const unsigned int xid, size[0] = 8; data[0] = buffer; - rc = SMB2_set_info_init(tcon, &rqst[1], + rc = SMB2_set_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_END_OF_FILE_INFORMATION, @@ -1595,7 +1607,8 @@ smb2_ioctl_query_info(const unsigned int xid, rqst[1].rq_iov = &vars->qi_iov[0]; rqst[1].rq_nvec = 1; - rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, + rc = SMB2_query_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, qi.file_info_class, qi.info_type, qi.additional_information, qi.input_buffer_length, @@ -1615,12 +1628,14 @@ smb2_ioctl_query_info(const unsigned int xid, rqst[2].rq_iov = &vars->close_iov[0]; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + rc = SMB2_close_init(tcon, server, + &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto iqinf_exit; smb2_set_related(&rqst[2]); - rc = compound_send_recv(xid, ses, flags, 3, rqst, + rc = compound_send_recv(xid, ses, server, + flags, 3, rqst, resp_buftype, rsp_iov); if (rc) goto iqinf_exit; @@ -2172,6 +2187,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_open_parms oparms; struct smb2_query_directory_rsp *qd_rsp = NULL; struct smb2_create_rsp *op_rsp = NULL; + struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); if (!utf16_path) @@ -2196,7 +2212,8 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, oparms.fid = fid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto qdf_free; smb2_set_next_command(tcon, &rqst[0]); @@ -2209,7 +2226,8 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, rqst[1].rq_iov = qd_iov; rqst[1].rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; - rc = SMB2_query_directory_init(xid, tcon, &rqst[1], + rc = SMB2_query_directory_init(xid, tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, 0, srch_inf->info_level); if (rc) @@ -2217,7 +2235,8 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, smb2_set_related(&rqst[1]); - rc = compound_send_recv(xid, tcon->ses, flags, 2, rqst, + rc = compound_send_recv(xid, tcon->ses, server, + flags, 2, rqst, resp_buftype, rsp_iov); /* If the open failed there is nothing to do */ @@ -2422,6 +2441,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb) { struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); int flags = 0; struct smb_rqst rqst[3]; int resp_buftype[3]; @@ -2452,7 +2472,8 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, oparms.fid = &fid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto qic_exit; smb2_set_next_command(tcon, &rqst[0]); @@ -2461,7 +2482,8 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, rqst[1].rq_iov = qi_iov; rqst[1].rq_nvec = 1; - rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, COMPOUND_FID, + rc = SMB2_query_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, class, type, 0, output_len, 0, NULL); @@ -2474,12 +2496,14 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + rc = SMB2_close_init(tcon, server, + &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto qic_exit; smb2_set_related(&rqst[2]); - rc = compound_send_recv(xid, ses, flags, 3, rqst, + rc = compound_send_recv(xid, ses, server, + flags, 3, rqst, resp_buftype, rsp_iov); if (rc) { free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); @@ -2811,6 +2835,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, struct kvec err_iov = {NULL, 0}; struct smb2_err_rsp *err_buf = NULL; struct smb2_symlink_err_rsp *symlink; + struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); unsigned int sub_len; unsigned int sub_offset; unsigned int print_len; @@ -2856,7 +2881,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, oparms.fid = &fid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto querty_exit; smb2_set_next_command(tcon, &rqst[0]); @@ -2867,7 +2893,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, rqst[1].rq_iov = io_iov; rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; - rc = SMB2_ioctl_init(tcon, &rqst[1], fid.persistent_fid, + rc = SMB2_ioctl_init(tcon, server, + &rqst[1], fid.persistent_fid, fid.volatile_fid, FSCTL_GET_REPARSE_POINT, true /* is_fctl */, NULL, 0, CIFSMaxBufSize - @@ -2885,13 +2912,15 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + rc = SMB2_close_init(tcon, server, + &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto querty_exit; smb2_set_related(&rqst[2]); - rc = compound_send_recv(xid, tcon->ses, flags, 3, rqst, + rc = compound_send_recv(xid, tcon->ses, server, + flags, 3, rqst, resp_buftype, rsp_iov); create_rsp = rsp_iov[0].iov_base; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 12de0af12f75..fe5a8452b213 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -98,14 +98,13 @@ int smb3_encryption_required(const struct cifs_tcon *tcon) static void smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, - const struct cifs_tcon *tcon) + const struct cifs_tcon *tcon, + struct TCP_Server_Info *server) { shdr->ProtocolId = SMB2_PROTO_NUMBER; shdr->StructureSize = cpu_to_le16(64); shdr->Command = smb2_cmd; - if (tcon && tcon->ses && tcon->ses->server) { - struct TCP_Server_Info *server = tcon->ses->server; - + if (server) { spin_lock(&server->req_lock); /* Request up to 10 credits but don't go over the limit. */ if (server->credits >= server->max_credits) @@ -125,8 +124,7 @@ smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */ /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ - if ((tcon->ses) && (tcon->ses->server) && - (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + if (server && (server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) shdr->CreditCharge = cpu_to_le16(1); /* else CreditCharge MBZ */ @@ -148,8 +146,7 @@ smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, /* if (tcon->share_flags & SHI1005_FLAGS_DFS) shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ - if (tcon->ses && tcon->ses->server && tcon->ses->server->sign && - !smb3_encryption_required(tcon)) + if (server && server->sign && !smb3_encryption_required(tcon)) shdr->Flags |= SMB2_FLAGS_SIGNED; out: return; @@ -267,12 +264,12 @@ static inline int __smb2_reconnect(const struct nls_table *nlsc, #endif static int -smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) +smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, + struct TCP_Server_Info *server) { int rc; struct nls_table *nls_codepage; struct cifs_ses *ses; - struct TCP_Server_Info *server; int retries; /* @@ -301,12 +298,10 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) } } if ((!tcon->ses) || (tcon->ses->status == CifsExiting) || - (!tcon->ses->server)) + (!tcon->ses->server) || !server) return -EIO; ses = tcon->ses; - server = ses->server; - retries = server->nr_targets; /* @@ -439,7 +434,9 @@ failed: } static void -fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, +fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, + void *buf, unsigned int *total_len) { struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf; @@ -452,7 +449,7 @@ fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, */ memset(buf, 0, 256); - smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon); + smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon, server); spdu->StructureSize2 = cpu_to_le16(parmsize); *total_len = parmsize + sizeof(struct smb2_sync_hdr); @@ -464,7 +461,8 @@ fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, * function must have filled in request_buf pointer. */ static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, - void **request_buf, unsigned int *total_len) + struct TCP_Server_Info *server, + void **request_buf, unsigned int *total_len) { /* BB eventually switch this to SMB2 specific small buf size */ if (smb2_command == SMB2_SET_INFO) @@ -476,7 +474,7 @@ static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, return -ENOMEM; } - fill_small_buf(smb2_command, tcon, + fill_small_buf(smb2_command, tcon, server, (struct smb2_sync_hdr *)(*request_buf), total_len); @@ -490,27 +488,30 @@ static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, } static int smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, void **request_buf, unsigned int *total_len) { int rc; - rc = smb2_reconnect(smb2_command, tcon); + rc = smb2_reconnect(smb2_command, tcon, server); if (rc) return rc; - return __smb2_plain_req_init(smb2_command, tcon, request_buf, + return __smb2_plain_req_init(smb2_command, tcon, server, request_buf, total_len); } static int smb2_ioctl_req_init(u32 opcode, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, void **request_buf, unsigned int *total_len) { /* Skip reconnect only for FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs */ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) { - return __smb2_plain_req_init(SMB2_IOCTL, tcon, request_buf, - total_len); + return __smb2_plain_req_init(SMB2_IOCTL, tcon, server, + request_buf, total_len); } - return smb2_plain_req_init(SMB2_IOCTL, tcon, request_buf, total_len); + return smb2_plain_req_init(SMB2_IOCTL, tcon, server, + request_buf, total_len); } /* For explanation of negotiate contexts see MS-SMB2 section 2.2.3.1 */ @@ -858,7 +859,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) return -EIO; } - rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server, + (void **) &req, &total_len); if (rc) return rc; @@ -916,7 +918,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(req); rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base; /* @@ -1227,8 +1230,9 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data) struct TCP_Server_Info *server = cifs_ses_server(ses); unsigned int total_len; - rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server, + (void **) &req, + &total_len); if (rc) return rc; @@ -1305,6 +1309,7 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data) /* BB add code to build os and lm fields */ rc = cifs_send_recv(sess_data->xid, sess_data->ses, + cifs_ses_server(sess_data->ses), &rqst, &sess_data->buf0_type, CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov); @@ -1689,7 +1694,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) if (ses->need_reconnect) goto smb2_session_already_dead; - rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server, + (void **) &req, &total_len); if (rc) return rc; @@ -1710,7 +1716,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, ses->server, + &rqst, &resp_buf_type, flags, &rsp_iov); cifs_small_buf_release(req); /* * No tcon so can't do @@ -1751,7 +1758,10 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, __le16 *unc_path = NULL; int flags = 0; unsigned int total_len; - struct TCP_Server_Info *server = ses->server; + struct TCP_Server_Info *server; + + /* always use master channel */ + server = ses->server; cifs_dbg(FYI, "TCON\n"); @@ -1772,8 +1782,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, /* SMB2 TREE_CONNECT request must be called with TreeId == 0 */ tcon->tid = 0; atomic_set(&tcon->num_remote_opens, 0); - rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server, + (void **) &req, &total_len); if (rc) { kfree(unc_path); return rc; @@ -1812,7 +1822,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, /* Need 64 for max size write so ask for more in case not there yet */ req->sync_hdr.CreditRequest = cpu_to_le16(64); - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(req); rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); @@ -1897,8 +1908,9 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) close_shroot_lease(&tcon->crfid); - rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, ses->server, + (void **) &req, + &total_len); if (rc) return rc; |