Commit 33c9de29 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '6.11-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:
 "Six smb3 client fixes, most for stable including important netfs fixes:

   - various netfs related fixes for cifs addressing some regressions in
     6.10 (e.g. generic/708 and some multichannel crediting related
     issues)

   - fix for a noisy log message on copy_file_range

   - add trace point for read/write credits"

* tag '6.11-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: Fix missing fscache invalidation
  cifs: Add a tracepoint to track credits involved in R/W requests
  cifs: Fix setting of zero_point after DIO write
  cifs: Fix missing error code set
  cifs: Fix server re-repick on subrequest retry
  cifs: fix noisy message on copy_file_range
parents 8e313211 a07d38af
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1359,7 +1359,7 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
	target_tcon = tlink_tcon(smb_file_target->tlink);

	if (src_tcon->ses != target_tcon->ses) {
		cifs_dbg(VFS, "source and target of copy not on same server\n");
		cifs_dbg(FYI, "source and target of copy not on same server\n");
		goto out;
	}

+10 −7
Original line number Diff line number Diff line
@@ -290,7 +290,7 @@ struct smb_version_operations {
	int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *,
			     bool);
	void (*add_credits)(struct TCP_Server_Info *server,
			    const struct cifs_credits *credits,
			    struct cifs_credits *credits,
			    const int optype);
	void (*set_credits)(struct TCP_Server_Info *, const int);
	int * (*get_credits_field)(struct TCP_Server_Info *, const int);
@@ -550,8 +550,8 @@ struct smb_version_operations {
				size_t *, struct cifs_credits *);
	/* adjust previously taken mtu credits to request size */
	int (*adjust_credits)(struct TCP_Server_Info *server,
			      struct cifs_credits *credits,
			      const unsigned int payload_size);
			      struct cifs_io_subrequest *subreq,
			      unsigned int /*enum smb3_rw_credits_trace*/ trace);
	/* check if we need to issue closedir */
	bool (*dir_needs_close)(struct cifsFileInfo *);
	long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
@@ -848,6 +848,9 @@ static inline void cifs_server_unlock(struct TCP_Server_Info *server)
struct cifs_credits {
	unsigned int value;
	unsigned int instance;
	unsigned int in_flight_check;
	unsigned int rreq_debug_id;
	unsigned int rreq_debug_index;
};

static inline unsigned int
@@ -873,7 +876,7 @@ has_credits(struct TCP_Server_Info *server, int *credits, int num_credits)
}

static inline void
add_credits(struct TCP_Server_Info *server, const struct cifs_credits *credits,
add_credits(struct TCP_Server_Info *server, struct cifs_credits *credits,
	    const int optype)
{
	server->ops->add_credits(server, credits, optype);
@@ -897,11 +900,11 @@ set_credits(struct TCP_Server_Info *server, const int val)
}

static inline int
adjust_credits(struct TCP_Server_Info *server, struct cifs_credits *credits,
	       const unsigned int payload_size)
adjust_credits(struct TCP_Server_Info *server, struct cifs_io_subrequest *subreq,
	       unsigned int /* enum smb3_rw_credits_trace */ trace)
{
	return server->ops->adjust_credits ?
		server->ops->adjust_credits(server, credits, payload_size) : 0;
		server->ops->adjust_credits(server, subreq, trace) : 0;
}

static inline __le64
+48 −5
Original line number Diff line number Diff line
@@ -80,6 +80,16 @@ static void cifs_prepare_write(struct netfs_io_subrequest *subreq)
		return netfs_prepare_write_failed(subreq);
	}

	wdata->credits.rreq_debug_id = subreq->rreq->debug_id;
	wdata->credits.rreq_debug_index = subreq->debug_index;
	wdata->credits.in_flight_check = 1;
	trace_smb3_rw_credits(wdata->rreq->debug_id,
			      wdata->subreq.debug_index,
			      wdata->credits.value,
			      server->credits, server->in_flight,
			      wdata->credits.value,
			      cifs_trace_rw_credits_write_prepare);

