NFS: Create a submount rpc_op
authorBryan Schumaker <bjschuma@netapp.com>
Fri, 27 Apr 2012 17:27:45 +0000 (13:27 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 27 Apr 2012 18:10:39 +0000 (14:10 -0400)
This simplifies the code for v2 and v3 and gives v4 a chance to decide
on referrals without needing to modify the generic client.

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/proc.c
include/linux/nfs_xdr.h

index d6994443f28553d8c0c1304c8bfa17dc534fd1cc..0fd1efaf1cff14c03e679e946b1675528daad9a8 100644 (file)
@@ -185,17 +185,6 @@ static inline void nfs_fs_proc_exit(void)
 }
 #endif
 
-/* nfs4namespace.c */
-#ifdef CONFIG_NFS_V4
-extern struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry);
-#else
-static inline
-struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
-{
-       return ERR_PTR(-ENOENT);
-}
-#endif
-
 /* callback_xdr.c */
 extern struct svc_version nfs4_callback_version1;
 extern struct svc_version nfs4_callback_version4;
@@ -286,6 +275,10 @@ extern void nfs_sb_deactive(struct super_block *sb);
 extern char *nfs_path(char **p, struct dentry *dentry,
                      char *buffer, ssize_t buflen);
 extern struct vfsmount *nfs_d_automount(struct path *path);
+struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,
+                             struct nfs_fh *, struct nfs_fattr *);
+struct vfsmount *nfs_do_submount(struct dentry *, struct nfs_fh *,
+                                struct nfs_fattr *, rpc_authflavor_t);
 
 /* getroot.c */
 extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
index 2a9591b0b1501ea23329d7a1493a3e0234aaa710..e36fd8a518196eb95a31fcbad97b76f88a008a05 100644 (file)
@@ -26,11 +26,6 @@ static LIST_HEAD(nfs_automount_list);
 static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
 int nfs_mountpoint_expiry_timeout = 500 * HZ;
 
-static struct vfsmount *nfs_do_submount(struct dentry *dentry,
-                                       struct nfs_fh *fh,
-                                       struct nfs_fattr *fattr,
-                                       rpc_authflavor_t authflavor);
-
 /*
  * nfs_path - reconstruct the path given an arbitrary dentry
  * @base - used to return pointer to the end of devname part of path
@@ -118,35 +113,6 @@ Elong:
        return ERR_PTR(-ENAMETOOLONG);
 }
 
-#ifdef CONFIG_NFS_V4
-static struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
-                                             struct qstr *name,
-                                             struct nfs_fh *fh,
-                                             struct nfs_fattr *fattr)
-{
-       int err;
-
-       if (NFS_PROTO(dir)->version == 4)
-               return nfs4_proc_lookup_mountpoint(dir, name, fh, fattr);
-
-       err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
-       if (err)
-               return ERR_PTR(err);
-       return rpc_clone_client(NFS_SERVER(dir)->client);
-}
-#else /* CONFIG_NFS_V4 */
-static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
-                                                    struct qstr *name,
-                                                    struct nfs_fh *fh,
-                                                    struct nfs_fattr *fattr)
-{
-       int err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
-       if (err)
-               return ERR_PTR(err);
-       return rpc_clone_client(NFS_SERVER(dir)->client);
-}
-#endif /* CONFIG_NFS_V4 */
-
 /*
  * nfs_d_automount - Handle crossing a mountpoint on the server
  * @path - The mountpoint
@@ -162,10 +128,9 @@ static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
 struct vfsmount *nfs_d_automount(struct path *path)
 {
        struct vfsmount *mnt;
-       struct dentry *parent;
+       struct nfs_server *server = NFS_SERVER(path->dentry->d_inode);
        struct nfs_fh *fh = NULL;
        struct nfs_fattr *fattr = NULL;
-       struct rpc_clnt *client;
 
        dprintk("--> nfs_d_automount()\n");
 
@@ -181,21 +146,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
 
        dprintk("%s: enter\n", __func__);
 
-       /* Look it up again to get its attributes */
-       parent = dget_parent(path->dentry);
-       client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr);
-       dput(parent);
-       if (IS_ERR(client)) {
-               mnt = ERR_CAST(client);
-               goto out;
-       }
-
-       if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
-               mnt = nfs_do_refmount(client, path->dentry);
-       else
-               mnt = nfs_do_submount(path->dentry, fh, fattr, client->cl_auth->au_flavor);
-       rpc_shutdown_client(client);
-
+       mnt = server->nfs_client->rpc_ops->submount(server, path->dentry, fh, fattr);
        if (IS_ERR(mnt))
                goto out;
 
@@ -268,10 +219,8 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
  * @authflavor - security flavor to use when performing the mount
  *
  */
