From: Christoph Hellwig <hch@lst.de>
To: Andrey Albershteyn <aalbersh@kernel.org>
Cc: "Darrick J . Wong" <djwong@kernel.org>,
Hans Holmberg <hans.holmberg@wdc.com>,
linux-xfs@vger.kernel.org
Subject: [PATCH 07/43] xfs: move xfs_bmapi_reserve_delalloc to xfs_iomap.c
Date: Mon, 14 Apr 2025 07:35:50 +0200 [thread overview]
Message-ID: <20250414053629.360672-8-hch@lst.de> (raw)
In-Reply-To: <20250414053629.360672-1-hch@lst.de>
Source kernel commit: 7c879c8275c0505c551f0fc6c152299c8d11f756
Delalloc reservations are not supported in userspace, and thus it doesn't
make sense to share this helper with xfsprogs.c. Move it to xfs_iomap.c
toward the two callers.
Note that there rest of the delalloc handling should probably eventually
also move out of xfs_bmap.c, but that will require a bit more surgery.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
libxfs/xfs_bmap.c | 294 ++--------------------------------------------
libxfs/xfs_bmap.h | 5 +-
2 files changed, 8 insertions(+), 291 deletions(-)
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 07c553d92423..4dc66e77744f 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -165,18 +165,16 @@ xfs_bmbt_update(
* Compute the worst-case number of indirect blocks that will be used
* for ip's delayed extent of length "len".
*/
-STATIC xfs_filblks_t
+xfs_filblks_t
xfs_bmap_worst_indlen(
- xfs_inode_t *ip, /* incore inode pointer */
- xfs_filblks_t len) /* delayed extent length */
+ struct xfs_inode *ip, /* incore inode pointer */
+ xfs_filblks_t len) /* delayed extent length */
{
- int level; /* btree level number */
- int maxrecs; /* maximum record count at this level */
- xfs_mount_t *mp; /* mount structure */
- xfs_filblks_t rval; /* return value */
+ struct xfs_mount *mp = ip->i_mount;
+ int maxrecs = mp->m_bmap_dmxr[0];
+ int level;
+ xfs_filblks_t rval;
- mp = ip->i_mount;
- maxrecs = mp->m_bmap_dmxr[0];
for (level = 0, rval = 0;
level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
level++) {
@@ -2565,146 +2563,6 @@ done:
#undef PREV
}
-/*
- * Convert a hole to a delayed allocation.
- */
-STATIC void
-xfs_bmap_add_extent_hole_delay(
- xfs_inode_t *ip, /* incore inode pointer */
- int whichfork,
- struct xfs_iext_cursor *icur,
- xfs_bmbt_irec_t *new) /* new data to add to file extents */
-{
- struct xfs_ifork *ifp; /* inode fork pointer */
- xfs_bmbt_irec_t left; /* left neighbor extent entry */
- xfs_filblks_t newlen=0; /* new indirect size */
- xfs_filblks_t oldlen=0; /* old indirect size */
- xfs_bmbt_irec_t right; /* right neighbor extent entry */
- uint32_t state = xfs_bmap_fork_to_state(whichfork);
- xfs_filblks_t temp; /* temp for indirect calculations */
-
- ifp = xfs_ifork_ptr(ip, whichfork);
- ASSERT(isnullstartblock(new->br_startblock));
-
- /*
- * Check and set flags if this segment has a left neighbor
- */
- if (xfs_iext_peek_prev_extent(ifp, icur, &left)) {
- state |= BMAP_LEFT_VALID;
- if (isnullstartblock(left.br_startblock))
- state |= BMAP_LEFT_DELAY;
- }
-
- /*
- * Check and set flags if the current (right) segment exists.
- * If it doesn't exist, we're converting the hole at end-of-file.
- */
- if (xfs_iext_get_extent(ifp, icur, &right)) {
- state |= BMAP_RIGHT_VALID;
- if (isnullstartblock(right.br_startblock))
- state |= BMAP_RIGHT_DELAY;
- }
-
- /*
- * Set contiguity flags on the left and right neighbors.
- * Don't let extents get too large, even if the pieces are contiguous.
- */
- if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) &&
- left.br_startoff + left.br_blockcount == new->br_startoff &&
- left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
- state |= BMAP_LEFT_CONTIG;
-
- if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) &&
- new->br_startoff + new->br_blockcount == right.br_startoff &&
- new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
- (!(state & BMAP_LEFT_CONTIG) ||
- (left.br_blockcount + new->br_blockcount +
- right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)))
- state |= BMAP_RIGHT_CONTIG;
-
- /*
- * Switch out based on the contiguity flags.
- */
- switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) {
- case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
- /*
- * New allocation is contiguous with delayed allocations
- * on the left and on the right.
- * Merge all three into a single extent record.
- */
- temp = left.br_blockcount + new->br_blockcount +
- right.br_blockcount;
-
- oldlen = startblockval(left.br_startblock) +
- startblockval(new->br_startblock) +
- startblockval(right.br_startblock);
- newlen = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
- oldlen);
- left.br_startblock = nullstartblock(newlen);
- left.br_blockcount = temp;
-
- xfs_iext_remove(ip, icur, state);
- xfs_iext_prev(ifp, icur);
- xfs_iext_update_extent(ip, state, icur, &left);
- break;
-
- case BMAP_LEFT_CONTIG:
- /*
- * New allocation is contiguous with a delayed allocation
- * on the left.
- * Merge the new allocation with the left neighbor.
- */
- temp = left.br_blockcount + new->br_blockcount;
-
- oldlen = startblockval(left.br_startblock) +
- startblockval(new->br_startblock);
- newlen = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
- oldlen);
- left.br_blockcount = temp;
- left.br_startblock = nullstartblock(newlen);
-
- xfs_iext_prev(ifp, icur);
- xfs_iext_update_extent(ip, state, icur, &left);
- break;
-
- case BMAP_RIGHT_CONTIG:
- /*
- * New allocation is contiguous with a delayed allocation
- * on the right.
- * Merge the new allocation with the right neighbor.
- */
- temp = new->br_blockcount + right.br_blockcount;
- oldlen = startblockval(new->br_startblock) +
- startblockval(right.br_startblock);
- newlen = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
- oldlen);
- right.br_startoff = new->br_startoff;
- right.br_startblock = nullstartblock(newlen);
- right.br_blockcount = temp;
- xfs_iext_update_extent(ip, state, icur, &right);
- break;
-
- case 0:
- /*
- * New allocation is not contiguous with another
- * delayed allocation.
- * Insert a new entry.
- */
- oldlen = newlen = 0;
- xfs_iext_insert(ip, icur, new, state);
- break;
- }
- if (oldlen != newlen) {
- ASSERT(oldlen > newlen);
- xfs_add_fdblocks(ip->i_mount, oldlen - newlen);
-
- /*
- * Nothing to do for disk quota accounting here.
- */
- xfs_mod_delalloc(ip, 0, (int64_t)newlen - oldlen);
- }
-}
-
/*
* Convert a hole to a real allocation.
*/
@@ -4033,144 +3891,6 @@ xfs_bmapi_read(
return 0;
}
-/*
- * Add a delayed allocation extent to an inode. Blocks are reserved from the
- * global pool and the extent inserted into the inode in-core extent tree.
- *
- * On entry, got refers to the first extent beyond the offset of the extent to
- * allocate or eof is specified if no such extent exists. On return, got refers
- * to the extent record that was inserted to the inode fork.
- *
- * Note that the allocated extent may have been merged with contiguous extents
- * during insertion into the inode fork. Thus, got does not reflect the current
- * state of the inode fork on return. If necessary, the caller can use lastx to
- * look up the updated record in the inode fork.
- */
-int
-xfs_bmapi_reserve_delalloc(
- struct xfs_inode *ip,
- int whichfork,
- xfs_fileoff_t off,
- xfs_filblks_t len,
- xfs_filblks_t prealloc,
- struct xfs_bmbt_irec *got,
- struct xfs_iext_cursor *icur,
- int eof)
-{
- struct xfs_mount *mp = ip->i_mount;
- struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
- xfs_extlen_t alen;
- xfs_extlen_t indlen;
- uint64_t fdblocks;
- int error;
- xfs_fileoff_t aoff;
- bool use_cowextszhint =
- whichfork == XFS_COW_FORK && !prealloc;
-
-retry:
- /*
- * Cap the alloc length. Keep track of prealloc so we know whether to
- * tag the inode before we return.
- */
- aoff = off;
- alen = XFS_FILBLKS_MIN(len + prealloc, XFS_MAX_BMBT_EXTLEN);
- if (!eof)
- alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
- if (prealloc && alen >= len)
- prealloc = alen - len;
-
- /*
- * If we're targetting the COW fork but aren't creating a speculative
- * posteof preallocation, try to expand the reservation to align with
- * the COW extent size hint if there's sufficient free space.
- *
- * Unlike the data fork, the CoW cancellation functions will free all
- * the reservations at inactivation, so we don't require that every
- * delalloc reservation have a dirty pagecache.
- */
- if (use_cowextszhint) {
- struct xfs_bmbt_irec prev;
- xfs_extlen_t extsz = xfs_get_cowextsz_hint(ip);
-
- if (!xfs_iext_peek_prev_extent(ifp, icur, &prev))
- prev.br_startoff = NULLFILEOFF;
-
- error = xfs_bmap_extsize_align(mp, got, &prev, extsz, 0, eof,
- 1, 0, &aoff, &alen);
- ASSERT(!error);
- }
-
- /*
- * Make a transaction-less quota reservation for delayed allocation
- * blocks. This number gets adjusted later. We return if we haven't
- * allocated blocks already inside this loop.
- */
- error = xfs_quota_reserve_blkres(ip, alen);
- if (error)
- goto out;
-
- /*
- * Split changing sb for alen and indlen since they could be coming
- * from different places.
- */
- indlen = (xfs_extlen_t)xfs_bmap_worst_indlen(ip, alen);
- ASSERT(indlen > 0);
-
- fdblocks = indlen;
- if (XFS_IS_REALTIME_INODE(ip)) {
- error = xfs_dec_frextents(mp, xfs_blen_to_rtbxlen(mp, alen));
- if (error)
- goto out_unreserve_quota;
- } else {
- fdblocks += alen;
- }
-
- error = xfs_dec_fdblocks(mp, fdblocks, false);
- if (error)
- goto out_unreserve_frextents;
-
- ip->i_delayed_blks += alen;
- xfs_mod_delalloc(ip, alen, indlen);
-
- got->br_startoff = aoff;
- got->br_startblock = nullstartblock(indlen);
- got->br_blockcount = alen;
- got->br_state = XFS_EXT_NORM;
-
- xfs_bmap_add_extent_hole_delay(ip, whichfork, icur, got);
-
- /*
- * Tag the inode if blocks were preallocated. Note that COW fork
- * preallocation can occur at the start or end of the extent, even when
- * prealloc == 0, so we must also check the aligned offset and length.
- */
- if (whichfork == XFS_DATA_FORK && prealloc)
- xfs_inode_set_eofblocks_tag(ip);
- if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len))
- xfs_inode_set_cowblocks_tag(ip);
-
- return 0;
-
-out_unreserve_frextents:
- if (XFS_IS_REALTIME_INODE(ip))
- xfs_add_frextents(mp, xfs_blen_to_rtbxlen(mp, alen));
-out_unreserve_quota:
- if (XFS_IS_QUOTA_ON(mp))
- xfs_quota_unreserve_blkres(ip, alen);
-out:
- if (error == -ENOSPC || error == -EDQUOT) {
- trace_xfs_delalloc_enospc(ip, off, len);
-
- if (prealloc || use_cowextszhint) {
- /* retry without any preallocation */
- use_cowextszhint = false;
- prealloc = 0;
- goto retry;
- }
- }
- return error;
-}
-
static int
xfs_bmapi_allocate(
struct xfs_bmalloca *bma)
diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h
index 4b721d935994..4d48087fd3a8 100644
--- a/libxfs/xfs_bmap.h
+++ b/libxfs/xfs_bmap.h
@@ -219,10 +219,6 @@ int xfs_bmap_insert_extents(struct xfs_trans *tp, struct xfs_inode *ip,
bool *done, xfs_fileoff_t stop_fsb);
int xfs_bmap_split_extent(struct xfs_trans *tp, struct xfs_inode *ip,
xfs_fileoff_t split_offset);
-int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
- xfs_fileoff_t off, xfs_filblks_t len, xfs_filblks_t prealloc,
- struct xfs_bmbt_irec *got, struct xfs_iext_cursor *cur,
- int eof);
int xfs_bmapi_convert_delalloc(struct xfs_inode *ip, int whichfork,
xfs_off_t offset, struct iomap *iomap, unsigned int *seq);
int xfs_bmap_add_extent_unwritten_real(struct xfs_trans *tp,
@@ -233,6 +229,7 @@ xfs_extlen_t xfs_bmapi_minleft(struct xfs_trans *tp, struct xfs_inode *ip,
int fork);
int xfs_bmap_btalloc_low_space(struct xfs_bmalloca *ap,
struct xfs_alloc_arg *args);
+xfs_filblks_t xfs_bmap_worst_indlen(struct xfs_inode *ip, xfs_filblks_t len);
enum xfs_bmap_intent_type {
XFS_BMAP_MAP = 1,
--
2.47.2
next prev parent reply other threads:[~2025-04-14 5:36 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-14 5:35 xfsprogs support for zoned devices v2 Christoph Hellwig
2025-04-14 5:35 ` [PATCH 01/43] xfs: generalize the freespace and reserved blocks handling Christoph Hellwig
2025-04-14 5:35 ` [PATCH 02/43] FIXUP: " Christoph Hellwig
2025-04-14 5:35 ` [PATCH 03/43] xfs: make metabtree reservations global Christoph Hellwig
2025-04-14 5:35 ` [PATCH 04/43] FIXUP: " Christoph Hellwig
2025-04-14 5:35 ` [PATCH 05/43] xfs: reduce metafile reservations Christoph Hellwig
2025-04-14 5:35 ` [PATCH 06/43] xfs: add a rtg_blocks helper Christoph Hellwig
2025-04-14 5:35 ` Christoph Hellwig [this message]
2025-04-14 5:35 ` [PATCH 08/43] xfs: support XFS_BMAPI_REMAP in xfs_bmap_del_extent_delay Christoph Hellwig
2025-04-14 5:35 ` [PATCH 09/43] xfs: add a xfs_rtrmap_highest_rgbno helper Christoph Hellwig
2025-04-14 5:35 ` [PATCH 10/43] xfs: define the zoned on-disk format Christoph Hellwig
2025-04-14 5:35 ` [PATCH 11/43] FIXUP: " Christoph Hellwig
2025-04-14 5:35 ` [PATCH 12/43] xfs: allow internal RT devices for zoned mode Christoph Hellwig
2025-04-14 5:35 ` [PATCH 13/43] FIXUP: " Christoph Hellwig
2025-04-14 20:16 ` Darrick J. Wong
2025-04-14 5:35 ` [PATCH 14/43] xfs: export zoned geometry via XFS_FSOP_GEOM Christoph Hellwig
2025-04-14 5:35 ` [PATCH 15/43] xfs: disable sb_frextents for zoned file systems Christoph Hellwig
2025-04-14 5:35 ` [PATCH 16/43] xfs: parse and validate hardware zone information Christoph Hellwig
2025-04-14 5:36 ` [PATCH 17/43] FIXUP: " Christoph Hellwig
2025-04-14 5:36 ` [PATCH 18/43] xfs: add the zoned space allocator Christoph Hellwig
2025-04-14 5:36 ` [PATCH 19/43] xfs: add support for zoned space reservations Christoph Hellwig
2025-04-14 5:36 ` [PATCH 20/43] FIXUP: " Christoph Hellwig
2025-04-14 5:36 ` [PATCH 21/43] xfs: implement zoned garbage collection Christoph Hellwig
2025-04-14 5:36 ` [PATCH 22/43] xfs: enable fsmap reporting for internal RT devices Christoph Hellwig
2025-04-14 5:36 ` [PATCH 23/43] xfs: enable the zoned RT device feature Christoph Hellwig
2025-04-14 5:36 ` [PATCH 24/43] xfs: support zone gaps Christoph Hellwig
2025-04-14 5:36 ` [PATCH 25/43] FIXUP: " Christoph Hellwig
2025-04-14 5:36 ` [PATCH 26/43] libfrog: report the zoned geometry Christoph Hellwig
2025-04-14 22:16 ` Darrick J. Wong
2025-04-14 5:36 ` [PATCH 27/43] xfs_repair: support repairing zoned file systems Christoph Hellwig
2025-04-15 0:38 ` Darrick J. Wong
2025-04-14 5:36 ` [PATCH 28/43] xfs_repair: fix the RT device check in process_dinode_int Christoph Hellwig
2025-04-15 0:34 ` Darrick J. Wong
2025-04-14 5:36 ` [PATCH 29/43] xfs_repair: validate rt groups vs reported hardware zones Christoph Hellwig
2025-04-15 0:39 ` Darrick J. Wong
2025-04-14 5:36 ` [PATCH 30/43] xfs_mkfs: factor out a validate_rtgroup_geometry helper Christoph Hellwig
2025-04-15 0:40 ` Darrick J. Wong
2025-04-14 5:36 ` [PATCH 31/43] xfs_mkfs: support creating file system with zoned RT devices Christoph Hellwig
2025-04-15 0:41 ` Darrick J. Wong
2025-04-14 5:36 ` [PATCH 32/43] xfs_mkfs: calculate zone overprovisioning when specifying size Christoph Hellwig
2025-04-14 5:36 ` [PATCH 33/43] xfs_mkfs: default to rtinherit=1 for zoned file systems Christoph Hellwig
2025-04-15 0:37 ` Darrick J. Wong
2025-04-15 8:09 ` Christoph Hellwig
2025-04-14 5:36 ` [PATCH 34/43] xfs_mkfs: reflink conflicts with zoned file systems for now Christoph Hellwig
2025-04-14 5:36 ` [PATCH 35/43] xfs_mkfs: document the new zoned options in the man page Christoph Hellwig
2025-04-14 5:36 ` [PATCH 36/43] man: document XFS_FSOP_GEOM_FLAGS_ZONED Christoph Hellwig
2025-04-15 0:36 ` Darrick J. Wong
2025-04-14 5:36 ` [PATCH 37/43] xfs_io: correctly report RGs with internal rt dev in bmap output Christoph Hellwig
2025-04-14 5:36 ` [PATCH 38/43] xfs_io: don't re-query fs_path information in fsmap_f Christoph Hellwig
2025-04-14 5:36 ` [PATCH 39/43] xfs_io: handle internal RT devices in fsmap output Christoph Hellwig
2025-04-14 5:36 ` [PATCH 40/43] xfs_spaceman: handle internal RT devices Christoph Hellwig
2025-04-14 5:36 ` [PATCH 41/43] xfs_scrub: support internal RT device Christoph Hellwig
2025-04-15 0:35 ` Darrick J. Wong
2025-04-14 5:36 ` [PATCH 42/43] xfs_mdrestore: support internal RT devices Christoph Hellwig
2025-04-14 5:36 ` [PATCH 43/43] xfs_growfs: " Christoph Hellwig
2025-04-25 15:48 ` [PATCH 44/43] xfs_repair: fix libxfs abstraction mess Darrick J. Wong
2025-04-28 13:17 ` Christoph Hellwig
2025-04-28 16:28 ` Andrey Albershteyn
2025-04-29 12:24 ` Christoph Hellwig
2025-04-28 16:31 ` Andrey Albershteyn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250414053629.360672-8-hch@lst.de \
--to=hch@lst.de \
--cc=aalbersh@kernel.org \
--cc=djwong@kernel.org \
--cc=hans.holmberg@wdc.com \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox