aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs/xfs_refcount.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/libxfs/xfs_refcount.c')
-rw-r--r--fs/xfs/libxfs/xfs_refcount.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index b177ef33cd4c..82a38d86ebad 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -1629,13 +1629,28 @@ xfs_refcount_recover_cow_leftovers(
1629 if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START) 1629 if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START)
1630 return -EOPNOTSUPP; 1630 return -EOPNOTSUPP;
1631 1631
1632 error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); 1632 INIT_LIST_HEAD(&debris);
1633
1634 /*
1635 * In this first part, we use an empty transaction to gather up
1636 * all the leftover CoW extents so that we can subsequently
1637 * delete them. The empty transaction is used to avoid
1638 * a buffer lock deadlock if there happens to be a loop in the
1639 * refcountbt because we're allowed to re-grab a buffer that is
1640 * already attached to our transaction. When we're done
1641 * recording the CoW debris we cancel the (empty) transaction
1642 * and everything goes away cleanly.
1643 */
1644 error = xfs_trans_alloc_empty(mp, &tp);
1633 if (error) 1645 if (error)
1634 return error; 1646 return error;
1635 cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); 1647
1648 error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
1649 if (error)
1650 goto out_trans;
1651 cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, NULL);
1636 1652
1637 /* Find all the leftover CoW staging extents. */ 1653 /* Find all the leftover CoW staging extents. */
1638 INIT_LIST_HEAD(&debris);
1639 memset(&low, 0, sizeof(low)); 1654 memset(&low, 0, sizeof(low));
1640 memset(&high, 0, sizeof(high)); 1655 memset(&high, 0, sizeof(high));
1641 low.rc.rc_startblock = XFS_REFC_COW_START; 1656 low.rc.rc_startblock = XFS_REFC_COW_START;
@@ -1645,10 +1660,11 @@ xfs_refcount_recover_cow_leftovers(
1645 if (error) 1660 if (error)
1646 goto out_cursor; 1661 goto out_cursor;
1647 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 1662 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
1648 xfs_buf_relse(agbp); 1663 xfs_trans_brelse(tp, agbp);
1664 xfs_trans_cancel(tp);
1649 1665
1650 /* Now iterate the list to free the leftovers */ 1666 /* Now iterate the list to free the leftovers */
1651 list_for_each_entry(rr, &debris, rr_list) { 1667 list_for_each_entry_safe(rr, n, &debris, rr_list) {
1652 /* Set up transaction. */ 1668 /* Set up transaction. */
1653 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp); 1669 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp);
1654 if (error) 1670 if (error)
@@ -1676,8 +1692,16 @@ xfs_refcount_recover_cow_leftovers(
1676 error = xfs_trans_commit(tp); 1692 error = xfs_trans_commit(tp);
1677 if (error) 1693 if (error)
1678 goto out_free; 1694 goto out_free;
1695
1696 list_del(&rr->rr_list);
1697 kmem_free(rr);
1679 } 1698 }
1680 1699
1700 return error;
1701out_defer:
1702 xfs_defer_cancel(&dfops);
1703out_trans:
1704 xfs_trans_cancel(tp);
1681out_free: 1705out_free:
1682 /* Free the leftover list */ 1706 /* Free the leftover list */
1683 list_for_each_entry_safe(rr, n, &debris, rr_list) { 1707 list_for_each_entry_safe(rr, n, &debris, rr_list) {
@@ -1688,11 +1712,6 @@ out_free:
1688 1712
1689out_cursor: 1713out_cursor:
1690 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 1714 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
1691 xfs_buf_relse(agbp); 1715 xfs_trans_brelse(tp, agbp);
1692 goto out_free; 1716 goto out_trans;
1693
1694out_defer:
1695 xfs_defer_cancel(&dfops);
1696 xfs_trans_cancel(tp);
1697 goto out_free;
1698} 1717}