diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2011-12-26 07:39:39 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-31 18:20:24 -0500 |
commit | c21a588f35b1c50304e505fad542b3aab0814266 (patch) | |
tree | 2dda83e8d5f62eb9892c425941265aeeb278e952 /net/sunrpc/rpc_pipe.c | |
parent | 90c4e82999c517e0cd00d0782c68d186cb18b784 (diff) |
SUNRPC: pipefs per-net operations helper introduced
During per-net pipes creation and destruction we have to make sure, that pipefs
sb exists for the whole creation/destruction cycle. This is done by using
special mutex which controls pipefs sb reference on network namespace context.
Helper consists of two parts: first of them (rpc_get_dentry_net) searches for
dentry with specified name and returns with mutex taken on success. When pipe
creation or destructions is completed, caller should release this mutex by
rpc_put_dentry_net call.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/rpc_pipe.c')
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index e5e1f357b561..f075f8817773 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -1023,6 +1023,40 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb, | |||
1023 | } | 1023 | } |
1024 | EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); | 1024 | EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); |
1025 | 1025 | ||
1026 | void rpc_pipefs_init_net(struct net *net) | ||
1027 | { | ||
1028 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1029 | |||
1030 | mutex_init(&sn->pipefs_sb_lock); | ||
1031 | } | ||
1032 | |||
1033 | /* | ||
1034 | * This call will be used for per network namespace operations calls. | ||
1035 | * Note: Function will be returned with pipefs_sb_lock taken if superblock was | ||
1036 | * found. This lock have to be released by rpc_put_sb_net() when all operations | ||
1037 | * will be completed. | ||
1038 | */ | ||
1039 | struct super_block *rpc_get_sb_net(const struct net *net) | ||
1040 | { | ||
1041 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1042 | |||
1043 | mutex_lock(&sn->pipefs_sb_lock); | ||
1044 | if (sn->pipefs_sb) | ||
1045 | return sn->pipefs_sb; | ||
1046 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1047 | return NULL; | ||
1048 | } | ||
1049 | EXPORT_SYMBOL_GPL(rpc_get_sb_net); | ||
1050 | |||
1051 | void rpc_put_sb_net(const struct net *net) | ||
1052 | { | ||
1053 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1054 | |||
1055 | BUG_ON(sn->pipefs_sb == NULL); | ||
1056 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1057 | } | ||
1058 | EXPORT_SYMBOL_GPL(rpc_put_sb_net); | ||
1059 | |||
1026 | static int | 1060 | static int |
1027 | rpc_fill_super(struct super_block *sb, void *data, int silent) | 1061 | rpc_fill_super(struct super_block *sb, void *data, int silent) |
1028 | { | 1062 | { |
@@ -1077,7 +1111,9 @@ void rpc_kill_sb(struct super_block *sb) | |||
1077 | struct net *net = sb->s_fs_info; | 1111 | struct net *net = sb->s_fs_info; |
1078 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1112 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1079 | 1113 | ||
1114 | mutex_lock(&sn->pipefs_sb_lock); | ||
1080 | sn->pipefs_sb = NULL; | 1115 | sn->pipefs_sb = NULL; |
1116 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1081 | put_net(net); | 1117 | put_net(net); |
1082 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | 1118 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
1083 | RPC_PIPEFS_UMOUNT, | 1119 | RPC_PIPEFS_UMOUNT, |