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>
This commit is contained in:
parent
90c4e82999
commit
c21a588f35
@ -53,6 +53,9 @@ enum {
|
|||||||
|
|
||||||
extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
|
extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
|
||||||
const unsigned char *dir_name);
|
const unsigned char *dir_name);
|
||||||
|
extern void rpc_pipefs_init_net(struct net *net);
|
||||||
|
extern struct super_block *rpc_get_sb_net(const struct net *net);
|
||||||
|
extern void rpc_put_sb_net(const struct net *net);
|
||||||
|
|
||||||
extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
|
extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
|
||||||
char __user *, size_t);
|
char __user *, size_t);
|
||||||
|
@ -11,6 +11,7 @@ struct sunrpc_net {
|
|||||||
struct cache_detail *ip_map_cache;
|
struct cache_detail *ip_map_cache;
|
||||||
|
|
||||||
struct super_block *pipefs_sb;
|
struct super_block *pipefs_sb;
|
||||||
|
struct mutex pipefs_sb_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int sunrpc_net_id;
|
extern int sunrpc_net_id;
|
||||||
|
@ -1023,6 +1023,40 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
|
EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
|
||||||
|
|
||||||
|
void rpc_pipefs_init_net(struct net *net)
|
||||||
|
{
|
||||||
|
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||||
|
|
||||||
|
mutex_init(&sn->pipefs_sb_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This call will be used for per network namespace operations calls.
|
||||||
|
* Note: Function will be returned with pipefs_sb_lock taken if superblock was
|
||||||
|
* found. This lock have to be released by rpc_put_sb_net() when all operations
|
||||||
|
* will be completed.
|
||||||
|
*/
|
||||||
|
struct super_block *rpc_get_sb_net(const struct net *net)
|
||||||
|
{
|
||||||
|
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||||
|
|
||||||
|
mutex_lock(&sn->pipefs_sb_lock);
|
||||||
|
if (sn->pipefs_sb)
|
||||||
|
return sn->pipefs_sb;
|
||||||
|
mutex_unlock(&sn->pipefs_sb_lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rpc_get_sb_net);
|
||||||
|
|
||||||
|
void rpc_put_sb_net(const struct net *net)
|
||||||
|
{
|
||||||
|
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||||
|
|
||||||
|
BUG_ON(sn->pipefs_sb == NULL);
|
||||||
|
mutex_unlock(&sn->pipefs_sb_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rpc_put_sb_net);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rpc_fill_super(struct super_block *sb, void *data, int silent)
|
rpc_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
{
|
{
|
||||||
@ -1077,7 +1111,9 @@ void rpc_kill_sb(struct super_block *sb)
|
|||||||
struct net *net = sb->s_fs_info;
|
struct net *net = sb->s_fs_info;
|
||||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||||
|
|
||||||
|
mutex_lock(&sn->pipefs_sb_lock);
|
||||||
sn->pipefs_sb = NULL;
|
sn->pipefs_sb = NULL;
|
||||||
|
mutex_unlock(&sn->pipefs_sb_lock);
|
||||||
put_net(net);
|
put_net(net);
|
||||||
blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
|
blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
|
||||||
RPC_PIPEFS_UMOUNT,
|
RPC_PIPEFS_UMOUNT,
|
||||||
|
@ -38,6 +38,7 @@ static __net_init int sunrpc_init_net(struct net *net)
|
|||||||
if (err)
|
if (err)
|
||||||
goto err_ipmap;
|
goto err_ipmap;
|
||||||
|
|
||||||
|
rpc_pipefs_init_net(net);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_ipmap:
|
err_ipmap:
|
||||||
|
Loading…
Reference in New Issue
Block a user