@@ -263,6 +263,42 @@ xfs_rtalloc_block_count(
263
263
* register overflow from temporaries in the calculations.
264
264
*/
265
265
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
+
266
302
/*
267
303
* Compute the log reservation required to handle the refcount update
268
304
* transaction. Refcount updates are always done via deferred log items.
@@ -280,19 +316,10 @@ xfs_calc_refcountbt_reservation(
280
316
struct xfs_mount * mp ,
281
317
unsigned int nr_ops )
282
318
{
283
- unsigned int blksz = XFS_FSB_TO_B (mp , 1 );
284
- unsigned int t1 , t2 = 0 ;
319
+ unsigned int t1 , t2 ;
285
320
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 );
296
323
297
324
return max (t1 , t2 );
298
325
}
@@ -379,6 +406,96 @@ xfs_calc_write_reservation_minlogsize(
379
406
return xfs_calc_write_reservation (mp , true);
380
407
}
381
408
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
+
382
499
/*
383
500
* In truncating a file we free up to two extents at once. We can modify (t1):
384
501
* the inode being truncated: inode size
@@ -411,16 +528,8 @@ xfs_calc_itruncate_reservation(
411
528
t1 = xfs_calc_inode_res (mp , 1 ) +
412
529
xfs_calc_buf_res (XFS_BM_MAXLEVELS (mp , XFS_DATA_FORK ) + 1 , blksz );
413
530
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 );
424
533
425
534
/*
426
535
* In the early days of reflink, we included enough reservation to log
@@ -501,9 +610,7 @@ xfs_calc_rename_reservation(
501
610
xfs_calc_buf_res (2 * XFS_DIROP_LOG_COUNT (mp ),
502
611
XFS_FSB_TO_B (mp , 1 ));
503
612
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 );
507
614
508
615
if (xfs_has_parent (mp )) {
509
616
unsigned int rename_overhead , exchange_overhead ;
@@ -611,9 +718,7 @@ xfs_calc_link_reservation(
611
718
overhead += xfs_calc_iunlink_remove_reservation (mp );
612
719
t1 = xfs_calc_inode_res (mp , 2 ) +
613
720
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 );
617
722
618
723
if (xfs_has_parent (mp )) {
619
724
t3 = resp -> tr_attrsetm .tr_logres ;
@@ -676,9 +781,7 @@ xfs_calc_remove_reservation(
676
781
677
782
t1 = xfs_calc_inode_res (mp , 2 ) +
678
783
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 );
682
785
683
786
if (xfs_has_parent (mp )) {
684
787
t3 = resp -> tr_attrrm .tr_logres ;
0 commit comments