]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
smb:client: smb: client: Add reverse mapping from tcon to superblocks
authorWang Zhaolong <wangzhaolong1@huawei.com>
Mon, 31 Mar 2025 13:33:13 +0000 (21:33 +0800)
committerSteve French <stfrench@microsoft.com>
Tue, 1 Apr 2025 02:12:31 +0000 (21:12 -0500)
Currently, when a SMB connection is reset and renegotiated with the
server, there's no way to update all related mount points with new
negotiated sizes. This is because while superblocks (cifs_sb_info)
maintain references to tree connections (tcon) through tcon_link
structures, there is no reverse mapping from a tcon back to all the
superblocks using it.

This patch adds a bidirectional relationship between tcon and
cifs_sb_info structures by:

1. Adding a cifs_sb_list to tcon structure with appropriate locking
2. Adding tcon_sb_link to cifs_sb_info to join the list
3. Managing the list entries during mount and umount operations

The bidirectional relationship enables future functionality to locate and
update all superblocks connected to a specific tree connection, such as:

- Updating negotiated parameters after reconnection
- Efficiently notifying all affected mounts of capability changes

This is the first part of a series to improve connection resilience
by keeping all mount parameters in sync with server capabilities
after reconnection.

Signed-off-by: Wang Zhaolong <wangzhaolong1@huawei.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifs_fs_sb.h
fs/smb/client/cifsglob.h
fs/smb/client/connect.c
fs/smb/client/misc.c

index 65175919228014001a7b5c0b0acc4df8c72ed8b2..5e8d163cb5f801eaa25a14e6745ea86311c5008e 100644 (file)
@@ -49,6 +49,7 @@
 
 struct cifs_sb_info {
        struct rb_root tlink_tree;
+       struct list_head tcon_sb_link;
        spinlock_t tlink_tree_lock;
        struct tcon_link *master_tlink;
        struct nls_table *local_nls;
index 6ae170a2a04269022741e60cd3c188c55d0f6793..2cb352c16c1ad4d66d5d6e369cfc63fc3fdb62ac 100644 (file)
@@ -1321,7 +1321,8 @@ struct cifs_tcon {
 #endif
        struct list_head pending_opens; /* list of incomplete opens */
        struct cached_fids *cfids;
-       /* BB add field for back pointer to sb struct(s)? */
+       struct list_head cifs_sb_list;
+       spinlock_t sb_list_lock;
 #ifdef CONFIG_CIFS_DFS_UPCALL
        struct delayed_work dfs_cache_work;
        struct list_head dfs_ses_list;
index 0721e557f2e0c3f00d7856354a9a01b6ec833110..2349597d5bfcbc0186dfc141f0c40fa6d9935c30 100644 (file)
@@ -3477,6 +3477,7 @@ int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
        struct smb3_fs_context *ctx = cifs_sb->ctx;
 
        INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
+       INIT_LIST_HEAD(&cifs_sb->tcon_sb_link);
 
        spin_lock_init(&cifs_sb->tlink_tree_lock);
        cifs_sb->tlink_tree = RB_ROOT;
@@ -3709,6 +3710,10 @@ static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
        tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
        spin_unlock(&cifs_sb->tlink_tree_lock);
 
+       spin_lock(&tcon->sb_list_lock);
+       list_add(&cifs_sb->tcon_sb_link, &tcon->cifs_sb_list);
+       spin_unlock(&tcon->sb_list_lock);
+
        queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
                                TLINK_IDLE_EXPIRE);
        return 0;
@@ -4050,9 +4055,19 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
        struct rb_root *root = &cifs_sb->tlink_tree;
        struct rb_node *node;
        struct tcon_link *tlink;
+       struct cifs_tcon *tcon = NULL;
 
        cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
 
+       if (cifs_sb->master_tlink) {
+               tcon = cifs_sb->master_tlink->tl_tcon;
+               if (tcon) {
+                       spin_lock(&tcon->sb_list_lock);
+                       list_del_init(&cifs_sb->tcon_sb_link);
+                       spin_unlock(&tcon->sb_list_lock);
+               }
+       }
+
        spin_lock(&cifs_sb->tlink_tree_lock);
        while ((node = rb_first(root))) {
                tlink = rb_entry(node, struct tcon_link, tl_rbnode);
index b328dc5c7988dea9c8fee05e8b032301e4c5a035..7b6ed9b23e713d5b99c0188a72eed9afc2a3dbc3 100644 (file)
@@ -137,8 +137,10 @@ tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace)
        spin_lock_init(&ret_buf->tc_lock);
        INIT_LIST_HEAD(&ret_buf->openFileList);
        INIT_LIST_HEAD(&ret_buf->tcon_list);
+       INIT_LIST_HEAD(&ret_buf->cifs_sb_list);
        spin_lock_init(&ret_buf->open_file_lock);
        spin_lock_init(&ret_buf->stat_lock);
+       spin_lock_init(&ret_buf->sb_list_lock);
        atomic_set(&ret_buf->num_local_opens, 0);
        atomic_set(&ret_buf->num_remote_opens, 0);
        ret_buf->stats_from_time = ktime_get_real_seconds();