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_trans.h" 1662306a36Sopenharmony_ci#include "xfs_trans_priv.h" 1762306a36Sopenharmony_ci#include "xfs_rmap_item.h" 1862306a36Sopenharmony_ci#include "xfs_log.h" 1962306a36Sopenharmony_ci#include "xfs_rmap.h" 2062306a36Sopenharmony_ci#include "xfs_error.h" 2162306a36Sopenharmony_ci#include "xfs_log_priv.h" 2262306a36Sopenharmony_ci#include "xfs_log_recover.h" 2362306a36Sopenharmony_ci#include "xfs_ag.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct kmem_cache *xfs_rui_cache; 2662306a36Sopenharmony_cistruct kmem_cache *xfs_rud_cache; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_rui_item_ops; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic inline struct xfs_rui_log_item *RUI_ITEM(struct xfs_log_item *lip) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci return container_of(lip, struct xfs_rui_log_item, rui_item); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciSTATIC void 3662306a36Sopenharmony_cixfs_rui_item_free( 3762306a36Sopenharmony_ci struct xfs_rui_log_item *ruip) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci kmem_free(ruip->rui_item.li_lv_shadow); 4062306a36Sopenharmony_ci if (ruip->rui_format.rui_nextents > XFS_RUI_MAX_FAST_EXTENTS) 4162306a36Sopenharmony_ci kmem_free(ruip); 4262306a36Sopenharmony_ci else 4362306a36Sopenharmony_ci kmem_cache_free(xfs_rui_cache, ruip); 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* 4762306a36Sopenharmony_ci * Freeing the RUI requires that we remove it from the AIL if it has already 4862306a36Sopenharmony_ci * been placed there. However, the RUI may not yet have been placed in the AIL 4962306a36Sopenharmony_ci * when called by xfs_rui_release() from RUD processing due to the ordering of 5062306a36Sopenharmony_ci * committed vs unpin operations in bulk insert operations. Hence the reference 5162306a36Sopenharmony_ci * count to ensure only the last caller frees the RUI. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ciSTATIC void 5462306a36Sopenharmony_cixfs_rui_release( 5562306a36Sopenharmony_ci struct xfs_rui_log_item *ruip) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci ASSERT(atomic_read(&ruip->rui_refcount) > 0); 5862306a36Sopenharmony_ci if (!atomic_dec_and_test(&ruip->rui_refcount)) 5962306a36Sopenharmony_ci return; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci xfs_trans_ail_delete(&ruip->rui_item, 0); 6262306a36Sopenharmony_ci xfs_rui_item_free(ruip); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciSTATIC void 6662306a36Sopenharmony_cixfs_rui_item_size( 6762306a36Sopenharmony_ci struct xfs_log_item *lip, 6862306a36Sopenharmony_ci int *nvecs, 6962306a36Sopenharmony_ci int *nbytes) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct xfs_rui_log_item *ruip = RUI_ITEM(lip); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci *nvecs += 1; 7462306a36Sopenharmony_ci *nbytes += xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* 7862306a36Sopenharmony_ci * This is called to fill in the vector of log iovecs for the 7962306a36Sopenharmony_ci * given rui log item. We use only 1 iovec, and we point that 8062306a36Sopenharmony_ci * at the rui_log_format structure embedded in the rui item. 8162306a36Sopenharmony_ci * It is at this point that we assert that all of the extent 8262306a36Sopenharmony_ci * slots in the rui item have been filled. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ciSTATIC void 8562306a36Sopenharmony_cixfs_rui_item_format( 8662306a36Sopenharmony_ci struct xfs_log_item *lip, 8762306a36Sopenharmony_ci struct xfs_log_vec *lv) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci struct xfs_rui_log_item *ruip = RUI_ITEM(lip); 9062306a36Sopenharmony_ci struct xfs_log_iovec *vecp = NULL; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci ASSERT(atomic_read(&ruip->rui_next_extent) == 9362306a36Sopenharmony_ci ruip->rui_format.rui_nextents); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci ruip->rui_format.rui_type = XFS_LI_RUI; 9662306a36Sopenharmony_ci ruip->rui_format.rui_size = 1; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUI_FORMAT, &ruip->rui_format, 9962306a36Sopenharmony_ci xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents)); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* 10362306a36Sopenharmony_ci * The unpin operation is the last place an RUI is manipulated in the log. It is 10462306a36Sopenharmony_ci * either inserted in the AIL or aborted in the event of a log I/O error. In 10562306a36Sopenharmony_ci * either case, the RUI transaction has been successfully committed to make it 10662306a36Sopenharmony_ci * this far. Therefore, we expect whoever committed the RUI to either construct 10762306a36Sopenharmony_ci * and commit the RUD or drop the RUD's reference in the event of error. Simply 10862306a36Sopenharmony_ci * drop the log's RUI reference now that the log is done with it. 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_ciSTATIC void 11162306a36Sopenharmony_cixfs_rui_item_unpin( 11262306a36Sopenharmony_ci struct xfs_log_item *lip, 11362306a36Sopenharmony_ci int remove) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct xfs_rui_log_item *ruip = RUI_ITEM(lip); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci xfs_rui_release(ruip); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* 12162306a36Sopenharmony_ci * The RUI has been either committed or aborted if the transaction has been 12262306a36Sopenharmony_ci * cancelled. If the transaction was cancelled, an RUD isn't going to be 12362306a36Sopenharmony_ci * constructed and thus we free the RUI here directly. 12462306a36Sopenharmony_ci */ 12562306a36Sopenharmony_ciSTATIC void 12662306a36Sopenharmony_cixfs_rui_item_release( 12762306a36Sopenharmony_ci struct xfs_log_item *lip) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci xfs_rui_release(RUI_ITEM(lip)); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci/* 13362306a36Sopenharmony_ci * Allocate and initialize an rui item with the given number of extents. 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ciSTATIC struct xfs_rui_log_item * 13662306a36Sopenharmony_cixfs_rui_init( 13762306a36Sopenharmony_ci struct xfs_mount *mp, 13862306a36Sopenharmony_ci uint nextents) 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci struct xfs_rui_log_item *ruip; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci ASSERT(nextents > 0); 14462306a36Sopenharmony_ci if (nextents > XFS_RUI_MAX_FAST_EXTENTS) 14562306a36Sopenharmony_ci ruip = kmem_zalloc(xfs_rui_log_item_sizeof(nextents), 0); 14662306a36Sopenharmony_ci else 14762306a36Sopenharmony_ci ruip = kmem_cache_zalloc(xfs_rui_cache, 14862306a36Sopenharmony_ci GFP_KERNEL | __GFP_NOFAIL); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci xfs_log_item_init(mp, &ruip->rui_item, XFS_LI_RUI, &xfs_rui_item_ops); 15162306a36Sopenharmony_ci ruip->rui_format.rui_nextents = nextents; 15262306a36Sopenharmony_ci ruip->rui_format.rui_id = (uintptr_t)(void *)ruip; 15362306a36Sopenharmony_ci atomic_set(&ruip->rui_next_extent, 0); 15462306a36Sopenharmony_ci atomic_set(&ruip->rui_refcount, 2); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return ruip; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic inline struct xfs_rud_log_item *RUD_ITEM(struct xfs_log_item *lip) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci return container_of(lip, struct xfs_rud_log_item, rud_item); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciSTATIC void 16562306a36Sopenharmony_cixfs_rud_item_size( 16662306a36Sopenharmony_ci struct xfs_log_item *lip, 16762306a36Sopenharmony_ci int *nvecs, 16862306a36Sopenharmony_ci int *nbytes) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci *nvecs += 1; 17162306a36Sopenharmony_ci *nbytes += sizeof(struct xfs_rud_log_format); 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* 17562306a36Sopenharmony_ci * This is called to fill in the vector of log iovecs for the 17662306a36Sopenharmony_ci * given rud log item. We use only 1 iovec, and we point that 17762306a36Sopenharmony_ci * at the rud_log_format structure embedded in the rud item. 17862306a36Sopenharmony_ci * It is at this point that we assert that all of the extent 17962306a36Sopenharmony_ci * slots in the rud item have been filled. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ciSTATIC void 18262306a36Sopenharmony_cixfs_rud_item_format( 18362306a36Sopenharmony_ci struct xfs_log_item *lip, 18462306a36Sopenharmony_ci struct xfs_log_vec *lv) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct xfs_rud_log_item *rudp = RUD_ITEM(lip); 18762306a36Sopenharmony_ci struct xfs_log_iovec *vecp = NULL; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci rudp->rud_format.rud_type = XFS_LI_RUD; 19062306a36Sopenharmony_ci rudp->rud_format.rud_size = 1; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUD_FORMAT, &rudp->rud_format, 19362306a36Sopenharmony_ci sizeof(struct xfs_rud_log_format)); 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci/* 19762306a36Sopenharmony_ci * The RUD is either committed or aborted if the transaction is cancelled. If 19862306a36Sopenharmony_ci * the transaction is cancelled, drop our reference to the RUI and free the 19962306a36Sopenharmony_ci * RUD. 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ciSTATIC void 20262306a36Sopenharmony_cixfs_rud_item_release( 20362306a36Sopenharmony_ci struct xfs_log_item *lip) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct xfs_rud_log_item *rudp = RUD_ITEM(lip); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci xfs_rui_release(rudp->rud_ruip); 20862306a36Sopenharmony_ci kmem_free(rudp->rud_item.li_lv_shadow); 20962306a36Sopenharmony_ci kmem_cache_free(xfs_rud_cache, rudp); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic struct xfs_log_item * 21362306a36Sopenharmony_cixfs_rud_item_intent( 21462306a36Sopenharmony_ci struct xfs_log_item *lip) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci return &RUD_ITEM(lip)->rud_ruip->rui_item; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_rud_item_ops = { 22062306a36Sopenharmony_ci .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED | 22162306a36Sopenharmony_ci XFS_ITEM_INTENT_DONE, 22262306a36Sopenharmony_ci .iop_size = xfs_rud_item_size, 22362306a36Sopenharmony_ci .iop_format = xfs_rud_item_format, 22462306a36Sopenharmony_ci .iop_release = xfs_rud_item_release, 22562306a36Sopenharmony_ci .iop_intent = xfs_rud_item_intent, 22662306a36Sopenharmony_ci}; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic struct xfs_rud_log_item * 22962306a36Sopenharmony_cixfs_trans_get_rud( 23062306a36Sopenharmony_ci struct xfs_trans *tp, 23162306a36Sopenharmony_ci struct xfs_rui_log_item *ruip) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct xfs_rud_log_item *rudp; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci rudp = kmem_cache_zalloc(xfs_rud_cache, GFP_KERNEL | __GFP_NOFAIL); 23662306a36Sopenharmony_ci xfs_log_item_init(tp->t_mountp, &rudp->rud_item, XFS_LI_RUD, 23762306a36Sopenharmony_ci &xfs_rud_item_ops); 23862306a36Sopenharmony_ci rudp->rud_ruip = ruip; 23962306a36Sopenharmony_ci rudp->rud_format.rud_rui_id = ruip->rui_format.rui_id; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci xfs_trans_add_item(tp, &rudp->rud_item); 24262306a36Sopenharmony_ci return rudp; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci/* Set the map extent flags for this reverse mapping. */ 24662306a36Sopenharmony_cistatic void 24762306a36Sopenharmony_cixfs_trans_set_rmap_flags( 24862306a36Sopenharmony_ci struct xfs_map_extent *map, 24962306a36Sopenharmony_ci enum xfs_rmap_intent_type type, 25062306a36Sopenharmony_ci int whichfork, 25162306a36Sopenharmony_ci xfs_exntst_t state) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci map->me_flags = 0; 25462306a36Sopenharmony_ci if (state == XFS_EXT_UNWRITTEN) 25562306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN; 25662306a36Sopenharmony_ci if (whichfork == XFS_ATTR_FORK) 25762306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK; 25862306a36Sopenharmony_ci switch (type) { 25962306a36Sopenharmony_ci case XFS_RMAP_MAP: 26062306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_MAP; 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci case XFS_RMAP_MAP_SHARED: 26362306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED; 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci case XFS_RMAP_UNMAP: 26662306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_UNMAP; 26762306a36Sopenharmony_ci break; 26862306a36Sopenharmony_ci case XFS_RMAP_UNMAP_SHARED: 26962306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED; 27062306a36Sopenharmony_ci break; 27162306a36Sopenharmony_ci case XFS_RMAP_CONVERT: 27262306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_CONVERT; 27362306a36Sopenharmony_ci break; 27462306a36Sopenharmony_ci case XFS_RMAP_CONVERT_SHARED: 27562306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED; 27662306a36Sopenharmony_ci break; 27762306a36Sopenharmony_ci case XFS_RMAP_ALLOC: 27862306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_ALLOC; 27962306a36Sopenharmony_ci break; 28062306a36Sopenharmony_ci case XFS_RMAP_FREE: 28162306a36Sopenharmony_ci map->me_flags |= XFS_RMAP_EXTENT_FREE; 28262306a36Sopenharmony_ci break; 28362306a36Sopenharmony_ci default: 28462306a36Sopenharmony_ci ASSERT(0); 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/* 28962306a36Sopenharmony_ci * Finish an rmap update and log it to the RUD. Note that the transaction is 29062306a36Sopenharmony_ci * marked dirty regardless of whether the rmap update succeeds or fails to 29162306a36Sopenharmony_ci * support the RUI/RUD lifecycle rules. 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_cistatic int 29462306a36Sopenharmony_cixfs_trans_log_finish_rmap_update( 29562306a36Sopenharmony_ci struct xfs_trans *tp, 29662306a36Sopenharmony_ci struct xfs_rud_log_item *rudp, 29762306a36Sopenharmony_ci struct xfs_rmap_intent *ri, 29862306a36Sopenharmony_ci struct xfs_btree_cur **pcur) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci int error; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci error = xfs_rmap_finish_one(tp, ri, pcur); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* 30562306a36Sopenharmony_ci * Mark the transaction dirty, even on error. This ensures the 30662306a36Sopenharmony_ci * transaction is aborted, which: 30762306a36Sopenharmony_ci * 30862306a36Sopenharmony_ci * 1.) releases the RUI and frees the RUD 30962306a36Sopenharmony_ci * 2.) shuts down the filesystem 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE; 31262306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &rudp->rud_item.li_flags); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci return error; 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci/* Sort rmap intents by AG. */ 31862306a36Sopenharmony_cistatic int 31962306a36Sopenharmony_cixfs_rmap_update_diff_items( 32062306a36Sopenharmony_ci void *priv, 32162306a36Sopenharmony_ci const struct list_head *a, 32262306a36Sopenharmony_ci const struct list_head *b) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct xfs_rmap_intent *ra; 32562306a36Sopenharmony_ci struct xfs_rmap_intent *rb; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci ra = container_of(a, struct xfs_rmap_intent, ri_list); 32862306a36Sopenharmony_ci rb = container_of(b, struct xfs_rmap_intent, ri_list); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci/* Log rmap updates in the intent item. */ 33462306a36Sopenharmony_ciSTATIC void 33562306a36Sopenharmony_cixfs_rmap_update_log_item( 33662306a36Sopenharmony_ci struct xfs_trans *tp, 33762306a36Sopenharmony_ci struct xfs_rui_log_item *ruip, 33862306a36Sopenharmony_ci struct xfs_rmap_intent *ri) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci uint next_extent; 34162306a36Sopenharmony_ci struct xfs_map_extent *map; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY; 34462306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &ruip->rui_item.li_flags); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* 34762306a36Sopenharmony_ci * atomic_inc_return gives us the value after the increment; 34862306a36Sopenharmony_ci * we want to use it as an array index so we need to subtract 1 from 34962306a36Sopenharmony_ci * it. 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_ci next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1; 35262306a36Sopenharmony_ci ASSERT(next_extent < ruip->rui_format.rui_nextents); 35362306a36Sopenharmony_ci map = &ruip->rui_format.rui_extents[next_extent]; 35462306a36Sopenharmony_ci map->me_owner = ri->ri_owner; 35562306a36Sopenharmony_ci map->me_startblock = ri->ri_bmap.br_startblock; 35662306a36Sopenharmony_ci map->me_startoff = ri->ri_bmap.br_startoff; 35762306a36Sopenharmony_ci map->me_len = ri->ri_bmap.br_blockcount; 35862306a36Sopenharmony_ci xfs_trans_set_rmap_flags(map, ri->ri_type, ri->ri_whichfork, 35962306a36Sopenharmony_ci ri->ri_bmap.br_state); 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic struct xfs_log_item * 36362306a36Sopenharmony_cixfs_rmap_update_create_intent( 36462306a36Sopenharmony_ci struct xfs_trans *tp, 36562306a36Sopenharmony_ci struct list_head *items, 36662306a36Sopenharmony_ci unsigned int count, 36762306a36Sopenharmony_ci bool sort) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 37062306a36Sopenharmony_ci struct xfs_rui_log_item *ruip = xfs_rui_init(mp, count); 37162306a36Sopenharmony_ci struct xfs_rmap_intent *ri; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci ASSERT(count > 0); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci xfs_trans_add_item(tp, &ruip->rui_item); 37662306a36Sopenharmony_ci if (sort) 37762306a36Sopenharmony_ci list_sort(mp, items, xfs_rmap_update_diff_items); 37862306a36Sopenharmony_ci list_for_each_entry(ri, items, ri_list) 37962306a36Sopenharmony_ci xfs_rmap_update_log_item(tp, ruip, ri); 38062306a36Sopenharmony_ci return &ruip->rui_item; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci/* Get an RUD so we can process all the deferred rmap updates. */ 38462306a36Sopenharmony_cistatic struct xfs_log_item * 38562306a36Sopenharmony_cixfs_rmap_update_create_done( 38662306a36Sopenharmony_ci struct xfs_trans *tp, 38762306a36Sopenharmony_ci struct xfs_log_item *intent, 38862306a36Sopenharmony_ci unsigned int count) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci return &xfs_trans_get_rud(tp, RUI_ITEM(intent))->rud_item; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci/* Take a passive ref to the AG containing the space we're rmapping. */ 39462306a36Sopenharmony_civoid 39562306a36Sopenharmony_cixfs_rmap_update_get_group( 39662306a36Sopenharmony_ci struct xfs_mount *mp, 39762306a36Sopenharmony_ci struct xfs_rmap_intent *ri) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci xfs_agnumber_t agno; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci agno = XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock); 40262306a36Sopenharmony_ci ri->ri_pag = xfs_perag_intent_get(mp, agno); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci/* Release a passive AG ref after finishing rmapping work. */ 40662306a36Sopenharmony_cistatic inline void 40762306a36Sopenharmony_cixfs_rmap_update_put_group( 40862306a36Sopenharmony_ci struct xfs_rmap_intent *ri) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci xfs_perag_intent_put(ri->ri_pag); 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci/* Process a deferred rmap update. */ 41462306a36Sopenharmony_ciSTATIC int 41562306a36Sopenharmony_cixfs_rmap_update_finish_item( 41662306a36Sopenharmony_ci struct xfs_trans *tp, 41762306a36Sopenharmony_ci struct xfs_log_item *done, 41862306a36Sopenharmony_ci struct list_head *item, 41962306a36Sopenharmony_ci struct xfs_btree_cur **state) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct xfs_rmap_intent *ri; 42262306a36Sopenharmony_ci int error; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci ri = container_of(item, struct xfs_rmap_intent, ri_list); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci error = xfs_trans_log_finish_rmap_update(tp, RUD_ITEM(done), ri, 42762306a36Sopenharmony_ci state); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci xfs_rmap_update_put_group(ri); 43062306a36Sopenharmony_ci kmem_cache_free(xfs_rmap_intent_cache, ri); 43162306a36Sopenharmony_ci return error; 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci/* Abort all pending RUIs. */ 43562306a36Sopenharmony_ciSTATIC void 43662306a36Sopenharmony_cixfs_rmap_update_abort_intent( 43762306a36Sopenharmony_ci struct xfs_log_item *intent) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci xfs_rui_release(RUI_ITEM(intent)); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci/* Cancel a deferred rmap update. */ 44362306a36Sopenharmony_ciSTATIC void 44462306a36Sopenharmony_cixfs_rmap_update_cancel_item( 44562306a36Sopenharmony_ci struct list_head *item) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct xfs_rmap_intent *ri; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci ri = container_of(item, struct xfs_rmap_intent, ri_list); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci xfs_rmap_update_put_group(ri); 45262306a36Sopenharmony_ci kmem_cache_free(xfs_rmap_intent_cache, ri); 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ciconst struct xfs_defer_op_type xfs_rmap_update_defer_type = { 45662306a36Sopenharmony_ci .max_items = XFS_RUI_MAX_FAST_EXTENTS, 45762306a36Sopenharmony_ci .create_intent = xfs_rmap_update_create_intent, 45862306a36Sopenharmony_ci .abort_intent = xfs_rmap_update_abort_intent, 45962306a36Sopenharmony_ci .create_done = xfs_rmap_update_create_done, 46062306a36Sopenharmony_ci .finish_item = xfs_rmap_update_finish_item, 46162306a36Sopenharmony_ci .finish_cleanup = xfs_rmap_finish_one_cleanup, 46262306a36Sopenharmony_ci .cancel_item = xfs_rmap_update_cancel_item, 46362306a36Sopenharmony_ci}; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci/* Is this recovered RUI ok? */ 46662306a36Sopenharmony_cistatic inline bool 46762306a36Sopenharmony_cixfs_rui_validate_map( 46862306a36Sopenharmony_ci struct xfs_mount *mp, 46962306a36Sopenharmony_ci struct xfs_map_extent *map) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci if (!xfs_has_rmapbt(mp)) 47262306a36Sopenharmony_ci return false; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci if (map->me_flags & ~XFS_RMAP_EXTENT_FLAGS) 47562306a36Sopenharmony_ci return false; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci switch (map->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) { 47862306a36Sopenharmony_ci case XFS_RMAP_EXTENT_MAP: 47962306a36Sopenharmony_ci case XFS_RMAP_EXTENT_MAP_SHARED: 48062306a36Sopenharmony_ci case XFS_RMAP_EXTENT_UNMAP: 48162306a36Sopenharmony_ci case XFS_RMAP_EXTENT_UNMAP_SHARED: 48262306a36Sopenharmony_ci case XFS_RMAP_EXTENT_CONVERT: 48362306a36Sopenharmony_ci case XFS_RMAP_EXTENT_CONVERT_SHARED: 48462306a36Sopenharmony_ci case XFS_RMAP_EXTENT_ALLOC: 48562306a36Sopenharmony_ci case XFS_RMAP_EXTENT_FREE: 48662306a36Sopenharmony_ci break; 48762306a36Sopenharmony_ci default: 48862306a36Sopenharmony_ci return false; 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci if (!XFS_RMAP_NON_INODE_OWNER(map->me_owner) && 49262306a36Sopenharmony_ci !xfs_verify_ino(mp, map->me_owner)) 49362306a36Sopenharmony_ci return false; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len)) 49662306a36Sopenharmony_ci return false; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci return xfs_verify_fsbext(mp, map->me_startblock, map->me_len); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci/* 50262306a36Sopenharmony_ci * Process an rmap update intent item that was recovered from the log. 50362306a36Sopenharmony_ci * We need to update the rmapbt. 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_ciSTATIC int 50662306a36Sopenharmony_cixfs_rui_item_recover( 50762306a36Sopenharmony_ci struct xfs_log_item *lip, 50862306a36Sopenharmony_ci struct list_head *capture_list) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci struct xfs_trans_res resv; 51162306a36Sopenharmony_ci struct xfs_rui_log_item *ruip = RUI_ITEM(lip); 51262306a36Sopenharmony_ci struct xfs_rud_log_item *rudp; 51362306a36Sopenharmony_ci struct xfs_trans *tp; 51462306a36Sopenharmony_ci struct xfs_btree_cur *rcur = NULL; 51562306a36Sopenharmony_ci struct xfs_mount *mp = lip->li_log->l_mp; 51662306a36Sopenharmony_ci int i; 51762306a36Sopenharmony_ci int error = 0; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci /* 52062306a36Sopenharmony_ci * First check the validity of the extents described by the 52162306a36Sopenharmony_ci * RUI. If any are bad, then assume that all are bad and 52262306a36Sopenharmony_ci * just toss the RUI. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_ci for (i = 0; i < ruip->rui_format.rui_nextents; i++) { 52562306a36Sopenharmony_ci if (!xfs_rui_validate_map(mp, 52662306a36Sopenharmony_ci &ruip->rui_format.rui_extents[i])) { 52762306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 52862306a36Sopenharmony_ci &ruip->rui_format, 52962306a36Sopenharmony_ci sizeof(ruip->rui_format)); 53062306a36Sopenharmony_ci return -EFSCORRUPTED; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate); 53562306a36Sopenharmony_ci error = xfs_trans_alloc(mp, &resv, mp->m_rmap_maxlevels, 0, 53662306a36Sopenharmony_ci XFS_TRANS_RESERVE, &tp); 53762306a36Sopenharmony_ci if (error) 53862306a36Sopenharmony_ci return error; 53962306a36Sopenharmony_ci rudp = xfs_trans_get_rud(tp, ruip); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci for (i = 0; i < ruip->rui_format.rui_nextents; i++) { 54262306a36Sopenharmony_ci struct xfs_rmap_intent fake = { }; 54362306a36Sopenharmony_ci struct xfs_map_extent *map; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci map = &ruip->rui_format.rui_extents[i]; 54662306a36Sopenharmony_ci switch (map->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) { 54762306a36Sopenharmony_ci case XFS_RMAP_EXTENT_MAP: 54862306a36Sopenharmony_ci fake.ri_type = XFS_RMAP_MAP; 54962306a36Sopenharmony_ci break; 55062306a36Sopenharmony_ci case XFS_RMAP_EXTENT_MAP_SHARED: 55162306a36Sopenharmony_ci fake.ri_type = XFS_RMAP_MAP_SHARED; 55262306a36Sopenharmony_ci break; 55362306a36Sopenharmony_ci case XFS_RMAP_EXTENT_UNMAP: 55462306a36Sopenharmony_ci fake.ri_type = XFS_RMAP_UNMAP; 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci case XFS_RMAP_EXTENT_UNMAP_SHARED: 55762306a36Sopenharmony_ci fake.ri_type = XFS_RMAP_UNMAP_SHARED; 55862306a36Sopenharmony_ci break; 55962306a36Sopenharmony_ci case XFS_RMAP_EXTENT_CONVERT: 56062306a36Sopenharmony_ci fake.ri_type = XFS_RMAP_CONVERT; 56162306a36Sopenharmony_ci break; 56262306a36Sopenharmony_ci case XFS_RMAP_EXTENT_CONVERT_SHARED: 56362306a36Sopenharmony_ci fake.ri_type = XFS_RMAP_CONVERT_SHARED; 56462306a36Sopenharmony_ci break; 56562306a36Sopenharmony_ci case XFS_RMAP_EXTENT_ALLOC: 56662306a36Sopenharmony_ci fake.ri_type = XFS_RMAP_ALLOC; 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci case XFS_RMAP_EXTENT_FREE: 56962306a36Sopenharmony_ci fake.ri_type = XFS_RMAP_FREE; 57062306a36Sopenharmony_ci break; 57162306a36Sopenharmony_ci default: 57262306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 57362306a36Sopenharmony_ci &ruip->rui_format, 57462306a36Sopenharmony_ci sizeof(ruip->rui_format)); 57562306a36Sopenharmony_ci error = -EFSCORRUPTED; 57662306a36Sopenharmony_ci goto abort_error; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci fake.ri_owner = map->me_owner; 58062306a36Sopenharmony_ci fake.ri_whichfork = (map->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ? 58162306a36Sopenharmony_ci XFS_ATTR_FORK : XFS_DATA_FORK; 58262306a36Sopenharmony_ci fake.ri_bmap.br_startblock = map->me_startblock; 58362306a36Sopenharmony_ci fake.ri_bmap.br_startoff = map->me_startoff; 58462306a36Sopenharmony_ci fake.ri_bmap.br_blockcount = map->me_len; 58562306a36Sopenharmony_ci fake.ri_bmap.br_state = (map->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ? 58662306a36Sopenharmony_ci XFS_EXT_UNWRITTEN : XFS_EXT_NORM; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci xfs_rmap_update_get_group(mp, &fake); 58962306a36Sopenharmony_ci error = xfs_trans_log_finish_rmap_update(tp, rudp, &fake, 59062306a36Sopenharmony_ci &rcur); 59162306a36Sopenharmony_ci if (error == -EFSCORRUPTED) 59262306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 59362306a36Sopenharmony_ci map, sizeof(*map)); 59462306a36Sopenharmony_ci xfs_rmap_update_put_group(&fake); 59562306a36Sopenharmony_ci if (error) 59662306a36Sopenharmony_ci goto abort_error; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci xfs_rmap_finish_one_cleanup(tp, rcur, error); 60162306a36Sopenharmony_ci return xfs_defer_ops_capture_and_commit(tp, capture_list); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ciabort_error: 60462306a36Sopenharmony_ci xfs_rmap_finish_one_cleanup(tp, rcur, error); 60562306a36Sopenharmony_ci xfs_trans_cancel(tp); 60662306a36Sopenharmony_ci return error; 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ciSTATIC bool 61062306a36Sopenharmony_cixfs_rui_item_match( 61162306a36Sopenharmony_ci struct xfs_log_item *lip, 61262306a36Sopenharmony_ci uint64_t intent_id) 61362306a36Sopenharmony_ci{ 61462306a36Sopenharmony_ci return RUI_ITEM(lip)->rui_format.rui_id == intent_id; 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci/* Relog an intent item to push the log tail forward. */ 61862306a36Sopenharmony_cistatic struct xfs_log_item * 61962306a36Sopenharmony_cixfs_rui_item_relog( 62062306a36Sopenharmony_ci struct xfs_log_item *intent, 62162306a36Sopenharmony_ci struct xfs_trans *tp) 62262306a36Sopenharmony_ci{ 62362306a36Sopenharmony_ci struct xfs_rud_log_item *rudp; 62462306a36Sopenharmony_ci struct xfs_rui_log_item *ruip; 62562306a36Sopenharmony_ci struct xfs_map_extent *map; 62662306a36Sopenharmony_ci unsigned int count; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci count = RUI_ITEM(intent)->rui_format.rui_nextents; 62962306a36Sopenharmony_ci map = RUI_ITEM(intent)->rui_format.rui_extents; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY; 63262306a36Sopenharmony_ci rudp = xfs_trans_get_rud(tp, RUI_ITEM(intent)); 63362306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &rudp->rud_item.li_flags); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci ruip = xfs_rui_init(tp->t_mountp, count); 63662306a36Sopenharmony_ci memcpy(ruip->rui_format.rui_extents, map, count * sizeof(*map)); 63762306a36Sopenharmony_ci atomic_set(&ruip->rui_next_extent, count); 63862306a36Sopenharmony_ci xfs_trans_add_item(tp, &ruip->rui_item); 63962306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &ruip->rui_item.li_flags); 64062306a36Sopenharmony_ci return &ruip->rui_item; 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_rui_item_ops = { 64462306a36Sopenharmony_ci .flags = XFS_ITEM_INTENT, 64562306a36Sopenharmony_ci .iop_size = xfs_rui_item_size, 64662306a36Sopenharmony_ci .iop_format = xfs_rui_item_format, 64762306a36Sopenharmony_ci .iop_unpin = xfs_rui_item_unpin, 64862306a36Sopenharmony_ci .iop_release = xfs_rui_item_release, 64962306a36Sopenharmony_ci .iop_recover = xfs_rui_item_recover, 65062306a36Sopenharmony_ci .iop_match = xfs_rui_item_match, 65162306a36Sopenharmony_ci .iop_relog = xfs_rui_item_relog, 65262306a36Sopenharmony_ci}; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistatic inline void 65562306a36Sopenharmony_cixfs_rui_copy_format( 65662306a36Sopenharmony_ci struct xfs_rui_log_format *dst, 65762306a36Sopenharmony_ci const struct xfs_rui_log_format *src) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci unsigned int i; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci memcpy(dst, src, offsetof(struct xfs_rui_log_format, rui_extents)); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci for (i = 0; i < src->rui_nextents; i++) 66462306a36Sopenharmony_ci memcpy(&dst->rui_extents[i], &src->rui_extents[i], 66562306a36Sopenharmony_ci sizeof(struct xfs_map_extent)); 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci/* 66962306a36Sopenharmony_ci * This routine is called to create an in-core extent rmap update 67062306a36Sopenharmony_ci * item from the rui format structure which was logged on disk. 67162306a36Sopenharmony_ci * It allocates an in-core rui, copies the extents from the format 67262306a36Sopenharmony_ci * structure into it, and adds the rui to the AIL with the given 67362306a36Sopenharmony_ci * LSN. 67462306a36Sopenharmony_ci */ 67562306a36Sopenharmony_ciSTATIC int 67662306a36Sopenharmony_cixlog_recover_rui_commit_pass2( 67762306a36Sopenharmony_ci struct xlog *log, 67862306a36Sopenharmony_ci struct list_head *buffer_list, 67962306a36Sopenharmony_ci struct xlog_recover_item *item, 68062306a36Sopenharmony_ci xfs_lsn_t lsn) 68162306a36Sopenharmony_ci{ 68262306a36Sopenharmony_ci struct xfs_mount *mp = log->l_mp; 68362306a36Sopenharmony_ci struct xfs_rui_log_item *ruip; 68462306a36Sopenharmony_ci struct xfs_rui_log_format *rui_formatp; 68562306a36Sopenharmony_ci size_t len; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci rui_formatp = item->ri_buf[0].i_addr; 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci if (item->ri_buf[0].i_len < xfs_rui_log_format_sizeof(0)) { 69062306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 69162306a36Sopenharmony_ci item->ri_buf[0].i_addr, item->ri_buf[0].i_len); 69262306a36Sopenharmony_ci return -EFSCORRUPTED; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci len = xfs_rui_log_format_sizeof(rui_formatp->rui_nextents); 69662306a36Sopenharmony_ci if (item->ri_buf[0].i_len != len) { 69762306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 69862306a36Sopenharmony_ci item->ri_buf[0].i_addr, item->ri_buf[0].i_len); 69962306a36Sopenharmony_ci return -EFSCORRUPTED; 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci ruip = xfs_rui_init(mp, rui_formatp->rui_nextents); 70362306a36Sopenharmony_ci xfs_rui_copy_format(&ruip->rui_format, rui_formatp); 70462306a36Sopenharmony_ci atomic_set(&ruip->rui_next_extent, rui_formatp->rui_nextents); 70562306a36Sopenharmony_ci /* 70662306a36Sopenharmony_ci * Insert the intent into the AIL directly and drop one reference so 70762306a36Sopenharmony_ci * that finishing or canceling the work will drop the other. 70862306a36Sopenharmony_ci */ 70962306a36Sopenharmony_ci xfs_trans_ail_insert(log->l_ailp, &ruip->rui_item, lsn); 71062306a36Sopenharmony_ci xfs_rui_release(ruip); 71162306a36Sopenharmony_ci return 0; 71262306a36Sopenharmony_ci} 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ciconst struct xlog_recover_item_ops xlog_rui_item_ops = { 71562306a36Sopenharmony_ci .item_type = XFS_LI_RUI, 71662306a36Sopenharmony_ci .commit_pass2 = xlog_recover_rui_commit_pass2, 71762306a36Sopenharmony_ci}; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci/* 72062306a36Sopenharmony_ci * This routine is called when an RUD format structure is found in a committed 72162306a36Sopenharmony_ci * transaction in the log. Its purpose is to cancel the corresponding RUI if it 72262306a36Sopenharmony_ci * was still in the log. To do this it searches the AIL for the RUI with an id 72362306a36Sopenharmony_ci * equal to that in the RUD format structure. If we find it we drop the RUD 72462306a36Sopenharmony_ci * reference, which removes the RUI from the AIL and frees it. 72562306a36Sopenharmony_ci */ 72662306a36Sopenharmony_ciSTATIC int 72762306a36Sopenharmony_cixlog_recover_rud_commit_pass2( 72862306a36Sopenharmony_ci struct xlog *log, 72962306a36Sopenharmony_ci struct list_head *buffer_list, 73062306a36Sopenharmony_ci struct xlog_recover_item *item, 73162306a36Sopenharmony_ci xfs_lsn_t lsn) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci struct xfs_rud_log_format *rud_formatp; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci rud_formatp = item->ri_buf[0].i_addr; 73662306a36Sopenharmony_ci if (item->ri_buf[0].i_len != sizeof(struct xfs_rud_log_format)) { 73762306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp, 73862306a36Sopenharmony_ci rud_formatp, item->ri_buf[0].i_len); 73962306a36Sopenharmony_ci return -EFSCORRUPTED; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci xlog_recover_release_intent(log, XFS_LI_RUI, rud_formatp->rud_rui_id); 74362306a36Sopenharmony_ci return 0; 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ciconst struct xlog_recover_item_ops xlog_rud_item_ops = { 74762306a36Sopenharmony_ci .item_type = XFS_LI_RUD, 74862306a36Sopenharmony_ci .commit_pass2 = xlog_recover_rud_commit_pass2, 74962306a36Sopenharmony_ci}; 750