Hi all,
Convert the xfs_mount perag tree to use an xarray instead of a radix tree. There should be no functional changes here.
If you're going to start using this code, I strongly recommend pulling from my git trees, which are linked below.
With a bit of luck, this should all go splendidly. Comments and questions are, as always, welcome.
--D
kernel git tree: https://git.kernel.org/cgit/linux/kernel/git/djwong/xfs-linux.git/log/?h=per... --- Commits in this patchset: * xfs: fix simplify extent lookup in xfs_can_free_eofblocks * xfs: fix superfluous clearing of info->low in __xfs_getfsmap_datadev * xfs: remove the unused pagb_count field in struct xfs_perag * xfs: remove the unused pag_active_wq field in struct xfs_perag * xfs: pass a pag to xfs_difree_inode_chunk * xfs: remove the agno argument to xfs_free_ag_extent * xfs: add xfs_agbno_to_fsb and xfs_agbno_to_daddr helpers * xfs: add a xfs_agino_to_ino helper * xfs: pass a pag to xfs_extent_busy_{search,reuse} * xfs: keep a reference to the pag for busy extents * xfs: remove the mount field from struct xfs_busy_extents * xfs: remove the unused trace_xfs_iwalk_ag trace point * xfs: remove the unused xrep_bmap_walk_rmap trace point * xfs: constify pag arguments to trace points * xfs: pass a perag structure to the xfs_ag_resv_init_error trace point * xfs: pass objects to the xfs_irec_merge_{pre,post} trace points * xfs: pass the iunlink item to the xfs_iunlink_update_dinode trace point * xfs: pass objects to the xrep_ibt_walk_rmap tracepoint * xfs: pass the pag to the trace_xrep_calc_ag_resblks{,_btsize} trace points * xfs: pass the pag to the xrep_newbt_extent_class tracepoints * xfs: convert remaining trace points to pass pag structures * xfs: split xfs_initialize_perag * xfs: insert the pag structures into the xarray later --- fs/xfs/libxfs/xfs_ag.c | 135 ++++++++++++++----------- fs/xfs/libxfs/xfs_ag.h | 30 +++++- fs/xfs/libxfs/xfs_ag_resv.c | 3 - fs/xfs/libxfs/xfs_alloc.c | 32 +++--- fs/xfs/libxfs/xfs_alloc.h | 5 - fs/xfs/libxfs/xfs_alloc_btree.c | 2 fs/xfs/libxfs/xfs_btree.c | 7 + fs/xfs/libxfs/xfs_ialloc.c | 67 ++++++------- fs/xfs/libxfs/xfs_ialloc_btree.c | 2 fs/xfs/libxfs/xfs_inode_util.c | 4 - fs/xfs/libxfs/xfs_refcount.c | 11 +- fs/xfs/libxfs/xfs_refcount_btree.c | 3 - fs/xfs/libxfs/xfs_rmap_btree.c | 2 fs/xfs/scrub/agheader_repair.c | 16 +-- fs/xfs/scrub/alloc_repair.c | 10 +- fs/xfs/scrub/bmap.c | 5 - fs/xfs/scrub/bmap_repair.c | 4 - fs/xfs/scrub/common.c | 2 fs/xfs/scrub/cow_repair.c | 18 +-- fs/xfs/scrub/ialloc.c | 8 +- fs/xfs/scrub/ialloc_repair.c | 25 ++--- fs/xfs/scrub/newbt.c | 46 ++++----- fs/xfs/scrub/reap.c | 8 +- fs/xfs/scrub/refcount_repair.c | 5 - fs/xfs/scrub/repair.c | 13 +- fs/xfs/scrub/rmap_repair.c | 9 +- fs/xfs/scrub/trace.h | 161 ++++++++++++++---------------- fs/xfs/xfs_bmap_util.c | 8 +- fs/xfs/xfs_buf_item_recover.c | 5 - fs/xfs/xfs_discard.c | 20 ++-- fs/xfs/xfs_extent_busy.c | 31 ++---- fs/xfs/xfs_extent_busy.h | 14 +-- fs/xfs/xfs_extfree_item.c | 4 - fs/xfs/xfs_filestream.c | 5 - fs/xfs/xfs_fsmap.c | 25 ++--- fs/xfs/xfs_health.c | 8 +- fs/xfs/xfs_inode.c | 5 - fs/xfs/xfs_iunlink_item.c | 13 +- fs/xfs/xfs_iwalk.c | 17 ++- fs/xfs/xfs_log_cil.c | 3 - fs/xfs/xfs_log_recover.c | 5 - fs/xfs/xfs_trace.c | 1 fs/xfs/xfs_trace.h | 191 +++++++++++++++--------------------- fs/xfs/xfs_trans.c | 2 44 files changed, 459 insertions(+), 531 deletions(-)
From: Darrick J. Wong djwong@kernel.org
In commit 11f4c3a53adde, we tried to simplify the extent lookup in xfs_can_free_eofblocks so that it doesn't incur the overhead of all the extra stuff that xfs_bmapi_read does around the iext lookup.
Unfortunately, this causes regressions on generic/603, xfs/108, generic/219, xfs/173, generic/694, xfs/052, generic/230, and xfs/441 when always_cow is turned on. In all cases, the regressions take the form of alwayscow files consuming rather more space than the golden output is expecting. I observed that in all these cases, the cause of the excess space usage was due to CoW fork delalloc reservations that go beyond EOF.
For alwayscow files we allow posteof delalloc CoW reservations because all writes go through the CoW fork. Recall that all extents in the CoW fork are accounted for via i_delayed_blks, which means that prior to this patch, we'd invoke xfs_free_eofblocks on first close if anything was in the CoW fork. Now we don't do that.
Fix the problem by reverting the removal of the i_delayed_blks check.
Cc: stable@vger.kernel.org # v6.12-rc1 Fixes: 11f4c3a53adde ("xfs: simplify extent lookup in xfs_can_free_eofblocks") Signed-off-by: Darrick J. Wong djwong@kernel.org Reviewed-by: Christoph Hellwig hch@lst.de --- fs/xfs/xfs_bmap_util.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 4719ec90029cb7..edaf193dbd5ccc 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -546,10 +546,14 @@ xfs_can_free_eofblocks( return false;
/* - * Check if there is an post-EOF extent to free. + * Check if there is an post-EOF extent to free. If there are any + * delalloc blocks attached to the inode (data fork delalloc + * reservations or CoW extents of any kind), we need to free them so + * that inactivation doesn't fail to erase them. */ xfs_ilock(ip, XFS_ILOCK_SHARED); - if (xfs_iext_lookup_extent(ip, &ip->i_df, end_fsb, &icur, &imap)) + if (ip->i_delayed_blks || + xfs_iext_lookup_extent(ip, &ip->i_df, end_fsb, &icur, &imap)) found_blocks = true; xfs_iunlock(ip, XFS_ILOCK_SHARED); return found_blocks;
linux-stable-mirror@lists.linaro.org