|
46 | 46 | #include "xfs_rmap_item.h"
|
47 | 47 | #include "xfs_buf_item.h"
|
48 | 48 | #include "xfs_refcount_item.h"
|
| 49 | +#include "xfs_bmap_item.h" |
49 | 50 |
|
50 | 51 | #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1)
|
51 | 52 |
|
@@ -1927,6 +1928,8 @@ xlog_recover_reorder_trans(
|
1927 | 1928 | case XFS_LI_RUD:
|
1928 | 1929 | case XFS_LI_CUI:
|
1929 | 1930 | case XFS_LI_CUD:
|
| 1931 | + case XFS_LI_BUI: |
| 1932 | + case XFS_LI_BUD: |
1930 | 1933 | trace_xfs_log_recover_item_reorder_tail(log,
|
1931 | 1934 | trans, item, pass);
|
1932 | 1935 | list_move_tail(&item->ri_list, &inode_list);
|
@@ -3670,6 +3673,125 @@ xlog_recover_cud_pass2(
|
3670 | 3673 | return 0;
|
3671 | 3674 | }
|
3672 | 3675 |
|
| 3676 | +/* |
| 3677 | + * Copy an BUI format buffer from the given buf, and into the destination |
| 3678 | + * BUI format structure. The BUI/BUD items were designed not to need any |
| 3679 | + * special alignment handling. |
| 3680 | + */ |
| 3681 | +static int |
| 3682 | +xfs_bui_copy_format( |
| 3683 | + struct xfs_log_iovec *buf, |
| 3684 | + struct xfs_bui_log_format *dst_bui_fmt) |
| 3685 | +{ |
| 3686 | + struct xfs_bui_log_format *src_bui_fmt; |
| 3687 | + uint len; |
| 3688 | + |
| 3689 | + src_bui_fmt = buf->i_addr; |
| 3690 | + len = xfs_bui_log_format_sizeof(src_bui_fmt->bui_nextents); |
| 3691 | + |
| 3692 | + if (buf->i_len == len) { |
| 3693 | + memcpy(dst_bui_fmt, src_bui_fmt, len); |
| 3694 | + return 0; |
| 3695 | + } |
| 3696 | + return -EFSCORRUPTED; |
| 3697 | +} |
| 3698 | + |
| 3699 | +/* |
| 3700 | + * This routine is called to create an in-core extent bmap update |
| 3701 | + * item from the bui format structure which was logged on disk. |
| 3702 | + * It allocates an in-core bui, copies the extents from the format |
| 3703 | + * structure into it, and adds the bui to the AIL with the given |
| 3704 | + * LSN. |
| 3705 | + */ |
| 3706 | +STATIC int |
| 3707 | +xlog_recover_bui_pass2( |
| 3708 | + struct xlog *log, |
| 3709 | + struct xlog_recover_item *item, |
| 3710 | + xfs_lsn_t lsn) |
| 3711 | +{ |
| 3712 | + int error; |
| 3713 | + struct xfs_mount *mp = log->l_mp; |
| 3714 | + struct xfs_bui_log_item *buip; |
| 3715 | + struct xfs_bui_log_format *bui_formatp; |
| 3716 | + |
| 3717 | + bui_formatp = item->ri_buf[0].i_addr; |
| 3718 | + |
| 3719 | + if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) |
| 3720 | + return -EFSCORRUPTED; |
| 3721 | + buip = xfs_bui_init(mp); |
| 3722 | + error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format); |
| 3723 | + if (error) { |
| 3724 | + xfs_bui_item_free(buip); |
| 3725 | + return error; |
| 3726 | + } |
| 3727 | + atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents); |
| 3728 | + |
| 3729 | + spin_lock(&log->l_ailp->xa_lock); |
| 3730 | + /* |
| 3731 | + * The RUI has two references. One for the RUD and one for RUI to ensure |
| 3732 | + * it makes it into the AIL. Insert the RUI into the AIL directly and |
| 3733 | + * drop the RUI reference. Note that xfs_trans_ail_update() drops the |
| 3734 | + * AIL lock. |
| 3735 | + */ |
| 3736 | + xfs_trans_ail_update(log->l_ailp, &buip->bui_item, lsn); |
| 3737 | + xfs_bui_release(buip); |
| 3738 | + return 0; |
| 3739 | +} |
| 3740 | + |
| 3741 | + |
| 3742 | +/* |
| 3743 | + * This routine is called when an BUD format structure is found in a committed |
| 3744 | + * transaction in the log. Its purpose is to cancel the corresponding BUI if it |
| 3745 | + * was still in the log. To do this it searches the AIL for the BUI with an id |
| 3746 | + * equal to that in the BUD format structure. If we find it we drop the BUD |
| 3747 | + * reference, which removes the BUI from the AIL and frees it. |
| 3748 | + */ |
| 3749 | +STATIC int |
| 3750 | +xlog_recover_bud_pass2( |
| 3751 | + struct xlog *log, |
| 3752 | + struct xlog_recover_item *item) |
| 3753 | +{ |
| 3754 | + struct xfs_bud_log_format *bud_formatp; |
| 3755 | + struct xfs_bui_log_item *buip = NULL; |
| 3756 | + struct xfs_log_item *lip; |
| 3757 | + __uint64_t bui_id; |
| 3758 | + struct xfs_ail_cursor cur; |
| 3759 | + struct xfs_ail *ailp = log->l_ailp; |
| 3760 | + |
| 3761 | + bud_formatp = item->ri_buf[0].i_addr; |
| 3762 | + if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) |
| 3763 | + return -EFSCORRUPTED; |
| 3764 | + bui_id = bud_formatp->bud_bui_id; |
| 3765 | + |
| 3766 | + /* |
| 3767 | + * Search for the BUI with the id in the BUD format structure in the |
| 3768 | + * AIL. |
| 3769 | + */ |
| 3770 | + spin_lock(&ailp->xa_lock); |
| 3771 | + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); |
| 3772 | + while (lip != NULL) { |
| 3773 | + if (lip->li_type == XFS_LI_BUI) { |
| 3774 | + buip = (struct xfs_bui_log_item *)lip; |
| 3775 | + if (buip->bui_format.bui_id == bui_id) { |
| 3776 | + /* |
| 3777 | + * Drop the BUD reference to the BUI. This |
| 3778 | + * removes the BUI from the AIL and frees it. |
| 3779 | + */ |
| 3780 | + spin_unlock(&ailp->xa_lock); |
| 3781 | + xfs_bui_release(buip); |
| 3782 | + spin_lock(&ailp->xa_lock); |
| 3783 | + break; |
| 3784 | + } |
| 3785 | + } |
| 3786 | + lip = xfs_trans_ail_cursor_next(ailp, &cur); |
| 3787 | + } |
| 3788 | + |
| 3789 | + xfs_trans_ail_cursor_done(&cur); |
| 3790 | + spin_unlock(&ailp->xa_lock); |
| 3791 | + |
| 3792 | + return 0; |
| 3793 | +} |
| 3794 | + |
3673 | 3795 | /*
|
3674 | 3796 | * This routine is called when an inode create format structure is found in a
|
3675 | 3797 | * committed transaction in the log. It's purpose is to initialise the inodes
|
@@ -3899,6 +4021,8 @@ xlog_recover_ra_pass2(
|
3899 | 4021 | case XFS_LI_RUD:
|
3900 | 4022 | case XFS_LI_CUI:
|
3901 | 4023 | case XFS_LI_CUD:
|
| 4024 | + case XFS_LI_BUI: |
| 4025 | + case XFS_LI_BUD: |
3902 | 4026 | default:
|
3903 | 4027 | break;
|
3904 | 4028 | }
|
@@ -3926,6 +4050,8 @@ xlog_recover_commit_pass1(
|
3926 | 4050 | case XFS_LI_RUD:
|
3927 | 4051 | case XFS_LI_CUI:
|
3928 | 4052 | case XFS_LI_CUD:
|
| 4053 | + case XFS_LI_BUI: |
| 4054 | + case XFS_LI_BUD: |
3929 | 4055 | /* nothing to do in pass 1 */
|
3930 | 4056 | return 0;
|
3931 | 4057 | default:
|
@@ -3964,6 +4090,10 @@ xlog_recover_commit_pass2(
|
3964 | 4090 | return xlog_recover_cui_pass2(log, item, trans->r_lsn);
|
3965 | 4091 | case XFS_LI_CUD:
|
3966 | 4092 | return xlog_recover_cud_pass2(log, item);
|
| 4093 | + case XFS_LI_BUI: |
| 4094 | + return xlog_recover_bui_pass2(log, item, trans->r_lsn); |
| 4095 | + case XFS_LI_BUD: |
| 4096 | + return xlog_recover_bud_pass2(log, item); |
3967 | 4097 | case XFS_LI_DQUOT:
|
3968 | 4098 | return xlog_recover_dquot_pass2(log, buffer_list, item,
|
3969 | 4099 | trans->r_lsn);
|
@@ -4591,13 +4721,54 @@ xlog_recover_cancel_cui(
|
4591 | 4721 | spin_lock(&ailp->xa_lock);
|
4592 | 4722 | }
|
4593 | 4723 |
|
| 4724 | +/* Recover the BUI if necessary. */ |
| 4725 | +STATIC int |
| 4726 | +xlog_recover_process_bui( |
| 4727 | + struct xfs_mount *mp, |
| 4728 | + struct xfs_ail *ailp, |
| 4729 | + struct xfs_log_item *lip) |
| 4730 | +{ |
| 4731 | + struct xfs_bui_log_item *buip; |
| 4732 | + int error; |
| 4733 | + |
| 4734 | + /* |
| 4735 | + * Skip BUIs that we've already processed. |
| 4736 | + */ |
| 4737 | + buip = container_of(lip, struct xfs_bui_log_item, bui_item); |
| 4738 | + if (test_bit(XFS_BUI_RECOVERED, &buip->bui_flags)) |
| 4739 | + return 0; |
| 4740 | + |
| 4741 | + spin_unlock(&ailp->xa_lock); |
| 4742 | + error = xfs_bui_recover(mp, buip); |
| 4743 | + spin_lock(&ailp->xa_lock); |
| 4744 | + |
| 4745 | + return error; |
| 4746 | +} |
| 4747 | + |
| 4748 | +/* Release the BUI since we're cancelling everything. */ |
| 4749 | +STATIC void |
| 4750 | +xlog_recover_cancel_bui( |
| 4751 | + struct xfs_mount *mp, |
| 4752 | + struct xfs_ail *ailp, |
| 4753 | + struct xfs_log_item *lip) |
| 4754 | +{ |
| 4755 | + struct xfs_bui_log_item *buip; |
| 4756 | + |
| 4757 | + buip = container_of(lip, struct xfs_bui_log_item, bui_item); |
| 4758 | + |
| 4759 | + spin_unlock(&ailp->xa_lock); |
| 4760 | + xfs_bui_release(buip); |
| 4761 | + spin_lock(&ailp->xa_lock); |
| 4762 | +} |
| 4763 | + |
4594 | 4764 | /* Is this log item a deferred action intent? */
|
4595 | 4765 | static inline bool xlog_item_is_intent(struct xfs_log_item *lip)
|
4596 | 4766 | {
|
4597 | 4767 | switch (lip->li_type) {
|
4598 | 4768 | case XFS_LI_EFI:
|
4599 | 4769 | case XFS_LI_RUI:
|
4600 | 4770 | case XFS_LI_CUI:
|
| 4771 | + case XFS_LI_BUI: |
4601 | 4772 | return true;
|
4602 | 4773 | default:
|
4603 | 4774 | return false;
|
@@ -4664,6 +4835,9 @@ xlog_recover_process_intents(
|
4664 | 4835 | case XFS_LI_CUI:
|
4665 | 4836 | error = xlog_recover_process_cui(log->l_mp, ailp, lip);
|
4666 | 4837 | break;
|
| 4838 | + case XFS_LI_BUI: |
| 4839 | + error = xlog_recover_process_bui(log->l_mp, ailp, lip); |
| 4840 | + break; |
4667 | 4841 | }
|
4668 | 4842 | if (error)
|
4669 | 4843 | goto out;
|
@@ -4714,6 +4888,9 @@ xlog_recover_cancel_intents(
|
4714 | 4888 | case XFS_LI_CUI:
|
4715 | 4889 | xlog_recover_cancel_cui(log->l_mp, ailp, lip);
|
4716 | 4890 | break;
|
| 4891 | + case XFS_LI_BUI: |
| 4892 | + xlog_recover_cancel_bui(log->l_mp, ailp, lip); |
| 4893 | + break; |
4717 | 4894 | }
|
4718 | 4895 |
|
4719 | 4896 | lip = xfs_trans_ail_cursor_next(ailp, &cur);
|
|
0 commit comments