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

Merge tag '6.5-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - Two reconnect fixes: important fix to address inFlight count to leak
   (which can leak credits), and fix for better handling a deleted share

 - DFS fix

 - SMB1 cleanup fix

 - deferred close fix

* tag '6.5-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: fix mid leak during reconnection after timeout threshold
  cifs: is_network_name_deleted should return a bool
  smb: client: fix missed ses refcounting
  smb: client: Fix -Wstringop-overflow issues
  cifs: if deferred close is disabled then close files immediately
parents 20edcec2 69cba9d3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -532,7 +532,7 @@ struct smb_version_operations {
	/* Check for STATUS_IO_TIMEOUT */
	bool (*is_status_io_timeout)(char *buf);
	/* Check for STATUS_NETWORK_NAME_DELETED */
	void (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
	bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
};

struct smb_version_values {
+1 −1
Original line number Diff line number Diff line
@@ -3184,7 +3184,7 @@ int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
	param_offset = offsetof(struct smb_com_transaction2_spi_req,
				InformationLevel) - 4;
	offset = param_offset + params;
	parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
	parm_data = ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) + offset;
	pSMB->ParameterOffset = cpu_to_le16(param_offset);

	/* convert to on the wire format for POSIX ACL */
+23 −7
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ extern bool disable_legacy_dialects;
#define TLINK_IDLE_EXPIRE	(600 * HZ)

/* Drop the connection to not overload the server */
#define NUM_STATUS_IO_TIMEOUT   5
#define MAX_STATUS_IO_TIMEOUT   5

static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
@@ -1117,6 +1117,7 @@ cifs_demultiplex_thread(void *p)
	struct mid_q_entry *mids[MAX_COMPOUND];
	char *bufs[MAX_COMPOUND];
	unsigned int noreclaim_flag, num_io_timeout = 0;
	bool pending_reconnect = false;

	noreclaim_flag = memalloc_noreclaim_save();
	cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
@@ -1156,6 +1157,8 @@ cifs_demultiplex_thread(void *p)
		cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
		if (!is_smb_response(server, buf[0]))
			continue;

		pending_reconnect = false;
next_pdu:
		server->pdu_size = pdu_length;

@@ -1213,10 +1216,13 @@ cifs_demultiplex_thread(void *p)
		if (server->ops->is_status_io_timeout &&
		    server->ops->is_status_io_timeout(buf)) {
			num_io_timeout++;
			if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
				cifs_reconnect(server, false);
			if (num_io_timeout > MAX_STATUS_IO_TIMEOUT) {
				cifs_server_dbg(VFS,
						"Number of request timeouts exceeded %d. Reconnecting",
						MAX_STATUS_IO_TIMEOUT);

				pending_reconnect = true;
				num_io_timeout = 0;
				continue;
			}
		}

@@ -1226,9 +1232,14 @@ cifs_demultiplex_thread(void *p)
			if (mids[i] != NULL) {
				mids[i]->resp_buf_size = server->pdu_size;

				if (bufs[i] && server->ops->is_network_name_deleted)
				if (bufs[i] != NULL) {
					if (server->ops->is_network_name_deleted &&
					    server->ops->is_network_name_deleted(bufs[i],
									server);
										 server)) {
						cifs_server_dbg(FYI,
								"Share deleted. Reconnect needed");
					}
				}

				if (!mids[i]->multiRsp || mids[i]->multiEnd)
					mids[i]->callback(mids[i]);
@@ -1263,6 +1274,11 @@ cifs_demultiplex_thread(void *p)
			buf = server->smallbuf;
			goto next_pdu;
		}

		/* do this reconnect at the very end after processing all MIDs */
		if (pending_reconnect)
			cifs_reconnect(server, true);

	} /* end while !EXITING */

	/* buffer usually freed in free_mid - need to free it here on exit */
+10 −16
Original line number Diff line number Diff line
@@ -66,6 +66,12 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
	return rc;
}

/*
 * Track individual DFS referral servers used by new DFS mount.
 *
 * On success, their lifetime will be shared by final tcon (dfs_ses_list).
 * Otherwise, they will be put by dfs_put_root_smb_sessions() in cifs_mount().
 */
static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
{
	struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
@@ -80,11 +86,12 @@ static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
		INIT_LIST_HEAD(&root_ses->list);

		spin_lock(&cifs_tcp_ses_lock);
		ses->ses_count++;
		cifs_smb_ses_inc_refcount(ses);
		spin_unlock(&cifs_tcp_ses_lock);
		root_ses->ses = ses;
		list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list);
	}
	/* Select new DFS referral server so that new referrals go through it */
	ctx->dfs_root_ses = ses;
	return 0;
}
@@ -242,7 +249,6 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
{
	struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
	struct cifs_ses *ses;
	bool nodfs = ctx->nodfs;
	int rc;

@@ -276,20 +282,8 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
	}

	*isdfs = true;
	/*
	 * Prevent DFS root session of being put in the first call to
	 * cifs_mount_put_conns().  If another DFS root server was not found
	 * while chasing the referrals (@ctx->dfs_root_ses == @ses), then we
	 * can safely put extra refcount of @ses.
	 */
	ses = mnt_ctx->ses;
	mnt_ctx->ses = NULL;
	mnt_ctx->server = NULL;
	rc = __dfs_mount_share(mnt_ctx);
	if (ses == ctx->dfs_root_ses)
		cifs_put_smb_ses(ses);

	return rc;
	add_root_smb_session(mnt_ctx);
	return __dfs_mount_share(mnt_ctx);
}

/* Update dfs referral path of superblock */
+2 −2
Original line number Diff line number Diff line
@@ -1080,8 +1080,8 @@ int cifs_close(struct inode *inode, struct file *file)
		cfile = file->private_data;
		file->private_data = NULL;
		dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
		if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
		    cinode->lease_granted &&
		if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG)
		    && cinode->lease_granted &&
		    !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) &&
		    dclose) {
			if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
Loading