diff options
Diffstat (limited to 'fs/xfs/xfs_trans.c')
-rw-r--r-- | fs/xfs/xfs_trans.c | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index cc2d60951e21..7133fd9ab868 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -427,6 +427,14 @@ undo_blocks: | |||
427 | * | 427 | * |
428 | * Mark the transaction structure to indicate that the superblock | 428 | * Mark the transaction structure to indicate that the superblock |
429 | * needs to be updated before committing. | 429 | * needs to be updated before committing. |
430 | * | ||
431 | * Because we may not be keeping track of allocated/free inodes and | ||
432 | * used filesystem blocks in the superblock, we do not mark the | ||
433 | * superblock dirty in this transaction if we modify these fields. | ||
434 | * We still need to update the transaction deltas so that they get | ||
435 | * applied to the incore superblock, but we don't want them to | ||
436 | * cause the superblock to get locked and logged if these are the | ||
437 | * only fields in the superblock that the transaction modifies. | ||
430 | */ | 438 | */ |
431 | void | 439 | void |
432 | xfs_trans_mod_sb( | 440 | xfs_trans_mod_sb( |
@@ -434,13 +442,19 @@ xfs_trans_mod_sb( | |||
434 | uint field, | 442 | uint field, |
435 | int64_t delta) | 443 | int64_t delta) |
436 | { | 444 | { |
445 | uint32_t flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY); | ||
446 | xfs_mount_t *mp = tp->t_mountp; | ||
437 | 447 | ||
438 | switch (field) { | 448 | switch (field) { |
439 | case XFS_TRANS_SB_ICOUNT: | 449 | case XFS_TRANS_SB_ICOUNT: |
440 | tp->t_icount_delta += delta; | 450 | tp->t_icount_delta += delta; |
451 | if (xfs_sb_version_haslazysbcount(&mp->m_sb)) | ||
452 | flags &= ~XFS_TRANS_SB_DIRTY; | ||
441 | break; | 453 | break; |
442 | case XFS_TRANS_SB_IFREE: | 454 | case XFS_TRANS_SB_IFREE: |
443 | tp->t_ifree_delta += delta; | 455 | tp->t_ifree_delta += delta; |
456 | if (xfs_sb_version_haslazysbcount(&mp->m_sb)) | ||
457 | flags &= ~XFS_TRANS_SB_DIRTY; | ||
444 | break; | 458 | break; |
445 | case XFS_TRANS_SB_FDBLOCKS: | 459 | case XFS_TRANS_SB_FDBLOCKS: |
446 | /* | 460 | /* |
@@ -453,6 +467,8 @@ xfs_trans_mod_sb( | |||
453 | ASSERT(tp->t_blk_res_used <= tp->t_blk_res); | 467 | ASSERT(tp->t_blk_res_used <= tp->t_blk_res); |
454 | } | 468 | } |
455 | tp->t_fdblocks_delta += delta; | 469 | tp->t_fdblocks_delta += delta; |
470 | if (xfs_sb_version_haslazysbcount(&mp->m_sb)) | ||
471 | flags &= ~XFS_TRANS_SB_DIRTY; | ||
456 | break; | 472 | break; |
457 | case XFS_TRANS_SB_RES_FDBLOCKS: | 473 | case XFS_TRANS_SB_RES_FDBLOCKS: |
458 | /* | 474 | /* |
@@ -462,6 +478,8 @@ xfs_trans_mod_sb( | |||
462 | */ | 478 | */ |
463 | ASSERT(delta < 0); | 479 | ASSERT(delta < 0); |
464 | tp->t_res_fdblocks_delta += delta; | 480 | tp->t_res_fdblocks_delta += delta; |
481 | if (xfs_sb_version_haslazysbcount(&mp->m_sb)) | ||
482 | flags &= ~XFS_TRANS_SB_DIRTY; | ||
465 | break; | 483 | break; |
466 | case XFS_TRANS_SB_FREXTENTS: | 484 | case XFS_TRANS_SB_FREXTENTS: |
467 | /* | 485 | /* |
@@ -544,18 +562,23 @@ xfs_trans_apply_sb_deltas( | |||
544 | (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta + | 562 | (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta + |
545 | tp->t_ag_btree_delta)); | 563 | tp->t_ag_btree_delta)); |
546 | 564 | ||
547 | if (tp->t_icount_delta != 0) { | 565 | /* |
548 | INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta); | 566 | * Only update the superblock counters if we are logging them |
549 | } | 567 | */ |
550 | if (tp->t_ifree_delta != 0) { | 568 | if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) { |
551 | INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta); | 569 | if (tp->t_icount_delta != 0) { |
552 | } | 570 | INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta); |
571 | } | ||
572 | if (tp->t_ifree_delta != 0) { | ||
573 | INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta); | ||
574 | } | ||
553 | 575 | ||
554 | if (tp->t_fdblocks_delta != 0) { | 576 | if (tp->t_fdblocks_delta != 0) { |
555 | INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta); | 577 | INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta); |
556 | } | 578 | } |
557 | if (tp->t_res_fdblocks_delta != 0) { | 579 | if (tp->t_res_fdblocks_delta != 0) { |
558 | INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta); | 580 | INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta); |
581 | } | ||
559 | } | 582 | } |
560 | 583 | ||
561 | if (tp->t_frextents_delta != 0) { | 584 | if (tp->t_frextents_delta != 0) { |
@@ -627,6 +650,7 @@ xfs_trans_unreserve_and_mod_sb( | |||
627 | { | 650 | { |
628 | xfs_mod_sb_t msb[14]; /* If you add cases, add entries */ | 651 | xfs_mod_sb_t msb[14]; /* If you add cases, add entries */ |
629 | xfs_mod_sb_t *msbp; | 652 | xfs_mod_sb_t *msbp; |
653 | xfs_mount_t *mp = tp->t_mountp; | ||
630 | /* REFERENCED */ | 654 | /* REFERENCED */ |
631 | int error; | 655 | int error; |
632 | int rsvd; | 656 | int rsvd; |
@@ -659,8 +683,15 @@ xfs_trans_unreserve_and_mod_sb( | |||
659 | * The t_res_fdblocks_delta and t_res_frextents_delta fields are | 683 | * The t_res_fdblocks_delta and t_res_frextents_delta fields are |
660 | * explicitly NOT applied to the in-core superblock. | 684 | * explicitly NOT applied to the in-core superblock. |
661 | * The idea is that that has already been done. | 685 | * The idea is that that has already been done. |
686 | * | ||
687 | * If we are not logging superblock counters, then the inode | ||
688 | * allocated/free and used block counts are not updated in the | ||
689 | * on disk superblock. In this case, XFS_TRANS_SB_DIRTY will | ||
690 | * not be set when the transaction is updated but we still need | ||
691 | * to update the incore superblock with the changes. | ||
662 | */ | 692 | */ |
663 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { | 693 | if (xfs_sb_version_haslazysbcount(&mp->m_sb) || |
694 | (tp->t_flags & XFS_TRANS_SB_DIRTY)) { | ||
664 | if (tp->t_icount_delta != 0) { | 695 | if (tp->t_icount_delta != 0) { |
665 | msbp->msb_field = XFS_SBS_ICOUNT; | 696 | msbp->msb_field = XFS_SBS_ICOUNT; |
666 | msbp->msb_delta = tp->t_icount_delta; | 697 | msbp->msb_delta = tp->t_icount_delta; |
@@ -676,6 +707,9 @@ xfs_trans_unreserve_and_mod_sb( | |||
676 | msbp->msb_delta = tp->t_fdblocks_delta; | 707 | msbp->msb_delta = tp->t_fdblocks_delta; |
677 | msbp++; | 708 | msbp++; |
678 | } | 709 | } |
710 | } | ||
711 | |||
712 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { | ||
679 | if (tp->t_frextents_delta != 0) { | 713 | if (tp->t_frextents_delta != 0) { |
680 | msbp->msb_field = XFS_SBS_FREXTENTS; | 714 | msbp->msb_field = XFS_SBS_FREXTENTS; |
681 | msbp->msb_delta = tp->t_frextents_delta; | 715 | msbp->msb_delta = tp->t_frextents_delta; |