Commit c2f2ea78 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4/RPCSEC_GSS: Make Frank's server->client_sys feature use

RPC cloning in order to avoid duplicating sockets etc. Make
NFSv4 share a single socket for all communication to the same
server.
parent 8d51075e
...@@ -493,10 +493,17 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) ...@@ -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); server->client = nfs_create_client(server, data);
if (server->client == NULL) if (server->client == NULL)
goto out_fail; goto out_fail;
data->pseudoflavor = RPC_AUTH_UNIX; /* RFC 2623, sec 2.3.2 */ /* RFC 2623, sec 2.3.2 */
server->client_sys = nfs_create_client(server, data); if (authflavor != RPC_AUTH_UNIX) {
server->client_sys = rpc_clone_client(server->client);
if (server->client_sys == NULL) if (server->client_sys == NULL)
goto out_shutdown; 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 */ /* Fire up rpciod if not yet running */
if (rpciod_up() != 0) { if (rpciod_up() != 0) {
...@@ -1349,6 +1356,7 @@ static struct file_system_type nfs_fs_type = { ...@@ -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) static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
{ {
struct nfs_server *server; struct nfs_server *server;
struct nfs4_client *clp = NULL;
struct rpc_xprt *xprt = NULL; struct rpc_xprt *xprt = NULL;
struct rpc_clnt *clnt = NULL; struct rpc_clnt *clnt = NULL;
struct rpc_timeout timeparms; struct rpc_timeout timeparms;
...@@ -1398,13 +1406,13 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, ...@@ -1398,13 +1406,13 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
return -EINVAL; return -EINVAL;
} }
/* Now create transport and client */ clp = nfs4_get_client(&server->addr.sin_addr);
xprt = xprt_create_proto(proto, &server->addr, &timeparms); if (!clp) {
if (xprt == NULL) { printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
goto out_fail; goto out_fail;
} }
/* Now create transport and client */
authflavour = RPC_AUTH_UNIX; authflavour = RPC_AUTH_UNIX;
if (data->auth_flavourlen != 0) { if (data->auth_flavourlen != 0) {
if (data->auth_flavourlen > 1) if (data->auth_flavourlen > 1)
...@@ -1414,34 +1422,61 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, ...@@ -1414,34 +1422,61 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
goto out_fail; goto out_fail;
} }
} }
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, clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
server->rpc_ops->version, authflavour); server->rpc_ops->version, authflavour);
if (clnt == NULL) { if (clnt == NULL) {
up_write(&clp->cl_sem);
printk(KERN_WARNING "NFS: cannot create RPC client.\n"); printk(KERN_WARNING "NFS: cannot create RPC client.\n");
xprt_destroy(xprt); xprt_destroy(xprt);
goto out_fail; 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");
goto out_fail;
}
clnt->cl_intr = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0; clnt->cl_intr = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0; clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
clnt->cl_chatty = 1;
server->client = clnt; 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 */ /* Fire up rpciod if not yet running */
if (rpciod_up() != 0) { if (rpciod_up() != 0) {
printk(KERN_WARNING "NFS: couldn't start rpciod!\n"); printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
goto out_shutdown; goto out_shutdown;
} }
if (create_nfsv4_state(server, data))
goto out_shutdown;
if ((server->idmap = nfs_idmap_new(server)) == NULL) if ((server->idmap = nfs_idmap_new(server)) == NULL)
printk(KERN_WARNING "NFS: couldn't start IDmap\n"); printk(KERN_WARNING "NFS: couldn't start IDmap\n");
err = nfs_sb_init(sb, authflavour); err = nfs_sb_init(sb, authflavour);
if (err == 0) if (err == 0)
return 0; return 0;
clp = NULL;
rpciod_down(); rpciod_down();
destroy_nfsv4_state(server); destroy_nfsv4_state(server);
if (server->idmap != NULL) if (server->idmap != NULL)
...@@ -1449,6 +1484,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, ...@@ -1449,6 +1484,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
out_shutdown: out_shutdown:
rpc_shutdown_client(server->client); rpc_shutdown_client(server->client);
out_fail: out_fail:
if (clp)
nfs4_put_client(clp);
return err; return err;
} }
......
...@@ -762,9 +762,7 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -762,9 +762,7 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
struct qstr q; struct qstr q;
int status; int status;
clp = server->nfs4_state = nfs4_get_client(&server->addr.sin_addr); clp = server->nfs4_state;
if (!clp)
return -ENOMEM;
down_write(&clp->cl_sem); down_write(&clp->cl_sem);
/* Has the clientid already been initialized? */ /* Has the clientid already been initialized? */
...@@ -850,8 +848,6 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -850,8 +848,6 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
return status; return status;
out_unlock: out_unlock:
up_write(&clp->cl_sem); up_write(&clp->cl_sem);
nfs4_put_client(clp);
server->nfs4_state = NULL;
return status; return status;
} }
......
...@@ -93,6 +93,10 @@ nfs4_free_client(struct nfs4_client *clp) ...@@ -93,6 +93,10 @@ nfs4_free_client(struct nfs4_client *clp)
kfree(sp); kfree(sp);
} }
BUG_ON(!list_empty(&clp->cl_state_owners)); 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); kfree(clp);
} }
......
...@@ -489,6 +489,14 @@ struct nfs4_client { ...@@ -489,6 +489,14 @@ struct nfs4_client {
int cl_nunused; int cl_nunused;
spinlock_t cl_lock; spinlock_t cl_lock;
atomic_t cl_count; 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); ...@@ -558,13 +566,6 @@ extern void nfs4_increment_seqid(u32 status, struct nfs4_state_owner *sp);
struct nfs4_mount_data; 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 static inline void
destroy_nfsv4_state(struct nfs_server *server) destroy_nfsv4_state(struct nfs_server *server)
{ {
......
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