summaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorAl Viro2013-10-03 18:53:37 +0200
committerAl Viro2013-10-25 05:43:27 +0200
commit2e32cf5ef2683a196df24ccd2cd2b4ed735ad9d3 (patch)
tree14861a1a6e31bec8e6d46cc8facf02b71760b92d /fs/cifs/connect.c
parentautofs4: make freeing sbi rcu-delayed (diff)
downloadkernel-qcow2-linux-2e32cf5ef2683a196df24ccd2cd2b4ed735ad9d3.tar.gz
kernel-qcow2-linux-2e32cf5ef2683a196df24ccd2cd2b4ed735ad9d3.tar.xz
kernel-qcow2-linux-2e32cf5ef2683a196df24ccd2cd2b4ed735ad9d3.zip
cifs: rcu-delay unload_nls() and freeing sbi
makes ->d_hash(), ->d_compare() and ->permission() safety in RCU mode independent from vfsmount_lock. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index a279ffc0bc29..886db8b41e35 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3755,6 +3755,13 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
return rc;
}
+static void delayed_free(struct rcu_head *p)
+{
+ struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
+ unload_nls(sbi->local_nls);
+ kfree(sbi);
+}
+
void
cifs_umount(struct cifs_sb_info *cifs_sb)
{
@@ -3779,8 +3786,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
bdi_destroy(&cifs_sb->bdi);
kfree(cifs_sb->mountdata);
- unload_nls(cifs_sb->local_nls);
- kfree(cifs_sb);
+ call_rcu(&cifs_sb->rcu, delayed_free);
}
int