summaryrefslogtreecommitdiffstats
path: root/fs/ncpfs/inode.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-10-03 19:22:44 +0200
committerAl Viro <viro@zeniv.linux.org.uk>2013-10-25 05:43:28 +0200
commit1dcddd4abd2c6df7f28928ad5cafa4a1cd20030b (patch)
tree5aad2d4a6ec078b16750b77217e10a8a3172d38a /fs/ncpfs/inode.c
parentfat: rcu-delay unloading nls and freeing sbi (diff)
downloadlinux-1dcddd4abd2c6df7f28928ad5cafa4a1cd20030b.tar.xz
linux-1dcddd4abd2c6df7f28928ad5cafa4a1cd20030b.zip
ncpfs: rcu-delay unload_nls() and freeing ncp_server
makes ->d_hash() and ->d_compare() safety in RCU mode independent from vfsmount_lock. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ncpfs/inode.c')
-rw-r--r--fs/ncpfs/inode.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 4659da67e7f6..2cf2ebecb55f 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -782,6 +782,17 @@ out:
return error;
}
+static void delayed_free(struct rcu_head *p)
+{
+ struct ncp_server *server = container_of(p, struct ncp_server, rcu);
+#ifdef CONFIG_NCPFS_NLS
+ /* unload the NLS charsets */
+ unload_nls(server->nls_vol);
+ unload_nls(server->nls_io);
+#endif /* CONFIG_NCPFS_NLS */
+ kfree(server);
+}
+
static void ncp_put_super(struct super_block *sb)
{
struct ncp_server *server = NCP_SBP(sb);
@@ -792,11 +803,6 @@ static void ncp_put_super(struct super_block *sb)
ncp_stop_tasks(server);
-#ifdef CONFIG_NCPFS_NLS
- /* unload the NLS charsets */
- unload_nls(server->nls_vol);
- unload_nls(server->nls_io);
-#endif /* CONFIG_NCPFS_NLS */
mutex_destroy(&server->rcv.creq_mutex);
mutex_destroy(&server->root_setup_lock);
mutex_destroy(&server->mutex);
@@ -813,8 +819,7 @@ static void ncp_put_super(struct super_block *sb)
vfree(server->rxbuf);
vfree(server->txbuf);
vfree(server->packet);
- sb->s_fs_info = NULL;
- kfree(server);
+ call_rcu(&server->rcu, delayed_free);
}
static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)