nfsd: convert nfs4_client->cl_cb_flags to a generic flags field
authorJeff Layton <jlayton@redhat.com>
Wed, 21 Mar 2012 13:52:02 +0000 (09:52 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Mon, 26 Mar 2012 15:49:47 +0000 (11:49 -0400)
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>
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/state.h

index cf6e4190e41c7963d2f024525b9b3b99ce24728f..0840fc4f7e4a48a30aeac9a99423467a0430682e 100644 (file)
@@ -754,9 +754,9 @@ static void do_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;
-       set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+       set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
        do_probe_callback(clp);
 }
 
@@ -915,7 +915,7 @@ void nfsd4_destroy_callback_queue(void)
 /* must be called under the state lock */
 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;
         * 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);
                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;
        spin_lock(&clp->cl_lock);
        /*
         * Only serialized callback code is allowed to clear these
         * flags; main nfsd code can only set them:
         */
-       BUG_ON(!clp->cl_cb_flags);
-       clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+       BUG_ON(!(clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK));
+       clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
        memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
        c = __nfsd4_find_backchannel(clp);
        if (c) {
@@ -1000,7 +1000,7 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
        struct nfs4_client *clp = cb->cb_clp;
        struct rpc_clnt *clnt;
 
-       if (clp->cl_cb_flags)
+       if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)
                nfsd4_process_cb_update(cb);
 
        clnt = clp->cl_cb_client;
index 2a9036670b8fcb776ae791a3f71224925c9bca12..2ed14dfd00a231e9c813b78b3d728bcdfb849b06 100644 (file)
@@ -319,7 +319,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
         * Before RECLAIM_COMPLETE done, server should deny new lock
         */
        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)
                return nfserr_grace;
 
index 0b3e875d1abd5e4cd962d5ed5df29f22c7ca546d..6523809839c3ce853f70981d4f233b5439041464 100644 (file)
@@ -126,9 +126,8 @@ void nfsd4_create_clid_dir(struct nfs4_client *clp)
 
        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;
-       clp->cl_firststate = 1;
        if (!rec_file)
                return;
        status = nfs4_save_creds(&original_cred);
@@ -271,13 +270,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
        const struct cred *original_cred;
        int status;
 
-       if (!rec_file || !clp->cl_firststate)
+       if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
                return;
 
        status = mnt_want_write_file(rec_file);
        if (status)
                goto out;
-       clp->cl_firststate = 0;
+       clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
 
        status = nfs4_save_creds(&original_cred);
        if (status < 0)
index a0a2b535b0e0f82f5e88d6a204fb584e2eefa563..8be612abd0d758647709f5582911fead04dfb213 100644 (file)
@@ -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
index 1e2b582bc9dc02326309ced2d932c98a69f5f122..115215723f7685bc16cc9286f4d8b8198d18d69d 100644 (file)
@@ -236,14 +236,17 @@ struct nfs4_client {
        struct svc_cred         cl_cred;        /* setclientid principal */
        clientid_t              cl_clientid;    /* generated by server */
        nfs4_verifier           cl_confirm;     /* generated by server */
-       u32                     cl_firststate;  /* recovery dir creation */
        u32                     cl_minorversion;
 
        /* for v4.0 and v4.1 callbacks: */
        struct nfs4_cb_conn     cl_cb_conn;
-#define NFSD4_CLIENT_CB_UPDATE 1
-#define NFSD4_CLIENT_KILL      2
-       unsigned long           cl_cb_flags;
+#define NFSD4_CLIENT_CB_UPDATE         (0)
+#define NFSD4_CLIENT_CB_KILL           (1)
+#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;
        u32                     cl_cb_ident;
 #define NFSD4_CB_UP            0