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

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
...@@ -1562,6 +1562,10 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, ...@@ -1562,6 +1562,10 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
/* fscache server cookies are based on primary channel only */ /* fscache server cookies are based on primary channel only */
if (!CIFS_SERVER_IS_CHAN(tcp_ses)) if (!CIFS_SERVER_IS_CHAN(tcp_ses))
cifs_fscache_get_client_cookie(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 echo request delayed work */
queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); 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) ...@@ -3046,12 +3050,6 @@ static int mount_get_conns(struct mount_ctx *mnt_ctx)
cifs_dbg(VFS, "read only mount of RW share\n"); cifs_dbg(VFS, "read only mount of RW share\n");
/* no need to log a RW mount of a typical RW share */ /* 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 ...@@ -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_put_conns(mnt_ctx);
mount_get_dfs_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); full_path = build_unc_path_to_root(ctx, cifs_sb, true);
if (IS_ERR(full_path)) if (IS_ERR(full_path))
......
...@@ -16,14 +16,7 @@ ...@@ -16,14 +16,7 @@
* Key layout of CIFS server cache index object * Key layout of CIFS server cache index object
*/ */
struct cifs_server_key { struct cifs_server_key {
struct { __u64 conn_id;
uint16_t family; /* address family */
__be16 port; /* IP port */
} hdr;
union {
struct in_addr ipv4_addr;
struct in6_addr ipv6_addr;
};
} __packed; } __packed;
/* /*
...@@ -31,42 +24,23 @@ struct cifs_server_key { ...@@ -31,42 +24,23 @@ struct cifs_server_key {
*/ */
void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) 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; 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 * Check if cookie was already initialized so don't reinitialize it.
* sa_family field * 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; if (server->fscache)
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;
return; return;
}
memset(&key, 0, sizeof(key));
key.conn_id = server->conn_id;
server->fscache = server->fscache =
fscache_acquire_cookie(cifs_fscache_netfs.primary_index, fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
&cifs_fscache_server_index_def, &cifs_fscache_server_index_def,
&key, key_len, &key, sizeof(key),
NULL, 0, NULL, 0,
server, 0, true); server, 0, true);
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
...@@ -92,7 +66,7 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) ...@@ -92,7 +66,7 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
* In the future, as we integrate with newer fscache features, * In the future, as we integrate with newer fscache features,
* we may want to instead add a check if cookie has changed * we may want to instead add a check if cookie has changed
*/ */
if (tcon->fscache == NULL) if (tcon->fscache)
return; return;
sharename = extract_sharename(tcon->treeName); sharename = extract_sharename(tcon->treeName);
......
...@@ -1376,6 +1376,13 @@ struct inode *cifs_root_iget(struct super_block *sb) ...@@ -1376,6 +1376,13 @@ struct inode *cifs_root_iget(struct super_block *sb)
inode = ERR_PTR(rc); 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: out:
kfree(path); kfree(path);
free_xid(xid); free_xid(xid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment