aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4callback.c14
-rw-r--r--fs/nfsd/nfs4proc.c3
-rw-r--r--fs/nfsd/nfs4recover.c7
-rw-r--r--fs/nfsd/nfs4state.c45
-rw-r--r--fs/nfsd/state.h11
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 */
755void nfsd4_probe_callback(struct nfs4_client *clp) 755void 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 */
916void nfsd4_shutdown_callback(struct nfs4_client *clp) 916void 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
2816nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session) 2817nfs4_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. */
4509static struct nfs4_client_reclaim * 4504static struct nfs4_client_reclaim *
4510nfs4_find_reclaim_client(clientid_t *clid) 4505nfsd4_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
4524static int
4525nfsd4_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
4540nfs4_check_open_reclaim(clientid_t *clid) 4544nfs4_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