aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2011-01-06 06:36:26 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-01-06 14:46:32 -0500
commit2130ff663633e8a57921779ebfe62fc39d5585ec (patch)
treee100ef526b266a45ed3216be087d144df8cdbaed /fs/nfs
parentcf7d63f1f9895713551df2e6d18b006f8af26e91 (diff)
pnfs: add layout to client list before sending rpc
Since this list will be used to search for layouts to recall, this is necessary to avoid a race where the recall comes in, sees there is nothing in the client list, and prepares to return NOMATCHING, while the LAYOUTGET gets processed before the recall updates the stateid. Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/pnfs.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 59ed68bf79fa..c00b673261f9 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -469,14 +469,6 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo,
469 dprintk("%s:Begin\n", __func__); 469 dprintk("%s:Begin\n", __func__);
470 470
471 assert_spin_locked(&lo->plh_inode->i_lock); 471 assert_spin_locked(&lo->plh_inode->i_lock);
472 if (list_empty(&lo->plh_segs)) {
473 struct nfs_client *clp = NFS_SERVER(lo->plh_inode)->nfs_client;
474
475 spin_lock(&clp->cl_lock);
476 BUG_ON(!list_empty(&lo->plh_layouts));
477 list_add_tail(&lo->plh_layouts, &clp->cl_layouts);
478 spin_unlock(&clp->cl_lock);
479 }
480 list_for_each_entry(lp, &lo->plh_segs, pls_list) { 472 list_for_each_entry(lp, &lo->plh_segs, pls_list) {
481 if (cmp_layout(lp->pls_range.iomode, lseg->pls_range.iomode) > 0) 473 if (cmp_layout(lp->pls_range.iomode, lseg->pls_range.iomode) > 0)
482 continue; 474 continue;
@@ -597,6 +589,7 @@ pnfs_update_layout(struct inode *ino,
597 enum pnfs_iomode iomode) 589 enum pnfs_iomode iomode)
598{ 590{
599 struct nfs_inode *nfsi = NFS_I(ino); 591 struct nfs_inode *nfsi = NFS_I(ino);
592 struct nfs_client *clp = NFS_SERVER(ino)->nfs_client;
600 struct pnfs_layout_hdr *lo; 593 struct pnfs_layout_hdr *lo;
601 struct pnfs_layout_segment *lseg = NULL; 594 struct pnfs_layout_segment *lseg = NULL;
602 595
@@ -626,9 +619,27 @@ pnfs_update_layout(struct inode *ino,
626 atomic_inc(&lo->plh_outstanding); 619 atomic_inc(&lo->plh_outstanding);
627 620
628 get_layout_hdr_locked(lo); 621 get_layout_hdr_locked(lo);
622 if (list_empty(&lo->plh_segs)) {
623 /* The lo must be on the clp list if there is any
624 * chance of a CB_LAYOUTRECALL(FILE) coming in.
625 */
626 spin_lock(&clp->cl_lock);
627 BUG_ON(!list_empty(&lo->plh_layouts));
628 list_add_tail(&lo->plh_layouts, &clp->cl_layouts);
629 spin_unlock(&clp->cl_lock);
630 }
629 spin_unlock(&ino->i_lock); 631 spin_unlock(&ino->i_lock);
630 632
631 lseg = send_layoutget(lo, ctx, iomode); 633 lseg = send_layoutget(lo, ctx, iomode);
634 if (!lseg) {
635 spin_lock(&ino->i_lock);
636 if (list_empty(&lo->plh_segs)) {
637 spin_lock(&clp->cl_lock);
638 list_del_init(&lo->plh_layouts);
639 spin_unlock(&clp->cl_lock);
640 }
641 spin_unlock(&ino->i_lock);
642 }
632 atomic_dec(&lo->plh_outstanding); 643 atomic_dec(&lo->plh_outstanding);
633 put_layout_hdr(ino); 644 put_layout_hdr(ino);
634out: 645out: