mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 15:19:51 +00:00
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: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
1df00640c9
commit
a52d726bbd
@ -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)
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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 {
|
|||||||
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user