aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2010-04-30 18:51:44 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-01-11 15:04:10 -0500
commit77a3569d6c4e14e89fa628df383b6dccc0cce6be (patch)
tree3e89bd0aa2fe679ec212212bc232651f08ef7b2b
parentf0418aa4b1103f959d64dc18273efa04ee0140e9 (diff)
nfsd4: keep finer-grained callback status
Distinguish between when the callback channel is known to be down, and when it is not yet confirmed. This will be useful in the 4.1 case. Also, we don't seem to be using the fact that this field is atomic. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--fs/nfsd/nfs4callback.c26
-rw-r--r--fs/nfsd/nfs4state.c8
-rw-r--r--fs/nfsd/state.h5
3 files changed, 22 insertions, 17 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 18b740bd29ac..d32f49d6ca2c 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -470,8 +470,6 @@ static int max_cb_time(void)
470 return max(nfsd4_lease/10, (time_t)1) * HZ; 470 return max(nfsd4_lease/10, (time_t)1) * HZ;
471} 471}
472 472
473/* Reference counting, callback cleanup, etc., all look racy as heck.
474 * And why is cl_cb_set an atomic? */
475 473
476static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) 474static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
477{ 475{
@@ -526,14 +524,20 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason)
526 (int)clp->cl_name.len, clp->cl_name.data, reason); 524 (int)clp->cl_name.len, clp->cl_name.data, reason);
527} 525}
528 526
527static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason)
528{
529 clp->cl_cb_state = NFSD4_CB_DOWN;
530 warn_no_callback_path(clp, reason);
531}
532
529static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) 533static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
530{ 534{
531 struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); 535 struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
532 536
533 if (task->tk_status) 537 if (task->tk_status)
534 warn_no_callback_path(clp, task->tk_status); 538 nfsd4_mark_cb_down(clp, task->tk_status);
535 else 539 else
536 atomic_set(&clp->cl_cb_set, 1); 540 clp->cl_cb_state = NFSD4_CB_UP;
537} 541}
538 542
539static const struct rpc_call_ops nfsd4_cb_probe_ops = { 543static const struct rpc_call_ops nfsd4_cb_probe_ops = {
@@ -579,14 +583,15 @@ static void do_probe_callback(struct nfs4_client *clp)
579 */ 583 */
580void nfsd4_probe_callback(struct nfs4_client *clp) 584void nfsd4_probe_callback(struct nfs4_client *clp)
581{ 585{
586 /* XXX: atomicity? Also, should we be using cl_cb_flags? */
587 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
582 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); 588 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
583 do_probe_callback(clp); 589 do_probe_callback(clp);
584} 590}
585 591
586void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) 592void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
587{ 593{
588 BUG_ON(atomic_read(&clp->cl_cb_set)); 594 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
589
590 spin_lock(&clp->cl_lock); 595 spin_lock(&clp->cl_lock);
591 memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn)); 596 memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn));
592 spin_unlock(&clp->cl_lock); 597 spin_unlock(&clp->cl_lock);
@@ -693,8 +698,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
693 break; 698 break;
694 default: 699 default:
695 /* Network partition? */ 700 /* Network partition? */
696 atomic_set(&clp->cl_cb_set, 0); 701 nfsd4_mark_cb_down(clp, task->tk_status);
697 warn_no_callback_path(clp, task->tk_status);
698 if (current_rpc_client != task->tk_client) { 702 if (current_rpc_client != task->tk_client) {
699 /* queue a callback on the new connection: */ 703 /* queue a callback on the new connection: */
700 atomic_inc(&dp->dl_count); 704 atomic_inc(&dp->dl_count);
@@ -707,10 +711,8 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
707 task->tk_status = 0; 711 task->tk_status = 0;
708 rpc_restart_call_prepare(task); 712 rpc_restart_call_prepare(task);
709 return; 713 return;
710 } else { 714 } else
711 atomic_set(&clp->cl_cb_set, 0); 715 nfsd4_mark_cb_down(clp, task->tk_status);
712 warn_no_callback_path(clp, task->tk_status);
713 }
714} 716}
715 717
716static void nfsd4_cb_recall_release(void *calldata) 718static void nfsd4_cb_recall_release(void *calldata)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 290370bc9ae7..919ad25660d6 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1071,7 +1071,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
1071 1071
1072 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); 1072 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
1073 atomic_set(&clp->cl_refcount, 0); 1073 atomic_set(&clp->cl_refcount, 0);
1074 atomic_set(&clp->cl_cb_set, 0); 1074 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
1075 INIT_LIST_HEAD(&clp->cl_idhash); 1075 INIT_LIST_HEAD(&clp->cl_idhash);
1076 INIT_LIST_HEAD(&clp->cl_strhash); 1076 INIT_LIST_HEAD(&clp->cl_strhash);
1077 INIT_LIST_HEAD(&clp->cl_openowners); 1077 INIT_LIST_HEAD(&clp->cl_openowners);
@@ -2003,7 +2003,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2003 if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) 2003 if (!same_creds(&conf->cl_cred, &unconf->cl_cred))
2004 status = nfserr_clid_inuse; 2004 status = nfserr_clid_inuse;
2005 else { 2005 else {
2006 atomic_set(&conf->cl_cb_set, 0);
2007 nfsd4_change_callback(conf, &unconf->cl_cb_conn); 2006 nfsd4_change_callback(conf, &unconf->cl_cb_conn);
2008 nfsd4_probe_callback(conf); 2007 nfsd4_probe_callback(conf);
2009 expire_client(unconf); 2008 expire_client(unconf);
@@ -2633,7 +2632,8 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2633{ 2632{
2634 struct nfs4_delegation *dp; 2633 struct nfs4_delegation *dp;
2635 struct nfs4_stateowner *sop = stp->st_stateowner; 2634 struct nfs4_stateowner *sop = stp->st_stateowner;
2636 int cb_up = atomic_read(&sop->so_client->cl_cb_set); 2635 /* XXX: or unknown and nfsv4.1: */
2636 int cb_up = (sop->so_client->cl_cb_state == NFSD4_CB_UP);
2637 struct file_lock *fl; 2637 struct file_lock *fl;
2638 int status, flag = 0; 2638 int status, flag = 0;
2639 2639
@@ -2823,7 +2823,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2823 renew_client(clp); 2823 renew_client(clp);
2824 status = nfserr_cb_path_down; 2824 status = nfserr_cb_path_down;
2825 if (!list_empty(&clp->cl_delegations) 2825 if (!list_empty(&clp->cl_delegations)
2826 && !atomic_read(&clp->cl_cb_set)) 2826 && clp->cl_cb_state != NFSD4_CB_UP)
2827 goto out; 2827 goto out;
2828 status = nfs_ok; 2828 status = nfs_ok;
2829out: 2829out:
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 442f6d8e024c..32ff615c36f4 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -242,7 +242,10 @@ struct nfs4_client {
242 unsigned long cl_cb_flags; 242 unsigned long cl_cb_flags;
243 struct rpc_clnt *cl_cb_client; 243 struct rpc_clnt *cl_cb_client;
244 u32 cl_cb_ident; 244 u32 cl_cb_ident;
245 atomic_t cl_cb_set; 245#define NFSD4_CB_UP 0
246#define NFSD4_CB_UNKNOWN 1
247#define NFSD4_CB_DOWN 2
248 int cl_cb_state;
246 struct nfsd4_callback cl_cb_null; 249 struct nfsd4_callback cl_cb_null;
247 struct nfsd4_session *cl_cb_session; 250 struct nfsd4_session *cl_cb_session;
248 251