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:
Родитель
90c4e82999
Коммит
c21a588f35
|
@ -53,6 +53,9 @@ enum {
|
|||
|
||||
extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
|
||||
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 *,
|
||||
char __user *, size_t);
|
||||
|
|
|
@ -11,6 +11,7 @@ struct sunrpc_net {
|
|||
struct cache_detail *ip_map_cache;
|
||||
|
||||
struct super_block *pipefs_sb;
|
||||
struct mutex pipefs_sb_lock;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
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 sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
|
||||
mutex_lock(&sn->pipefs_sb_lock);
|
||||
sn->pipefs_sb = NULL;
|
||||
mutex_unlock(&sn->pipefs_sb_lock);
|
||||
put_net(net);
|
||||
blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
|
||||
RPC_PIPEFS_UMOUNT,
|
||||
|
|
|
@ -38,6 +38,7 @@ static __net_init int sunrpc_init_net(struct net *net)
|
|||
if (err)
|
||||
goto err_ipmap;
|
||||
|
||||
rpc_pipefs_init_net(net);
|
||||
return 0;
|
||||
|
||||
err_ipmap:
|
||||
|
|
Загрузка…
Ссылка в новой задаче