aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2012-06-20 15:03:34 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-07-16 14:39:00 -0400
commit293b3b065c5ec5d15c3087ca42a52c991d7d8235 (patch)
tree32b9422aa2d097af2618d225b925535b75492ee0
parent366d50521c57939e61e25dc27f009367447563e6 (diff)
NFSv4.1 do not send LAYOUTRETURN on emtpy plh_segs list
mark_matching_lsegs_invalid() resets the mds_threshold counters and can dereference the layout hdr on an initial empty plh_segs list. It returns 0 both in the case of an initial empty list and in a non-emtpy list that was cleared by calls to mark_lseg_invalid. Don't send a LAYOUTRETURN if the list was initially empty. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/pnfs.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 3ad768f2cef4..7fbd25afe418 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -651,7 +651,14 @@ out_err_free:
651 return NULL; 651 return NULL;
652} 652}
653 653
654/* Initiates a LAYOUTRETURN(FILE) */ 654/*
655 * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
656 * when the layout segment list is empty.
657 *
658 * Note that a pnfs_layout_hdr can exist with an empty layout segment
659 * list when LAYOUTGET has failed, or when LAYOUTGET succeeded, but the
660 * deviceid is marked invalid.
661 */
655int 662int
656_pnfs_return_layout(struct inode *ino) 663_pnfs_return_layout(struct inode *ino)
657{ 664{
@@ -660,7 +667,7 @@ _pnfs_return_layout(struct inode *ino)
660 LIST_HEAD(tmp_list); 667 LIST_HEAD(tmp_list);
661 struct nfs4_layoutreturn *lrp; 668 struct nfs4_layoutreturn *lrp;
662 nfs4_stateid stateid; 669 nfs4_stateid stateid;
663 int status = 0; 670 int status = 0, empty;
664 671
665 dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino); 672 dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);
666 673
@@ -668,13 +675,21 @@ _pnfs_return_layout(struct inode *ino)
668 lo = nfsi->layout; 675 lo = nfsi->layout;
669 if (!lo || pnfs_test_layout_returned(lo)) { 676 if (!lo || pnfs_test_layout_returned(lo)) {
670 spin_unlock(&ino->i_lock); 677 spin_unlock(&ino->i_lock);
671 dprintk("%s: no layout to return\n", __func__); 678 dprintk("NFS: %s no layout to return\n", __func__);
672 return status; 679 goto out;
673 } 680 }
674 stateid = nfsi->layout->plh_stateid; 681 stateid = nfsi->layout->plh_stateid;
675 /* Reference matched in nfs4_layoutreturn_release */ 682 /* Reference matched in nfs4_layoutreturn_release */
676 get_layout_hdr(lo); 683 get_layout_hdr(lo);
684 empty = list_empty(&lo->plh_segs);
677 mark_matching_lsegs_invalid(lo, &tmp_list, NULL); 685 mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
686 /* Don't send a LAYOUTRETURN if list was initially empty */
687 if (empty) {
688 spin_unlock(&ino->i_lock);
689 put_layout_hdr(lo);
690 dprintk("NFS: %s no layout segments to return\n", __func__);
691 goto out;
692 }
678 lo->plh_block_lgets++; 693 lo->plh_block_lgets++;
679 pnfs_mark_layout_returned(lo); 694 pnfs_mark_layout_returned(lo);
680 spin_unlock(&ino->i_lock); 695 spin_unlock(&ino->i_lock);