diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-23 13:23:31 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-23 15:20:57 -0400 |
commit | 7b38c3682c5cab4f98751d5fe57b78a59020653d (patch) | |
tree | c6c2ea72b99b59b60a3c7ba3d142a4926664398e /fs/nfs/nfs4proc.c | |
parent | acdeb69d9c5934a678a732b4e24770326bf9471e (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.c | 79 |
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 | */ | ||
5613 | static 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 | |||
5606 | int nfs4_init_session(struct nfs_server *server) | 5627 | int 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 | ||
5636 | int nfs4_init_ds_session(struct nfs_client *clp) | 5655 | int 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 | } |
5654 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | 5679 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); |
5655 | 5680 | ||