SUNRPC: split SUNPRC PipeFS dentry and private pipe data creation
authorStanislav Kinsbursky <skinsbursky@parallels.com>
Mon, 26 Dec 2011 12:44:06 +0000 (15:44 +0300)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 31 Jan 2012 23:20:25 +0000 (18:20 -0500)
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: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/blocklayout/blocklayout.c
fs/nfs/blocklayout/blocklayout.h
fs/nfs/blocklayout/blocklayoutdev.c
fs/nfs/blocklayout/blocklayoutdm.c
fs/nfs/idmap.c
include/linux/sunrpc/rpc_pipe_fs.h
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/rpc_pipe.c

index 48cfac31f64ce2b3679362b91f324ff9afc4e262..848660fd58c47b1b928df902f25fdafca9030954 100644 (file)
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Andy Adamson <andros@citi.umich.edu>");
 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;
 
 static void print_page(struct page *page)
@@ -1051,16 +1051,23 @@ static int __init nfs4blocklayout_init(void)
        if (ret)
                goto out_putrpc;
 
-       bl_device_pipe = rpc_mkpipe(path.dentry, "blocklayout", NULL,
-                                   &bl_upcall_ops, 0);
+       bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0);
        path_put(&path);
        if (IS_ERR(bl_device_pipe)) {
                ret = PTR_ERR(bl_device_pipe);
                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:
        return ret;
 
+out_destroy_pipe:
+       rpc_destroy_pipe_data(bl_device_pipe);
 out_putrpc:
        rpc_put_mount();
 out_remove:
@@ -1074,7 +1081,8 @@ static void __exit nfs4blocklayout_exit(void)
               __func__);
 
        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();
 }
 
index e31a2df28e70aca040560b8d94403d85d67cd170..49c670b18a9e4d4ca7e928857221729e7f211a12 100644 (file)
@@ -161,7 +161,7 @@ struct bl_msg_hdr {
        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;
 
 #define BL_DEVICE_UMOUNT               0x0 /* Umount--delete devices */
index 81019190e46d80ccd43d50f659292842225c0909..949b62478799d6c4c7a159b2afe67a40433aa9a9 100644 (file)
@@ -146,7 +146,7 @@ nfs4_blk_decode_device(struct nfs_server *server,
 
        dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
        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) {
                remove_wait_queue(&bl_wq, &wq);
                rv = ERR_PTR(rc);
index 3c38244a87248e52169de269fed116d25a950c95..631f254d12abf85cd802faf55d13a72f999a28c6 100644 (file)
@@ -66,7 +66,7 @@ static void dev_remove(dev_t dev)
        msg.len = sizeof(bl_msg) + bl_msg.totallen;
 
        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);
                goto out;
        }
index 3c63c47c793d48df0a89788e75d85b53bad7ec80..2992cb854e12e1a6d843bafa23e145e50143d185 100644 (file)
@@ -410,7 +410,7 @@ struct idmap_hashtable {
 };
 
 struct idmap {
-       struct dentry           *idmap_dentry;
+       struct rpc_pipe         *idmap_pipe;
        wait_queue_head_t       idmap_wq;
        struct idmap_msg        idmap_im;
        struct mutex            idmap_lock;     /* Serializes upcalls */
@@ -435,6 +435,7 @@ int
 nfs_idmap_new(struct nfs_client *clp)
 {
        struct idmap *idmap;
+       struct rpc_pipe *pipe;
        int error;
 
        BUG_ON(clp->cl_idmap != NULL);
@@ -443,14 +444,23 @@ nfs_idmap_new(struct nfs_client *clp)
        if (idmap == NULL)
                return -ENOMEM;
 
-       idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_path.dentry,
-                       "idmap", idmap, &idmap_upcall_ops, 0);
-       if (IS_ERR(idmap->idmap_dentry)) {
-               error = PTR_ERR(idmap->idmap_dentry);
+       pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
+       if (IS_ERR(pipe)) {
+               error = PTR_ERR(pipe);
                kfree(idmap);
                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_im_lock);
        init_waitqueue_head(&idmap->idmap_wq);
@@ -468,7 +478,9 @@ nfs_idmap_delete(struct nfs_client *clp)
 
        if (!idmap)
                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;
        kfree(idmap);
 }
@@ -589,7 +601,7 @@ nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h,
        msg.len = sizeof(*im);
 
        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);
                goto out;
        }
@@ -650,7 +662,7 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h,
 
        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);
                goto out;
        }
