NFSv4: Convert idmapper to use the new framework for pipefs dentries
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
5f42b016d7
commit
2127d82af3
184
fs/nfs/idmap.c
184
fs/nfs/idmap.c
|
@ -64,6 +64,7 @@ struct idmap_legacy_upcalldata {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct idmap {
|
struct idmap {
|
||||||
|
struct rpc_pipe_dir_object idmap_pdo;
|
||||||
struct rpc_pipe *idmap_pipe;
|
struct rpc_pipe *idmap_pipe;
|
||||||
struct idmap_legacy_upcalldata *idmap_upcall_data;
|
struct idmap_legacy_upcalldata *idmap_upcall_data;
|
||||||
struct mutex idmap_mutex;
|
struct mutex idmap_mutex;
|
||||||
|
@ -402,18 +403,23 @@ static struct key_type key_type_id_resolver_legacy = {
|
||||||
.request_key = nfs_idmap_legacy_upcall,
|
.request_key = nfs_idmap_legacy_upcall,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __nfs_idmap_unregister(struct rpc_pipe *pipe)
|
static void nfs_idmap_pipe_destroy(struct dentry *dir,
|
||||||
|
struct rpc_pipe_dir_object *pdo)
|
||||||
{
|
{
|
||||||
|
struct idmap *idmap = pdo->pdo_data;
|
||||||
|
struct rpc_pipe *pipe = idmap->idmap_pipe;
|
||||||
|
|
||||||
if (pipe->dentry) {
|
if (pipe->dentry) {
|
||||||
rpc_unlink(pipe->dentry);
|
rpc_unlink(pipe->dentry);
|
||||||
pipe->dentry = NULL;
|
pipe->dentry = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __nfs_idmap_register(struct dentry *dir,
|
static int nfs_idmap_pipe_create(struct dentry *dir,
|
||||||
struct idmap *idmap,
|
struct rpc_pipe_dir_object *pdo)
|
||||||
struct rpc_pipe *pipe)
|
|
||||||
{
|
{
|
||||||
|
struct idmap *idmap = pdo->pdo_data;
|
||||||
|
struct rpc_pipe *pipe = idmap->idmap_pipe;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
|
|
||||||
dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
|
dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
|
||||||
|
@ -423,36 +429,10 @@ static int __nfs_idmap_register(struct dentry *dir,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfs_idmap_unregister(struct nfs_client *clp,
|
static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = {
|
||||||
struct rpc_pipe *pipe)
|
.create = nfs_idmap_pipe_create,
|
||||||
{
|
.destroy = nfs_idmap_pipe_destroy,
|
||||||
struct net *net = clp->cl_net;
|
};
|
||||||
struct super_block *pipefs_sb;
|
|
||||||
|
|
||||||
pipefs_sb = rpc_get_sb_net(net);
|
|
||||||
if (pipefs_sb) {
|
|
||||||
__nfs_idmap_unregister(pipe);
|
|
||||||
rpc_put_sb_net(net);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nfs_idmap_register(struct nfs_client *clp,
|
|
||||||
struct idmap *idmap,
|
|
||||||
struct rpc_pipe *pipe)
|
|
||||||
{
|
|
||||||
struct net *net = clp->cl_net;
|
|
||||||
struct super_block *pipefs_sb;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
pipefs_sb = rpc_get_sb_net(net);
|
|
||||||
if (pipefs_sb) {
|
|
||||||
if (clp->cl_rpcclient->cl_dentry)
|
|
||||||
err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry,
|
|
||||||
idmap, pipe);
|
|
||||||
rpc_put_sb_net(net);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
nfs_idmap_new(struct nfs_client *clp)
|
nfs_idmap_new(struct nfs_client *clp)
|
||||||
|
@ -465,23 +445,31 @@ nfs_idmap_new(struct nfs_client *clp)
|
||||||
if (idmap == NULL)
|
if (idmap == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
rpc_init_pipe_dir_object(&idmap->idmap_pdo,
|
||||||
|
&nfs_idmap_pipe_dir_object_ops,
|
||||||
|
idmap);
|
||||||
|
|
||||||
pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
|
pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
|
||||||
if (IS_ERR(pipe)) {
|
if (IS_ERR(pipe)) {
|
||||||
error = PTR_ERR(pipe);
|
error = PTR_ERR(pipe);
|
||||||
kfree(idmap);
|
goto err;
|
||||||
return error;
|
|
||||||
}
|
|
||||||
error = nfs_idmap_register(clp, idmap, pipe);
|
|
||||||
if (error) {
|
|
||||||
rpc_destroy_pipe_data(pipe);
|
|
||||||
kfree(idmap);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
idmap->idmap_pipe = pipe;
|
idmap->idmap_pipe = pipe;
|
||||||
mutex_init(&idmap->idmap_mutex);
|
mutex_init(&idmap->idmap_mutex);
|
||||||
|
|
||||||
|
error = rpc_add_pipe_dir_object(clp->cl_net,
|
||||||
|
&clp->cl_rpcclient->cl_pipedir_objects,
|
||||||
|
&idmap->idmap_pdo);
|
||||||
|
if (error)
|
||||||
|
goto err_destroy_pipe;
|
||||||
|
|
||||||
clp->cl_idmap = idmap;
|
clp->cl_idmap = idmap;
|
||||||
return 0;
|
return 0;
|
||||||
|
err_destroy_pipe:
|
||||||
|
rpc_destroy_pipe_data(idmap->idmap_pipe);
|
||||||
|
err:
|
||||||
|
kfree(idmap);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -491,130 +479,26 @@ nfs_idmap_delete(struct nfs_client *clp)
|
||||||
|
|
||||||
if (!idmap)
|
if (!idmap)
|
||||||
return;
|
return;
|
||||||
nfs_idmap_unregister(clp, idmap->idmap_pipe);
|
|
||||||
rpc_destroy_pipe_data(idmap->idmap_pipe);
|
|
||||||
clp->cl_idmap = NULL;
|
clp->cl_idmap = NULL;
|
||||||
|
rpc_remove_pipe_dir_object(clp->cl_net,
|
||||||
|
&clp->cl_rpcclient->cl_pipedir_objects,
|
||||||
|
&idmap->idmap_pdo);
|
||||||
|
rpc_destroy_pipe_data(idmap->idmap_pipe);
|
||||||
kfree(idmap);
|
kfree(idmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event,
|
|
||||||
struct super_block *sb)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
switch (event) {
|
|
||||||
case RPC_PIPEFS_MOUNT:
|
|
||||||
err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry,
|
|
||||||
clp->cl_idmap,
|
|
||||||
clp->cl_idmap->idmap_pipe);
|
|
||||||
break;
|
|
||||||
case RPC_PIPEFS_UMOUNT:
|
|
||||||
if (clp->cl_idmap->idmap_pipe) {
|
|
||||||
struct dentry *parent;
|
|
||||||
|
|
||||||
parent = clp->cl_idmap->idmap_pipe->dentry->d_parent;
|
|
||||||
__nfs_idmap_unregister(clp->cl_idmap->idmap_pipe);
|
|
||||||
/*
|
|
||||||
* Note: This is a dirty hack. SUNRPC hook has been
|
|
||||||
* called already but simple_rmdir() call for the
|
|
||||||
* directory returned with error because of idmap pipe
|
|
||||||
* inside. Thus now we have to remove this directory
|
|
||||||
* here.
|
|
||||||
*/
|
|
||||||
if (rpc_rmdir(parent))
|
|
||||||
printk(KERN_ERR "NFS: %s: failed to remove "
|
|
||||||
"clnt dir!\n", __func__);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printk(KERN_ERR "NFS: %s: unknown event: %ld\n", __func__,
|
|
||||||
event);
|
|
||||||
return -ENOTSUPP;
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct nfs_client *nfs_get_client_for_event(struct net *net, int event)
|
|
||||||
{
|
|
||||||
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
|
||||||
struct dentry *cl_dentry;
|
|
||||||
struct nfs_client *clp;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
restart:
|
|
||||||
spin_lock(&nn->nfs_client_lock);
|
|
||||||
list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
|
|
||||||
/* Wait for initialisation to finish */
|
|
||||||
if (clp->cl_cons_state == NFS_CS_INITING) {
|
|
||||||
atomic_inc(&clp->cl_count);
|
|
||||||
spin_unlock(&nn->nfs_client_lock);
|
|
||||||
err = nfs_wait_client_init_complete(clp);
|
|
||||||
nfs_put_client(clp);
|
|
||||||
if (err)
|
|
||||||
return NULL;
|
|
||||||
goto restart;
|
|
||||||
}
|
|
||||||
/* Skip nfs_clients that failed to initialise */
|
|
||||||
if (clp->cl_cons_state < 0)
|
|
||||||
continue;
|
|
||||||
smp_rmb();
|
|
||||||
if (clp->rpc_ops != &nfs_v4_clientops)
|
|
||||||
continue;
|
|
||||||
cl_dentry = clp->cl_idmap->idmap_pipe->dentry;
|
|
||||||
if (((event == RPC_PIPEFS_MOUNT) && cl_dentry) ||
|
|
||||||
((event == RPC_PIPEFS_UMOUNT) && !cl_dentry))
|
|
||||||
continue;
|
|
||||||
atomic_inc(&clp->cl_count);
|
|
||||||
spin_unlock(&nn->nfs_client_lock);
|
|
||||||
return clp;
|
|
||||||
}
|
|
||||||
spin_unlock(&nn->nfs_client_lock);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
|
|
||||||
void *ptr)
|
|
||||||
{
|
|
||||||
struct super_block *sb = ptr;
|
|
||||||
struct nfs_client *clp;
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
if (!try_module_get(THIS_MODULE))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) {
|
|
||||||
error = __rpc_pipefs_event(clp, event, sb);
|
|
||||||
nfs_put_client(clp);
|
|
||||||
if (error)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
module_put(THIS_MODULE);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PIPEFS_NFS_PRIO 1
|
|
||||||
|
|
||||||
static struct notifier_block nfs_idmap_block = {
|
|
||||||
.notifier_call = rpc_pipefs_event,
|
|
||||||
.priority = SUNRPC_PIPEFS_NFS_PRIO,
|
|
||||||
};
|
|
||||||
|
|
||||||
int nfs_idmap_init(void)
|
int nfs_idmap_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
ret = nfs_idmap_init_keyring();
|
ret = nfs_idmap_init_keyring();
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out;
|
goto out;
|
||||||
ret = rpc_pipefs_notifier_register(&nfs_idmap_block);
|
|
||||||
if (ret != 0)
|
|
||||||
nfs_idmap_quit_keyring();
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfs_idmap_quit(void)
|
void nfs_idmap_quit(void)
|
||||||
{
|
{
|
||||||
rpc_pipefs_notifier_unregister(&nfs_idmap_block);
|
|
||||||
nfs_idmap_quit_keyring();
|
nfs_idmap_quit_keyring();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue