diff options
Diffstat (limited to '')
-rw-r--r-- | fs/xfs/xfs_refcount_item.c | 110 |
1 files changed, 56 insertions, 54 deletions
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c index 14919b33e4fe..27398512b179 100644 --- a/fs/xfs/xfs_refcount_item.c +++ b/fs/xfs/xfs_refcount_item.c @@ -21,6 +21,8 @@ #include "xfs_log_priv.h" #include "xfs_log_recover.h" #include "xfs_ag.h" +#include "xfs_btree.h" +#include "xfs_trace.h" struct kmem_cache *xfs_cui_cache; struct kmem_cache *xfs_cud_cache; @@ -227,6 +229,11 @@ static const struct xfs_item_ops xfs_cud_item_ops = { .iop_intent = xfs_cud_item_intent, }; +static inline struct xfs_refcount_intent *ci_entry(const struct list_head *e) +{ + return list_entry(e, struct xfs_refcount_intent, ri_list); +} + /* Sort refcount intents by AG. */ static int xfs_refcount_update_diff_items( @@ -234,34 +241,12 @@ xfs_refcount_update_diff_items( const struct list_head *a, const struct list_head *b) { - struct xfs_refcount_intent *ra; - struct xfs_refcount_intent *rb; - - ra = container_of(a, struct xfs_refcount_intent, ri_list); - rb = container_of(b, struct xfs_refcount_intent, ri_list); + struct xfs_refcount_intent *ra = ci_entry(a); + struct xfs_refcount_intent *rb = ci_entry(b); return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno; } -/* Set the phys extent flags for this reverse mapping. */ -static void -xfs_trans_set_refcount_flags( - struct xfs_phys_extent *pmap, - enum xfs_refcount_intent_type type) -{ - pmap->pe_flags = 0; - switch (type) { - case XFS_REFCOUNT_INCREASE: - case XFS_REFCOUNT_DECREASE: - case XFS_REFCOUNT_ALLOC_COW: - case XFS_REFCOUNT_FREE_COW: - pmap->pe_flags |= type; - break; - default: - ASSERT(0); - } -} - /* Log refcount updates in the intent item. */ STATIC void xfs_refcount_update_log_item( @@ -282,7 +267,18 @@ xfs_refcount_update_log_item( pmap = &cuip->cui_format.cui_extents[next_extent]; pmap->pe_startblock = ri->ri_startblock; pmap->pe_len = ri->ri_blockcount; - xfs_trans_set_refcount_flags(pmap, ri->ri_type); + + pmap->pe_flags = 0; + switch (ri->ri_type) { + case XFS_REFCOUNT_INCREASE: + case XFS_REFCOUNT_DECREASE: + case XFS_REFCOUNT_ALLOC_COW: + case XFS_REFCOUNT_FREE_COW: + pmap->pe_flags |= ri->ri_type; + break; + default: + ASSERT(0); + } } static struct xfs_log_item * @@ -324,24 +320,29 @@ xfs_refcount_update_create_done( return &cudp->cud_item; } -/* Take a passive ref to the AG containing the space we're refcounting. */ +/* Add this deferred CUI to the transaction. */ void -xfs_refcount_update_get_group( - struct xfs_mount *mp, +xfs_refcount_defer_add( + struct xfs_trans *tp, struct xfs_refcount_intent *ri) { - xfs_agnumber_t agno; + struct xfs_mount *mp = tp->t_mountp; + + trace_xfs_refcount_defer(mp, ri); - agno = XFS_FSB_TO_AGNO(mp, ri->ri_startblock); - ri->ri_pag = xfs_perag_intent_get(mp, agno); + ri->ri_pag = xfs_perag_intent_get(mp, ri->ri_startblock); + xfs_defer_add(tp, &ri->ri_list, &xfs_refcount_update_defer_type); } -/* Release a passive AG ref after finishing refcounting work. */ -static inline void -xfs_refcount_update_put_group( - struct xfs_refcount_intent *ri) +/* Cancel a deferred refcount update. */ +STATIC void +xfs_refcount_update_cancel_item( + struct list_head *item) { + struct xfs_refcount_intent *ri = ci_entry(item); + xfs_perag_intent_put(ri->ri_pag); + kmem_cache_free(xfs_refcount_intent_cache, ri); } /* Process a deferred refcount update. */ @@ -352,11 +353,9 @@ xfs_refcount_update_finish_item( struct list_head *item, struct xfs_btree_cur **state) { - struct xfs_refcount_intent *ri; + struct xfs_refcount_intent *ri = ci_entry(item); int error; - ri = container_of(item, struct xfs_refcount_intent, ri_list); - /* Did we run out of reservation? Requeue what we didn't finish. */ error = xfs_refcount_finish_one(tp, ri, state); if (!error && ri->ri_blockcount > 0) { @@ -365,30 +364,33 @@ xfs_refcount_update_finish_item( return -EAGAIN; } - xfs_refcount_update_put_group(ri); - kmem_cache_free(xfs_refcount_intent_cache, ri); + xfs_refcount_update_cancel_item(item); return error; } -/* Abort all pending CUIs. */ +/* Clean up after calling xfs_refcount_finish_one. */ STATIC void -xfs_refcount_update_abort_intent( - struct xfs_log_item *intent) +xfs_refcount_finish_one_cleanup( + struct xfs_trans *tp, + struct xfs_btree_cur *rcur, + int error) { - xfs_cui_release(CUI_ITEM(intent)); + struct xfs_buf *agbp; + + if (rcur == NULL) + return; + agbp = rcur->bc_ag.agbp; + xfs_btree_del_cursor(rcur, error); + if (error) + xfs_trans_brelse(tp, agbp); } -/* Cancel a deferred refcount update. */ +/* Abort all pending CUIs. */ STATIC void -xfs_refcount_update_cancel_item( - struct list_head *item) +xfs_refcount_update_abort_intent( + struct xfs_log_item *intent) { - struct xfs_refcount_intent *ri; - - ri = container_of(item, struct xfs_refcount_intent, ri_list); - - xfs_refcount_update_put_group(ri); - kmem_cache_free(xfs_refcount_intent_cache, ri); + xfs_cui_release(CUI_ITEM(intent)); } /* Is this recovered CUI ok? */ @@ -429,7 +431,7 @@ xfs_cui_recover_work( ri->ri_type = pmap->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK; ri->ri_startblock = pmap->pe_startblock; ri->ri_blockcount = pmap->pe_len; - xfs_refcount_update_get_group(mp, ri); + ri->ri_pag = xfs_perag_intent_get(mp, pmap->pe_startblock); xfs_defer_add_item(dfp, &ri->ri_list); } |