Commit c239d83b authored by Stanislav Kinsbursky's avatar Stanislav Kinsbursky Committed by Trond Myklebust

SUNRPC: split SUNPRC PipeFS dentry and private pipe data creation

This patch is a final step towards to removing PipeFS inode references from
kernel code other than PipeFS itself. It makes all kernel SUNRPC PipeFS users
depends on pipe private data, which state depend on their specific operations,
etc.
This patch completes SUNRPC PipeFS preparations and allows to create pipe
private data and PipeFS dentries independently.
Next step will be making SUNPRC PipeFS dentries allocated by SUNRPC PipeFS
network namespace aware routines.
Signed-off-by: default avatarStanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 9beae467
...@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); ...@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andy Adamson <andros@citi.umich.edu>"); MODULE_AUTHOR("Andy Adamson <andros@citi.umich.edu>");
MODULE_DESCRIPTION("The NFSv4.1 pNFS Block layout driver"); MODULE_DESCRIPTION("The NFSv4.1 pNFS Block layout driver");
struct dentry *bl_device_pipe; struct rpc_pipe *bl_device_pipe;
wait_queue_head_t bl_wq; wait_queue_head_t bl_wq;
static void print_page(struct page *page) static void print_page(struct page *page)
...@@ -1051,16 +1051,23 @@ static int __init nfs4blocklayout_init(void) ...@@ -1051,16 +1051,23 @@ static int __init nfs4blocklayout_init(void)
if (ret) if (ret)
goto out_putrpc; goto out_putrpc;
bl_device_pipe = rpc_mkpipe(path.dentry, "blocklayout", NULL, bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0);
&bl_upcall_ops, 0);
path_put(&path); path_put(&path);
if (IS_ERR(bl_device_pipe)) { if (IS_ERR(bl_device_pipe)) {
ret = PTR_ERR(bl_device_pipe); ret = PTR_ERR(bl_device_pipe);
goto out_putrpc; goto out_putrpc;
} }
bl_device_pipe->dentry = rpc_mkpipe_dentry(path.dentry, "blocklayout",
NULL, bl_device_pipe);
if (IS_ERR(bl_device_pipe->dentry)) {
ret = PTR_ERR(bl_device_pipe->dentry);
goto out_destroy_pipe;
}
out: out:
return ret; return ret;
out_destroy_pipe:
rpc_destroy_pipe_data(bl_device_pipe);
out_putrpc: out_putrpc:
rpc_put_mount(); rpc_put_mount();
out_remove: out_remove:
...@@ -1074,7 +1081,8 @@ static void __exit nfs4blocklayout_exit(void) ...@@ -1074,7 +1081,8 @@ static void __exit nfs4blocklayout_exit(void)
__func__); __func__);
pnfs_unregister_layoutdriver(&blocklayout_type); pnfs_unregister_layoutdriver(&blocklayout_type);
rpc_unlink(bl_device_pipe); rpc_unlink(bl_device_pipe->dentry);
rpc_destroy_pipe_data(bl_device_pipe);
rpc_put_mount(); rpc_put_mount();
} }
......
...@@ -161,7 +161,7 @@ struct bl_msg_hdr { ...@@ -161,7 +161,7 @@ struct bl_msg_hdr {
u16 totallen; /* length of entire message, including hdr itself */ u16 totallen; /* length of entire message, including hdr itself */
}; };
extern struct dentry *bl_device_pipe; extern struct rpc_pipe *bl_device_pipe;
extern wait_queue_head_t bl_wq; extern wait_queue_head_t bl_wq;
#define BL_DEVICE_UMOUNT 0x0 /* Umount--delete devices */ #define BL_DEVICE_UMOUNT 0x0 /* Umount--delete devices */
......
...@@ -146,7 +146,7 @@ nfs4_blk_decode_device(struct nfs_server *server, ...@@ -146,7 +146,7 @@ nfs4_blk_decode_device(struct nfs_server *server,
dprintk("%s CALLING USERSPACE DAEMON\n", __func__); dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
add_wait_queue(&bl_wq, &wq); add_wait_queue(&bl_wq, &wq);
rc = rpc_queue_upcall(RPC_I(bl_device_pipe->d_inode)->pipe, &msg); rc = rpc_queue_upcall(bl_device_pipe, &msg);
if (rc < 0) { if (rc < 0) {
remove_wait_queue(&bl_wq, &wq); remove_wait_queue(&bl_wq, &wq);
rv = ERR_PTR(rc); rv = ERR_PTR(rc);
......
...@@ -66,7 +66,7 @@ static void dev_remove(dev_t dev) ...@@ -66,7 +66,7 @@ static void dev_remove(dev_t dev)
msg.len = sizeof(bl_msg) + bl_msg.totallen; msg.len = sizeof(bl_msg) + bl_msg.totallen;
add_wait_queue(&bl_wq, &wq); add_wait_queue(&bl_wq, &wq);
if (rpc_queue_upcall(RPC_I(bl_device_pipe->d_inode)->pipe, &msg) < 0) { if (rpc_queue_upcall(bl_device_pipe, &msg) < 0) {
remove_wait_queue(&bl_wq, &wq); remove_wait_queue(&bl_wq, &wq);
goto out; goto out;
} }
......
...@@ -410,7 +410,7 @@ struct idmap_hashtable { ...@@ -410,7 +410,7 @@ struct idmap_hashtable {
}; };
struct idmap { struct idmap {
struct dentry *idmap_dentry; struct rpc_pipe *idmap_pipe;
wait_queue_head_t idmap_wq; wait_queue_head_t idmap_wq;
struct idmap_msg idmap_im; struct idmap_msg idmap_im;
struct mutex idmap_lock; /* Serializes upcalls */ struct mutex idmap_lock; /* Serializes upcalls */
...@@ -435,6 +435,7 @@ int ...@@ -435,6 +435,7 @@ int
nfs_idmap_new(struct nfs_client *clp) nfs_idmap_new(struct nfs_client *clp)
{ {
struct idmap *idmap; struct idmap *idmap;
struct rpc_pipe *pipe;
int error; int error;
BUG_ON(clp->cl_idmap != NULL); BUG_ON(clp->cl_idmap != NULL);
...@@ -443,14 +444,23 @@ nfs_idmap_new(struct nfs_client *clp) ...@@ -443,14 +444,23 @@ nfs_idmap_new(struct nfs_client *clp)
if (idmap == NULL) if (idmap == NULL)
return -ENOMEM; return -ENOMEM;
idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_path.dentry, pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
"idmap", idmap, &idmap_upcall_ops, 0); if (IS_ERR(pipe)) {
if (IS_ERR(idmap->idmap_dentry)) { error = PTR_ERR(pipe);
error = PTR_ERR(idmap->idmap_dentry);
kfree(idmap); kfree(idmap);
return error; return error;
} }
if (clp->cl_rpcclient->cl_path.dentry)
pipe->dentry = rpc_mkpipe_dentry(clp->cl_rpcclient->cl_path.dentry,
"idmap", idmap, pipe);
if (IS_ERR(pipe->dentry)) {
error = PTR_ERR(pipe->dentry);
rpc_destroy_pipe_data(pipe);
kfree(idmap);
return error;
}
idmap->idmap_pipe = pipe;
mutex_init(&idmap->idmap_lock); mutex_init(&idmap->idmap_lock);
mutex_init(&idmap->idmap_im_lock); mutex_init(&idmap->idmap_im_lock);
init_waitqueue_head(&idmap->idmap_wq); init_waitqueue_head(&idmap->idmap_wq);
...@@ -468,7 +478,9 @@ nfs_idmap_delete(struct nfs_client *clp) ...@@ -468,7 +478,9 @@ nfs_idmap_delete(struct nfs_client *clp)
if (!idmap) if (!idmap)
return; return;
rpc_unlink(idmap->idmap_dentry); if (idmap->idmap_pipe->dentry)
rpc_unlink(idmap->idmap_pipe->dentry);
rpc_destroy_pipe_data(idmap->idmap_pipe);
clp->cl_idmap = NULL; clp->cl_idmap = NULL;
kfree(idmap); kfree(idmap);
} }
...@@ -589,7 +601,7 @@ nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h, ...@@ -589,7 +601,7 @@ nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h,
msg.len = sizeof(*im); msg.len = sizeof(*im);
add_wait_queue(&idmap->idmap_wq, &wq); add_wait_queue(&idmap->idmap_wq, &wq);
if (rpc_queue_upcall(RPC_I(idmap->idmap_dentry->d_inode)->pipe, &msg) < 0) { if (rpc_queue_upcall(idmap->idmap_pipe, &msg) < 0) {
remove_wait_queue(&idmap->idmap_wq, &wq); remove_wait_queue(&idmap->idmap_wq, &wq);
goto out; goto out;
} }
...@@ -650,7 +662,7 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h, ...@@ -650,7 +662,7 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h,
add_wait_queue(&idmap->idmap_wq, &wq); add_wait_queue(&idmap->idmap_wq, &wq);
if (rpc_queue_upcall(RPC_I(idmap->idmap_dentry->d_inode)->pipe, &msg) < 0) { if (rpc_queue_upcall(idmap->idmap_pipe, &msg) < 0) {
remove_wait_queue(&idmap->idmap_wq, &wq); remove_wait_queue(&idmap->idmap_wq, &wq);
goto out; goto out;
} }
......
...@@ -34,6 +34,7 @@ struct rpc_pipe { ...@@ -34,6 +34,7 @@ struct rpc_pipe {
struct delayed_work queue_timeout; struct delayed_work queue_timeout;
const struct rpc_pipe_ops *ops; const struct rpc_pipe_ops *ops;
spinlock_t lock; spinlock_t lock;
struct dentry *dentry;
}; };
struct rpc_inode { struct rpc_inode {
...@@ -77,8 +78,10 @@ extern struct dentry *rpc_create_cache_dir(struct dentry *, ...@@ -77,8 +78,10 @@ extern struct dentry *rpc_create_cache_dir(struct dentry *,
struct cache_detail *); struct cache_detail *);
extern void rpc_remove_cache_dir(struct dentry *); extern void rpc_remove_cache_dir(struct dentry *);
extern struct dentry *rpc_mkpipe(struct dentry *, const char *, void *, struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags);
const struct rpc_pipe_ops *, int flags); void rpc_destroy_pipe_data(struct rpc_pipe *pipe);
extern struct dentry *rpc_mkpipe_dentry(struct dentry *, const char *, void *,
struct rpc_pipe *);
extern int rpc_unlink(struct dentry *); extern int rpc_unlink(struct dentry *);
extern struct vfsmount *rpc_get_mount(void); extern struct vfsmount *rpc_get_mount(void);
extern void rpc_put_mount(void); extern void rpc_put_mount(void);
......
...@@ -81,7 +81,7 @@ struct gss_auth { ...@@ -81,7 +81,7 @@ struct gss_auth {
* mechanism (for example, "krb5") and exists for * mechanism (for example, "krb5") and exists for
* backwards-compatibility with older gssd's. * backwards-compatibility with older gssd's.
*/ */
struct dentry *dentry[2]; struct rpc_pipe *pipe[2];
}; };
/* pipe_version >= 0 if and only if someone has a pipe open. */ /* pipe_version >= 0 if and only if someone has a pipe open. */
...@@ -449,7 +449,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, ...@@ -449,7 +449,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt,
kfree(gss_msg); kfree(gss_msg);
return ERR_PTR(vers); return ERR_PTR(vers);
} }
gss_msg->pipe = RPC_I(gss_auth->dentry[vers]->d_inode)->pipe; gss_msg->pipe = gss_auth->pipe[vers];
INIT_LIST_HEAD(&gss_msg->list); INIT_LIST_HEAD(&gss_msg->list);
rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
init_waitqueue_head(&gss_msg->waitqueue); init_waitqueue_head(&gss_msg->waitqueue);
...@@ -799,21 +799,33 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) ...@@ -799,21 +799,33 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
* that we supported only the old pipe. So we instead create * that we supported only the old pipe. So we instead create
* the new pipe first. * the new pipe first.
*/ */
gss_auth->dentry[1] = rpc_mkpipe(clnt->cl_path.dentry, gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1,
"gssd", RPC_PIPE_WAIT_FOR_OPEN);
clnt, &gss_upcall_ops_v1, if (IS_ERR(gss_auth->pipe[1])) {
RPC_PIPE_WAIT_FOR_OPEN); err = PTR_ERR(gss_auth->pipe[1]);
if (IS_ERR(gss_auth->dentry[1])) {
err = PTR_ERR(gss_auth->dentry[1]);
goto err_put_mech; goto err_put_mech;
} }
gss_auth->dentry[0] = rpc_mkpipe(clnt->cl_path.dentry, gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0,
gss_auth->mech->gm_name, RPC_PIPE_WAIT_FOR_OPEN);
clnt, &gss_upcall_ops_v0, if (IS_ERR(gss_auth->pipe[0])) {
RPC_PIPE_WAIT_FOR_OPEN); err = PTR_ERR(gss_auth->pipe[0]);
if (IS_ERR(gss_auth->dentry[0])) { goto err_destroy_pipe_1;
err = PTR_ERR(gss_auth->dentry[0]); }
gss_auth->pipe[1]->dentry = rpc_mkpipe_dentry(clnt->cl_path.dentry,
"gssd",
clnt, gss_auth->pipe[1]);
if (IS_ERR(gss_auth->pipe[1]->dentry)) {
err = PTR_ERR(gss_auth->pipe[1]->dentry);
goto err_destroy_pipe_0;
}
gss_auth->pipe[0]->dentry = rpc_mkpipe_dentry(clnt->cl_path.dentry,
gss_auth->mech->gm_name,
clnt, gss_auth->pipe[0]);
if (IS_ERR(gss_auth->pipe[0]->dentry)) {
err = PTR_ERR(gss_auth->pipe[0]->dentry);
goto err_unlink_pipe_1; goto err_unlink_pipe_1;
} }
err = rpcauth_init_credcache(auth); err = rpcauth_init_credcache(auth);
...@@ -822,9 +834,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) ...@@ -822,9 +834,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
return auth; return auth;
err_unlink_pipe_0: err_unlink_pipe_0:
rpc_unlink(gss_auth->dentry[0]); rpc_unlink(gss_auth->pipe[0]->dentry);
err_unlink_pipe_1: err_unlink_pipe_1:
rpc_unlink(gss_auth->dentry[1]); rpc_unlink(gss_auth->pipe[1]->dentry);
err_destroy_pipe_0:
rpc_destroy_pipe_data(gss_auth->pipe[0]);
err_destroy_pipe_1:
rpc_destroy_pipe_data(gss_auth->pipe[1]);
err_put_mech: err_put_mech:
gss_mech_put(gss_auth->mech); gss_mech_put(gss_auth->mech);
err_free: err_free:
...@@ -837,8 +853,10 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) ...@@ -837,8 +853,10 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
static void static void
gss_free(struct gss_auth *gss_auth) gss_free(struct gss_auth *gss_auth)
{ {
rpc_unlink(gss_auth->dentry[1]); rpc_unlink(gss_auth->pipe[0]->dentry);
rpc_unlink(gss_auth->dentry[0]); rpc_unlink(gss_auth->pipe[1]->dentry);
rpc_destroy_pipe_data(gss_auth->pipe[0]);
rpc_destroy_pipe_data(gss_auth->pipe[1]);
gss_mech_put(gss_auth->mech); gss_mech_put(gss_auth->mech);
kfree(gss_auth); kfree(gss_auth);
......
...@@ -206,7 +206,6 @@ static void ...@@ -206,7 +206,6 @@ static void
rpc_i_callback(struct rcu_head *head) rpc_i_callback(struct rcu_head *head)
{ {
struct inode *inode = container_of(head, struct inode, i_rcu); struct inode *inode = container_of(head, struct inode, i_rcu);
kfree(RPC_I(inode)->pipe);
kmem_cache_free(rpc_inode_cachep, RPC_I(inode)); kmem_cache_free(rpc_inode_cachep, RPC_I(inode));
} }
...@@ -575,34 +574,44 @@ init_pipe(struct rpc_pipe *pipe) ...@@ -575,34 +574,44 @@ init_pipe(struct rpc_pipe *pipe)
rpc_timeout_upcall_queue); rpc_timeout_upcall_queue);
pipe->ops = NULL; pipe->ops = NULL;
spin_lock_init(&pipe->lock); spin_lock_init(&pipe->lock);
pipe->dentry = NULL;
}
void rpc_destroy_pipe_data(struct rpc_pipe *pipe)
{
kfree(pipe);
} }
EXPORT_SYMBOL_GPL(rpc_destroy_pipe_data);
static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry, struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags)
umode_t mode,
const struct file_operations *i_fop,
void *private,
const struct rpc_pipe_ops *ops,
int flags)
{ {
struct rpc_pipe *pipe; struct rpc_pipe *pipe;
struct rpc_inode *rpci;
int err;
pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL); pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL);
if (!pipe) if (!pipe)
return -ENOMEM; return ERR_PTR(-ENOMEM);
init_pipe(pipe); init_pipe(pipe);
pipe->ops = ops;
pipe->flags = flags;
return pipe;
}
EXPORT_SYMBOL_GPL(rpc_mkpipe_data);
static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry,
umode_t mode,
const struct file_operations *i_fop,
void *private,
struct rpc_pipe *pipe)
{
struct rpc_inode *rpci;
int err;
err = __rpc_create_common(dir, dentry, S_IFIFO | mode, i_fop, private); err = __rpc_create_common(dir, dentry, S_IFIFO | mode, i_fop, private);
if (err) { if (err)
kfree(pipe);
return err; return err;
}
rpci = RPC_I(dentry->d_inode); rpci = RPC_I(dentry->d_inode);
rpci->private = private; rpci->private = private;
rpci->pipe = pipe; rpci->pipe = pipe;
rpci->pipe->flags = flags;
rpci->pipe->ops = ops;
fsnotify_create(dir, dentry); fsnotify_create(dir, dentry);
return 0; return 0;
} }
...@@ -819,9 +828,8 @@ static int rpc_rmdir_depopulate(struct dentry *dentry, ...@@ -819,9 +828,8 @@ static int rpc_rmdir_depopulate(struct dentry *dentry,
* The @private argument passed here will be available to all these methods * The @private argument passed here will be available to all these methods
* from the file pointer, via RPC_I(file->f_dentry->d_inode)->private. * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private.
*/ */
struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
void *private, const struct rpc_pipe_ops *ops, void *private, struct rpc_pipe *pipe)
int flags)
{ {
struct dentry *dentry; struct dentry *dentry;
struct inode *dir = parent->d_inode; struct inode *dir = parent->d_inode;
...@@ -829,9 +837,9 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, ...@@ -829,9 +837,9 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name,
struct qstr q; struct qstr q;
int err; int err;
if (ops->upcall == NULL) if (pipe->ops->upcall == NULL)
umode &= ~S_IRUGO; umode &= ~S_IRUGO;
if (ops->downcall == NULL) if (pipe->ops->downcall == NULL)
umode &= ~S_IWUGO; umode &= ~S_IWUGO;
q.name = name; q.name = name;
...@@ -842,8 +850,8 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, ...@@ -842,8 +850,8 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name,
dentry = __rpc_lookup_create_exclusive(parent, &q); dentry = __rpc_lookup_create_exclusive(parent, &q);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto out; goto out;
err = __rpc_mkpipe(dir, dentry, umode, &rpc_pipe_fops, err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
private, ops, flags); private, pipe);
if (err) if (err)
goto out_err; goto out_err;
out: out:
...@@ -856,7 +864,7 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, ...@@ -856,7 +864,7 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name,
err); err);
goto out; goto out;
} }
EXPORT_SYMBOL_GPL(rpc_mkpipe); EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
/** /**
* rpc_unlink - remove a pipe * rpc_unlink - remove a pipe
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment