aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-05-23 13:23:31 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-05-23 15:20:57 -0400
commit7b38c3682c5cab4f98751d5fe57b78a59020653d (patch)
treec6c2ea72b99b59b60a3c7ba3d142a4926664398e /fs/nfs/nfs4proc.c
parentacdeb69d9c5934a678a732b4e24770326bf9471e (diff)
NFSv4.1: Fix session initialisation races
Session initialisation is not complete until the lease manager has run. We need to ensure that both nfs4_init_session and nfs4_init_ds_session do so, and that they check for any resulting errors in clp->cl_cons_state. Only after this is done, can nfs4_ds_connect check the contents of clp->cl_exchange_flags. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: Andy Adamson <andros@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c79
1 files changed, 52 insertions, 27 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 0d46fe449f0b..c856298def7d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5603,53 +5603,78 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
5603 return status; 5603 return status;
5604} 5604}
5605 5605
5606/*
5607 * With sessions, the client is not marked ready until after a
5608 * successful EXCHANGE_ID and CREATE_SESSION.
5609 *
5610 * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate
5611 * other versions of NFS can be tried.
5612 */
5613static int nfs41_check_session_ready(struct nfs_client *clp)
5614{
5615 int ret;
5616
5617 if (clp->cl_cons_state == NFS_CS_SESSION_INITING) {
5618 ret = nfs4_client_recover_expired_lease(clp);
5619 if (ret)
5620 return ret;
5621 }
5622 if (clp->cl_cons_state < NFS_CS_READY)
5623 return -EPROTONOSUPPORT;
5624 return 0;
5625}
5626
5606int nfs4_init_session(struct nfs_server *server) 5627int nfs4_init_session(struct nfs_server *server)
5607{ 5628{
5608 struct nfs_client *clp = server->nfs_client; 5629 struct nfs_client *clp = server->nfs_client;
5609 struct nfs4_session *session; 5630 struct nfs4_session *session;
5610 unsigned int rsize, wsize; 5631 unsigned int rsize, wsize;
5611 int ret;
5612 5632
5613 if (!nfs4_has_session(clp)) 5633 if (!nfs4_has_session(clp))
5614 return 0; 5634 return 0;
5615 5635
5616 session = clp->cl_session; 5636 session = clp->cl_session;
5617 if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) 5637 spin_lock(&clp->cl_lock);
5618 return 0; 5638 if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
5619 5639
5620 rsize = server->rsize; 5640 rsize = server->rsize;
5621 if (rsize == 0) 5641 if (rsize == 0)
5622 rsize = NFS_MAX_FILE_IO_SIZE; 5642 rsize = NFS_MAX_FILE_IO_SIZE;
5623 wsize = server->wsize; 5643 wsize = server->wsize;
5624 if (wsize == 0) 5644 if (wsize == 0)
5625 wsize = NFS_MAX_FILE_IO_SIZE; 5645 wsize = NFS_MAX_FILE_IO_SIZE;
5626 5646
5627 session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; 5647 session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead;
5628 session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; 5648 session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead;
5649 }
5650 spin_unlock(&clp->cl_lock);
5629 5651
5630 ret = nfs4_recover_expired_lease(server); 5652 return nfs41_check_session_ready(clp);
5631 if (!ret)
5632 ret = nfs4_check_client_ready(clp);
5633 return ret;
5634} 5653}
5635 5654
5636int nfs4_init_ds_session(struct nfs_client *clp) 5655int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time)
5637{ 5656{
5638 struct nfs4_session *session = clp->cl_session; 5657 struct nfs4_session *session = clp->cl_session;
5639 int ret; 5658 int ret;
5640 5659
5641 if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) 5660 spin_lock(&clp->cl_lock);
5642 return 0; 5661 if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
5643 5662 /*
5644 ret = nfs4_client_recover_expired_lease(clp); 5663 * Do not set NFS_CS_CHECK_LEASE_TIME instead set the
5645 if (!ret) 5664 * DS lease to be equal to the MDS lease.
5646 /* Test for the DS role */ 5665 */
5647 if (!is_ds_client(clp)) 5666 clp->cl_lease_time = lease_time;
5648 ret = -ENODEV; 5667 clp->cl_last_renewal = jiffies;
5649 if (!ret) 5668 }
5650 ret = nfs4_check_client_ready(clp); 5669 spin_unlock(&clp->cl_lock);
5651 return ret;
5652 5670
5671 ret = nfs41_check_session_ready(clp);
5672 if (ret)
5673 return ret;
5674 /* Test for the DS role */
5675 if (!is_ds_client(clp))
5676 return -ENODEV;
5677 return 0;
5653} 5678}
5654EXPORT_SYMBOL_GPL(nfs4_init_ds_session); 5679EXPORT_SYMBOL_GPL(nfs4_init_ds_session);
5655 5680