summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_refcount_item.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2023-11-22 22:13:03 +0300
committerDarrick J. Wong <djwong@kernel.org>2023-12-07 05:45:15 +0300
commite70fb328d5277297ea2d9169a3a046de6412d777 (patch)
treef4359168cf1c5207c23c3594951a8a531475d49c /fs/xfs/xfs_refcount_item.c
parentdeb4cd8ba87f17b12c72b3827820d9c703e9fd95 (diff)
downloadlinux-e70fb328d5277297ea2d9169a3a046de6412d777.tar.xz
xfs: recreate work items when recovering intent items
Recreate work items for each xfs_defer_pending object when we are recovering intent items. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/xfs_refcount_item.c')
-rw-r--r--fs/xfs/xfs_refcount_item.c60
1 files changed, 28 insertions, 32 deletions
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index f1b259223802..4ffc34e6f0a0 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -468,6 +468,23 @@ xfs_cui_validate_phys(
return xfs_verify_fsbext(mp, pmap->pe_startblock, pmap->pe_len);
}
+static inline void
+xfs_cui_recover_work(
+ struct xfs_mount *mp,
+ struct xfs_defer_pending *dfp,
+ struct xfs_phys_extent *pmap)
+{
+ struct xfs_refcount_intent *ri;
+
+ ri = kmem_cache_alloc(xfs_refcount_intent_cache,
+ GFP_NOFS | __GFP_NOFAIL);
+ ri->ri_type = pmap->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK;
+ ri->ri_startblock = pmap->pe_startblock;
+ ri->ri_blockcount = pmap->pe_len;
+
+ xfs_defer_add_item(dfp, &ri->ri_list);
+}
+
/*
* Process a refcount update intent item that was recovered from the log.
* We need to update the refcountbt.
@@ -484,7 +501,7 @@ xfs_cui_item_recover(
struct xfs_trans *tp;
struct xfs_btree_cur *rcur = NULL;
struct xfs_mount *mp = lip->li_log->l_mp;
- unsigned int refc_type;
+ struct xfs_refcount_intent *fake;
bool requeue_only = false;
int i;
int error = 0;
@@ -502,6 +519,8 @@ xfs_cui_item_recover(
sizeof(cuip->cui_format));
return -EFSCORRUPTED;
}
+
+ xfs_cui_recover_work(mp, dfp, &cuip->cui_format.cui_extents[i]);
}
/*
@@ -525,35 +544,12 @@ xfs_cui_item_recover(
cudp = xfs_trans_get_cud(tp, cuip);
xlog_recover_transfer_intent(tp, dfp);
- for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
- struct xfs_refcount_intent fake = { };
- struct xfs_phys_extent *pmap;
-
- pmap = &cuip->cui_format.cui_extents[i];
- refc_type = pmap->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK;
- switch (refc_type) {
- case XFS_REFCOUNT_INCREASE:
- case XFS_REFCOUNT_DECREASE:
- case XFS_REFCOUNT_ALLOC_COW:
- case XFS_REFCOUNT_FREE_COW:
- fake.ri_type = refc_type;
- break;
- default:
- XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
- &cuip->cui_format,
- sizeof(cuip->cui_format));
- error = -EFSCORRUPTED;
- goto abort_error;
- }
-
- fake.ri_startblock = pmap->pe_startblock;
- fake.ri_blockcount = pmap->pe_len;
-
+ list_for_each_entry(fake, &dfp->dfp_work, ri_list) {
if (!requeue_only) {
- xfs_refcount_update_get_group(mp, &fake);
+ xfs_refcount_update_get_group(mp, fake);
error = xfs_trans_log_finish_refcount_update(tp, cudp,
- &fake, &rcur);
- xfs_refcount_update_put_group(&fake);
+ fake, &rcur);
+ xfs_refcount_update_put_group(fake);
}
if (error == -EFSCORRUPTED)
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
@@ -563,13 +559,13 @@ xfs_cui_item_recover(
goto abort_error;
/* Requeue what we didn't finish. */
- if (fake.ri_blockcount > 0) {
+ if (fake->ri_blockcount > 0) {
struct xfs_bmbt_irec irec = {
- .br_startblock = fake.ri_startblock,
- .br_blockcount = fake.ri_blockcount,
+ .br_startblock = fake->ri_startblock,
+ .br_blockcount = fake->ri_blockcount,
};
- switch (fake.ri_type) {
+ switch (fake->ri_type) {
case XFS_REFCOUNT_INCREASE:
xfs_refcount_increase_extent(tp, &irec);
break;