Commit 294ac32e authored by Jeff Layton's avatar Jeff Layton Committed by J. Bruce Fields

nfsd: protect clid and verifier generation with client_lock

The clid counter is a global counter currently. Move it to be a per-net
property so that it can be properly protected by the nn->client_lock
instead of relying on the client_mutex.

The verifier generator is also potentially racy if there are two
simultaneous callers. Generate the verifier when we generate the clid
value, so it's also created under the client_lock. With this, there's
no need to keep two counters as they'd always be in sync anyway, so
just use the clientid_counter for both.

As Trond points out, what would be best is to eventually move this
code to use IDR instead of the hash tables. That would also help ensure
uniqueness, but that's probably best done as a separate project.
Signed-off-by: default avatarJeff Layton <jlayton@primarydata.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent fd699b8a
...@@ -92,9 +92,7 @@ struct nfsd_net { ...@@ -92,9 +92,7 @@ struct nfsd_net {
bool nfsd_net_up; bool nfsd_net_up;
bool lockd_up; bool lockd_up;
/* /* Time of server startup */
* Time of server startup
*/
struct timeval nfssvc_boot; struct timeval nfssvc_boot;
/* /*
...@@ -103,6 +101,8 @@ struct nfsd_net { ...@@ -103,6 +101,8 @@ struct nfsd_net {
*/ */
unsigned int max_connections; unsigned int max_connections;
u32 clientid_counter;
struct svc_serv *nfsd_serv; struct svc_serv *nfsd_serv;
}; };
......
...@@ -1812,28 +1812,26 @@ static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp) ...@@ -1812,28 +1812,26 @@ static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal); return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal);
} }
static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn) static void gen_confirm(struct nfs4_client *clp, struct nfsd_net *nn)
{
static u32 current_clientid = 1;
clp->cl_clientid.cl_boot = nn->boot_time;
clp->cl_clientid.cl_id = current_clientid++;
}
static void gen_confirm(struct nfs4_client *clp)
{ {
__be32 verf[2]; __be32 verf[2];
static u32 i;
/* /*
* This is opaque to client, so no need to byte-swap. Use * This is opaque to client, so no need to byte-swap. Use
* __force to keep sparse happy * __force to keep sparse happy
*/ */
verf[0] = (__force __be32)get_seconds(); verf[0] = (__force __be32)get_seconds();
verf[1] = (__force __be32)i++; verf[1] = (__force __be32)nn->clientid_counter;
memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data)); memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data));
} }
static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
{
clp->cl_clientid.cl_boot = nn->boot_time;
clp->cl_clientid.cl_id = nn->clientid_counter++;
gen_confirm(clp, nn);
}
static struct nfs4_stid * static struct nfs4_stid *
find_stateid_locked(struct nfs4_client *cl, stateid_t *t) find_stateid_locked(struct nfs4_client *cl, stateid_t *t)
{ {
...@@ -1884,7 +1882,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name, ...@@ -1884,7 +1882,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
clear_bit(0, &clp->cl_cb_slot_busy); clear_bit(0, &clp->cl_cb_slot_busy);
copy_verf(clp, verf); copy_verf(clp, verf);
rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa); rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
gen_confirm(clp);
clp->cl_cb_session = NULL; clp->cl_cb_session = NULL;
clp->net = net; clp->net = net;
return clp; return clp;
......
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