Skip to content

Commit 974ae92

Browse files
Brian Fosterdchinner
authored andcommitted
xfs: track preallocation separately in xfs_bmapi_reserve_delalloc()
Speculative preallocation is currently processed entirely by the callers of xfs_bmapi_reserve_delalloc(). The caller determines how much preallocation to include, adjusts the extent length and passes down the resulting request. While this works fine for post-eof speculative preallocation, it is not as reliable for COW fork preallocation. COW fork preallocation is implemented via the cowextszhint, which aligns the start offset as well as the length of the extent. Further, it is difficult for the caller to accurately identify when preallocation occurs because the returned extent could have been merged with neighboring extents in the fork. To simplify this situation and facilitate further COW fork preallocation enhancements, update xfs_bmapi_reserve_delalloc() to take a separate preallocation parameter to incorporate into the allocation request. The preallocation blocks value is tacked onto the end of the request and adjusted to accommodate neighboring extents and extent size limits. Since xfs_bmapi_reserve_delalloc() now knows precisely how much preallocation was included in the allocation, it can also tag the inodes appropriately to support preallocation reclaim. Note that xfs_bmapi_reserve_delalloc() callers are not yet updated to use the preallocation mechanism. This patch should not change behavior outside of correctly tagging reflink inodes when start offset preallocation occurs (which the caller does not handle correctly). Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
1 parent fba3e59 commit 974ae92

File tree

4 files changed

+24
-5
lines changed

4 files changed

+24
-5
lines changed

fs/xfs/libxfs/xfs_bmap.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "xfs_ag_resv.h"
5151
#include "xfs_refcount.h"
5252
#include "xfs_rmap_btree.h"
53+
#include "xfs_icache.h"
5354

5455

5556
kmem_zone_t *xfs_bmap_free_item_zone;
@@ -4154,8 +4155,9 @@ int
41544155
xfs_bmapi_reserve_delalloc(
41554156
struct xfs_inode *ip,
41564157
int whichfork,
4157-
xfs_fileoff_t aoff,
4158+
xfs_fileoff_t off,
41584159
xfs_filblks_t len,
4160+
xfs_filblks_t prealloc,
41594161
struct xfs_bmbt_irec *got,
41604162
xfs_extnum_t *lastx,
41614163
int eof)
@@ -4167,10 +4169,17 @@ xfs_bmapi_reserve_delalloc(
41674169
char rt = XFS_IS_REALTIME_INODE(ip);
41684170
xfs_extlen_t extsz;
41694171
int error;
4172+
xfs_fileoff_t aoff = off;
41704173

4171-
alen = XFS_FILBLKS_MIN(len, MAXEXTLEN);
4174+
/*
4175+
* Cap the alloc length. Keep track of prealloc so we know whether to
4176+
* tag the inode before we return.
4177+
*/
4178+
alen = XFS_FILBLKS_MIN(len + prealloc, MAXEXTLEN);
41724179
if (!eof)
41734180
alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
4181+
if (prealloc && alen >= len)
4182+
prealloc = alen - len;
41744183

41754184
/* Figure out the extent size, adjust alen */
41764185
if (whichfork == XFS_COW_FORK)
@@ -4236,6 +4245,16 @@ xfs_bmapi_reserve_delalloc(
42364245
*/
42374246
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
42384247

4248+
/*
4249+
* Tag the inode if blocks were preallocated. Note that COW fork
4250+
* preallocation can occur at the start or end of the extent, even when
4251+
* prealloc == 0, so we must also check the aligned offset and length.
4252+
*/
4253+
if (whichfork == XFS_DATA_FORK && prealloc)
4254+
xfs_inode_set_eofblocks_tag(ip);
4255+
if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len))
4256+
xfs_inode_set_cowblocks_tag(ip);
4257+
42394258
ASSERT(got->br_startoff <= aoff);
42404259
ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
42414260
ASSERT(isnullstartblock(got->br_startblock));

fs/xfs/libxfs/xfs_bmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
238238
int num_exts);
239239
int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
240240
int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
241-
xfs_fileoff_t aoff, xfs_filblks_t len,
241+
xfs_fileoff_t off, xfs_filblks_t len, xfs_filblks_t prealloc,
242242
struct xfs_bmbt_irec *got, xfs_extnum_t *lastx, int eof);
243243

244244
enum xfs_bmap_intent_type {

fs/xfs/xfs_iomap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ xfs_file_iomap_begin_delay(
620620

621621
retry:
622622
error = xfs_bmapi_reserve_delalloc(ip, XFS_DATA_FORK, offset_fsb,
623-
end_fsb - offset_fsb, &got, &idx, eof);
623+
end_fsb - offset_fsb, 0, &got, &idx, eof);
624624
switch (error) {
625625
case 0:
626626
break;

fs/xfs/xfs_reflink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ xfs_reflink_reserve_cow(
295295

296296
retry:
297297
error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, imap->br_startoff,
298-
end_fsb - imap->br_startoff, &got, &idx, eof);
298+
end_fsb - imap->br_startoff, 0, &got, &idx, eof);
299299
switch (error) {
300300
case 0:
301301
break;

0 commit comments

Comments
 (0)