diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-03 12:53:37 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-24 23:43:27 -0400 |
commit | 2e32cf5ef2683a196df24ccd2cd2b4ed735ad9d3 (patch) | |
tree | 14861a1a6e31bec8e6d46cc8facf02b71760b92d /fs/cifs/connect.c | |
parent | baa40671d3e3b590a33b2c0e022db61cbebf5c00 (diff) | |
download | linux-2e32cf5ef2683a196df24ccd2cd2b4ed735ad9d3.tar.gz linux-2e32cf5ef2683a196df24ccd2cd2b4ed735ad9d3.tar.bz2 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.c | 10 |
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 |