Skip to content

Commit 0260d8f

Browse files
Brian Fosterdchinner
authored andcommitted
xfs: clean up cow fork reservation and tag inodes correctly
COW fork reservation is implemented via delayed allocation. The code is modeled after the traditional delalloc allocation code, but is slightly different in terms of how preallocation occurs. Rather than post-eof speculative preallocation, COW fork preallocation is implemented via a COW extent size hint that is designed to minimize fragmentation as a reflinked file is split over time. xfs_reflink_reserve_cow() still uses logic that is oriented towards dealing with post-eof speculative preallocation, however, and is stale or not necessarily correct. First, the EOF alignment to the COW extent size hint is implemented in xfs_bmapi_reserve_delalloc() (which does so correctly by aligning the start and end offsets) and so is not necessary in xfs_reflink_reserve_cow(). The backoff and retry logic on ENOSPC is also ineffective for the same reason, as xfs_bmapi_reserve_delalloc() will simply perform the same allocation request on the retry. Finally, since the COW extent size hint aligns the start and end offset of the range to allocate, the end_fsb != orig_end_fsb logic is not sufficient. Indeed, if a write request happens to end on an aligned offset, it is possible that we do not tag the inode for COW preallocation even though xfs_bmapi_reserve_delalloc() may have preallocated at the start offset. Kill the unnecessary, duplicate code in xfs_reflink_reserve_cow(). Remove the inode tag logic as well since xfs_bmapi_reserve_delalloc() has been updated to tag the inode 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 974ae92 commit 0260d8f

File tree

1 file changed

+3
-26
lines changed

1 file changed

+3
-26
lines changed

fs/xfs/xfs_reflink.c

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,9 @@ xfs_reflink_reserve_cow(
245245
{
246246
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
247247
struct xfs_bmbt_irec got;
248-
xfs_fileoff_t end_fsb, orig_end_fsb;
249248
int error = 0;
250249
bool eof = false, trimmed;
251250
xfs_extnum_t idx;
252-
xfs_extlen_t align;
253251

254252
/*
255253
* Search the COW fork extent list first. This serves two purposes:
@@ -287,33 +285,12 @@ xfs_reflink_reserve_cow(
287285
if (error)
288286
return error;
289287

290-
end_fsb = orig_end_fsb = imap->br_startoff + imap->br_blockcount;
291-
292-
align = xfs_eof_alignment(ip, xfs_get_cowextsz_hint(ip));
293-
if (align)
294-
end_fsb = roundup_64(end_fsb, align);
295-
296-
retry:
297288
error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, imap->br_startoff,
298-
end_fsb - imap->br_startoff, 0, &got, &idx, eof);
299-
switch (error) {
300-
case 0:
301-
break;
302-
case -ENOSPC:
303-
case -EDQUOT:
304-
/* retry without any preallocation */
289+
imap->br_blockcount, 0, &got, &idx, eof);
290+
if (error == -ENOSPC || error == -EDQUOT)
305291
trace_xfs_reflink_cow_enospc(ip, imap);
306-
if (end_fsb != orig_end_fsb) {
307-
end_fsb = orig_end_fsb;
308-
goto retry;
309-
}
310-
/*FALLTHRU*/
311-
default:
292+
if (error)
312293
return error;
313-
}
314-
315-
if (end_fsb != orig_end_fsb)
316-
xfs_inode_set_cowblocks_tag(ip);
317294

318295
trace_xfs_reflink_cow_alloc(ip, &got);
319296
return 0;

0 commit comments

Comments
 (0)