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

nfsd: convert nfs4_client->cl_cb_flags to a generic flags field

We'll need a way to flag the nfs4_client as already being recorded on
stable storage so that we don't continually upcall. Currently, that's
recorded in the cl_firststate field of the client struct. Using an
entire u32 to store a flag is rather wasteful though.

The cl_cb_flags field is only using 2 bits right now, so repurpose that
to a generic flags field. Rename NFSD4_CLIENT_KILL to
NFSD4_CLIENT_CB_KILL to make it evident that it's part of the callback
flags. Add a mask that we can use for existing checks that look to see
whether any flags are set, so that the new flags don't interfere.

Convert all references to cl_firstate to the NFSD4_CLIENT_STABLE flag,
and add a new NFSD4_CLIENT_RECLAIM_COMPLETE flag.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 1df00640
...@@ -754,9 +754,9 @@ static void do_probe_callback(struct nfs4_client *clp) ...@@ -754,9 +754,9 @@ static void do_probe_callback(struct nfs4_client *clp)
*/ */
void nfsd4_probe_callback(struct nfs4_client *clp) void nfsd4_probe_callback(struct nfs4_client *clp)
{ {
/* XXX: atomicity? Also, should we be using cl_cb_flags? */ /* XXX: atomicity? Also, should we be using cl_flags? */
clp->cl_cb_state = NFSD4_CB_UNKNOWN; clp->cl_cb_state = NFSD4_CB_UNKNOWN;
set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
do_probe_callback(clp); do_probe_callback(clp);
} }
...@@ -915,7 +915,7 @@ void nfsd4_destroy_callback_queue(void) ...@@ -915,7 +915,7 @@ void nfsd4_destroy_callback_queue(void)
/* must be called under the state lock */ /* must be called under the state lock */
void nfsd4_shutdown_callback(struct nfs4_client *clp) void nfsd4_shutdown_callback(struct nfs4_client *clp)
{ {
set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags); set_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags);
/* /*
* Note this won't actually result in a null callback; * Note this won't actually result in a null callback;
* instead, nfsd4_do_callback_rpc() will detect the killed * instead, nfsd4_do_callback_rpc() will detect the killed
...@@ -966,15 +966,15 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb) ...@@ -966,15 +966,15 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
svc_xprt_put(clp->cl_cb_conn.cb_xprt); svc_xprt_put(clp->cl_cb_conn.cb_xprt);
clp->cl_cb_conn.cb_xprt = NULL; clp->cl_cb_conn.cb_xprt = NULL;
} }
if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags)) if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags))
return; return;
spin_lock(&clp->cl_lock); spin_lock(&clp->cl_lock);
/* /*
* Only serialized callback code is allowed to clear these * Only serialized callback code is allowed to clear these
* flags; main nfsd code can only set them: * flags; main nfsd code can only set them:
*/ */
BUG_ON(!clp->cl_cb_flags); BUG_ON(!(clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK));
clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn)); memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
c = __nfsd4_find_backchannel(clp); c = __nfsd4_find_backchannel(clp);
if (c) { if (c) {
...@@ -1000,7 +1000,7 @@ void nfsd4_do_callback_rpc(struct work_struct *w) ...@@ -1000,7 +1000,7 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
struct nfs4_client *clp = cb->cb_clp; struct nfs4_client *clp = cb->cb_clp;
struct rpc_clnt *clnt; struct rpc_clnt *clnt;
if (clp->cl_cb_flags) if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)
nfsd4_process_cb_update(cb); nfsd4_process_cb_update(cb);
clnt = clp->cl_cb_client; clnt = clp->cl_cb_client;
......
...@@ -319,7 +319,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -319,7 +319,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
* Before RECLAIM_COMPLETE done, server should deny new lock * Before RECLAIM_COMPLETE done, server should deny new lock
*/ */
if (nfsd4_has_session(cstate) && if (nfsd4_has_session(cstate) &&
!cstate->session->se_client->cl_firststate && !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
&cstate->session->se_client->cl_flags) &&
open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
return nfserr_grace; return nfserr_grace;
......
...@@ -126,9 +126,8 @@ void nfsd4_create_clid_dir(struct nfs4_client *clp) ...@@ -126,9 +126,8 @@ void nfsd4_create_clid_dir(struct nfs4_client *clp)
dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
if (clp->cl_firststate) if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
return; return;
clp->cl_firststate = 1;
if (!rec_file) if (!rec_file)
return; return;
status = nfs4_save_creds(&original_cred); status = nfs4_save_creds(&original_cred);
...@@ -271,13 +270,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) ...@@ -271,13 +270,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
const struct cred *original_cred; const struct cred *original_cred;
int status; int status;
if (!rec_file || !clp->cl_firststate) if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
return; return;
status = mnt_want_write_file(rec_file); status = mnt_want_write_file(rec_file);
if (status) if (status)
goto out; goto out;
clp->cl_firststate = 0; clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
status = nfs4_save_creds(&original_cred); status = nfs4_save_creds(&original_cred);
if (status < 0) if (status < 0)
......
...@@ -2069,7 +2069,8 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta ...@@ -2069,7 +2069,8 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
nfs4_lock_state(); nfs4_lock_state();
status = nfserr_complete_already; status = nfserr_complete_already;
if (cstate->session->se_client->cl_firststate) if (test_and_set_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
&cstate->session->se_client->cl_flags))
goto out; goto out;
status = nfserr_stale_clientid; status = nfserr_stale_clientid;
...@@ -2816,12 +2817,6 @@ static void ...@@ -2816,12 +2817,6 @@ static void
nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session) nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session)
{ {
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
/*
* On a 4.1+ client, we don't create a state record for a client
* until it performs RECLAIM_COMPLETE:
*/
if (!has_session)
open->op_openowner->oo_owner.so_client->cl_firststate = 1;
} }
/* Should we give out recallable state?: */ /* Should we give out recallable state?: */
...@@ -4462,7 +4457,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id) ...@@ -4462,7 +4457,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
clp = find_confirmed_client_by_str(name, strhashval); clp = find_confirmed_client_by_str(name, strhashval);
if (!clp) if (!clp)
return 0; return 0;
return clp->cl_firststate; return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
} }
/* /*
...@@ -4507,18 +4502,11 @@ nfs4_release_reclaim(void) ...@@ -4507,18 +4502,11 @@ nfs4_release_reclaim(void)
/* /*
* called from OPEN, CLAIM_PREVIOUS with a new clientid. */ * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
static struct nfs4_client_reclaim * static struct nfs4_client_reclaim *
nfs4_find_reclaim_client(clientid_t *clid) nfsd4_find_reclaim_client(struct nfs4_client *clp)
{ {
unsigned int strhashval; unsigned int strhashval;
struct nfs4_client *clp;
struct nfs4_client_reclaim *crp = NULL; struct nfs4_client_reclaim *crp = NULL;
/* find clientid in conf_id_hashtbl */
clp = find_confirmed_client(clid);
if (clp == NULL)
return NULL;
dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n", dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
clp->cl_name.len, clp->cl_name.data, clp->cl_name.len, clp->cl_name.data,
clp->cl_recdir); clp->cl_recdir);
...@@ -4533,13 +4521,36 @@ nfs4_find_reclaim_client(clientid_t *clid) ...@@ -4533,13 +4521,36 @@ nfs4_find_reclaim_client(clientid_t *clid)
return NULL; return NULL;
} }
static int
nfsd4_client_record_check(struct nfs4_client *clp)
{
/* did we already find that this client is stable? */
if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
return 0;
/* look for it in the reclaim hashtable otherwise */
if (nfsd4_find_reclaim_client(clp)) {
set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
return 0;
}
return -ENOENT;
}
/* /*
* Called from OPEN. Look for clientid in reclaim list. * Called from OPEN. Look for clientid in reclaim list.
*/ */
__be32 __be32
nfs4_check_open_reclaim(clientid_t *clid) nfs4_check_open_reclaim(clientid_t *clid)
{ {
return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad; struct nfs4_client *clp;
/* find clientid in conf_id_hashtbl */
clp = find_confirmed_client(clid);
if (clp == NULL)
return nfserr_reclaim_bad;
return nfsd4_client_record_check(clp) ? nfserr_reclaim_bad : nfs_ok;
} }
#ifdef CONFIG_NFSD_FAULT_INJECTION #ifdef CONFIG_NFSD_FAULT_INJECTION
......
...@@ -236,14 +236,17 @@ struct nfs4_client { ...@@ -236,14 +236,17 @@ struct nfs4_client {
struct svc_cred cl_cred; /* setclientid principal */ struct svc_cred cl_cred; /* setclientid principal */
clientid_t cl_clientid; /* generated by server */ clientid_t cl_clientid; /* generated by server */
nfs4_verifier cl_confirm; /* generated by server */ nfs4_verifier cl_confirm; /* generated by server */
u32 cl_firststate; /* recovery dir creation */
u32 cl_minorversion; u32 cl_minorversion;
/* for v4.0 and v4.1 callbacks: */ /* for v4.0 and v4.1 callbacks: */
struct nfs4_cb_conn cl_cb_conn; struct nfs4_cb_conn cl_cb_conn;
#define NFSD4_CLIENT_CB_UPDATE 1 #define NFSD4_CLIENT_CB_UPDATE (0)
#define NFSD4_CLIENT_KILL 2 #define NFSD4_CLIENT_CB_KILL (1)
unsigned long cl_cb_flags; #define NFSD4_CLIENT_STABLE (2) /* client on stable storage */
#define NFSD4_CLIENT_RECLAIM_COMPLETE (3) /* reclaim_complete done */
#define NFSD4_CLIENT_CB_FLAG_MASK (1 << NFSD4_CLIENT_CB_UPDATE | \
1 << NFSD4_CLIENT_CB_KILL)
unsigned long cl_flags;
struct rpc_clnt *cl_cb_client; struct rpc_clnt *cl_cb_client;
u32 cl_cb_ident; u32 cl_cb_ident;
#define NFSD4_CB_UP 0 #define NFSD4_CB_UP 0
......
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