aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c81
1 files changed, 72 insertions, 9 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 48ac5aad6258..4bdffe0ba025 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -417,6 +417,16 @@ should_free_lseg(struct pnfs_layout_range *lseg_range,
417 lo_seg_intersecting(lseg_range, recall_range); 417 lo_seg_intersecting(lseg_range, recall_range);
418} 418}
419 419
420static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg,
421 struct list_head *tmp_list)
422{
423 if (!atomic_dec_and_test(&lseg->pls_refcount))
424 return false;
425 pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
426 list_add(&lseg->pls_list, tmp_list);
427 return true;
428}
429
420/* Returns 1 if lseg is removed from list, 0 otherwise */ 430/* Returns 1 if lseg is removed from list, 0 otherwise */
421static int mark_lseg_invalid(struct pnfs_layout_segment *lseg, 431static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
422 struct list_head *tmp_list) 432 struct list_head *tmp_list)
@@ -430,11 +440,8 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
430 */ 440 */
431 dprintk("%s: lseg %p ref %d\n", __func__, lseg, 441 dprintk("%s: lseg %p ref %d\n", __func__, lseg,
432 atomic_read(&lseg->pls_refcount)); 442 atomic_read(&lseg->pls_refcount));
433 if (atomic_dec_and_test(&lseg->pls_refcount)) { 443 if (pnfs_lseg_dec_and_remove_zero(lseg, tmp_list))
434 pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
435 list_add(&lseg->pls_list, tmp_list);
436 rv = 1; 444 rv = 1;
437 }
438 } 445 }
439 return rv; 446 return rv;
440} 447}
@@ -777,6 +784,21 @@ send_layoutget(struct pnfs_layout_hdr *lo,
777 return lseg; 784 return lseg;
778} 785}
779 786
787static void pnfs_clear_layoutcommit(struct inode *inode,
788 struct list_head *head)
789{
790 struct nfs_inode *nfsi = NFS_I(inode);
791 struct pnfs_layout_segment *lseg, *tmp;
792
793 if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
794 return;
795 list_for_each_entry_safe(lseg, tmp, &nfsi->layout->plh_segs, pls_list) {
796 if (!test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
797 continue;
798 pnfs_lseg_dec_and_remove_zero(lseg, head);
799 }
800}
801
780/* 802/*
781 * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr 803 * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
782 * when the layout segment list is empty. 804 * when the layout segment list is empty.
@@ -808,6 +830,7 @@ _pnfs_return_layout(struct inode *ino)
808 /* Reference matched in nfs4_layoutreturn_release */ 830 /* Reference matched in nfs4_layoutreturn_release */
809 pnfs_get_layout_hdr(lo); 831 pnfs_get_layout_hdr(lo);
810 empty = list_empty(&lo->plh_segs); 832 empty = list_empty(&lo->plh_segs);
833 pnfs_clear_layoutcommit(ino, &tmp_list);
811 pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL); 834 pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
812 /* Don't send a LAYOUTRETURN if list was initially empty */ 835 /* Don't send a LAYOUTRETURN if list was initially empty */
813 if (empty) { 836 if (empty) {
@@ -820,8 +843,6 @@ _pnfs_return_layout(struct inode *ino)
820 spin_unlock(&ino->i_lock); 843 spin_unlock(&ino->i_lock);
821 pnfs_free_lseg_list(&tmp_list); 844 pnfs_free_lseg_list(&tmp_list);
822 845
823 WARN_ON(test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags));
824
825 lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); 846 lrp = kzalloc(sizeof(*lrp), GFP_KERNEL);
826 if (unlikely(lrp == NULL)) { 847 if (unlikely(lrp == NULL)) {
827 status = -ENOMEM; 848 status = -ENOMEM;
@@ -845,6 +866,33 @@ out:
845} 866}
846EXPORT_SYMBOL_GPL(_pnfs_return_layout); 867EXPORT_SYMBOL_GPL(_pnfs_return_layout);
847 868
869int
870pnfs_commit_and_return_layout(struct inode *inode)
871{
872 struct pnfs_layout_hdr *lo;
873 int ret;
874
875 spin_lock(&inode->i_lock);
876 lo = NFS_I(inode)->layout;
877 if (lo == NULL) {
878 spin_unlock(&inode->i_lock);
879 return 0;
880 }
881 pnfs_get_layout_hdr(lo);
882 /* Block new layoutgets and read/write to ds */
883 lo->plh_block_lgets++;
884 spin_unlock(&inode->i_lock);
885 filemap_fdatawait(inode->i_mapping);
886 ret = pnfs_layoutcommit_inode(inode, true);
887 if (ret == 0)
888 ret = _pnfs_return_layout(inode);
889 spin_lock(&inode->i_lock);
890 lo->plh_block_lgets--;
891 spin_unlock(&inode->i_lock);
892 pnfs_put_layout_hdr(lo);
893 return ret;
894}
895
848bool pnfs_roc(struct inode *ino) 896bool pnfs_roc(struct inode *ino)
849{ 897{
850 struct pnfs_layout_hdr *lo; 898 struct pnfs_layout_hdr *lo;
@@ -1458,7 +1506,6 @@ static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
1458 dprintk("pnfs write error = %d\n", hdr->pnfs_error); 1506 dprintk("pnfs write error = %d\n", hdr->pnfs_error);
1459 if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & 1507 if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
1460 PNFS_LAYOUTRET_ON_ERROR) { 1508 PNFS_LAYOUTRET_ON_ERROR) {
1461 clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
1462 pnfs_return_layout(hdr->inode); 1509 pnfs_return_layout(hdr->inode);
1463 } 1510 }
1464 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) 1511 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
@@ -1613,7 +1660,6 @@ static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
1613 dprintk("pnfs read error = %d\n", hdr->pnfs_error); 1660 dprintk("pnfs read error = %d\n", hdr->pnfs_error);
1614 if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & 1661 if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
1615 PNFS_LAYOUTRET_ON_ERROR) { 1662 PNFS_LAYOUTRET_ON_ERROR) {
1616 clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
1617 pnfs_return_layout(hdr->inode); 1663 pnfs_return_layout(hdr->inode);
1618 } 1664 }
1619 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) 1665 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
@@ -1746,11 +1792,27 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
1746 1792
1747 list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) { 1793 list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
1748 if (lseg->pls_range.iomode == IOMODE_RW && 1794 if (lseg->pls_range.iomode == IOMODE_RW &&
1749 test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) 1795 test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
1750 list_add(&lseg->pls_lc_list, listp); 1796 list_add(&lseg->pls_lc_list, listp);
1751 } 1797 }
1752} 1798}
1753 1799
1800static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp)
1801{
1802 struct pnfs_layout_segment *lseg, *tmp;
1803 unsigned long *bitlock = &NFS_I(inode)->flags;
1804
1805 /* Matched by references in pnfs_set_layoutcommit */
1806 list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) {
1807 list_del_init(&lseg->pls_lc_list);
1808 pnfs_put_lseg(lseg);
1809 }
1810
1811 clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
1812 smp_mb__after_clear_bit();
1813 wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
1814}
1815
1754void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg) 1816void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
1755{ 1817{
1756 pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode); 1818 pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode);
@@ -1795,6 +1857,7 @@ void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data)
1795 1857
1796 if (nfss->pnfs_curr_ld->cleanup_layoutcommit) 1858 if (nfss->pnfs_curr_ld->cleanup_layoutcommit)
1797 nfss->pnfs_curr_ld->cleanup_layoutcommit(data); 1859 nfss->pnfs_curr_ld->cleanup_layoutcommit(data);
1860 pnfs_list_write_lseg_done(data->args.inode, &data->lseg_list);
1798} 1861}
1799 1862
1800/* 1863/*