162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2016 Oracle. All Rights Reserved. 462306a36Sopenharmony_ci * Author: Darrick J. Wong <darrick.wong@oracle.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include "xfs.h" 762306a36Sopenharmony_ci#include "xfs_fs.h" 862306a36Sopenharmony_ci#include "xfs_format.h" 962306a36Sopenharmony_ci#include "xfs_log_format.h" 1062306a36Sopenharmony_ci#include "xfs_trans_resv.h" 1162306a36Sopenharmony_ci#include "xfs_bit.h" 1262306a36Sopenharmony_ci#include "xfs_shared.h" 1362306a36Sopenharmony_ci#include "xfs_mount.h" 1462306a36Sopenharmony_ci#include "xfs_defer.h" 1562306a36Sopenharmony_ci#include "xfs_inode.h" 1662306a36Sopenharmony_ci#include "xfs_trans.h" 1762306a36Sopenharmony_ci#include "xfs_trans_priv.h" 1862306a36Sopenharmony_ci#include "xfs_bmap_item.h" 1962306a36Sopenharmony_ci#include "xfs_log.h" 2062306a36Sopenharmony_ci#include "xfs_bmap.h" 2162306a36Sopenharmony_ci#include "xfs_icache.h" 2262306a36Sopenharmony_ci#include "xfs_bmap_btree.h" 2362306a36Sopenharmony_ci#include "xfs_trans_space.h" 2462306a36Sopenharmony_ci#include "xfs_error.h" 2562306a36Sopenharmony_ci#include "xfs_log_priv.h" 2662306a36Sopenharmony_ci#include "xfs_log_recover.h" 2762306a36Sopenharmony_ci#include "xfs_ag.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct kmem_cache *xfs_bui_cache; 3062306a36Sopenharmony_cistruct kmem_cache *xfs_bud_cache; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_bui_item_ops; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic inline struct xfs_bui_log_item *BUI_ITEM(struct xfs_log_item *lip) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci return container_of(lip, struct xfs_bui_log_item, bui_item); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciSTATIC void 4062306a36Sopenharmony_cixfs_bui_item_free( 4162306a36Sopenharmony_ci struct xfs_bui_log_item *buip) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci kmem_free(buip->bui_item.li_lv_shadow); 4462306a36Sopenharmony_ci kmem_cache_free(xfs_bui_cache, buip); 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * Freeing the BUI requires that we remove it from the AIL if it has already 4962306a36Sopenharmony_ci * been placed there. However, the BUI may not yet have been placed in the AIL 5062306a36Sopenharmony_ci * when called by xfs_bui_release() from BUD processing due to the ordering of 5162306a36Sopenharmony_ci * committed vs unpin operations in bulk insert operations. Hence the reference 5262306a36Sopenharmony_ci * count to ensure only the last caller frees the BUI. 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_ciSTATIC void 5562306a36Sopenharmony_cixfs_bui_release( 5662306a36Sopenharmony_ci struct xfs_bui_log_item *buip) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci ASSERT(atomic_read(&buip->bui_refcount) > 0); 5962306a36Sopenharmony_ci if (!atomic_dec_and_test(&buip->bui_refcount)) 6062306a36Sopenharmony_ci return; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci xfs_trans_ail_delete(&buip->bui_item, 0); 6362306a36Sopenharmony_ci xfs_bui_item_free(buip); 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciSTATIC void 6862306a36Sopenharmony_cixfs_bui_item_size( 6962306a36Sopenharmony_ci struct xfs_log_item *lip, 7062306a36Sopenharmony_ci int *nvecs, 7162306a36Sopenharmony_ci int *nbytes) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct xfs_bui_log_item *buip = BUI_ITEM(lip); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci *nvecs += 1; 7662306a36Sopenharmony_ci *nbytes += xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* 8062306a36Sopenharmony_ci * This is called to fill in the vector of log iovecs for the 8162306a36Sopenharmony_ci * given bui log item. We use only 1 iovec, and we point that 8262306a36Sopenharmony_ci * at the bui_log_format structure embedded in the bui item. 8362306a36Sopenharmony_ci * It is at this point that we assert that all of the extent 8462306a36Sopenharmony_ci * slots in the bui item have been filled. 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_ciSTATIC void 8762306a36Sopenharmony_cixfs_bui_item_format( 8862306a36Sopenharmony_ci struct xfs_log_item *lip, 8962306a36Sopenharmony_ci struct xfs_log_vec *lv) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct xfs_bui_log_item *buip = BUI_ITEM(lip); 9262306a36Sopenharmony_ci struct xfs_log_iovec *vecp = NULL; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci ASSERT(atomic_read(&buip->bui_next_extent) == 9562306a36Sopenharmony_ci buip->bui_format.bui_nextents); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci buip->bui_format.bui_type = XFS_LI_BUI; 9862306a36Sopenharmony_ci buip->bui_format.bui_size = 1; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUI_FORMAT, &buip->bui_format, 10162306a36Sopenharmony_ci xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents)); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/* 10562306a36Sopenharmony_ci * The unpin operation is the last place an BUI is manipulated in the log. It is 10662306a36Sopenharmony_ci * either inserted in the AIL or aborted in the event of a log I/O error. In 10762306a36Sopenharmony_ci * either case, the BUI transaction has been successfully committed to make it 10862306a36Sopenharmony_ci * this far. Therefore, we expect whoever committed the BUI to either construct 10962306a36Sopenharmony_ci * and commit the BUD or drop the BUD's reference in the event of error. Simply 11062306a36Sopenharmony_ci * drop the log's BUI reference now that the log is done with it. 11162306a36Sopenharmony_ci */ 11262306a36Sopenharmony_ciSTATIC void 11362306a36Sopenharmony_cixfs_bui_item_unpin( 11462306a36Sopenharmony_ci struct xfs_log_item *lip, 11562306a36Sopenharmony_ci int remove) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct xfs_bui_log_item *buip = BUI_ITEM(lip); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci xfs_bui_release(buip); 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* 12362306a36Sopenharmony_ci * The BUI has been either committed or aborted if the transaction has been 12462306a36Sopenharmony_ci * cancelled. If the transaction was cancelled, an BUD isn't going to be 12562306a36Sopenharmony_ci * constructed and thus we free the BUI here directly. 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ciSTATIC void 12862306a36Sopenharmony_cixfs_bui_item_release( 12962306a36Sopenharmony_ci struct xfs_log_item *lip) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci xfs_bui_release(BUI_ITEM(lip)); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/* 13562306a36Sopenharmony_ci * Allocate and initialize an bui item with the given number of extents. 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_ciSTATIC struct xfs_bui_log_item * 13862306a36Sopenharmony_cixfs_bui_init( 13962306a36Sopenharmony_ci struct xfs_mount *mp) 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci struct xfs_bui_log_item *buip; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci buip = kmem_cache_zalloc(xfs_bui_cache, GFP_KERNEL | __GFP_NOFAIL); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops); 14762306a36Sopenharmony_ci buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS; 14862306a36Sopenharmony_ci buip->bui_format.bui_id = (uintptr_t)(void *)buip; 14962306a36Sopenharmony_ci atomic_set(&buip->bui_next_extent, 0); 15062306a36Sopenharmony_ci atomic_set(&buip->bui_refcount, 2); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return buip; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic inline struct xfs_bud_log_item *BUD_ITEM(struct xfs_log_item *lip) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci return container_of(lip, struct xfs_bud_log_item, bud_item); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ciSTATIC void 16162306a36Sopenharmony_cixfs_bud_item_size( 16262306a36Sopenharmony_ci struct xfs_log_item *lip, 16362306a36Sopenharmony_ci int *nvecs, 16462306a36Sopenharmony_ci int *nbytes) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci *nvecs += 1; 16762306a36Sopenharmony_ci *nbytes += sizeof(struct xfs_bud_log_format); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci/* 17162306a36Sopenharmony_ci * This is called to fill in the vector of log iovecs for the 17262306a36Sopenharmony_ci * given bud log item. We use only 1 iovec, and we point that 17362306a36Sopenharmony_ci * at the bud_log_format structure embedded in the bud item. 17462306a36Sopenharmony_ci * It is at this point that we assert that all of the extent 17562306a36Sopenharmony_ci * slots in the bud item have been filled. 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_ciSTATIC void 17862306a36Sopenharmony_cixfs_bud_item_format( 17962306a36Sopenharmony_ci struct xfs_log_item *lip, 18062306a36Sopenharmony_ci struct xfs_log_vec *lv) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci struct xfs_bud_log_item *budp = BUD_ITEM(lip); 18362306a36Sopenharmony_ci struct xfs_log_iovec *vecp = NULL; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci budp->bud_format.bud_type = XFS_LI_BUD; 18662306a36Sopenharmony_ci budp->bud_format.bud_size = 1; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUD_FORMAT, &budp->bud_format, 18962306a36Sopenharmony_ci sizeof(struct xfs_bud_log_format)); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci/* 19362306a36Sopenharmony_ci * The BUD is either committed or aborted if the transaction is cancelled. If 19462306a36Sopenharmony_ci * the transaction is cancelled, drop our reference to the BUI and free the 19562306a36Sopenharmony_ci * BUD. 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_ciSTATIC void 19862306a36Sopenharmony_cixfs_bud_item_release( 19962306a36Sopenharmony_ci struct xfs_log_item *lip) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct xfs_bud_log_item *budp = BUD_ITEM(lip); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci xfs_bui_release(budp->bud_buip); 20462306a36Sopenharmony_ci kmem_free(budp->bud_item.li_lv_shadow); 20562306a36Sopenharmony_ci kmem_cache_free(xfs_bud_cache, budp); 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic struct xfs_log_item * 20962306a36Sopenharmony_cixfs_bud_item_intent( 21062306a36Sopenharmony_ci struct xfs_log_item *lip) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci return &BUD_ITEM(lip)->bud_buip->bui_item; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_bud_item_ops = { 21662306a36Sopenharmony_ci .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED | 21762306a36Sopenharmony_ci XFS_ITEM_INTENT_DONE, 21862306a36Sopenharmony_ci .iop_size = xfs_bud_item_size, 21962306a36Sopenharmony_ci .iop_format = xfs_bud_item_format, 22062306a36Sopenharmony_ci .iop_release = xfs_bud_item_release, 22162306a36Sopenharmony_ci .iop_intent = xfs_bud_item_intent, 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic struct xfs_bud_log_item * 22562306a36Sopenharmony_cixfs_trans_get_bud( 22662306a36Sopenharmony_ci struct xfs_trans *tp, 22762306a36Sopenharmony_ci struct xfs_bui_log_item *buip) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct xfs_bud_log_item *budp; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci budp = kmem_cache_zalloc(xfs_bud_cache, GFP_KERNEL | __GFP_NOFAIL); 23262306a36Sopenharmony_ci xfs_log_item_init(tp->t_mountp, &budp->bud_item, XFS_LI_BUD, 23362306a36Sopenharmony_ci &xfs_bud_item_ops); 23462306a36Sopenharmony_ci budp->bud_buip = buip; 23562306a36Sopenharmony_ci budp->bud_format.bud_bui_id = buip->bui_format.bui_id; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci xfs_trans_add_item(tp, &budp->bud_item); 23862306a36Sopenharmony_ci return budp; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci/* 24262306a36Sopenharmony_ci * Finish an bmap update and log it to the BUD. Note that the 24362306a36Sopenharmony_ci * transaction is marked dirty regardless of whether the bmap update 24462306a36Sopenharmony_ci * succeeds or fails to support the BUI/BUD lifecycle rules. 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_cistatic int 24762306a36Sopenharmony_cixfs_trans_log_finish_bmap_update( 24862306a36Sopenharmony_ci struct xfs_trans *tp, 24962306a36Sopenharmony_ci struct xfs_bud_log_item *budp, 25062306a36Sopenharmony_ci struct xfs_bmap_intent *bi) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci int error; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci error = xfs_bmap_finish_one(tp, bi); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* 25762306a36Sopenharmony_ci * Mark the transaction dirty, even on error. This ensures the 25862306a36Sopenharmony_ci * transaction is aborted, which: 25962306a36Sopenharmony_ci * 26062306a36Sopenharmony_ci * 1.) releases the BUI and frees the BUD 26162306a36Sopenharmony_ci * 2.) shuts down the filesystem 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE; 26462306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci return error; 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci/* Sort bmap intents by inode. */ 27062306a36Sopenharmony_cistatic int 27162306a36Sopenharmony_cixfs_bmap_update_diff_items( 27262306a36Sopenharmony_ci void *priv, 27362306a36Sopenharmony_ci const struct list_head *a, 27462306a36Sopenharmony_ci const struct list_head *b) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci struct xfs_bmap_intent *ba; 27762306a36Sopenharmony_ci struct xfs_bmap_intent *bb; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci ba = container_of(a, struct xfs_bmap_intent, bi_list); 28062306a36Sopenharmony_ci bb = container_of(b, struct xfs_bmap_intent, bi_list); 28162306a36Sopenharmony_ci return ba->bi_owner->i_ino - bb->bi_owner->i_ino; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci/* Set the map extent flags for this mapping. */ 28562306a36Sopenharmony_cistatic void 28662306a36Sopenharmony_cixfs_trans_set_bmap_flags( 28762306a36Sopenharmony_ci struct xfs_map_extent *map, 28862306a36Sopenharmony_ci enum xfs_bmap_intent_type type, 28962306a36Sopenharmony_ci int whichfork, 29062306a36Sopenharmony_ci xfs_exntst_t state) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci map->me_flags = 0; 29362306a36Sopenharmony_ci switch (type) { 29462306a36Sopenharmony_ci case XFS_BMAP_MAP: 29562306a36Sopenharmony_ci case XFS_BMAP_UNMAP: 29662306a36Sopenharmony_ci map->me_flags = type; 29762306a36Sopenharmony_ci break; 29862306a36Sopenharmony_ci default: 29962306a36Sopenharmony_ci ASSERT(0); 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci if (state == XFS_EXT_UNWRITTEN) 30262306a36Sopenharmony_ci map->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN; 30362306a36Sopenharmony_ci if (whichfork == XFS_ATTR_FORK) 30462306a36Sopenharmony_ci map->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci/* Log bmap updates in the intent item. */ 30862306a36Sopenharmony_ciSTATIC void 30962306a36Sopenharmony_cixfs_bmap_update_log_item( 31062306a36Sopenharmony_ci struct xfs_trans *tp, 31162306a36Sopenharmony_ci struct xfs_bui_log_item *buip, 31262306a36Sopenharmony_ci struct xfs_bmap_intent *bi) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci uint next_extent; 31562306a36Sopenharmony_ci struct xfs_map_extent *map; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY; 31862306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* 32162306a36Sopenharmony_ci * atomic_inc_return gives us the value after the increment; 32262306a36Sopenharmony_ci * we want to use it as an array index so we need to subtract 1 from 32362306a36Sopenharmony_ci * it. 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_ci next_extent = atomic_inc_return(&buip->bui_next_extent) - 1; 32662306a36Sopenharmony_ci ASSERT(next_extent < buip->bui_format.bui_nextents); 32762306a36Sopenharmony_ci map = &buip->bui_format.bui_extents[next_extent]; 32862306a36Sopenharmony_ci map->me_owner = bi->bi_owner->i_ino; 32962306a36Sopenharmony_ci map->me_startblock = bi->bi_bmap.br_startblock; 33062306a36Sopenharmony_ci map->me_startoff = bi->bi_bmap.br_startoff; 33162306a36Sopenharmony_ci map->me_len = bi->bi_bmap.br_blockcount; 33262306a36Sopenharmony_ci xfs_trans_set_bmap_flags(map, bi->bi_type, bi->bi_whichfork, 33362306a36Sopenharmony_ci bi->bi_bmap.br_state); 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic struct xfs_log_item * 33762306a36Sopenharmony_cixfs_bmap_update_create_intent( 33862306a36Sopenharmony_ci struct xfs_trans *tp, 33962306a36Sopenharmony_ci struct list_head *items, 34062306a36Sopenharmony_ci unsigned int count, 34162306a36Sopenharmony_ci bool sort) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 34462306a36Sopenharmony_ci struct xfs_bui_log_item *buip = xfs_bui_init(mp); 34562306a36Sopenharmony_ci struct xfs_bmap_intent *bi; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci xfs_trans_add_item(tp, &buip->bui_item); 35062306a36Sopenharmony_ci if (sort) 35162306a36Sopenharmony_ci list_sort(mp, items, xfs_bmap_update_diff_items); 35262306a36Sopenharmony_ci list_for_each_entry(bi, items, bi_list) 35362306a36Sopenharmony_ci xfs_bmap_update_log_item(tp, buip, bi); 35462306a36Sopenharmony_ci return &buip->bui_item; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci/* Get an BUD so we can process all the deferred rmap updates. */ 35862306a36Sopenharmony_cistatic struct xfs_log_item * 35962306a36Sopenharmony_cixfs_bmap_update_create_done( 36062306a36Sopenharmony_ci struct xfs_trans *tp, 36162306a36Sopenharmony_ci struct xfs_log_item *intent, 36262306a36Sopenharmony_ci unsigned int count) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci return &xfs_trans_get_bud(tp, BUI_ITEM(intent))->bud_item; 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/* Take a passive ref to the AG containing the space we're mapping. */ 36862306a36Sopenharmony_civoid 36962306a36Sopenharmony_cixfs_bmap_update_get_group( 37062306a36Sopenharmony_ci struct xfs_mount *mp, 37162306a36Sopenharmony_ci struct xfs_bmap_intent *bi) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci xfs_agnumber_t agno; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci agno = XFS_FSB_TO_AGNO(mp, bi->bi_bmap.br_startblock); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* 37862306a36Sopenharmony_ci * Bump the intent count on behalf of the deferred rmap and refcount 37962306a36Sopenharmony_ci * intent items that that we can queue when we finish this bmap work. 38062306a36Sopenharmony_ci * This new intent item will bump the intent count before the bmap 38162306a36Sopenharmony_ci * intent drops the intent count, ensuring that the intent count 38262306a36Sopenharmony_ci * remains nonzero across the transaction roll. 38362306a36Sopenharmony_ci */ 38462306a36Sopenharmony_ci bi->bi_pag = xfs_perag_intent_get(mp, agno); 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci/* Release a passive AG ref after finishing mapping work. */ 38862306a36Sopenharmony_cistatic inline void 38962306a36Sopenharmony_cixfs_bmap_update_put_group( 39062306a36Sopenharmony_ci struct xfs_bmap_intent *bi) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci xfs_perag_intent_put(bi->bi_pag); 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci/* Process a deferred rmap update. */ 39662306a36Sopenharmony_ciSTATIC int 39762306a36Sopenharmony_cixfs_bmap_update_finish_item( 39862306a36Sopenharmony_ci struct xfs_trans *tp, 39962306a36Sopenharmony_ci struct xfs_log_item *done, 40062306a36Sopenharmony_ci struct list_head *item, 40162306a36Sopenharmony_ci struct xfs_btree_cur **state) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci struct xfs_bmap_intent *bi; 40462306a36Sopenharmony_ci int error; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci bi = container_of(item, struct xfs_bmap_intent, bi_list); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci error = xfs_trans_log_finish_bmap_update(tp, BUD_ITEM(done), bi); 40962306a36Sopenharmony_ci if (!error && bi->bi_bmap.br_blockcount > 0) { 41062306a36Sopenharmony_ci ASSERT(bi->bi_type == XFS_BMAP_UNMAP); 41162306a36Sopenharmony_ci return -EAGAIN; 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci xfs_bmap_update_put_group(bi); 41562306a36Sopenharmony_ci kmem_cache_free(xfs_bmap_intent_cache, bi); 41662306a36Sopenharmony_ci return error; 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci/* Abort all pending BUIs. */ 42062306a36Sopenharmony_ciSTATIC void 42162306a36Sopenharmony_cixfs_bmap_update_abort_intent( 42262306a36Sopenharmony_ci struct xfs_log_item *intent) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci xfs_bui_release(BUI_ITEM(intent)); 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci/* Cancel a deferred bmap update. */ 42862306a36Sopenharmony_ciSTATIC void 42962306a36Sopenharmony_cixfs_bmap_update_cancel_item( 43062306a36Sopenharmony_ci struct list_head *item) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci struct xfs_bmap_intent *bi; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci bi = container_of(item, struct xfs_bmap_intent, bi_list); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci xfs_bmap_update_put_group(bi); 43762306a36Sopenharmony_ci kmem_cache_free(xfs_bmap_intent_cache, bi); 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ciconst struct xfs_defer_op_type xfs_bmap_update_defer_type = { 44162306a36Sopenharmony_ci .max_items = XFS_BUI_MAX_FAST_EXTENTS, 44262306a36Sopenharmony_ci .create_intent = xfs_bmap_update_create_intent, 44362306a36Sopenharmony_ci .abort_intent = xfs_bmap_update_abort_intent, 44462306a36Sopenharmony_ci .create_done = xfs_bmap_update_create_done, 44562306a36Sopenharmony_ci .finish_item = xfs_bmap_update_finish_item, 44662306a36Sopenharmony_ci .cancel_item = xfs_bmap_update_cancel_item, 44762306a36Sopenharmony_ci}; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci/* Is this recovered BUI ok? */ 45062306a36Sopenharmony_cistatic inline bool 45162306a36Sopenharmony_cixfs_bui_validate( 45262306a36Sopenharmony_ci struct xfs_mount *mp, 45362306a36Sopenharmony_ci struct xfs_bui_log_item *buip) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci struct xfs_map_extent *map; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* Only one mapping operation per BUI... */ 45862306a36Sopenharmony_ci if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) 45962306a36Sopenharmony_ci return false; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci map = &buip->bui_format.bui_extents[0]; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (map->me_flags & ~XFS_BMAP_EXTENT_FLAGS) 46462306a36Sopenharmony_ci return false; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci switch (map->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) { 46762306a36Sopenharmony_ci case XFS_BMAP_MAP: 46862306a36Sopenharmony_ci case XFS_BMAP_UNMAP: 46962306a36Sopenharmony_ci break; 47062306a36Sopenharmony_ci default: 47162306a36Sopenharmony_ci return false; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci if (!xfs_verify_ino(mp, map->me_owner)) 47562306a36Sopenharmony_ci return false; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len)) 47862306a36Sopenharmony_ci return false; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci return xfs_verify_fsbext(mp, map->me_startblock, map->me_len); 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci/* 48462306a36Sopenharmony_ci * Process a bmap update intent item that was recovered from the log. 48562306a36Sopenharmony_ci * We need to update some inode's bmbt. 48662306a36Sopenharmony_ci */ 48762306a36Sopenharmony_ciSTATIC int 48862306a36Sopenharmony_cixfs_bui_item_recover( 48962306a36Sopenharmony_ci struct xfs_log_item *lip, 49062306a36Sopenharmony_ci struct list_head *capture_list) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci struct xfs_bmap_intent fake = { }; 49362306a36Sopenharmony_ci struct xfs_trans_res resv; 49462306a36Sopenharmony_ci struct xfs_bui_log_item *buip = BUI_ITEM(lip); 49562306a36Sopenharmony_ci struct xfs_trans *tp; 49662306a36Sopenharmony_ci struct xfs_inode *ip = NULL; 49762306a36Sopenharmony_ci struct xfs_mount *mp = lip->li_log->l_mp; 49862306a36Sopenharmony_ci struct xfs_map_extent *map; 49962306a36Sopenharmony_ci struct xfs_bud_log_item *budp; 50062306a36Sopenharmony_ci int iext_delta; 50162306a36Sopenharmony_ci int error = 0; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (!xfs_bui_validate(mp, buip)) { 50462306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 50562306a36Sopenharmony_ci &buip->bui_format, sizeof(buip->bui_format)); 50662306a36Sopenharmony_ci return -EFSCORRUPTED; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci map = &buip->bui_format.bui_extents[0]; 51062306a36Sopenharmony_ci fake.bi_whichfork = (map->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ? 51162306a36Sopenharmony_ci XFS_ATTR_FORK : XFS_DATA_FORK; 51262306a36Sopenharmony_ci fake.bi_type = map->me_flags & XFS_BMAP_EXTENT_TYPE_MASK; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci error = xlog_recover_iget(mp, map->me_owner, &ip); 51562306a36Sopenharmony_ci if (error) 51662306a36Sopenharmony_ci return error; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* Allocate transaction and do the work. */ 51962306a36Sopenharmony_ci resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate); 52062306a36Sopenharmony_ci error = xfs_trans_alloc(mp, &resv, 52162306a36Sopenharmony_ci XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp); 52262306a36Sopenharmony_ci if (error) 52362306a36Sopenharmony_ci goto err_rele; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci budp = xfs_trans_get_bud(tp, buip); 52662306a36Sopenharmony_ci xfs_ilock(ip, XFS_ILOCK_EXCL); 52762306a36Sopenharmony_ci xfs_trans_ijoin(tp, ip, 0); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (fake.bi_type == XFS_BMAP_MAP) 53062306a36Sopenharmony_ci iext_delta = XFS_IEXT_ADD_NOSPLIT_CNT; 53162306a36Sopenharmony_ci else 53262306a36Sopenharmony_ci iext_delta = XFS_IEXT_PUNCH_HOLE_CNT; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci error = xfs_iext_count_may_overflow(ip, fake.bi_whichfork, iext_delta); 53562306a36Sopenharmony_ci if (error == -EFBIG) 53662306a36Sopenharmony_ci error = xfs_iext_count_upgrade(tp, ip, iext_delta); 53762306a36Sopenharmony_ci if (error) 53862306a36Sopenharmony_ci goto err_cancel; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci fake.bi_owner = ip; 54162306a36Sopenharmony_ci fake.bi_bmap.br_startblock = map->me_startblock; 54262306a36Sopenharmony_ci fake.bi_bmap.br_startoff = map->me_startoff; 54362306a36Sopenharmony_ci fake.bi_bmap.br_blockcount = map->me_len; 54462306a36Sopenharmony_ci fake.bi_bmap.br_state = (map->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ? 54562306a36Sopenharmony_ci XFS_EXT_UNWRITTEN : XFS_EXT_NORM; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci xfs_bmap_update_get_group(mp, &fake); 54862306a36Sopenharmony_ci error = xfs_trans_log_finish_bmap_update(tp, budp, &fake); 54962306a36Sopenharmony_ci if (error == -EFSCORRUPTED) 55062306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, map, 55162306a36Sopenharmony_ci sizeof(*map)); 55262306a36Sopenharmony_ci xfs_bmap_update_put_group(&fake); 55362306a36Sopenharmony_ci if (error) 55462306a36Sopenharmony_ci goto err_cancel; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (fake.bi_bmap.br_blockcount > 0) { 55762306a36Sopenharmony_ci ASSERT(fake.bi_type == XFS_BMAP_UNMAP); 55862306a36Sopenharmony_ci xfs_bmap_unmap_extent(tp, ip, &fake.bi_bmap); 55962306a36Sopenharmony_ci } 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci /* 56262306a36Sopenharmony_ci * Commit transaction, which frees the transaction and saves the inode 56362306a36Sopenharmony_ci * for later replay activities. 56462306a36Sopenharmony_ci */ 56562306a36Sopenharmony_ci error = xfs_defer_ops_capture_and_commit(tp, capture_list); 56662306a36Sopenharmony_ci if (error) 56762306a36Sopenharmony_ci goto err_unlock; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci xfs_iunlock(ip, XFS_ILOCK_EXCL); 57062306a36Sopenharmony_ci xfs_irele(ip); 57162306a36Sopenharmony_ci return 0; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cierr_cancel: 57462306a36Sopenharmony_ci xfs_trans_cancel(tp); 57562306a36Sopenharmony_cierr_unlock: 57662306a36Sopenharmony_ci xfs_iunlock(ip, XFS_ILOCK_EXCL); 57762306a36Sopenharmony_cierr_rele: 57862306a36Sopenharmony_ci xfs_irele(ip); 57962306a36Sopenharmony_ci return error; 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ciSTATIC bool 58362306a36Sopenharmony_cixfs_bui_item_match( 58462306a36Sopenharmony_ci struct xfs_log_item *lip, 58562306a36Sopenharmony_ci uint64_t intent_id) 58662306a36Sopenharmony_ci{ 58762306a36Sopenharmony_ci return BUI_ITEM(lip)->bui_format.bui_id == intent_id; 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci/* Relog an intent item to push the log tail forward. */ 59162306a36Sopenharmony_cistatic struct xfs_log_item * 59262306a36Sopenharmony_cixfs_bui_item_relog( 59362306a36Sopenharmony_ci struct xfs_log_item *intent, 59462306a36Sopenharmony_ci struct xfs_trans *tp) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci struct xfs_bud_log_item *budp; 59762306a36Sopenharmony_ci struct xfs_bui_log_item *buip; 59862306a36Sopenharmony_ci struct xfs_map_extent *map; 59962306a36Sopenharmony_ci unsigned int count; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci count = BUI_ITEM(intent)->bui_format.bui_nextents; 60262306a36Sopenharmony_ci map = BUI_ITEM(intent)->bui_format.bui_extents; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY; 60562306a36Sopenharmony_ci budp = xfs_trans_get_bud(tp, BUI_ITEM(intent)); 60662306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci buip = xfs_bui_init(tp->t_mountp); 60962306a36Sopenharmony_ci memcpy(buip->bui_format.bui_extents, map, count * sizeof(*map)); 61062306a36Sopenharmony_ci atomic_set(&buip->bui_next_extent, count); 61162306a36Sopenharmony_ci xfs_trans_add_item(tp, &buip->bui_item); 61262306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags); 61362306a36Sopenharmony_ci return &buip->bui_item; 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_bui_item_ops = { 61762306a36Sopenharmony_ci .flags = XFS_ITEM_INTENT, 61862306a36Sopenharmony_ci .iop_size = xfs_bui_item_size, 61962306a36Sopenharmony_ci .iop_format = xfs_bui_item_format, 62062306a36Sopenharmony_ci .iop_unpin = xfs_bui_item_unpin, 62162306a36Sopenharmony_ci .iop_release = xfs_bui_item_release, 62262306a36Sopenharmony_ci .iop_recover = xfs_bui_item_recover, 62362306a36Sopenharmony_ci .iop_match = xfs_bui_item_match, 62462306a36Sopenharmony_ci .iop_relog = xfs_bui_item_relog, 62562306a36Sopenharmony_ci}; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_cistatic inline void 62862306a36Sopenharmony_cixfs_bui_copy_format( 62962306a36Sopenharmony_ci struct xfs_bui_log_format *dst, 63062306a36Sopenharmony_ci const struct xfs_bui_log_format *src) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci unsigned int i; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci memcpy(dst, src, offsetof(struct xfs_bui_log_format, bui_extents)); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci for (i = 0; i < src->bui_nextents; i++) 63762306a36Sopenharmony_ci memcpy(&dst->bui_extents[i], &src->bui_extents[i], 63862306a36Sopenharmony_ci sizeof(struct xfs_map_extent)); 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci/* 64262306a36Sopenharmony_ci * This routine is called to create an in-core extent bmap update 64362306a36Sopenharmony_ci * item from the bui format structure which was logged on disk. 64462306a36Sopenharmony_ci * It allocates an in-core bui, copies the extents from the format 64562306a36Sopenharmony_ci * structure into it, and adds the bui to the AIL with the given 64662306a36Sopenharmony_ci * LSN. 64762306a36Sopenharmony_ci */ 64862306a36Sopenharmony_ciSTATIC int 64962306a36Sopenharmony_cixlog_recover_bui_commit_pass2( 65062306a36Sopenharmony_ci struct xlog *log, 65162306a36Sopenharmony_ci struct list_head *buffer_list, 65262306a36Sopenharmony_ci struct xlog_recover_item *item, 65362306a36Sopenharmony_ci xfs_lsn_t lsn) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci struct xfs_mount *mp = log->l_mp; 65662306a36Sopenharmony_ci struct xfs_bui_log_item *buip; 65762306a36Sopenharmony_ci struct xfs_bui_log_format *bui_formatp; 65862306a36Sopenharmony_ci size_t len; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci bui_formatp = item->ri_buf[0].i_addr; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci if (item->ri_buf[0].i_len < xfs_bui_log_format_sizeof(0)) { 66362306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 66462306a36Sopenharmony_ci item->ri_buf[0].i_addr, item->ri_buf[0].i_len); 66562306a36Sopenharmony_ci return -EFSCORRUPTED; 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) { 66962306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 67062306a36Sopenharmony_ci item->ri_buf[0].i_addr, item->ri_buf[0].i_len); 67162306a36Sopenharmony_ci return -EFSCORRUPTED; 67262306a36Sopenharmony_ci } 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci len = xfs_bui_log_format_sizeof(bui_formatp->bui_nextents); 67562306a36Sopenharmony_ci if (item->ri_buf[0].i_len != len) { 67662306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 67762306a36Sopenharmony_ci item->ri_buf[0].i_addr, item->ri_buf[0].i_len); 67862306a36Sopenharmony_ci return -EFSCORRUPTED; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci buip = xfs_bui_init(mp); 68262306a36Sopenharmony_ci xfs_bui_copy_format(&buip->bui_format, bui_formatp); 68362306a36Sopenharmony_ci atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents); 68462306a36Sopenharmony_ci /* 68562306a36Sopenharmony_ci * Insert the intent into the AIL directly and drop one reference so 68662306a36Sopenharmony_ci * that finishing or canceling the work will drop the other. 68762306a36Sopenharmony_ci */ 68862306a36Sopenharmony_ci xfs_trans_ail_insert(log->l_ailp, &buip->bui_item, lsn); 68962306a36Sopenharmony_ci xfs_bui_release(buip); 69062306a36Sopenharmony_ci return 0; 69162306a36Sopenharmony_ci} 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ciconst struct xlog_recover_item_ops xlog_bui_item_ops = { 69462306a36Sopenharmony_ci .item_type = XFS_LI_BUI, 69562306a36Sopenharmony_ci .commit_pass2 = xlog_recover_bui_commit_pass2, 69662306a36Sopenharmony_ci}; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci/* 69962306a36Sopenharmony_ci * This routine is called when an BUD format structure is found in a committed 70062306a36Sopenharmony_ci * transaction in the log. Its purpose is to cancel the corresponding BUI if it 70162306a36Sopenharmony_ci * was still in the log. To do this it searches the AIL for the BUI with an id 70262306a36Sopenharmony_ci * equal to that in the BUD format structure. If we find it we drop the BUD 70362306a36Sopenharmony_ci * reference, which removes the BUI from the AIL and frees it. 70462306a36Sopenharmony_ci */ 70562306a36Sopenharmony_ciSTATIC int 70662306a36Sopenharmony_cixlog_recover_bud_commit_pass2( 70762306a36Sopenharmony_ci struct xlog *log, 70862306a36Sopenharmony_ci struct list_head *buffer_list, 70962306a36Sopenharmony_ci struct xlog_recover_item *item, 71062306a36Sopenharmony_ci xfs_lsn_t lsn) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci struct xfs_bud_log_format *bud_formatp; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci bud_formatp = item->ri_buf[0].i_addr; 71562306a36Sopenharmony_ci if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) { 71662306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp, 71762306a36Sopenharmony_ci item->ri_buf[0].i_addr, item->ri_buf[0].i_len); 71862306a36Sopenharmony_ci return -EFSCORRUPTED; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci xlog_recover_release_intent(log, XFS_LI_BUI, bud_formatp->bud_bui_id); 72262306a36Sopenharmony_ci return 0; 72362306a36Sopenharmony_ci} 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ciconst struct xlog_recover_item_ops xlog_bud_item_ops = { 72662306a36Sopenharmony_ci .item_type = XFS_LI_BUD, 72762306a36Sopenharmony_ci .commit_pass2 = xlog_recover_bud_commit_pass2, 72862306a36Sopenharmony_ci}; 729