162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * All Rights Reserved. 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_ag.h" 1562306a36Sopenharmony_ci#include "xfs_defer.h" 1662306a36Sopenharmony_ci#include "xfs_trans.h" 1762306a36Sopenharmony_ci#include "xfs_trans_priv.h" 1862306a36Sopenharmony_ci#include "xfs_extfree_item.h" 1962306a36Sopenharmony_ci#include "xfs_log.h" 2062306a36Sopenharmony_ci#include "xfs_btree.h" 2162306a36Sopenharmony_ci#include "xfs_rmap.h" 2262306a36Sopenharmony_ci#include "xfs_alloc.h" 2362306a36Sopenharmony_ci#include "xfs_bmap.h" 2462306a36Sopenharmony_ci#include "xfs_trace.h" 2562306a36Sopenharmony_ci#include "xfs_error.h" 2662306a36Sopenharmony_ci#include "xfs_log_priv.h" 2762306a36Sopenharmony_ci#include "xfs_log_recover.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct kmem_cache *xfs_efi_cache; 3062306a36Sopenharmony_cistruct kmem_cache *xfs_efd_cache; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_efi_item_ops; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic inline struct xfs_efi_log_item *EFI_ITEM(struct xfs_log_item *lip) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci return container_of(lip, struct xfs_efi_log_item, efi_item); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciSTATIC void 4062306a36Sopenharmony_cixfs_efi_item_free( 4162306a36Sopenharmony_ci struct xfs_efi_log_item *efip) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci kmem_free(efip->efi_item.li_lv_shadow); 4462306a36Sopenharmony_ci if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS) 4562306a36Sopenharmony_ci kmem_free(efip); 4662306a36Sopenharmony_ci else 4762306a36Sopenharmony_ci kmem_cache_free(xfs_efi_cache, efip); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* 5162306a36Sopenharmony_ci * Freeing the efi requires that we remove it from the AIL if it has already 5262306a36Sopenharmony_ci * been placed there. However, the EFI may not yet have been placed in the AIL 5362306a36Sopenharmony_ci * when called by xfs_efi_release() from EFD processing due to the ordering of 5462306a36Sopenharmony_ci * committed vs unpin operations in bulk insert operations. Hence the reference 5562306a36Sopenharmony_ci * count to ensure only the last caller frees the EFI. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_ciSTATIC void 5862306a36Sopenharmony_cixfs_efi_release( 5962306a36Sopenharmony_ci struct xfs_efi_log_item *efip) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci ASSERT(atomic_read(&efip->efi_refcount) > 0); 6262306a36Sopenharmony_ci if (!atomic_dec_and_test(&efip->efi_refcount)) 6362306a36Sopenharmony_ci return; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci xfs_trans_ail_delete(&efip->efi_item, 0); 6662306a36Sopenharmony_ci xfs_efi_item_free(efip); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciSTATIC void 7062306a36Sopenharmony_cixfs_efi_item_size( 7162306a36Sopenharmony_ci struct xfs_log_item *lip, 7262306a36Sopenharmony_ci int *nvecs, 7362306a36Sopenharmony_ci int *nbytes) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci struct xfs_efi_log_item *efip = EFI_ITEM(lip); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci *nvecs += 1; 7862306a36Sopenharmony_ci *nbytes += xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* 8262306a36Sopenharmony_ci * This is called to fill in the vector of log iovecs for the 8362306a36Sopenharmony_ci * given efi log item. We use only 1 iovec, and we point that 8462306a36Sopenharmony_ci * at the efi_log_format structure embedded in the efi item. 8562306a36Sopenharmony_ci * It is at this point that we assert that all of the extent 8662306a36Sopenharmony_ci * slots in the efi item have been filled. 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_ciSTATIC void 8962306a36Sopenharmony_cixfs_efi_item_format( 9062306a36Sopenharmony_ci struct xfs_log_item *lip, 9162306a36Sopenharmony_ci struct xfs_log_vec *lv) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci struct xfs_efi_log_item *efip = EFI_ITEM(lip); 9462306a36Sopenharmony_ci struct xfs_log_iovec *vecp = NULL; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci ASSERT(atomic_read(&efip->efi_next_extent) == 9762306a36Sopenharmony_ci efip->efi_format.efi_nextents); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci efip->efi_format.efi_type = XFS_LI_EFI; 10062306a36Sopenharmony_ci efip->efi_format.efi_size = 1; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT, 10362306a36Sopenharmony_ci &efip->efi_format, 10462306a36Sopenharmony_ci xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents)); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* 10962306a36Sopenharmony_ci * The unpin operation is the last place an EFI is manipulated in the log. It is 11062306a36Sopenharmony_ci * either inserted in the AIL or aborted in the event of a log I/O error. In 11162306a36Sopenharmony_ci * either case, the EFI transaction has been successfully committed to make it 11262306a36Sopenharmony_ci * this far. Therefore, we expect whoever committed the EFI to either construct 11362306a36Sopenharmony_ci * and commit the EFD or drop the EFD's reference in the event of error. Simply 11462306a36Sopenharmony_ci * drop the log's EFI reference now that the log is done with it. 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_ciSTATIC void 11762306a36Sopenharmony_cixfs_efi_item_unpin( 11862306a36Sopenharmony_ci struct xfs_log_item *lip, 11962306a36Sopenharmony_ci int remove) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct xfs_efi_log_item *efip = EFI_ITEM(lip); 12262306a36Sopenharmony_ci xfs_efi_release(efip); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* 12662306a36Sopenharmony_ci * The EFI has been either committed or aborted if the transaction has been 12762306a36Sopenharmony_ci * cancelled. If the transaction was cancelled, an EFD isn't going to be 12862306a36Sopenharmony_ci * constructed and thus we free the EFI here directly. 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_ciSTATIC void 13162306a36Sopenharmony_cixfs_efi_item_release( 13262306a36Sopenharmony_ci struct xfs_log_item *lip) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci xfs_efi_release(EFI_ITEM(lip)); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* 13862306a36Sopenharmony_ci * Allocate and initialize an efi item with the given number of extents. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ciSTATIC struct xfs_efi_log_item * 14162306a36Sopenharmony_cixfs_efi_init( 14262306a36Sopenharmony_ci struct xfs_mount *mp, 14362306a36Sopenharmony_ci uint nextents) 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci struct xfs_efi_log_item *efip; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci ASSERT(nextents > 0); 14962306a36Sopenharmony_ci if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { 15062306a36Sopenharmony_ci efip = kzalloc(xfs_efi_log_item_sizeof(nextents), 15162306a36Sopenharmony_ci GFP_KERNEL | __GFP_NOFAIL); 15262306a36Sopenharmony_ci } else { 15362306a36Sopenharmony_ci efip = kmem_cache_zalloc(xfs_efi_cache, 15462306a36Sopenharmony_ci GFP_KERNEL | __GFP_NOFAIL); 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops); 15862306a36Sopenharmony_ci efip->efi_format.efi_nextents = nextents; 15962306a36Sopenharmony_ci efip->efi_format.efi_id = (uintptr_t)(void *)efip; 16062306a36Sopenharmony_ci atomic_set(&efip->efi_next_extent, 0); 16162306a36Sopenharmony_ci atomic_set(&efip->efi_refcount, 2); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci return efip; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/* 16762306a36Sopenharmony_ci * Copy an EFI format buffer from the given buf, and into the destination 16862306a36Sopenharmony_ci * EFI format structure. 16962306a36Sopenharmony_ci * The given buffer can be in 32 bit or 64 bit form (which has different padding), 17062306a36Sopenharmony_ci * one of which will be the native format for this kernel. 17162306a36Sopenharmony_ci * It will handle the conversion of formats if necessary. 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_ciSTATIC int 17462306a36Sopenharmony_cixfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci xfs_efi_log_format_t *src_efi_fmt = buf->i_addr; 17762306a36Sopenharmony_ci uint i; 17862306a36Sopenharmony_ci uint len = xfs_efi_log_format_sizeof(src_efi_fmt->efi_nextents); 17962306a36Sopenharmony_ci uint len32 = xfs_efi_log_format32_sizeof(src_efi_fmt->efi_nextents); 18062306a36Sopenharmony_ci uint len64 = xfs_efi_log_format64_sizeof(src_efi_fmt->efi_nextents); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (buf->i_len == len) { 18362306a36Sopenharmony_ci memcpy(dst_efi_fmt, src_efi_fmt, 18462306a36Sopenharmony_ci offsetof(struct xfs_efi_log_format, efi_extents)); 18562306a36Sopenharmony_ci for (i = 0; i < src_efi_fmt->efi_nextents; i++) 18662306a36Sopenharmony_ci memcpy(&dst_efi_fmt->efi_extents[i], 18762306a36Sopenharmony_ci &src_efi_fmt->efi_extents[i], 18862306a36Sopenharmony_ci sizeof(struct xfs_extent)); 18962306a36Sopenharmony_ci return 0; 19062306a36Sopenharmony_ci } else if (buf->i_len == len32) { 19162306a36Sopenharmony_ci xfs_efi_log_format_32_t *src_efi_fmt_32 = buf->i_addr; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; 19462306a36Sopenharmony_ci dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; 19562306a36Sopenharmony_ci dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; 19662306a36Sopenharmony_ci dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; 19762306a36Sopenharmony_ci for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { 19862306a36Sopenharmony_ci dst_efi_fmt->efi_extents[i].ext_start = 19962306a36Sopenharmony_ci src_efi_fmt_32->efi_extents[i].ext_start; 20062306a36Sopenharmony_ci dst_efi_fmt->efi_extents[i].ext_len = 20162306a36Sopenharmony_ci src_efi_fmt_32->efi_extents[i].ext_len; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci return 0; 20462306a36Sopenharmony_ci } else if (buf->i_len == len64) { 20562306a36Sopenharmony_ci xfs_efi_log_format_64_t *src_efi_fmt_64 = buf->i_addr; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; 20862306a36Sopenharmony_ci dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; 20962306a36Sopenharmony_ci dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; 21062306a36Sopenharmony_ci dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; 21162306a36Sopenharmony_ci for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { 21262306a36Sopenharmony_ci dst_efi_fmt->efi_extents[i].ext_start = 21362306a36Sopenharmony_ci src_efi_fmt_64->efi_extents[i].ext_start; 21462306a36Sopenharmony_ci dst_efi_fmt->efi_extents[i].ext_len = 21562306a36Sopenharmony_ci src_efi_fmt_64->efi_extents[i].ext_len; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci return 0; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, NULL, buf->i_addr, 22062306a36Sopenharmony_ci buf->i_len); 22162306a36Sopenharmony_ci return -EFSCORRUPTED; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci return container_of(lip, struct xfs_efd_log_item, efd_item); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ciSTATIC void 23062306a36Sopenharmony_cixfs_efd_item_free(struct xfs_efd_log_item *efdp) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci kmem_free(efdp->efd_item.li_lv_shadow); 23362306a36Sopenharmony_ci if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS) 23462306a36Sopenharmony_ci kmem_free(efdp); 23562306a36Sopenharmony_ci else 23662306a36Sopenharmony_ci kmem_cache_free(xfs_efd_cache, efdp); 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ciSTATIC void 24062306a36Sopenharmony_cixfs_efd_item_size( 24162306a36Sopenharmony_ci struct xfs_log_item *lip, 24262306a36Sopenharmony_ci int *nvecs, 24362306a36Sopenharmony_ci int *nbytes) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci *nvecs += 1; 24862306a36Sopenharmony_ci *nbytes += xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents); 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci/* 25262306a36Sopenharmony_ci * This is called to fill in the vector of log iovecs for the 25362306a36Sopenharmony_ci * given efd log item. We use only 1 iovec, and we point that 25462306a36Sopenharmony_ci * at the efd_log_format structure embedded in the efd item. 25562306a36Sopenharmony_ci * It is at this point that we assert that all of the extent 25662306a36Sopenharmony_ci * slots in the efd item have been filled. 25762306a36Sopenharmony_ci */ 25862306a36Sopenharmony_ciSTATIC void 25962306a36Sopenharmony_cixfs_efd_item_format( 26062306a36Sopenharmony_ci struct xfs_log_item *lip, 26162306a36Sopenharmony_ci struct xfs_log_vec *lv) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 26462306a36Sopenharmony_ci struct xfs_log_iovec *vecp = NULL; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci efdp->efd_format.efd_type = XFS_LI_EFD; 26962306a36Sopenharmony_ci efdp->efd_format.efd_size = 1; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT, 27262306a36Sopenharmony_ci &efdp->efd_format, 27362306a36Sopenharmony_ci xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents)); 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci/* 27762306a36Sopenharmony_ci * The EFD is either committed or aborted if the transaction is cancelled. If 27862306a36Sopenharmony_ci * the transaction is cancelled, drop our reference to the EFI and free the EFD. 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ciSTATIC void 28162306a36Sopenharmony_cixfs_efd_item_release( 28262306a36Sopenharmony_ci struct xfs_log_item *lip) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci xfs_efi_release(efdp->efd_efip); 28762306a36Sopenharmony_ci xfs_efd_item_free(efdp); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic struct xfs_log_item * 29162306a36Sopenharmony_cixfs_efd_item_intent( 29262306a36Sopenharmony_ci struct xfs_log_item *lip) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci return &EFD_ITEM(lip)->efd_efip->efi_item; 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_efd_item_ops = { 29862306a36Sopenharmony_ci .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED | 29962306a36Sopenharmony_ci XFS_ITEM_INTENT_DONE, 30062306a36Sopenharmony_ci .iop_size = xfs_efd_item_size, 30162306a36Sopenharmony_ci .iop_format = xfs_efd_item_format, 30262306a36Sopenharmony_ci .iop_release = xfs_efd_item_release, 30362306a36Sopenharmony_ci .iop_intent = xfs_efd_item_intent, 30462306a36Sopenharmony_ci}; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci/* 30762306a36Sopenharmony_ci * Allocate an "extent free done" log item that will hold nextents worth of 30862306a36Sopenharmony_ci * extents. The caller must use all nextents extents, because we are not 30962306a36Sopenharmony_ci * flexible about this at all. 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_cistatic struct xfs_efd_log_item * 31262306a36Sopenharmony_cixfs_trans_get_efd( 31362306a36Sopenharmony_ci struct xfs_trans *tp, 31462306a36Sopenharmony_ci struct xfs_efi_log_item *efip, 31562306a36Sopenharmony_ci unsigned int nextents) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci struct xfs_efd_log_item *efdp; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci ASSERT(nextents > 0); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { 32262306a36Sopenharmony_ci efdp = kzalloc(xfs_efd_log_item_sizeof(nextents), 32362306a36Sopenharmony_ci GFP_KERNEL | __GFP_NOFAIL); 32462306a36Sopenharmony_ci } else { 32562306a36Sopenharmony_ci efdp = kmem_cache_zalloc(xfs_efd_cache, 32662306a36Sopenharmony_ci GFP_KERNEL | __GFP_NOFAIL); 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci xfs_log_item_init(tp->t_mountp, &efdp->efd_item, XFS_LI_EFD, 33062306a36Sopenharmony_ci &xfs_efd_item_ops); 33162306a36Sopenharmony_ci efdp->efd_efip = efip; 33262306a36Sopenharmony_ci efdp->efd_format.efd_nextents = nextents; 33362306a36Sopenharmony_ci efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci xfs_trans_add_item(tp, &efdp->efd_item); 33662306a36Sopenharmony_ci return efdp; 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci/* 34062306a36Sopenharmony_ci * Fill the EFD with all extents from the EFI when we need to roll the 34162306a36Sopenharmony_ci * transaction and continue with a new EFI. 34262306a36Sopenharmony_ci * 34362306a36Sopenharmony_ci * This simply copies all the extents in the EFI to the EFD rather than make 34462306a36Sopenharmony_ci * assumptions about which extents in the EFI have already been processed. We 34562306a36Sopenharmony_ci * currently keep the xefi list in the same order as the EFI extent list, but 34662306a36Sopenharmony_ci * that may not always be the case. Copying everything avoids leaving a landmine 34762306a36Sopenharmony_ci * were we fail to cancel all the extents in an EFI if the xefi list is 34862306a36Sopenharmony_ci * processed in a different order to the extents in the EFI. 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_cistatic void 35162306a36Sopenharmony_cixfs_efd_from_efi( 35262306a36Sopenharmony_ci struct xfs_efd_log_item *efdp) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci struct xfs_efi_log_item *efip = efdp->efd_efip; 35562306a36Sopenharmony_ci uint i; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci ASSERT(efip->efi_format.efi_nextents > 0); 35862306a36Sopenharmony_ci ASSERT(efdp->efd_next_extent < efip->efi_format.efi_nextents); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci for (i = 0; i < efip->efi_format.efi_nextents; i++) { 36162306a36Sopenharmony_ci efdp->efd_format.efd_extents[i] = 36262306a36Sopenharmony_ci efip->efi_format.efi_extents[i]; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci efdp->efd_next_extent = efip->efi_format.efi_nextents; 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/* 36862306a36Sopenharmony_ci * Free an extent and log it to the EFD. Note that the transaction is marked 36962306a36Sopenharmony_ci * dirty regardless of whether the extent free succeeds or fails to support the 37062306a36Sopenharmony_ci * EFI/EFD lifecycle rules. 37162306a36Sopenharmony_ci */ 37262306a36Sopenharmony_cistatic int 37362306a36Sopenharmony_cixfs_trans_free_extent( 37462306a36Sopenharmony_ci struct xfs_trans *tp, 37562306a36Sopenharmony_ci struct xfs_efd_log_item *efdp, 37662306a36Sopenharmony_ci struct xfs_extent_free_item *xefi) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci struct xfs_owner_info oinfo = { }; 37962306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 38062306a36Sopenharmony_ci struct xfs_extent *extp; 38162306a36Sopenharmony_ci uint next_extent; 38262306a36Sopenharmony_ci xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, 38362306a36Sopenharmony_ci xefi->xefi_startblock); 38462306a36Sopenharmony_ci int error; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci oinfo.oi_owner = xefi->xefi_owner; 38762306a36Sopenharmony_ci if (xefi->xefi_flags & XFS_EFI_ATTR_FORK) 38862306a36Sopenharmony_ci oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK; 38962306a36Sopenharmony_ci if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK) 39062306a36Sopenharmony_ci oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci trace_xfs_bmap_free_deferred(tp->t_mountp, xefi->xefi_pag->pag_agno, 0, 39362306a36Sopenharmony_ci agbno, xefi->xefi_blockcount); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci error = __xfs_free_extent(tp, xefi->xefi_pag, agbno, 39662306a36Sopenharmony_ci xefi->xefi_blockcount, &oinfo, xefi->xefi_agresv, 39762306a36Sopenharmony_ci xefi->xefi_flags & XFS_EFI_SKIP_DISCARD); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* 40062306a36Sopenharmony_ci * Mark the transaction dirty, even on error. This ensures the 40162306a36Sopenharmony_ci * transaction is aborted, which: 40262306a36Sopenharmony_ci * 40362306a36Sopenharmony_ci * 1.) releases the EFI and frees the EFD 40462306a36Sopenharmony_ci * 2.) shuts down the filesystem 40562306a36Sopenharmony_ci */ 40662306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE; 40762306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* 41062306a36Sopenharmony_ci * If we need a new transaction to make progress, the caller will log a 41162306a36Sopenharmony_ci * new EFI with the current contents. It will also log an EFD to cancel 41262306a36Sopenharmony_ci * the existing EFI, and so we need to copy all the unprocessed extents 41362306a36Sopenharmony_ci * in this EFI to the EFD so this works correctly. 41462306a36Sopenharmony_ci */ 41562306a36Sopenharmony_ci if (error == -EAGAIN) { 41662306a36Sopenharmony_ci xfs_efd_from_efi(efdp); 41762306a36Sopenharmony_ci return error; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci next_extent = efdp->efd_next_extent; 42162306a36Sopenharmony_ci ASSERT(next_extent < efdp->efd_format.efd_nextents); 42262306a36Sopenharmony_ci extp = &(efdp->efd_format.efd_extents[next_extent]); 42362306a36Sopenharmony_ci extp->ext_start = xefi->xefi_startblock; 42462306a36Sopenharmony_ci extp->ext_len = xefi->xefi_blockcount; 42562306a36Sopenharmony_ci efdp->efd_next_extent++; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci return error; 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci/* Sort bmap items by AG. */ 43162306a36Sopenharmony_cistatic int 43262306a36Sopenharmony_cixfs_extent_free_diff_items( 43362306a36Sopenharmony_ci void *priv, 43462306a36Sopenharmony_ci const struct list_head *a, 43562306a36Sopenharmony_ci const struct list_head *b) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct xfs_extent_free_item *ra; 43862306a36Sopenharmony_ci struct xfs_extent_free_item *rb; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci ra = container_of(a, struct xfs_extent_free_item, xefi_list); 44162306a36Sopenharmony_ci rb = container_of(b, struct xfs_extent_free_item, xefi_list); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno; 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci/* Log a free extent to the intent item. */ 44762306a36Sopenharmony_ciSTATIC void 44862306a36Sopenharmony_cixfs_extent_free_log_item( 44962306a36Sopenharmony_ci struct xfs_trans *tp, 45062306a36Sopenharmony_ci struct xfs_efi_log_item *efip, 45162306a36Sopenharmony_ci struct xfs_extent_free_item *xefi) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci uint next_extent; 45462306a36Sopenharmony_ci struct xfs_extent *extp; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY; 45762306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &efip->efi_item.li_flags); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* 46062306a36Sopenharmony_ci * atomic_inc_return gives us the value after the increment; 46162306a36Sopenharmony_ci * we want to use it as an array index so we need to subtract 1 from 46262306a36Sopenharmony_ci * it. 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_ci next_extent = atomic_inc_return(&efip->efi_next_extent) - 1; 46562306a36Sopenharmony_ci ASSERT(next_extent < efip->efi_format.efi_nextents); 46662306a36Sopenharmony_ci extp = &efip->efi_format.efi_extents[next_extent]; 46762306a36Sopenharmony_ci extp->ext_start = xefi->xefi_startblock; 46862306a36Sopenharmony_ci extp->ext_len = xefi->xefi_blockcount; 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic struct xfs_log_item * 47262306a36Sopenharmony_cixfs_extent_free_create_intent( 47362306a36Sopenharmony_ci struct xfs_trans *tp, 47462306a36Sopenharmony_ci struct list_head *items, 47562306a36Sopenharmony_ci unsigned int count, 47662306a36Sopenharmony_ci bool sort) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 47962306a36Sopenharmony_ci struct xfs_efi_log_item *efip = xfs_efi_init(mp, count); 48062306a36Sopenharmony_ci struct xfs_extent_free_item *xefi; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci ASSERT(count > 0); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci xfs_trans_add_item(tp, &efip->efi_item); 48562306a36Sopenharmony_ci if (sort) 48662306a36Sopenharmony_ci list_sort(mp, items, xfs_extent_free_diff_items); 48762306a36Sopenharmony_ci list_for_each_entry(xefi, items, xefi_list) 48862306a36Sopenharmony_ci xfs_extent_free_log_item(tp, efip, xefi); 48962306a36Sopenharmony_ci return &efip->efi_item; 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci/* Get an EFD so we can process all the free extents. */ 49362306a36Sopenharmony_cistatic struct xfs_log_item * 49462306a36Sopenharmony_cixfs_extent_free_create_done( 49562306a36Sopenharmony_ci struct xfs_trans *tp, 49662306a36Sopenharmony_ci struct xfs_log_item *intent, 49762306a36Sopenharmony_ci unsigned int count) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci return &xfs_trans_get_efd(tp, EFI_ITEM(intent), count)->efd_item; 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci/* Take a passive ref to the AG containing the space we're freeing. */ 50362306a36Sopenharmony_civoid 50462306a36Sopenharmony_cixfs_extent_free_get_group( 50562306a36Sopenharmony_ci struct xfs_mount *mp, 50662306a36Sopenharmony_ci struct xfs_extent_free_item *xefi) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci xfs_agnumber_t agno; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock); 51162306a36Sopenharmony_ci xefi->xefi_pag = xfs_perag_intent_get(mp, agno); 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci/* Release a passive AG ref after some freeing work. */ 51562306a36Sopenharmony_cistatic inline void 51662306a36Sopenharmony_cixfs_extent_free_put_group( 51762306a36Sopenharmony_ci struct xfs_extent_free_item *xefi) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci xfs_perag_intent_put(xefi->xefi_pag); 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci/* Process a free extent. */ 52362306a36Sopenharmony_ciSTATIC int 52462306a36Sopenharmony_cixfs_extent_free_finish_item( 52562306a36Sopenharmony_ci struct xfs_trans *tp, 52662306a36Sopenharmony_ci struct xfs_log_item *done, 52762306a36Sopenharmony_ci struct list_head *item, 52862306a36Sopenharmony_ci struct xfs_btree_cur **state) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci struct xfs_extent_free_item *xefi; 53162306a36Sopenharmony_ci int error; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci xefi = container_of(item, struct xfs_extent_free_item, xefi_list); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* 53862306a36Sopenharmony_ci * Don't free the XEFI if we need a new transaction to complete 53962306a36Sopenharmony_ci * processing of it. 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_ci if (error == -EAGAIN) 54262306a36Sopenharmony_ci return error; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci xfs_extent_free_put_group(xefi); 54562306a36Sopenharmony_ci kmem_cache_free(xfs_extfree_item_cache, xefi); 54662306a36Sopenharmony_ci return error; 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci/* Abort all pending EFIs. */ 55062306a36Sopenharmony_ciSTATIC void 55162306a36Sopenharmony_cixfs_extent_free_abort_intent( 55262306a36Sopenharmony_ci struct xfs_log_item *intent) 55362306a36Sopenharmony_ci{ 55462306a36Sopenharmony_ci xfs_efi_release(EFI_ITEM(intent)); 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci/* Cancel a free extent. */ 55862306a36Sopenharmony_ciSTATIC void 55962306a36Sopenharmony_cixfs_extent_free_cancel_item( 56062306a36Sopenharmony_ci struct list_head *item) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci struct xfs_extent_free_item *xefi; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci xefi = container_of(item, struct xfs_extent_free_item, xefi_list); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci xfs_extent_free_put_group(xefi); 56762306a36Sopenharmony_ci kmem_cache_free(xfs_extfree_item_cache, xefi); 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ciconst struct xfs_defer_op_type xfs_extent_free_defer_type = { 57162306a36Sopenharmony_ci .max_items = XFS_EFI_MAX_FAST_EXTENTS, 57262306a36Sopenharmony_ci .create_intent = xfs_extent_free_create_intent, 57362306a36Sopenharmony_ci .abort_intent = xfs_extent_free_abort_intent, 57462306a36Sopenharmony_ci .create_done = xfs_extent_free_create_done, 57562306a36Sopenharmony_ci .finish_item = xfs_extent_free_finish_item, 57662306a36Sopenharmony_ci .cancel_item = xfs_extent_free_cancel_item, 57762306a36Sopenharmony_ci}; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci/* 58062306a36Sopenharmony_ci * AGFL blocks are accounted differently in the reserve pools and are not 58162306a36Sopenharmony_ci * inserted into the busy extent list. 58262306a36Sopenharmony_ci */ 58362306a36Sopenharmony_ciSTATIC int 58462306a36Sopenharmony_cixfs_agfl_free_finish_item( 58562306a36Sopenharmony_ci struct xfs_trans *tp, 58662306a36Sopenharmony_ci struct xfs_log_item *done, 58762306a36Sopenharmony_ci struct list_head *item, 58862306a36Sopenharmony_ci struct xfs_btree_cur **state) 58962306a36Sopenharmony_ci{ 59062306a36Sopenharmony_ci struct xfs_owner_info oinfo = { }; 59162306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 59262306a36Sopenharmony_ci struct xfs_efd_log_item *efdp = EFD_ITEM(done); 59362306a36Sopenharmony_ci struct xfs_extent_free_item *xefi; 59462306a36Sopenharmony_ci struct xfs_extent *extp; 59562306a36Sopenharmony_ci struct xfs_buf *agbp; 59662306a36Sopenharmony_ci int error; 59762306a36Sopenharmony_ci xfs_agblock_t agbno; 59862306a36Sopenharmony_ci uint next_extent; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci xefi = container_of(item, struct xfs_extent_free_item, xefi_list); 60162306a36Sopenharmony_ci ASSERT(xefi->xefi_blockcount == 1); 60262306a36Sopenharmony_ci agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock); 60362306a36Sopenharmony_ci oinfo.oi_owner = xefi->xefi_owner; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci trace_xfs_agfl_free_deferred(mp, xefi->xefi_pag->pag_agno, 0, agbno, 60662306a36Sopenharmony_ci xefi->xefi_blockcount); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp); 60962306a36Sopenharmony_ci if (!error) 61062306a36Sopenharmony_ci error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno, 61162306a36Sopenharmony_ci agbno, agbp, &oinfo); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci /* 61462306a36Sopenharmony_ci * Mark the transaction dirty, even on error. This ensures the 61562306a36Sopenharmony_ci * transaction is aborted, which: 61662306a36Sopenharmony_ci * 61762306a36Sopenharmony_ci * 1.) releases the EFI and frees the EFD 61862306a36Sopenharmony_ci * 2.) shuts down the filesystem 61962306a36Sopenharmony_ci */ 62062306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY; 62162306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci next_extent = efdp->efd_next_extent; 62462306a36Sopenharmony_ci ASSERT(next_extent < efdp->efd_format.efd_nextents); 62562306a36Sopenharmony_ci extp = &(efdp->efd_format.efd_extents[next_extent]); 62662306a36Sopenharmony_ci extp->ext_start = xefi->xefi_startblock; 62762306a36Sopenharmony_ci extp->ext_len = xefi->xefi_blockcount; 62862306a36Sopenharmony_ci efdp->efd_next_extent++; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci xfs_extent_free_put_group(xefi); 63162306a36Sopenharmony_ci kmem_cache_free(xfs_extfree_item_cache, xefi); 63262306a36Sopenharmony_ci return error; 63362306a36Sopenharmony_ci} 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci/* sub-type with special handling for AGFL deferred frees */ 63662306a36Sopenharmony_ciconst struct xfs_defer_op_type xfs_agfl_free_defer_type = { 63762306a36Sopenharmony_ci .max_items = XFS_EFI_MAX_FAST_EXTENTS, 63862306a36Sopenharmony_ci .create_intent = xfs_extent_free_create_intent, 63962306a36Sopenharmony_ci .abort_intent = xfs_extent_free_abort_intent, 64062306a36Sopenharmony_ci .create_done = xfs_extent_free_create_done, 64162306a36Sopenharmony_ci .finish_item = xfs_agfl_free_finish_item, 64262306a36Sopenharmony_ci .cancel_item = xfs_extent_free_cancel_item, 64362306a36Sopenharmony_ci}; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci/* Is this recovered EFI ok? */ 64662306a36Sopenharmony_cistatic inline bool 64762306a36Sopenharmony_cixfs_efi_validate_ext( 64862306a36Sopenharmony_ci struct xfs_mount *mp, 64962306a36Sopenharmony_ci struct xfs_extent *extp) 65062306a36Sopenharmony_ci{ 65162306a36Sopenharmony_ci return xfs_verify_fsbext(mp, extp->ext_start, extp->ext_len); 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci/* 65562306a36Sopenharmony_ci * Process an extent free intent item that was recovered from 65662306a36Sopenharmony_ci * the log. We need to free the extents that it describes. 65762306a36Sopenharmony_ci */ 65862306a36Sopenharmony_ciSTATIC int 65962306a36Sopenharmony_cixfs_efi_item_recover( 66062306a36Sopenharmony_ci struct xfs_log_item *lip, 66162306a36Sopenharmony_ci struct list_head *capture_list) 66262306a36Sopenharmony_ci{ 66362306a36Sopenharmony_ci struct xfs_trans_res resv; 66462306a36Sopenharmony_ci struct xfs_efi_log_item *efip = EFI_ITEM(lip); 66562306a36Sopenharmony_ci struct xfs_mount *mp = lip->li_log->l_mp; 66662306a36Sopenharmony_ci struct xfs_efd_log_item *efdp; 66762306a36Sopenharmony_ci struct xfs_trans *tp; 66862306a36Sopenharmony_ci int i; 66962306a36Sopenharmony_ci int error = 0; 67062306a36Sopenharmony_ci bool requeue_only = false; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci /* 67362306a36Sopenharmony_ci * First check the validity of the extents described by the 67462306a36Sopenharmony_ci * EFI. If any are bad, then assume that all are bad and 67562306a36Sopenharmony_ci * just toss the EFI. 67662306a36Sopenharmony_ci */ 67762306a36Sopenharmony_ci for (i = 0; i < efip->efi_format.efi_nextents; i++) { 67862306a36Sopenharmony_ci if (!xfs_efi_validate_ext(mp, 67962306a36Sopenharmony_ci &efip->efi_format.efi_extents[i])) { 68062306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 68162306a36Sopenharmony_ci &efip->efi_format, 68262306a36Sopenharmony_ci sizeof(efip->efi_format)); 68362306a36Sopenharmony_ci return -EFSCORRUPTED; 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate); 68862306a36Sopenharmony_ci error = xfs_trans_alloc(mp, &resv, 0, 0, 0, &tp); 68962306a36Sopenharmony_ci if (error) 69062306a36Sopenharmony_ci return error; 69162306a36Sopenharmony_ci efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci for (i = 0; i < efip->efi_format.efi_nextents; i++) { 69462306a36Sopenharmony_ci struct xfs_extent_free_item fake = { 69562306a36Sopenharmony_ci .xefi_owner = XFS_RMAP_OWN_UNKNOWN, 69662306a36Sopenharmony_ci .xefi_agresv = XFS_AG_RESV_NONE, 69762306a36Sopenharmony_ci }; 69862306a36Sopenharmony_ci struct xfs_extent *extp; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci extp = &efip->efi_format.efi_extents[i]; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci fake.xefi_startblock = extp->ext_start; 70362306a36Sopenharmony_ci fake.xefi_blockcount = extp->ext_len; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci if (!requeue_only) { 70662306a36Sopenharmony_ci xfs_extent_free_get_group(mp, &fake); 70762306a36Sopenharmony_ci error = xfs_trans_free_extent(tp, efdp, &fake); 70862306a36Sopenharmony_ci xfs_extent_free_put_group(&fake); 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci /* 71262306a36Sopenharmony_ci * If we can't free the extent without potentially deadlocking, 71362306a36Sopenharmony_ci * requeue the rest of the extents to a new so that they get 71462306a36Sopenharmony_ci * run again later with a new transaction context. 71562306a36Sopenharmony_ci */ 71662306a36Sopenharmony_ci if (error == -EAGAIN || requeue_only) { 71762306a36Sopenharmony_ci error = xfs_free_extent_later(tp, fake.xefi_startblock, 71862306a36Sopenharmony_ci fake.xefi_blockcount, 71962306a36Sopenharmony_ci &XFS_RMAP_OINFO_ANY_OWNER, 72062306a36Sopenharmony_ci fake.xefi_agresv); 72162306a36Sopenharmony_ci if (!error) { 72262306a36Sopenharmony_ci requeue_only = true; 72362306a36Sopenharmony_ci continue; 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci if (error == -EFSCORRUPTED) 72862306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 72962306a36Sopenharmony_ci extp, sizeof(*extp)); 73062306a36Sopenharmony_ci if (error) 73162306a36Sopenharmony_ci goto abort_error; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci return xfs_defer_ops_capture_and_commit(tp, capture_list); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ciabort_error: 73862306a36Sopenharmony_ci xfs_trans_cancel(tp); 73962306a36Sopenharmony_ci return error; 74062306a36Sopenharmony_ci} 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ciSTATIC bool 74362306a36Sopenharmony_cixfs_efi_item_match( 74462306a36Sopenharmony_ci struct xfs_log_item *lip, 74562306a36Sopenharmony_ci uint64_t intent_id) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci return EFI_ITEM(lip)->efi_format.efi_id == intent_id; 74862306a36Sopenharmony_ci} 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci/* Relog an intent item to push the log tail forward. */ 75162306a36Sopenharmony_cistatic struct xfs_log_item * 75262306a36Sopenharmony_cixfs_efi_item_relog( 75362306a36Sopenharmony_ci struct xfs_log_item *intent, 75462306a36Sopenharmony_ci struct xfs_trans *tp) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci struct xfs_efd_log_item *efdp; 75762306a36Sopenharmony_ci struct xfs_efi_log_item *efip; 75862306a36Sopenharmony_ci struct xfs_extent *extp; 75962306a36Sopenharmony_ci unsigned int count; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci count = EFI_ITEM(intent)->efi_format.efi_nextents; 76262306a36Sopenharmony_ci extp = EFI_ITEM(intent)->efi_format.efi_extents; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY; 76562306a36Sopenharmony_ci efdp = xfs_trans_get_efd(tp, EFI_ITEM(intent), count); 76662306a36Sopenharmony_ci efdp->efd_next_extent = count; 76762306a36Sopenharmony_ci memcpy(efdp->efd_format.efd_extents, extp, count * sizeof(*extp)); 76862306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags); 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci efip = xfs_efi_init(tp->t_mountp, count); 77162306a36Sopenharmony_ci memcpy(efip->efi_format.efi_extents, extp, count * sizeof(*extp)); 77262306a36Sopenharmony_ci atomic_set(&efip->efi_next_extent, count); 77362306a36Sopenharmony_ci xfs_trans_add_item(tp, &efip->efi_item); 77462306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &efip->efi_item.li_flags); 77562306a36Sopenharmony_ci return &efip->efi_item; 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_efi_item_ops = { 77962306a36Sopenharmony_ci .flags = XFS_ITEM_INTENT, 78062306a36Sopenharmony_ci .iop_size = xfs_efi_item_size, 78162306a36Sopenharmony_ci .iop_format = xfs_efi_item_format, 78262306a36Sopenharmony_ci .iop_unpin = xfs_efi_item_unpin, 78362306a36Sopenharmony_ci .iop_release = xfs_efi_item_release, 78462306a36Sopenharmony_ci .iop_recover = xfs_efi_item_recover, 78562306a36Sopenharmony_ci .iop_match = xfs_efi_item_match, 78662306a36Sopenharmony_ci .iop_relog = xfs_efi_item_relog, 78762306a36Sopenharmony_ci}; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci/* 79062306a36Sopenharmony_ci * This routine is called to create an in-core extent free intent 79162306a36Sopenharmony_ci * item from the efi format structure which was logged on disk. 79262306a36Sopenharmony_ci * It allocates an in-core efi, copies the extents from the format 79362306a36Sopenharmony_ci * structure into it, and adds the efi to the AIL with the given 79462306a36Sopenharmony_ci * LSN. 79562306a36Sopenharmony_ci */ 79662306a36Sopenharmony_ciSTATIC int 79762306a36Sopenharmony_cixlog_recover_efi_commit_pass2( 79862306a36Sopenharmony_ci struct xlog *log, 79962306a36Sopenharmony_ci struct list_head *buffer_list, 80062306a36Sopenharmony_ci struct xlog_recover_item *item, 80162306a36Sopenharmony_ci xfs_lsn_t lsn) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci struct xfs_mount *mp = log->l_mp; 80462306a36Sopenharmony_ci struct xfs_efi_log_item *efip; 80562306a36Sopenharmony_ci struct xfs_efi_log_format *efi_formatp; 80662306a36Sopenharmony_ci int error; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci efi_formatp = item->ri_buf[0].i_addr; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci if (item->ri_buf[0].i_len < xfs_efi_log_format_sizeof(0)) { 81162306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, 81262306a36Sopenharmony_ci item->ri_buf[0].i_addr, item->ri_buf[0].i_len); 81362306a36Sopenharmony_ci return -EFSCORRUPTED; 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci efip = xfs_efi_init(mp, efi_formatp->efi_nextents); 81762306a36Sopenharmony_ci error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format); 81862306a36Sopenharmony_ci if (error) { 81962306a36Sopenharmony_ci xfs_efi_item_free(efip); 82062306a36Sopenharmony_ci return error; 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci atomic_set(&efip->efi_next_extent, efi_formatp->efi_nextents); 82362306a36Sopenharmony_ci /* 82462306a36Sopenharmony_ci * Insert the intent into the AIL directly and drop one reference so 82562306a36Sopenharmony_ci * that finishing or canceling the work will drop the other. 82662306a36Sopenharmony_ci */ 82762306a36Sopenharmony_ci xfs_trans_ail_insert(log->l_ailp, &efip->efi_item, lsn); 82862306a36Sopenharmony_ci xfs_efi_release(efip); 82962306a36Sopenharmony_ci return 0; 83062306a36Sopenharmony_ci} 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ciconst struct xlog_recover_item_ops xlog_efi_item_ops = { 83362306a36Sopenharmony_ci .item_type = XFS_LI_EFI, 83462306a36Sopenharmony_ci .commit_pass2 = xlog_recover_efi_commit_pass2, 83562306a36Sopenharmony_ci}; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci/* 83862306a36Sopenharmony_ci * This routine is called when an EFD format structure is found in a committed 83962306a36Sopenharmony_ci * transaction in the log. Its purpose is to cancel the corresponding EFI if it 84062306a36Sopenharmony_ci * was still in the log. To do this it searches the AIL for the EFI with an id 84162306a36Sopenharmony_ci * equal to that in the EFD format structure. If we find it we drop the EFD 84262306a36Sopenharmony_ci * reference, which removes the EFI from the AIL and frees it. 84362306a36Sopenharmony_ci */ 84462306a36Sopenharmony_ciSTATIC int 84562306a36Sopenharmony_cixlog_recover_efd_commit_pass2( 84662306a36Sopenharmony_ci struct xlog *log, 84762306a36Sopenharmony_ci struct list_head *buffer_list, 84862306a36Sopenharmony_ci struct xlog_recover_item *item, 84962306a36Sopenharmony_ci xfs_lsn_t lsn) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci struct xfs_efd_log_format *efd_formatp; 85262306a36Sopenharmony_ci int buflen = item->ri_buf[0].i_len; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci efd_formatp = item->ri_buf[0].i_addr; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci if (buflen < sizeof(struct xfs_efd_log_format)) { 85762306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp, 85862306a36Sopenharmony_ci efd_formatp, buflen); 85962306a36Sopenharmony_ci return -EFSCORRUPTED; 86062306a36Sopenharmony_ci } 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci if (item->ri_buf[0].i_len != xfs_efd_log_format32_sizeof( 86362306a36Sopenharmony_ci efd_formatp->efd_nextents) && 86462306a36Sopenharmony_ci item->ri_buf[0].i_len != xfs_efd_log_format64_sizeof( 86562306a36Sopenharmony_ci efd_formatp->efd_nextents)) { 86662306a36Sopenharmony_ci XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp, 86762306a36Sopenharmony_ci efd_formatp, buflen); 86862306a36Sopenharmony_ci return -EFSCORRUPTED; 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci xlog_recover_release_intent(log, XFS_LI_EFI, efd_formatp->efd_efi_id); 87262306a36Sopenharmony_ci return 0; 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ciconst struct xlog_recover_item_ops xlog_efd_item_ops = { 87662306a36Sopenharmony_ci .item_type = XFS_LI_EFD, 87762306a36Sopenharmony_ci .commit_pass2 = xlog_recover_efd_commit_pass2, 87862306a36Sopenharmony_ci}; 879