-static struct vfsmount *nfs_do_submount(struct dentry *dentry,
-                                       struct nfs_fh *fh,
-                                       struct nfs_fattr *fattr,
-                                       rpc_authflavor_t authflavor)
+struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
+                                struct nfs_fattr *fattr, rpc_authflavor_t authflavor)
 {
        struct nfs_clone_mount mountdata = {
                .sb = dentry->d_sb,
@@ -304,3 +253,19 @@ out:
        dprintk("<-- nfs_do_submount() = %p\n", mnt);
        return mnt;
 }
+
+struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry,
+                             struct nfs_fh *fh, struct nfs_fattr *fattr)
+{
+       int err;
+       struct dentry *parent = dget_parent(dentry);
+
+       /* Look it up again to get its attributes */
+       err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode,
+                                                 &dentry->d_name, fh, fattr);
+       dput(parent);
+       if (err != 0)
+               return ERR_PTR(err);
+
+       return nfs_do_submount(dentry, fh, fattr, server->client->cl_auth->au_flavor);
+}
index 56dcefc2f3f71628bf3e80d908c762f113e75416..c23214d55ecfd51f2ca54cf5dbc2e022c0cb1b9c 100644 (file)
@@ -885,6 +885,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .file_inode_ops = &nfs3_file_inode_operations,
        .file_ops       = &nfs_file_operations,
        .getroot        = nfs3_proc_get_root,
+       .submount       = nfs_submount,
        .getattr        = nfs3_proc_getattr,
        .setattr        = nfs3_proc_setattr,
        .lookup         = nfs3_proc_lookup,
index 53a487ee9867ad1fa7b6e90cfdfa4791904e59e0..97365b0f9d3f340494e5cf23f82e2a6608e9b12d 100644 (file)
@@ -208,6 +208,8 @@ extern const struct inode_operations nfs4_dir_inode_operations;
 /* nfs4namespace.c */
 rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
 struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *);
+struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *,
+                              struct nfs_fh *, struct nfs_fattr *);
 
 /* nfs4proc.c */
 extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
index a69ee3952bbe8a9a7f6328560533b7f7f0efb8a2..80fc0fe7095e4e149396310cf1218ef91f9826de 100644 (file)
@@ -329,7 +329,7 @@ out:
  * @dentry - dentry of referral
  *
  */
-struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
+static struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
 {
        struct vfsmount *mnt = ERR_PTR(-ENOMEM);
        struct dentry *parent;
@@ -370,3 +370,25 @@ out:
        dprintk("%s: done\n", __func__);
        return mnt;
 }
+
+struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry,
+                              struct nfs_fh *fh, struct nfs_fattr *fattr)
+{
+       struct dentry *parent = dget_parent(dentry);
+       struct rpc_clnt *client;
+       struct vfsmount *mnt;
+
+       /* Look it up again to get its attributes and sec flavor */
+       client = nfs4_proc_lookup_mountpoint(parent->d_inode, &dentry->d_name, fh, fattr);
+       dput(parent);
+       if (IS_ERR(client))
+               return ERR_CAST(client);
+
+       if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
+               mnt = nfs_do_refmount(client, dentry);
+       else
+               mnt = nfs_do_submount(dentry, fh, fattr, client->cl_auth->au_flavor);
+
+       rpc_shutdown_client(client);
+       return mnt;
+}
index fa661b91e57cfd23e0ea03e4d50025209ca6c7c1..2091af294c61b5223c4d20ca9f2e2459ca8d52bd 100644 (file)
@@ -6571,6 +6571,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .file_inode_ops = &nfs4_file_inode_operations,
        .file_ops       = &nfs4_file_operations,
        .getroot        = nfs4_proc_get_root,
+       .submount       = nfs4_submount,
        .getattr        = nfs4_proc_getattr,
        .setattr        = nfs4_proc_setattr,
        .lookup         = nfs4_proc_lookup,
index 22ee70586875adf7ff0313e5c3541581e222f1b5..76b3229fc527ec86b2bcc5a349502ef11e5afbaf 100644 (file)
@@ -742,6 +742,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
        .file_inode_ops = &nfs_file_inode_operations,
        .file_ops       = &nfs_file_operations,
        .getroot        = nfs_proc_get_root,
+       .submount       = nfs_submount,
        .getattr        = nfs_proc_getattr,
        .setattr        = nfs_proc_setattr,
        .lookup         = nfs_proc_lookup,
index eb1f143042f415b197cb57104758c026b026dace..4dada94eba7d1b71b838d0b82a93580323d5c5de 100644 (file)
@@ -1341,6 +1341,8 @@ struct nfs_rpc_ops {
 
        int     (*getroot) (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fsinfo *);
+       struct vfsmount *(*submount) (struct nfs_server *, struct dentry *,
+                                     struct nfs_fh *, struct nfs_fattr *);
        int     (*getattr) (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fattr *);
        int     (*setattr) (struct dentry *, struct nfs_fattr *,