diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-03 13:22:44 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-24 23:43:28 -0400 |
commit | 1dcddd4abd2c6df7f28928ad5cafa4a1cd20030b (patch) | |
tree | 5aad2d4a6ec078b16750b77217e10a8a3172d38a | |
parent | cac45b062c67f86dc1d91d675128838773523243 (diff) | |
download | linux-1dcddd4abd2c6df7f28928ad5cafa4a1cd20030b.tar.bz2 |
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>
-rw-r--r-- | fs/ncpfs/inode.c | 19 | ||||
-rw-r--r-- | fs/ncpfs/ncp_fs_sb.h | 2 |
2 files changed, 13 insertions, 8 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) diff --git a/fs/ncpfs/ncp_fs_sb.h b/fs/ncpfs/ncp_fs_sb.h index c51b2c543539..b81e97adc5a9 100644 --- a/fs/ncpfs/ncp_fs_sb.h +++ b/fs/ncpfs/ncp_fs_sb.h @@ -38,7 +38,7 @@ struct ncp_mount_data_kernel { }; struct ncp_server { - + struct rcu_head rcu; struct ncp_mount_data_kernel m; /* Nearly all of the mount data is of interest for us later, so we store it completely. */ |