diff options
| -rw-r--r-- | fs/nfs/pnfs.c | 23 |
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 | */ | ||
| 655 | int | 662 | int |
| 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); |
