Commit a86b83f7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'v6.11-rc6-cifs-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - fix potential mount hang

 - fix retry problem in two types of compound operations

 - important netfs integration fix in SMB1 read paths

 - fix potential uninitialized zero point of inode

 - minor patch to improve debugging for potential crediting problems

* tag 'v6.11-rc6-cifs-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  netfs, cifs: Improve some debugging bits
  cifs: Fix SMB1 readv/writev callback in the same way as SMB2/3
  cifs: Fix zero_point init on inode initialisation
  smb: client: fix double put of @cfile in smb2_set_path_size()
  smb: client: fix double put of @cfile in smb2_rename_path()
  smb: client: fix hang in wait_for_response() for negproto
parents 9d4c3040 ab852189
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -270,7 +270,7 @@ static void netfs_reset_subreq_iter(struct netfs_io_request *rreq,
	if (count == remaining)
		return;

	_debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x\n",
	_debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x",
	       rreq->debug_id, subreq->debug_index,
	       iov_iter_count(&subreq->io_iter), subreq->transferred,
	       subreq->len, rreq->i_size,
+46 −8
Original line number Diff line number Diff line
@@ -1261,16 +1261,32 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
	return rc;
}

static void cifs_readv_worker(struct work_struct *work)
{
	struct cifs_io_subrequest *rdata =
		container_of(work, struct cifs_io_subrequest, subreq.work);

	netfs_subreq_terminated(&rdata->subreq,
				(rdata->result == 0 || rdata->result == -EAGAIN) ?
				rdata->got_bytes : rdata->result, true);
}

static void
cifs_readv_callback(struct mid_q_entry *mid)
{
	struct cifs_io_subrequest *rdata = mid->callback_data;
	struct netfs_inode *ictx = netfs_inode(rdata->rreq->inode);
	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
	struct TCP_Server_Info *server = tcon->ses->server;
	struct smb_rqst rqst = { .rq_iov = rdata->iov,
				 .rq_nvec = 2,
				 .rq_iter = rdata->subreq.io_iter };
	struct cifs_credits credits = { .value = 1, .instance = 0 };
	struct cifs_credits credits = {
		.value = 1,
		.instance = 0,
		.rreq_debug_id = rdata->rreq->debug_id,
		.rreq_debug_index = rdata->subreq.debug_index,
	};

	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
		 __func__, mid->mid, mid->mid_state, rdata->result,
@@ -1282,6 +1298,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
		if (server->sign) {
			int rc = 0;

			iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
			rc = cifs_verify_signature(&rqst, server,
						  mid->sequence_number);
			if (rc)
@@ -1306,13 +1323,21 @@ cifs_readv_callback(struct mid_q_entry *mid)
		rdata->result = -EIO;
	}

	if (rdata->result == 0 || rdata->result == -EAGAIN)
		iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
	if (rdata->result == -ENODATA) {
		__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
		rdata->result = 0;
	} else {
		if (rdata->got_bytes < rdata->actual_len &&
		    rdata->subreq.start + rdata->subreq.transferred + rdata->got_bytes ==
		    ictx->remote_i_size) {
			__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
			rdata->result = 0;
		}
	}

	rdata->credits.value = 0;
	netfs_subreq_terminated(&rdata->subreq,
				(rdata->result == 0 || rdata->result == -EAGAIN) ?
				rdata->got_bytes : rdata->result,
				false);
	INIT_WORK(&rdata->subreq.work, cifs_readv_worker);
	queue_work(cifsiod_wq, &rdata->subreq.work);
	release_mid(mid);
	add_credits(server, &credits, 0);
}
@@ -1619,9 +1644,15 @@ static void
cifs_writev_callback(struct mid_q_entry *mid)
{
	struct cifs_io_subrequest *wdata = mid->callback_data;
	struct TCP_Server_Info *server = wdata->server;
	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
	struct cifs_credits credits = { .value = 1, .instance = 0 };
	struct cifs_credits credits = {
		.value = 1,
		.instance = 0,
		.rreq_debug_id = wdata->rreq->debug_id,
		.rreq_debug_index = wdata->subreq.debug_index,
	};
	ssize_t result;
	size_t written;

@@ -1657,9 +1688,16 @@ cifs_writev_callback(struct mid_q_entry *mid)
		break;
	}

	trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index,
			      wdata->credits.value,
			      server->credits, server->in_flight,
			      0, cifs_trace_rw_credits_write_response_clear);
	wdata->credits.value = 0;
	cifs_write_subrequest_terminated(wdata, result, true);
	release_mid(mid);
	trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0,
			      server->credits, server->in_flight,
			      credits.value, cifs_trace_rw_credits_write_response_add);
	add_credits(tcon->ses->server, &credits, 0);
}

+13 −1
Original line number Diff line number Diff line
@@ -656,6 +656,19 @@ allocate_buffers(struct TCP_Server_Info *server)
static bool
server_unresponsive(struct TCP_Server_Info *server)
{
	/*
	 * If we're in the process of mounting a share or reconnecting a session
	 * and the server abruptly shut down (e.g. socket wasn't closed, packet
	 * had been ACK'ed but no SMB response), don't wait longer than 20s to
	 * negotiate protocol.
	 */
	spin_lock(&server->srv_lock);
	if (server->tcpStatus == CifsInNegotiate &&
	    time_after(jiffies, server->lstrp + 20 * HZ)) {
		spin_unlock(&server->srv_lock);
		cifs_reconnect(server, false);
		return true;
	}
	/*
	 * We need to wait 3 echo intervals to make sure we handle such
	 * situations right:
@@ -667,7 +680,6 @@ server_unresponsive(struct TCP_Server_Info *server)
	 * 65s kernel_recvmsg times out, and we see that we haven't gotten
	 *     a response in >60s.
	 */
	spin_lock(&server->srv_lock);
	if ((server->tcpStatus == CifsGood ||
	    server->tcpStatus == CifsNeedNegotiate) &&
	    (!server->ops->can_echo || server->ops->can_echo(server)) &&
+2 −0
Original line number Diff line number Diff line
@@ -172,6 +172,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
		CIFS_I(inode)->time = 0; /* force reval */
		return -ESTALE;
	}
	if (inode->i_state & I_NEW)
		CIFS_I(inode)->netfs.zero_point = fattr->cf_eof;

	cifs_revalidate_cache(inode, fattr);

+3 −0
Original line number Diff line number Diff line
@@ -1106,6 +1106,8 @@ int smb2_rename_path(const unsigned int xid,
				  co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
	if (rc == -EINVAL) {
		cifs_dbg(FYI, "invalid lease key, resending request without lease");
		cifs_get_writable_path(tcon, from_name,
				       FIND_WR_WITH_DELETE, &cfile);
		rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
				  co, DELETE, SMB2_OP_RENAME, cfile, NULL);
	}
@@ -1149,6 +1151,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
			      cfile, NULL, NULL, dentry);
	if (rc == -EINVAL) {
		cifs_dbg(FYI, "invalid lease key, resending request without lease");
		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
		rc = smb2_compound_op(xid, tcon, cifs_sb,
				      full_path, &oparms, &in_iov,
				      &(int){SMB2_OP_SET_EOF}, 1,
Loading