Commit 352d96f3 authored by Aurelien Aptel's avatar Aurelien Aptel Committed by Steve French
Browse files

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: default avatarAurelien Aptel <aaptel@suse.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 7c06514a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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);
+19 −13
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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];
+30 −14
Original line number Diff line number Diff line
@@ -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,7 +146,8 @@ 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,
@@ -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);

Loading