Skip to content

Commit c47260d

Browse files
author
Darrick J. Wong
committed
xfs: count EFIs when deciding to ask for a continuation of a refcount update
A long time ago, I added to XFS the ability to use deferred reference count operations as part of a transaction chain. This enabled us to avoid blowing out the transaction reservation when the blocks in a physical extent all had different reference counts because we could ask the deferred operation manager for a continuation, which would get us a clean transaction. The refcount code asks for a continuation when the number of refcount record updates reaches the point where we think that the transaction has logged enough full btree blocks due to refcount (and free space) btree shape changes and refcount record updates that we're in danger of overflowing the transaction. We did not previously count the EFIs logged to the refcount update transaction because the clamps on the length of a bunmap operation were sufficient to avoid overflowing the transaction reservation even in the worst case situation where every other block of the unmapped extent is shared. Unfortunately, the restrictions on bunmap length avoid failure in the worst case by imposing a maximum unmap length of ~3000 blocks, even for non-pathological cases. This seriously limits performance when freeing large extents. Therefore, track EFIs with the same counter as refcount record updates, and use that information as input into when we should ask for a continuation. This enables the next patch to drop the clumsy bunmap limitation. Depends: 27dada0 ("xfs: change the order in which child and parent defer ops ar finished") Depends: 74f4d6a ("xfs: only relog deferred intent items if free space in the log gets low") Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Dave Chinner <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent 1edf805 commit c47260d

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

fs/xfs/libxfs/xfs_refcount.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,7 @@ xfs_refcount_adjust_extents(
960960
* Either cover the hole (increment) or
961961
* delete the range (decrement).
962962
*/
963+
cur->bc_ag.refc.nr_ops++;
963964
if (tmp.rc_refcount) {
964965
error = xfs_refcount_insert(cur, &tmp,
965966
&found_tmp);
@@ -970,7 +971,6 @@ xfs_refcount_adjust_extents(
970971
error = -EFSCORRUPTED;
971972
goto out_error;
972973
}
973-
cur->bc_ag.refc.nr_ops++;
974974
} else {
975975
fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
976976
cur->bc_ag.pag->pag_agno,
@@ -1001,11 +1001,11 @@ xfs_refcount_adjust_extents(
10011001
ext.rc_refcount += adj;
10021002
trace_xfs_refcount_modify_extent(cur->bc_mp,
10031003
cur->bc_ag.pag->pag_agno, &ext);
1004+
cur->bc_ag.refc.nr_ops++;
10041005
if (ext.rc_refcount > 1) {
10051006
error = xfs_refcount_update(cur, &ext);
10061007
if (error)
10071008
goto out_error;
1008-
cur->bc_ag.refc.nr_ops++;
10091009
} else if (ext.rc_refcount == 1) {
10101010
error = xfs_refcount_delete(cur, &found_rec);
10111011
if (error)
@@ -1014,7 +1014,6 @@ xfs_refcount_adjust_extents(
10141014
error = -EFSCORRUPTED;
10151015
goto out_error;
10161016
}
1017-
cur->bc_ag.refc.nr_ops++;
10181017
goto advloop;
10191018
} else {
10201019
fsbno = XFS_AGB_TO_FSB(cur->bc_mp,

fs/xfs/libxfs/xfs_refcount.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp,
6767
* log (plus any key updates) so we'll conservatively assume 32 bytes
6868
* per record. We must also leave space for btree splits on both ends
6969
* of the range and space for the CUD and a new CUI.
70+
*
71+
* Each EFI that we attach to the transaction is assumed to consume ~32 bytes.
72+
* This is a low estimate for an EFI tracking a single extent (16 bytes for the
73+
* EFI header, 16 for the extent, and 12 for the xlog op header), but the
74+
* estimate is acceptable if there's more than one extent being freed.
75+
* In the worst case of freeing every other block during a refcount decrease
76+
* operation, we amortize the space used for one EFI log item across 16
77+
* extents.
7078
*/
7179
#define XFS_REFCOUNT_ITEM_OVERHEAD 32
7280

0 commit comments

Comments
 (0)