diff options
Diffstat (limited to 'fs/smb/client/misc.c')
| -rw-r--r-- | fs/smb/client/misc.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index bc24c92b8b95..2aff1cab6c31 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -28,6 +28,11 @@ #include "fs_context.h" #include "cached_dir.h" +struct tcon_list { + struct list_head entry; + struct cifs_tcon *tcon; +}; + /* The xid serves as a useful identifier for each incoming vfs request, in a similar way to the mid which is useful to track each sent smb, and CurrentXid can also provide a running counter (although it @@ -554,6 +559,43 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) } } +void cifs_close_all_deferred_files_sb(struct cifs_sb_info *cifs_sb) +{ + struct rb_root *root = &cifs_sb->tlink_tree; + struct rb_node *node; + struct cifs_tcon *tcon; + struct tcon_link *tlink; + struct tcon_list *tmp_list, *q; + LIST_HEAD(tcon_head); + + spin_lock(&cifs_sb->tlink_tree_lock); + for (node = rb_first(root); node; node = rb_next(node)) { + tlink = rb_entry(node, struct tcon_link, tl_rbnode); + tcon = tlink_tcon(tlink); + if (IS_ERR(tcon)) + continue; + tmp_list = kmalloc_obj(struct tcon_list, GFP_ATOMIC); + if (tmp_list == NULL) + break; + tmp_list->tcon = tcon; + /* Take a reference on tcon to prevent it from being freed */ + spin_lock(&tcon->tc_lock); + ++tcon->tc_count; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_close_defer_files); + spin_unlock(&tcon->tc_lock); + list_add_tail(&tmp_list->entry, &tcon_head); + } + spin_unlock(&cifs_sb->tlink_tree_lock); + + list_for_each_entry_safe(tmp_list, q, &tcon_head, entry) { + cifs_close_all_deferred_files(tmp_list->tcon); + list_del(&tmp_list->entry); + cifs_put_tcon(tmp_list->tcon, netfs_trace_tcon_ref_put_close_defer_files); + kfree(tmp_list); + } +} + void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, struct dentry *dentry) { |