#ifdef CONFIG_CIFS_SMB_DIRECT
	if (server->smbd_conn)
		subreq->max_nr_segs = server->smbd_conn->max_frmr_depth;
@@ -101,7 +111,7 @@ static void cifs_issue_write(struct netfs_io_subrequest *subreq)
		goto fail;
	}

	rc = adjust_credits(wdata->server, &wdata->credits, wdata->subreq.len);
	rc = adjust_credits(wdata->server, wdata, cifs_trace_rw_credits_issue_write_adjust);
	if (rc)
		goto fail;

@@ -123,6 +133,11 @@ static void cifs_issue_write(struct netfs_io_subrequest *subreq)
	goto out;
}

static void cifs_netfs_invalidate_cache(struct netfs_io_request *wreq)
{
	cifs_invalidate_cache(wreq->inode, 0);
}

/*
 * Split the read up according to how many credits we can get for each piece.
 * It's okay to sleep here if we need to wait for more credit to become
@@ -158,7 +173,18 @@ static bool cifs_clamp_length(struct netfs_io_subrequest *subreq)
		return false;
	}

	rdata->credits.in_flight_check = 1;
	rdata->credits.rreq_debug_id = rreq->debug_id;
	rdata->credits.rreq_debug_index = subreq->debug_index;

	trace_smb3_rw_credits(rdata->rreq->debug_id,
			      rdata->subreq.debug_index,
			      rdata->credits.value,
			      server->credits, server->in_flight, 0,
			      cifs_trace_rw_credits_read_submit);

	subreq->len = min_t(size_t, subreq->len, rsize);

#ifdef CONFIG_CIFS_SMB_DIRECT
	if (server->smbd_conn)
		subreq->max_nr_segs = server->smbd_conn->max_frmr_depth;
@@ -289,6 +315,15 @@ static void cifs_free_subrequest(struct netfs_io_subrequest *subreq)
#endif
	}

	if (rdata->credits.value != 0)
		trace_smb3_rw_credits(rdata->rreq->debug_id,
				      rdata->subreq.debug_index,
				      rdata->credits.value,
				      rdata->server ? rdata->server->credits : 0,
				      rdata->server ? rdata->server->in_flight : 0,
				      -rdata->credits.value,
				      cifs_trace_rw_credits_free_subreq);

	add_credits_and_wake_if(rdata->server, &rdata->credits, 0);
	if (rdata->have_xid)
		free_xid(rdata->xid);
@@ -307,6 +342,7 @@ const struct netfs_request_ops cifs_req_ops = {
	.begin_writeback	= cifs_begin_writeback,
	.prepare_write		= cifs_prepare_write,
	.issue_write		= cifs_issue_write,
	.invalidate_cache	= cifs_netfs_invalidate_cache,
};

/*
@@ -2358,13 +2394,18 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t
				      bool was_async)
{
	struct netfs_io_request *wreq = wdata->rreq;
	loff_t new_server_eof;
	struct netfs_inode *ictx = netfs_inode(wreq->inode);
	loff_t wrend;

	if (result > 0) {
		new_server_eof = wdata->subreq.start + wdata->subreq.transferred + result;
		wrend = wdata->subreq.start + wdata->subreq.transferred + result;

		if (new_server_eof > netfs_inode(wreq->inode)->remote_i_size)
			netfs_resize_file(netfs_inode(wreq->inode), new_server_eof, true);
		if (wrend > ictx->zero_point &&
		    (wdata->rreq->origin == NETFS_UNBUFFERED_WRITE ||
		     wdata->rreq->origin == NETFS_DIO_WRITE))
			ictx->zero_point = wrend;
		if (wrend > ictx->remote_i_size)
			netfs_resize_file(ictx, wrend, true);
	}

	netfs_write_subrequest_terminated(&wdata->subreq, result, was_async);
@@ -2877,6 +2918,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
		rc = netfs_start_io_direct(inode);
		if (rc < 0)
			goto out;
		rc = -EACCES;
		down_read(&cinode->lock_sem);
		if (!cifs_find_lock_conflict(
			    cfile, iocb->ki_pos, iov_iter_count(to),
@@ -2889,6 +2931,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
		rc = netfs_start_io_read(inode);
		if (rc < 0)
			goto out;
		rc = -EACCES;
		down_read(&cinode->lock_sem);
		if (!cifs_find_lock_conflict(
			    cfile, iocb->ki_pos, iov_iter_count(to),
+1 −1
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)

static void
cifs_add_credits(struct TCP_Server_Info *server,
		 const struct cifs_credits *credits, const int optype)
		 struct cifs_credits *credits, const int optype)
{
	spin_lock(&server->req_lock);
	server->credits += credits->value;
+37 −5
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ change_conf(struct TCP_Server_Info *server)

static void
smb2_add_credits(struct TCP_Server_Info *server,
		 const struct cifs_credits *credits, const int optype)
		 struct cifs_credits *credits, const int optype)
{
	int *val, rc = -1;
	int scredits, in_flight;
@@ -94,7 +94,21 @@ smb2_add_credits(struct TCP_Server_Info *server,
					    server->conn_id, server->hostname, *val,
					    add, server->in_flight);
	}
	WARN_ON_ONCE(server->in_flight == 0);
	if (credits->in_flight_check > 1) {
		pr_warn_once("rreq R=%08x[%x] Credits not in flight\n",
			     credits->rreq_debug_id, credits->rreq_debug_index);
	} else {
		credits->in_flight_check = 2;
	}
	if (WARN_ON_ONCE(server->in_flight == 0)) {
		pr_warn_once("rreq R=%08x[%x] Zero in_flight\n",
			     credits->rreq_debug_id, credits->rreq_debug_index);
		trace_smb3_rw_credits(credits->rreq_debug_id,
				      credits->rreq_debug_index,
				      credits->value,
				      server->credits, server->in_flight, 0,
				      cifs_trace_rw_credits_zero_in_flight);
	}
	server->in_flight--;
	if (server->in_flight == 0 &&
	   ((optype & CIFS_OP_MASK) != CIFS_NEG_OP) &&
@@ -283,16 +297,23 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, size_t size,

static int
smb2_adjust_credits(struct TCP_Server_Info *server,
		    struct cifs_credits *credits,
		    const unsigned int payload_size)
		    struct cifs_io_subrequest *subreq,
		    unsigned int /*enum smb3_rw_credits_trace*/ trace)
{
	int new_val = DIV_ROUND_UP(payload_size, SMB2_MAX_BUFFER_SIZE);
	struct cifs_credits *credits = &subreq->credits;
	int new_val = DIV_ROUND_UP(subreq->subreq.len, SMB2_MAX_BUFFER_SIZE);
	int scredits, in_flight;

	if (!credits->value || credits->value == new_val)
		return 0;

	if (credits->value < new_val) {
		trace_smb3_rw_credits(subreq->rreq->debug_id,
				      subreq->subreq.debug_index,
				      credits->value,
				      server->credits, server->in_flight,
				      new_val - credits->value,
				      cifs_trace_rw_credits_no_adjust_up);
		trace_smb3_too_many_credits(server->CurrentMid,
				server->conn_id, server->hostname, 0, credits->value - new_val, 0);
		cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)",
@@ -308,6 +329,12 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
		in_flight = server->in_flight;
		spin_unlock(&server->req_lock);

		trace_smb3_rw_credits(subreq->rreq->debug_id,
				      subreq->subreq.debug_index,
				      credits->value,
				      server->credits, server->in_flight,
				      new_val - credits->value,
				      cifs_trace_rw_credits_old_session);
		trace_smb3_reconnect_detected(server->CurrentMid,
			server->conn_id, server->hostname, scredits,
			credits->value - new_val, in_flight);
@@ -316,6 +343,11 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
		return -EAGAIN;
	}

	trace_smb3_rw_credits(subreq->rreq->debug_id,
			      subreq->subreq.debug_index,
			      credits->value,
			      server->credits, server->in_flight,
			      new_val - credits->value, trace);
	server->credits += credits->value - new_val;
	scredits = server->credits;
	in_flight = server->in_flight;
Loading