@@ -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 ;
0 commit comments