Commit 105b6c05 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull cfis updates from Steve French:
 "Handlecache,  unmount, fiemap and two reconnect fixes"

* tag '5.18-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: use a different reconnect helper for non-cifsd threads
  cifs: we do not need a spinlock around the tree access during umount
  Adjust cifssb maximum read size
  cifs: truncate the inode and mapping when we simulate fcollapse
  cifs: fix handlecache and multiuser
parents ef510682 dca65818
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -396,11 +396,11 @@ static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const ch
	switch (state) {
	case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE:
		cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name);
		cifs_mark_tcp_ses_conns_for_reconnect(swnreg->tcon->ses->server, true);
		cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
		break;
	case CIFS_SWN_RESOURCE_STATE_AVAILABLE:
		cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name);
		cifs_mark_tcp_ses_conns_for_reconnect(swnreg->tcon->ses->server, true);
		cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
		break;
	case CIFS_SWN_RESOURCE_STATE_UNKNOWN:
		cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name);
@@ -498,7 +498,7 @@ static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *a
		goto unlock;
	}

	cifs_mark_tcp_ses_conns_for_reconnect(tcon->ses->server, false);
	cifs_signal_cifsd_for_reconnect(tcon->ses->server, false);

unlock:
	mutex_unlock(&tcon->ses->server->srv_mutex);
+11 −3
Original line number Diff line number Diff line
@@ -210,6 +210,9 @@ cifs_read_super(struct super_block *sb)
	if (rc)
		goto out_no_root;
	/* tune readahead according to rsize if readahead size not set on mount */
	if (cifs_sb->ctx->rsize == 0)
		cifs_sb->ctx->rsize =
			tcon->ses->server->ops->negotiate_rsize(tcon, cifs_sb->ctx);
	if (cifs_sb->ctx->rasize)
		sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE;
	else
@@ -254,6 +257,9 @@ static void cifs_kill_sb(struct super_block *sb)
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifs_tcon *tcon;
	struct cached_fid *cfid;
	struct rb_root *root = &cifs_sb->tlink_tree;
	struct rb_node *node;
	struct tcon_link *tlink;

	/*
	 * We ned to release all dentries for the cached directories
@@ -263,16 +269,18 @@ static void cifs_kill_sb(struct super_block *sb)
		dput(cifs_sb->root);
		cifs_sb->root = NULL;
	}
	tcon = cifs_sb_master_tcon(cifs_sb);
	if (tcon) {
	node = rb_first(root);
	while (node != NULL) {
		tlink = rb_entry(node, struct tcon_link, tl_rbnode);
		tcon = tlink_tcon(tlink);
		cfid = &tcon->crfid;
		mutex_lock(&cfid->fid_mutex);
		if (cfid->dentry) {

			dput(cfid->dentry);
			cfid->dentry = NULL;
		}
		mutex_unlock(&cfid->fid_mutex);
		node = rb_next(node);
	}

	kill_anon_super(sb);
+3 −0
Original line number Diff line number Diff line
@@ -132,6 +132,9 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
			struct smb_hdr *out_buf,
			int *bytes_returned);
void
cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
				      bool all_channels);
void
cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
				      bool mark_smb_session);
extern int cifs_reconnect(struct TCP_Server_Info *server,
+41 −1
Original line number Diff line number Diff line
@@ -162,11 +162,51 @@ static void cifs_resolve_server(struct work_struct *work)
	mutex_unlock(&server->srv_mutex);
}

/*
 * Update the tcpStatus for the server.
 * This is used to signal the cifsd thread to call cifs_reconnect
 * ONLY cifsd thread should call cifs_reconnect. For any other
 * thread, use this function
 *
 * @server: the tcp ses for which reconnect is needed
 * @all_channels: if this needs to be done for all channels
 */
void
cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
				bool all_channels)
{
	struct TCP_Server_Info *pserver;
	struct cifs_ses *ses;
	int i;

	/* If server is a channel, select the primary channel */
	pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;

	spin_lock(&cifs_tcp_ses_lock);
	if (!all_channels) {
		pserver->tcpStatus = CifsNeedReconnect;
		spin_unlock(&cifs_tcp_ses_lock);
		return;
	}

	list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
		spin_lock(&ses->chan_lock);
		for (i = 0; i < ses->chan_count; i++)
			ses->chans[i].server->tcpStatus = CifsNeedReconnect;
		spin_unlock(&ses->chan_lock);
	}
	spin_unlock(&cifs_tcp_ses_lock);
}

/*
 * Mark all sessions and tcons for reconnect.
 * IMPORTANT: make sure that this gets called only from
 * cifsd thread. For any other thread, use
 * cifs_signal_cifsd_for_reconnect
 *
 * @server: the tcp ses for which reconnect is needed
 * @server needs to be previously set to CifsNeedReconnect.
 *
 * @mark_smb_session: whether even sessions need to be marked
 */
void
cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
+1 −1
Original line number Diff line number Diff line
@@ -1355,7 +1355,7 @@ static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cach
	}

	cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__);
	cifs_mark_tcp_ses_conns_for_reconnect(tcon->ses->server, true);
	cifs_signal_cifsd_for_reconnect(tcon->ses->server, true);
}

/* Refresh dfs referral of tcon and mark it for reconnect if needed */
Loading