Skip to content

Commit 805f898

Browse files
author
Darrick J. Wong
committed
xfs: add helpers to compute transaction reservation for finishing intent items
In the transaction reservation code, hoist the logic that computes the reservation needed to finish one log intent item into separate helper functions. These will be used in subsequent patches to estimate the number of blocks that an online repair can commit to reaping in the same transaction as the change committing the new data structure. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: John Garry <[email protected]> Signed-off-by: John Garry <[email protected]>
1 parent 6d1bdc7 commit 805f898

File tree

2 files changed

+152
-31
lines changed

2 files changed

+152
-31
lines changed

fs/xfs/libxfs/xfs_trans_resv.c

Lines changed: 134 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,42 @@ xfs_rtalloc_block_count(
263263
* register overflow from temporaries in the calculations.
264264
*/
265265

266+
/*
267+
* Finishing a data device refcount updates (t1):
268+
* the agfs of the ags containing the blocks: nr_ops * sector size
269+
* the refcount btrees: nr_ops * 1 trees * (2 * max depth - 1) * block size
270+
*/
271+
inline unsigned int
272+
xfs_calc_finish_cui_reservation(
273+
struct xfs_mount *mp,
274+
unsigned int nr_ops)
275+
{
276+
if (!xfs_has_reflink(mp))
277+
return 0;
278+
279+
return xfs_calc_buf_res(nr_ops, mp->m_sb.sb_sectsize) +
280+
xfs_calc_buf_res(xfs_refcountbt_block_count(mp, nr_ops),
281+
mp->m_sb.sb_blocksize);
282+
}
283+
284+
/*
285+
* Realtime refcount updates (t2);
286+
* the rt refcount inode
287+
* the rtrefcount btrees: nr_ops * 1 trees * (2 * max depth - 1) * block size
288+
*/
289+
inline unsigned int
290+
xfs_calc_finish_rt_cui_reservation(
291+
struct xfs_mount *mp,
292+
unsigned int nr_ops)
293+
{
294+
if (!xfs_has_rtreflink(mp))
295+
return 0;
296+
297+
return xfs_calc_inode_res(mp, 1) +
298+
xfs_calc_buf_res(xfs_rtrefcountbt_block_count(mp, nr_ops),
299+
mp->m_sb.sb_blocksize);
300+
}
301+
266302
/*
267303
* Compute the log reservation required to handle the refcount update
268304
* transaction. Refcount updates are always done via deferred log items.
@@ -280,19 +316,10 @@ xfs_calc_refcountbt_reservation(
280316
struct xfs_mount *mp,
281317
unsigned int nr_ops)
282318
{
283-
unsigned int blksz = XFS_FSB_TO_B(mp, 1);
284-
unsigned int t1, t2 = 0;
319+
unsigned int t1, t2;
285320

286-
if (!xfs_has_reflink(mp))
287-
return 0;
288-
289-
t1 = xfs_calc_buf_res(nr_ops, mp->m_sb.sb_sectsize) +
290-
xfs_calc_buf_res(xfs_refcountbt_block_count(mp, nr_ops), blksz);
291-
292-
if (xfs_has_realtime(mp))
293-
t2 = xfs_calc_inode_res(mp, 1) +
294-
xfs_calc_buf_res(xfs_rtrefcountbt_block_count(mp, nr_ops),
295-
blksz);
321+
t1 = xfs_calc_finish_cui_reservation(mp, nr_ops);
322+
t2 = xfs_calc_finish_rt_cui_reservation(mp, nr_ops);
296323

297324
return max(t1, t2);
298325
}
@@ -379,6 +406,96 @@ xfs_calc_write_reservation_minlogsize(
379406
return xfs_calc_write_reservation(mp, true);
380407
}
381408

409+
/*
410+
* Finishing an EFI can free the blocks and bmap blocks (t2):
411+
* the agf for each of the ags: nr * sector size
412+
* the agfl for each of the ags: nr * sector size
413+
* the super block to reflect the freed blocks: sector size
414+
* worst case split in allocation btrees per extent assuming nr extents:
415+
* nr exts * 2 trees * (2 * max depth - 1) * block size
416+
*/
417+
inline unsigned int
418+
xfs_calc_finish_efi_reservation(
419+
struct xfs_mount *mp,
420+
unsigned int nr)
421+
{
422+
return xfs_calc_buf_res((2 * nr) + 1, mp->m_sb.sb_sectsize) +
423+
xfs_calc_buf_res(xfs_allocfree_block_count(mp, nr),
424+
mp->m_sb.sb_blocksize);
425+
}
426+
427+
/*
428+
* Or, if it's a realtime file (t3):
429+
* the agf for each of the ags: 2 * sector size
430+
* the agfl for each of the ags: 2 * sector size
431+
* the super block to reflect the freed blocks: sector size
432+
* the realtime bitmap:
433+
* 2 exts * ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
434+
* the realtime summary: 2 exts * 1 block
435+
* worst case split in allocation btrees per extent assuming 2 extents:
436+
* 2 exts * 2 trees * (2 * max depth - 1) * block size
437+
*/
438+
inline unsigned int
439+
xfs_calc_finish_rt_efi_reservation(
440+
struct xfs_mount *mp,
441+
unsigned int nr)
442+
{
443+
if (!xfs_has_realtime(mp))
444+
return 0;
445+
446+
return xfs_calc_buf_res((2 * nr) + 1, mp->m_sb.sb_sectsize) +
447+
xfs_calc_buf_res(xfs_rtalloc_block_count(mp, nr),
448+
mp->m_sb.sb_blocksize) +
449+
xfs_calc_buf_res(xfs_allocfree_block_count(mp, nr),
450+
mp->m_sb.sb_blocksize);
451+
}
452+
453+
/*
454+
* Finishing an RUI is the same as an EFI. We can split the rmap btree twice
455+
* on each end of the record, and that can cause the AGFL to be refilled or
456+
* emptied out.
457+
*/
458+
inline unsigned int
459+
xfs_calc_finish_rui_reservation(
460+
struct xfs_mount *mp,
461+
unsigned int nr)
462+
{
463+
if (!xfs_has_rmapbt(mp))
464+
return 0;
465+
return xfs_calc_finish_efi_reservation(mp, nr);
466+
}
467+
468+
/*
469+
* Finishing an RUI is the same as an EFI. We can split the rmap btree twice
470+
* on each end of the record, and that can cause the AGFL to be refilled or
471+
* emptied out.
472+
*/
473+
inline unsigned int
474+
xfs_calc_finish_rt_rui_reservation(
475+
struct xfs_mount *mp,
476+
unsigned int nr)
477+
{
478+
if (!xfs_has_rtrmapbt(mp))
479+
return 0;
480+
return xfs_calc_finish_rt_efi_reservation(mp, nr);
481+
}
482+
483+
/*
484+
* In finishing a BUI, we can modify:
485+
* the inode being truncated: inode size
486+
* dquots
487+
* the inode's bmap btree: (max depth + 1) * block size
488+
*/
489+
inline unsigned int
490+
xfs_calc_finish_bui_reservation(
491+
struct xfs_mount *mp,
492+
unsigned int nr)
493+
{
494+
return xfs_calc_inode_res(mp, 1) + XFS_DQUOT_LOGRES +
495+
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1,
496+
mp->m_sb.sb_blocksize);
497+
}
498+
382499
/*
383500
* In truncating a file we free up to two extents at once. We can modify (t1):
384501
* the inode being truncated: inode size
@@ -411,16 +528,8 @@ xfs_calc_itruncate_reservation(
411528
t1 = xfs_calc_inode_res(mp, 1) +
412529
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
413530

414-
t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
415-
xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4), blksz);
416-
417-
if (xfs_has_realtime(mp)) {
418-
t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
419-
xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 2), blksz) +
420-
xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
421-
} else {
422-
t3 = 0;
423-
}
531+
t2 = xfs_calc_finish_efi_reservation(mp, 4);
532+
t3 = xfs_calc_finish_rt_efi_reservation(mp, 2);
424533

425534
/*
426535
* In the early days of reflink, we included enough reservation to log
@@ -501,9 +610,7 @@ xfs_calc_rename_reservation(
501610
xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
502611
XFS_FSB_TO_B(mp, 1));
503612

504-
t2 = xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
505-
xfs_calc_buf_res(xfs_allocfree_block_count(mp, 3),
506-
XFS_FSB_TO_B(mp, 1));
613+
t2 = xfs_calc_finish_efi_reservation(mp, 3);
507614

508615
if (xfs_has_parent(mp)) {
509616
unsigned int rename_overhead, exchange_overhead;
@@ -611,9 +718,7 @@ xfs_calc_link_reservation(
611718
overhead += xfs_calc_iunlink_remove_reservation(mp);
612719
t1 = xfs_calc_inode_res(mp, 2) +
613720
xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1));
614-
t2 = xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
615-
xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
616-
XFS_FSB_TO_B(mp, 1));
721+
t2 = xfs_calc_finish_efi_reservation(mp, 1);
617722

618723
if (xfs_has_parent(mp)) {
619724
t3 = resp->tr_attrsetm.tr_logres;
@@ -676,9 +781,7 @@ xfs_calc_remove_reservation(
676781

677782
t1 = xfs_calc_inode_res(mp, 2) +
678783
xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1));
679-
t2 = xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
680-
xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
681-
XFS_FSB_TO_B(mp, 1));
784+
t2 = xfs_calc_finish_efi_reservation(mp, 2);
682785

683786
if (xfs_has_parent(mp)) {
684787
t3 = resp->tr_attrrm.tr_logres;

fs/xfs/libxfs/xfs_trans_resv.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,24 @@ struct xfs_trans_resv {
9898
void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp);
9999
uint xfs_allocfree_block_count(struct xfs_mount *mp, uint num_ops);
100100

101+
unsigned int xfs_calc_finish_bui_reservation(struct xfs_mount *mp,
102+
unsigned int nr_ops);
103+
104+
unsigned int xfs_calc_finish_efi_reservation(struct xfs_mount *mp,
105+
unsigned int nr_ops);
106+
unsigned int xfs_calc_finish_rt_efi_reservation(struct xfs_mount *mp,
107+
unsigned int nr_ops);
108+
109+
unsigned int xfs_calc_finish_rui_reservation(struct xfs_mount *mp,
110+
unsigned int nr_ops);
111+
unsigned int xfs_calc_finish_rt_rui_reservation(struct xfs_mount *mp,
112+
unsigned int nr_ops);
113+
114+
unsigned int xfs_calc_finish_cui_reservation(struct xfs_mount *mp,
115+
unsigned int nr_ops);
116+
unsigned int xfs_calc_finish_rt_cui_reservation(struct xfs_mount *mp,
117+
unsigned int nr_ops);
118+
101119
unsigned int xfs_calc_itruncate_reservation_minlogsize(struct xfs_mount *mp);
102120
unsigned int xfs_calc_write_reservation_minlogsize(struct xfs_mount *mp);
103121
unsigned int xfs_calc_qm_dqalloc_reservation_minlogsize(struct xfs_mount *mp);

0 commit comments

Comments
 (0)