Skip to content

Commit

Permalink
Merge tag '5.16-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linus Torvalds committed Dec 4, 2021
2 parents bbef3c7 + bbb9db5 commit 23b55d6
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 42 deletions.
11 changes: 5 additions & 6 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

/*
Expand Down Expand Up @@ -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))
Expand Down
46 changes: 10 additions & 36 deletions fs/cifs/fscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,57 +16,31 @@
* 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;

/*
* Get a cookie for a server object keyed by {IPaddress,port,family} tuple
*/
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",
Expand All @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 23b55d6

Please sign in to comment.