]> git.hungrycats.org Git - linux/commitdiff
NFSv4/RPCSEC_GSS: Make Frank's server->client_sys feature use
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 7 Feb 2004 15:50:51 +0000 (16:50 +0100)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 7 Feb 2004 15:50:51 +0000 (16:50 +0100)
RPC cloning in order to avoid duplicating sockets etc. Make
NFSv4 share a single socket for all communication to the same
server.

fs/nfs/inode.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
include/linux/nfs_fs.h

index af022760107a6ecea244bf1d48019c1f92449c77..5cd28cb5076a04ab0268676f2285c181cb43718f 100644 (file)
@@ -493,10 +493,17 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
        server->client = nfs_create_client(server, data);
        if (server->client == NULL)
                goto out_fail;
-       data->pseudoflavor = RPC_AUTH_UNIX;     /* RFC 2623, sec 2.3.2 */
-       server->client_sys = nfs_create_client(server, data);
-       if (server->client_sys == NULL)
-               goto out_shutdown;
+       /* RFC 2623, sec 2.3.2 */
+       if (authflavor != RPC_AUTH_UNIX) {
+               server->client_sys = rpc_clone_client(server->client);
+               if (server->client_sys == NULL)
+                       goto out_shutdown;
+               if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys))
+                       goto out_shutdown;
+       } else {
+               atomic_inc(&server->client->cl_count);
+               server->client_sys = server->client;
+       }
 
        /* Fire up rpciod if not yet running */
        if (rpciod_up() != 0) {
@@ -1349,6 +1356,7 @@ static struct file_system_type nfs_fs_type = {
 static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
 {
        struct nfs_server *server;
+       struct nfs4_client *clp = NULL;
        struct rpc_xprt *xprt = NULL;
        struct rpc_clnt *clnt = NULL;
        struct rpc_timeout timeparms;
@@ -1398,13 +1406,13 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
                return -EINVAL;
        }
 
-       /* Now create transport and client */
-       xprt = xprt_create_proto(proto, &server->addr, &timeparms);
-       if (xprt == NULL) {
-               printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
+       clp = nfs4_get_client(&server->addr.sin_addr);
+       if (!clp) {
+               printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
                goto out_fail;
        }
 
+       /* Now create transport and client */
        authflavour = RPC_AUTH_UNIX;
        if (data->auth_flavourlen != 0) {
                if (data->auth_flavourlen > 1)
@@ -1414,34 +1422,61 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
                        goto out_fail;
                }
        }
-       clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
-                                server->rpc_ops->version, authflavour);
+
+       down_write(&clp->cl_sem);
+       if (clp->cl_rpcclient == NULL) {
+               xprt = xprt_create_proto(proto, &server->addr, &timeparms);
+               if (xprt == NULL) {
+                       up_write(&clp->cl_sem);
+                       printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
+                       goto out_fail;
+               }
+               clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
+                               server->rpc_ops->version, authflavour);
+               if (clnt == NULL) {
+                       up_write(&clp->cl_sem);
+                       printk(KERN_WARNING "NFS: cannot create RPC client.\n");
+                       xprt_destroy(xprt);
+                       goto out_fail;
+               }
+               clnt->cl_chatty   = 1;
+               clp->cl_rpcclient = clnt;
+               clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0);
+               memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
+       }
+       clnt = rpc_clone_client(clp->cl_rpcclient);
+       server->nfs4_state = clp;
+       up_write(&clp->cl_sem);
+
        if (clnt == NULL) {
                printk(KERN_WARNING "NFS: cannot create RPC client.\n");
-               xprt_destroy(xprt);
                goto out_fail;
        }
 
        clnt->cl_intr     = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
        clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
-       clnt->cl_chatty   = 1;
        server->client    = clnt;
 
+       if (clnt->cl_auth->au_flavor != authflavour) {
+               if (rpcauth_create(authflavour, clnt) == NULL) {
+                       printk(KERN_WARNING "NFS: couldn't create credcache!\n");
+                       goto out_shutdown;
+               }
+       }
+
        /* Fire up rpciod if not yet running */
        if (rpciod_up() != 0) {
                printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
                goto out_shutdown;
        }
 
-       if (create_nfsv4_state(server, data))
-               goto out_shutdown;
-
        if ((server->idmap = nfs_idmap_new(server)) == NULL)
                printk(KERN_WARNING "NFS: couldn't start IDmap\n");
 
        err = nfs_sb_init(sb, authflavour);
        if (err == 0)
                return 0;
+       clp = NULL;
        rpciod_down();
        destroy_nfsv4_state(server);
        if (server->idmap != NULL)
@@ -1449,6 +1484,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
 out_shutdown:
        rpc_shutdown_client(server->client);
 out_fail:
+       if (clp)
+               nfs4_put_client(clp);
        return err;
 }
 
index f447a7a0544949d7aead405e2ffe2fa2c2c9ab4c..2d6850d65dd3345109ac2e0ea14d1738bf5a3c0c 100644 (file)
@@ -762,9 +762,7 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
        struct qstr             q;
        int                     status;
 
-       clp = server->nfs4_state = nfs4_get_client(&server->addr.sin_addr);
-       if (!clp)
-               return -ENOMEM;
+       clp = server->nfs4_state;
 
        down_write(&clp->cl_sem);
        /* Has the clientid already been initialized? */
@@ -850,8 +848,6 @@ no_setclientid:
        return status;
 out_unlock:
        up_write(&clp->cl_sem);
-       nfs4_put_client(clp);
-       server->nfs4_state = NULL;
        return status;
 }
 
index 42a2344a28935e102e144da2850bb3c273932f49..960899db68e2b705a951a41dfe0c18c370f54213 100644 (file)
@@ -93,6 +93,10 @@ nfs4_free_client(struct nfs4_client *clp)
                kfree(sp);
        }
        BUG_ON(!list_empty(&clp->cl_state_owners));
+       if (clp->cl_cred)
+               put_rpccred(clp->cl_cred);
+       if (clp->cl_rpcclient)
+               rpc_shutdown_client(clp->cl_rpcclient);
        kfree(clp);
 }
 
index 5ae592b26d632e0402453eeb57723d3e2956b801..1ba07430279605a85c900bcf954b9fac674f8540 100644 (file)
@@ -489,6 +489,14 @@ struct nfs4_client {
        int                     cl_nunused;
        spinlock_t              cl_lock;
        atomic_t                cl_count;
+
+       struct rpc_clnt *       cl_rpcclient;
+       struct rpc_cred *       cl_cred;
+
+       /* Our own IP address, as a null-terminated string.
+        * This is used to generate the clientid, and the callback address.
+        */
+       char                    cl_ipaddr[16];
 };
 
 /*
@@ -558,13 +566,6 @@ extern void nfs4_increment_seqid(u32 status, struct nfs4_state_owner *sp);
 
 
 struct nfs4_mount_data;
-static inline int
-create_nfsv4_state(struct nfs_server *server, struct nfs4_mount_data *data)
-{
-       server->nfs4_state = NULL;
-       return 0;
-}
-
 static inline void
 destroy_nfsv4_state(struct nfs_server *server)
 {