index 3ebc257e2b43ec48d808f0161f28069dfeef3fb9..0d1f748f76dada94002831b127f2748b4a0fb920 100644 (file)
@@ -34,6 +34,7 @@ struct rpc_pipe {
        struct delayed_work queue_timeout;
        const struct rpc_pipe_ops *ops;
        spinlock_t lock;
+       struct dentry *dentry;
 };
 
 struct rpc_inode {
@@ -77,8 +78,10 @@ extern struct dentry *rpc_create_cache_dir(struct dentry *,
                                           struct cache_detail *);
 extern void rpc_remove_cache_dir(struct dentry *);
 
-extern struct dentry *rpc_mkpipe(struct dentry *, const char *, void *,
-                                const struct rpc_pipe_ops *, int flags);
+struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *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 struct vfsmount *rpc_get_mount(void);
 extern void rpc_put_mount(void);
index 304b8309f217856ff5946ff7f279be88869b224e..f684ce606667bf9697c872a0fc7ce57a97ce628e 100644 (file)
@@ -81,7 +81,7 @@ struct gss_auth {
         * mechanism (for example, "krb5") and exists for
         * 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. */
@@ -449,7 +449,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt,
                kfree(gss_msg);
                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);
        rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
        init_waitqueue_head(&gss_msg->waitqueue);
@@ -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
         * the new pipe first.
         */
-       gss_auth->dentry[1] = rpc_mkpipe(clnt->cl_path.dentry,
-                                        "gssd",
-                                        clnt, &gss_upcall_ops_v1,
-                                        RPC_PIPE_WAIT_FOR_OPEN);
-       if (IS_ERR(gss_auth->dentry[1])) {
-               err = PTR_ERR(gss_auth->dentry[1]);
+       gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1,
+                                           RPC_PIPE_WAIT_FOR_OPEN);
+       if (IS_ERR(gss_auth->pipe[1])) {
+               err = PTR_ERR(gss_auth->pipe[1]);
                goto err_put_mech;
        }
 
-       gss_auth->dentry[0] = rpc_mkpipe(clnt->cl_path.dentry,
-                                        gss_auth->mech->gm_name,
-                                        clnt, &gss_upcall_ops_v0,
-                                        RPC_PIPE_WAIT_FOR_OPEN);
-       if (IS_ERR(gss_auth->dentry[0])) {
-               err = PTR_ERR(gss_auth->dentry[0]);
+       gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0,
+                                           RPC_PIPE_WAIT_FOR_OPEN);
+       if (IS_ERR(gss_auth->pipe[0])) {
+               err = PTR_ERR(gss_auth->pipe[0]);
+               goto err_destroy_pipe_1;
+       }
+
+       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;
        }
        err = rpcauth_init_credcache(auth);
@@ -822,9 +834,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 
        return auth;
 err_unlink_pipe_0:
-       rpc_unlink(gss_auth->dentry[0]);
+       rpc_unlink(gss_auth->pipe[0]->dentry);
 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:
        gss_mech_put(gss_auth->mech);
 err_free:
@@ -837,8 +853,10 @@ out_dec:
 static void
 gss_free(struct gss_auth *gss_auth)
 {
-       rpc_unlink(gss_auth->dentry[1]);
-       rpc_unlink(gss_auth->dentry[0]);
+       rpc_unlink(gss_auth->pipe[0]->dentry);
+       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);
 
        kfree(gss_auth);
index 4093da79d5123c5e643456f54524759d22fd0496..6dd8b96e8df75e7c75c9571c017b22e15507d513 100644 (file)
@@ -206,7 +206,6 @@ static void
 rpc_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       kfree(RPC_I(inode)->pipe);
        kmem_cache_free(rpc_inode_cachep, RPC_I(inode));
 }
 
@@ -575,34 +574,44 @@ init_pipe(struct rpc_pipe *pipe)
                            rpc_timeout_upcall_queue);
        pipe->ops = NULL;
        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,
-                       umode_t mode,
-                       const struct file_operations *i_fop,
-                       void *private,
-                       const struct rpc_pipe_ops *ops,
-                       int flags)
+struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags)
 {
        struct rpc_pipe *pipe;
-       struct rpc_inode *rpci;
-       int err;
 
        pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL);
        if (!pipe)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
        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);
-       if (err) {
-               kfree(pipe);
+       if (err)
                return err;
-       }
        rpci = RPC_I(dentry->d_inode);
        rpci->private = private;
        rpci->pipe = pipe;
-       rpci->pipe->flags = flags;
-       rpci->pipe->ops = ops;
        fsnotify_create(dir, dentry);
        return 0;
 }
@@ -819,9 +828,8 @@ static int rpc_rmdir_depopulate(struct dentry *dentry,
  * 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.
  */
-struct dentry *rpc_mkpipe(struct dentry *parent, const char *name,
-                         void *private, const struct rpc_pipe_ops *ops,
-                         int flags)
+struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
+                                void *private, struct rpc_pipe *pipe)
 {
        struct dentry *dentry;
        struct inode *dir = parent->d_inode;
@@ -829,9 +837,9 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name,
        struct qstr q;
        int err;
 
-       if (ops->upcall == NULL)
+       if (pipe->ops->upcall == NULL)
                umode &= ~S_IRUGO;
-       if (ops->downcall == NULL)
+       if (pipe->ops->downcall == NULL)
                umode &= ~S_IWUGO;
 
        q.name = name;
@@ -842,8 +850,8 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name,
        dentry = __rpc_lookup_create_exclusive(parent, &q);
        if (IS_ERR(dentry))
                goto out;
-       err = __rpc_mkpipe(dir, dentry, umode, &rpc_pipe_fops,
-                          private, ops, flags);
+       err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
+                                 private, pipe);
        if (err)
                goto out_err;
 out:
@@ -856,7 +864,7 @@ out_err:
                        err);
        goto out;
 }
-EXPORT_SYMBOL_GPL(rpc_mkpipe);
+EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
 
 /**
  * rpc_unlink - remove a pipe