summaryrefslogtreecommitdiff
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-03-21 13:52:02 (GMT)
committerJ. Bruce Fields <bfields@redhat.com>2012-03-26 15:49:47 (GMT)
commita52d726bbd928164609e6abc4dc967e819dbf09c (patch)
tree604df65589a95311ab297f80ce377e82525ce597 /fs/nfsd/nfs4state.c
parent1df00640c9111c881633d9b219f18e66c52599ec (diff)
downloadlinux-a52d726bbd928164609e6abc4dc967e819dbf09c.tar.xz
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>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index a0a2b53..8be612a 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2069,7 +2069,8 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
nfs4_lock_state();
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;
status = nfserr_stale_clientid;
@@ -2816,12 +2817,6 @@ static void
nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session)
{
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?: */
@@ -4462,7 +4457,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
clp = find_confirmed_client_by_str(name, strhashval);
if (!clp)
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. */
static struct nfs4_client_reclaim *
-nfs4_find_reclaim_client(clientid_t *clid)
+nfsd4_find_reclaim_client(struct nfs4_client *clp)
{
unsigned int strhashval;
- struct nfs4_client *clp;
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",
clp->cl_name.len, clp->cl_name.data,
clp->cl_recdir);
@@ -4533,13 +4521,36 @@ nfs4_find_reclaim_client(clientid_t *clid)
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.
*/
__be32
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