diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-03-21 09:52:02 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-03-26 11:49:47 -0400 |
commit | a52d726bbd928164609e6abc4dc967e819dbf09c (patch) | |
tree | 604df65589a95311ab297f80ce377e82525ce597 | |
parent | 1df00640c9111c881633d9b219f18e66c52599ec (diff) |
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>
-rw-r--r-- | fs/nfsd/nfs4callback.c | 14 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 7 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 45 | ||||
-rw-r--r-- | fs/nfsd/state.h | 11 |
5 files changed, 47 insertions, 33 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index cf6e4190e41c..0840fc4f7e4a 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -754,9 +754,9 @@ static void do_probe_callback(struct nfs4_client *clp) | |||
754 | */ | 754 | */ |
755 | void nfsd4_probe_callback(struct nfs4_client *clp) | 755 | void nfsd4_probe_callback(struct nfs4_client *clp) |
756 | { | 756 | { |
757 | /* XXX: atomicity? Also, should we be using cl_cb_flags? */ | 757 | /* XXX: atomicity? Also, should we be using cl_flags? */ |
758 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; | 758 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; |
759 | set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); | 759 | set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags); |
760 | do_probe_callback(clp); | 760 | do_probe_callback(clp); |
761 | } | 761 | } |
762 | 762 | ||
@@ -915,7 +915,7 @@ void nfsd4_destroy_callback_queue(void) | |||
915 | /* must be called under the state lock */ | 915 | /* must be called under the state lock */ |
916 | void nfsd4_shutdown_callback(struct nfs4_client *clp) | 916 | void nfsd4_shutdown_callback(struct nfs4_client *clp) |
917 | { | 917 | { |
918 | set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags); | 918 | set_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags); |
919 | /* | 919 | /* |
920 | * Note this won't actually result in a null callback; | 920 | * Note this won't actually result in a null callback; |
921 | * instead, nfsd4_do_callback_rpc() will detect the killed | 921 | * instead, nfsd4_do_callback_rpc() will detect the killed |
@@ -966,15 +966,15 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb) | |||
966 | svc_xprt_put(clp->cl_cb_conn.cb_xprt); | 966 | svc_xprt_put(clp->cl_cb_conn.cb_xprt); |
967 | clp->cl_cb_conn.cb_xprt = NULL; | 967 | clp->cl_cb_conn.cb_xprt = NULL; |
968 | } | 968 | } |
969 | if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags)) | 969 | if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags)) |
970 | return; | 970 | return; |
971 | spin_lock(&clp->cl_lock); | 971 | spin_lock(&clp->cl_lock); |
972 | /* | 972 | /* |
973 | * Only serialized callback code is allowed to clear these | 973 | * Only serialized callback code is allowed to clear these |
974 | * flags; main nfsd code can only set them: | 974 | * flags; main nfsd code can only set them: |
975 | */ | 975 | */ |
976 | BUG_ON(!clp->cl_cb_flags); | 976 | BUG_ON(!(clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)); |
977 | clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); | 977 | clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags); |
978 | memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn)); | 978 | memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn)); |
979 | c = __nfsd4_find_backchannel(clp); | 979 | c = __nfsd4_find_backchannel(clp); |
980 | if (c) { | 980 | if (c) { |
@@ -1000,7 +1000,7 @@ void nfsd4_do_callback_rpc(struct work_struct *w) | |||
1000 | struct nfs4_client *clp = cb->cb_clp; | 1000 | struct nfs4_client *clp = cb->cb_clp; |
1001 | struct rpc_clnt *clnt; | 1001 | struct rpc_clnt *clnt; |
1002 | 1002 | ||
1003 | if (clp->cl_cb_flags) | 1003 | if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK) |
1004 | nfsd4_process_cb_update(cb); | 1004 | nfsd4_process_cb_update(cb); |
1005 | 1005 | ||
1006 | clnt = clp->cl_cb_client; | 1006 | clnt = clp->cl_cb_client; |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 2a9036670b8f..2ed14dfd00a2 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -319,7 +319,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
319 | * Before RECLAIM_COMPLETE done, server should deny new lock | 319 | * Before RECLAIM_COMPLETE done, server should deny new lock |
320 | */ | 320 | */ |
321 | if (nfsd4_has_session(cstate) && | 321 | if (nfsd4_has_session(cstate) && |
322 | !cstate->session->se_client->cl_firststate && | 322 | !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE, |
323 | &cstate->session->se_client->cl_flags) && | ||
323 | open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) | 324 | open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) |
324 | return nfserr_grace; | 325 | return nfserr_grace; |
325 | 326 | ||
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 0b3e875d1abd..6523809839c3 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -126,9 +126,8 @@ void nfsd4_create_clid_dir(struct nfs4_client *clp) | |||
126 | 126 | ||
127 | dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); | 127 | dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); |
128 | 128 | ||
129 | if (clp->cl_firststate) | 129 | if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) |
130 | return; | 130 | return; |
131 | clp->cl_firststate = 1; | ||
132 | if (!rec_file) | 131 | if (!rec_file) |
133 | return; | 132 | return; |
134 | status = nfs4_save_creds(&original_cred); | 133 | status = nfs4_save_creds(&original_cred); |
@@ -271,13 +270,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) | |||
271 | const struct cred *original_cred; | 270 | const struct cred *original_cred; |
272 | int status; | 271 | int status; |
273 | 272 | ||
274 | if (!rec_file || !clp->cl_firststate) | 273 | if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) |
275 | return; | 274 | return; |
276 | 275 | ||
277 | status = mnt_want_write_file(rec_file); | 276 | status = mnt_want_write_file(rec_file); |
278 | if (status) | 277 | if (status) |
279 | goto out; | 278 | goto out; |
280 | clp->cl_firststate = 0; | 279 | clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); |
281 | 280 | ||
282 | status = nfs4_save_creds(&original_cred); | 281 | status = nfs4_save_creds(&original_cred); |
283 | if (status < 0) | 282 | if (status < 0) |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a0a2b535b0e0..8be612abd0d7 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 | |||
2069 | 2069 | ||
2070 | nfs4_lock_state(); | 2070 | nfs4_lock_state(); |
2071 | status = nfserr_complete_already; | 2071 | status = nfserr_complete_already; |
2072 | if (cstate->session->se_client->cl_firststate) | 2072 | if (test_and_set_bit(NFSD4_CLIENT_RECLAIM_COMPLETE, |
2073 | &cstate->session->se_client->cl_flags)) | ||
2073 | goto out; | 2074 | goto out; |
2074 | 2075 | ||
2075 | status = nfserr_stale_clientid; | 2076 | status = nfserr_stale_clientid; |
@@ -2816,12 +2817,6 @@ static void | |||
2816 | nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session) | 2817 | nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session) |
2817 | { | 2818 | { |
2818 | open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; | 2819 | open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; |
2819 | /* | ||
2820 | * On a 4.1+ client, we don't create a state record for a client | ||
2821 | * until it performs RECLAIM_COMPLETE: | ||
2822 | */ | ||
2823 | if (!has_session) | ||
2824 | open->op_openowner->oo_owner.so_client->cl_firststate = 1; | ||
2825 | } | 2820 | } |
2826 | 2821 | ||
2827 | /* Should we give out recallable state?: */ | 2822 | /* Should we give out recallable state?: */ |
@@ -4462,7 +4457,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id) | |||
4462 | clp = find_confirmed_client_by_str(name, strhashval); | 4457 | clp = find_confirmed_client_by_str(name, strhashval); |
4463 | if (!clp) | 4458 | if (!clp) |
4464 | return 0; | 4459 | return 0; |
4465 | return clp->cl_firststate; | 4460 | return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); |
4466 | } | 4461 | } |
4467 | 4462 | ||
4468 | /* | 4463 | /* |
@@ -4507,18 +4502,11 @@ nfs4_release_reclaim(void) | |||
4507 | /* | 4502 | /* |
4508 | * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ | 4503 | * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ |
4509 | static struct nfs4_client_reclaim * | 4504 | static struct nfs4_client_reclaim * |
4510 | nfs4_find_reclaim_client(clientid_t *clid) | 4505 | nfsd4_find_reclaim_client(struct nfs4_client *clp) |
4511 | { | 4506 | { |
4512 | unsigned int strhashval; | 4507 | unsigned int strhashval; |
4513 | struct nfs4_client *clp; | ||
4514 | struct nfs4_client_reclaim *crp = NULL; | 4508 | struct nfs4_client_reclaim *crp = NULL; |
4515 | 4509 | ||
4516 | |||
4517 | /* find clientid in conf_id_hashtbl */ | ||
4518 | clp = find_confirmed_client(clid); | ||
4519 | if (clp == NULL) | ||
4520 | return NULL; | ||
4521 | |||
4522 | dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n", | 4510 | dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n", |
4523 | clp->cl_name.len, clp->cl_name.data, | 4511 | clp->cl_name.len, clp->cl_name.data, |
4524 | clp->cl_recdir); | 4512 | clp->cl_recdir); |
@@ -4533,13 +4521,36 @@ nfs4_find_reclaim_client(clientid_t *clid) | |||
4533 | return NULL; | 4521 | return NULL; |
4534 | } | 4522 | } |
4535 | 4523 | ||
4524 | static int | ||
4525 | nfsd4_client_record_check(struct nfs4_client *clp) | ||
4526 | { | ||
4527 | /* did we already find that this client is stable? */ | ||
4528 | if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) | ||
4529 | return 0; | ||
4530 | |||
4531 | /* look for it in the reclaim hashtable otherwise */ | ||
4532 | if (nfsd4_find_reclaim_client(clp)) { | ||
4533 | set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); | ||
4534 | return 0; | ||
4535 | } | ||
4536 | |||
4537 | return -ENOENT; | ||
4538 | } | ||
4539 | |||
4536 | /* | 4540 | /* |
4537 | * Called from OPEN. Look for clientid in reclaim list. | 4541 | * Called from OPEN. Look for clientid in reclaim list. |
4538 | */ | 4542 | */ |
4539 | __be32 | 4543 | __be32 |
4540 | nfs4_check_open_reclaim(clientid_t *clid) | 4544 | nfs4_check_open_reclaim(clientid_t *clid) |
4541 | { | 4545 | { |
4542 | return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad; | 4546 | struct nfs4_client *clp; |
4547 | |||
4548 | /* find clientid in conf_id_hashtbl */ | ||
4549 | clp = find_confirmed_client(clid); | ||
4550 | if (clp == NULL) | ||
4551 | return nfserr_reclaim_bad; | ||
4552 | |||
4553 | return nfsd4_client_record_check(clp) ? nfserr_reclaim_bad : nfs_ok; | ||
4543 | } | 4554 | } |
4544 | 4555 | ||
4545 | #ifdef CONFIG_NFSD_FAULT_INJECTION | 4556 | #ifdef CONFIG_NFSD_FAULT_INJECTION |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 1e2b582bc9dc..115215723f76 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -236,14 +236,17 @@ struct nfs4_client { | |||
236 | struct svc_cred cl_cred; /* setclientid principal */ | 236 | struct svc_cred cl_cred; /* setclientid principal */ |
237 | clientid_t cl_clientid; /* generated by server */ | 237 | clientid_t cl_clientid; /* generated by server */ |
238 | nfs4_verifier cl_confirm; /* generated by server */ | 238 | nfs4_verifier cl_confirm; /* generated by server */ |
239 | u32 cl_firststate; /* recovery dir creation */ | ||
240 | u32 cl_minorversion; | 239 | u32 cl_minorversion; |
241 | 240 | ||
242 | /* for v4.0 and v4.1 callbacks: */ | 241 | /* for v4.0 and v4.1 callbacks: */ |
243 | struct nfs4_cb_conn cl_cb_conn; | 242 | struct nfs4_cb_conn cl_cb_conn; |
244 | #define NFSD4_CLIENT_CB_UPDATE 1 | 243 | #define NFSD4_CLIENT_CB_UPDATE (0) |
245 | #define NFSD4_CLIENT_KILL 2 | 244 | #define NFSD4_CLIENT_CB_KILL (1) |
246 | unsigned long cl_cb_flags; | 245 | #define NFSD4_CLIENT_STABLE (2) /* client on stable storage */ |
246 | #define NFSD4_CLIENT_RECLAIM_COMPLETE (3) /* reclaim_complete done */ | ||
247 | #define NFSD4_CLIENT_CB_FLAG_MASK (1 << NFSD4_CLIENT_CB_UPDATE | \ | ||
248 | 1 << NFSD4_CLIENT_CB_KILL) | ||
249 | unsigned long cl_flags; | ||
247 | struct rpc_clnt *cl_cb_client; | 250 | struct rpc_clnt *cl_cb_client; |
248 | u32 cl_cb_ident; | 251 | u32 cl_cb_ident; |
249 | #define NFSD4_CB_UP 0 | 252 | #define NFSD4_CB_UP 0 |