Commit 23b55d67 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull cifs fixes from Steve French:
 "Three SMB3 multichannel/fscache fixes and a DFS fix.

  In testing multichannel reconnect scenarios recently various problems
  with the cifs.ko implementation of fscache were found (e.g. incorrect
  initialization of fscache cookies in some cases)"

* tag '5.16-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: avoid use of dstaddr as key for fscache client cookie
  cifs: add server conn_id to fscache client cookie
  cifs: wait for tcon resource_id before getting fscache super
  cifs: fix missed refcounting of ipc tcon
parents bbef3c7a bbb9db5e
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -1562,6 +1562,10 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
	/* fscache server cookies are based on primary channel only */
	if (!CIFS_SERVER_IS_CHAN(tcp_ses))
		cifs_fscache_get_client_cookie(tcp_ses);
#ifdef CONFIG_CIFS_FSCACHE
	else
		tcp_ses->fscache = tcp_ses->primary_server->fscache;
#endif /* CONFIG_CIFS_FSCACHE */

	/* queue echo request delayed work */
	queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
@@ -3046,12 +3050,6 @@ static int mount_get_conns(struct mount_ctx *mnt_ctx)
				cifs_dbg(VFS, "read only mount of RW share\n");
			/* no need to log a RW mount of a typical RW share */
		}
		/*
		 * The cookie is initialized from volume info returned above.
		 * Inside cifs_fscache_get_super_cookie it checks
		 * that we do not get super cookie twice.
		 */
		cifs_fscache_get_super_cookie(tcon);
	}

	/*
@@ -3426,6 +3424,7 @@ static int connect_dfs_root(struct mount_ctx *mnt_ctx, struct dfs_cache_tgt_list
	 */
	mount_put_conns(mnt_ctx);
	mount_get_dfs_conns(mnt_ctx);
	set_root_ses(mnt_ctx);

	full_path = build_unc_path_to_root(ctx, cifs_sb, true);
	if (IS_ERR(full_path))
+10 −36
Original line number Diff line number Diff line
@@ -16,14 +16,7 @@
 * Key layout of CIFS server cache index object
 */
struct cifs_server_key {
	struct {
		uint16_t	family;		/* address family */
		__be16		port;		/* IP port */
	} hdr;
	union {
		struct in_addr	ipv4_addr;
		struct in6_addr	ipv6_addr;
	};
	__u64 conn_id;
} __packed;

/*
@@ -31,42 +24,23 @@ struct cifs_server_key {
 */
void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
{
	const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr;
	const struct sockaddr_in *addr = (struct sockaddr_in *) sa;
	const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa;
	struct cifs_server_key key;
	uint16_t key_len = sizeof(key.hdr);

	memset(&key, 0, sizeof(key));

	/*
	 * Should not be a problem as sin_family/sin6_family overlays
	 * sa_family field
	 * Check if cookie was already initialized so don't reinitialize it.
	 * In the future, as we integrate with newer fscache features,
	 * we may want to instead add a check if cookie has changed
	 */
	key.hdr.family = sa->sa_family;
	switch (sa->sa_family) {
	case AF_INET:
		key.hdr.port = addr->sin_port;
		key.ipv4_addr = addr->sin_addr;
		key_len += sizeof(key.ipv4_addr);
		break;

	case AF_INET6:
		key.hdr.port = addr6->sin6_port;
		key.ipv6_addr = addr6->sin6_addr;
		key_len += sizeof(key.ipv6_addr);
		break;

	default:
		cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
		server->fscache = NULL;
	if (server->fscache)
		return;
	}

	memset(&key, 0, sizeof(key));
	key.conn_id = server->conn_id;

	server->fscache =
		fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
				       &cifs_fscache_server_index_def,
				       &key, key_len,
				       &key, sizeof(key),
				       NULL, 0,
				       server, 0, true);
	cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
@@ -92,7 +66,7 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
	 * In the future, as we integrate with newer fscache features,
	 * we may want to instead add a check if cookie has changed
	 */
	if (tcon->fscache == NULL)
	if (tcon->fscache)
		return;

	sharename = extract_sharename(tcon->treeName);
+7 −0
Original line number Diff line number Diff line
@@ -1376,6 +1376,13 @@ struct inode *cifs_root_iget(struct super_block *sb)
		inode = ERR_PTR(rc);
	}

	/*
	 * The cookie is initialized from volume info returned above.
	 * Inside cifs_fscache_get_super_cookie it checks
	 * that we do not get super cookie twice.
	 */
	cifs_fscache_get_super_cookie(tcon);

out:
	kfree(path);
	free_xid(xid);