diff options
author | Dave Chinner <dchinner@redhat.com> | 2014-09-28 19:45:03 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-09-28 19:45:03 -0400 |
commit | eeb1168810d8a140f6834f8c4975f7bb3277d790 (patch) | |
tree | 82c48f9856db5e6a7d9b547ab9a47d0bdf1a198e /fs/xfs | |
parent | 52addcf9d6669fa439387610bc65c92fa0980cef (diff) |
xfs: refactor xlog_recover_process_data()
Clean up xlog_recover_process_data() structure in preparation for
fixing the allocation and freeing context of the transaction being
recovered.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 208 |
1 files changed, 132 insertions, 76 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 1fd5787add99..8105b8571979 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -3535,12 +3535,124 @@ out: | |||
3535 | } | 3535 | } |
3536 | 3536 | ||
3537 | STATIC int | 3537 | STATIC int |
3538 | xlog_recover_unmount_trans( | 3538 | xlog_recovery_process_trans( |
3539 | struct xlog *log) | 3539 | struct xlog *log, |
3540 | struct xlog_recover *trans, | ||
3541 | xfs_caddr_t dp, | ||
3542 | unsigned int len, | ||
3543 | unsigned int flags, | ||
3544 | int pass) | ||
3540 | { | 3545 | { |
3541 | /* Do nothing now */ | 3546 | int error = -EIO; |
3542 | xfs_warn(log->l_mp, "%s: Unmount LR", __func__); | 3547 | |
3543 | return 0; | 3548 | /* mask off ophdr transaction container flags */ |
3549 | flags &= ~XLOG_END_TRANS; | ||
3550 | if (flags & XLOG_WAS_CONT_TRANS) | ||
3551 | flags &= ~XLOG_CONTINUE_TRANS; | ||
3552 | |||
3553 | switch (flags) { | ||
3554 | /* expected flag values */ | ||
3555 | case 0: | ||
3556 | case XLOG_CONTINUE_TRANS: | ||
3557 | error = xlog_recover_add_to_trans(log, trans, dp, len); | ||
3558 | break; | ||
3559 | case XLOG_WAS_CONT_TRANS: | ||
3560 | error = xlog_recover_add_to_cont_trans(log, trans, dp, len); | ||
3561 | break; | ||
3562 | case XLOG_COMMIT_TRANS: | ||
3563 | error = xlog_recover_commit_trans(log, trans, pass); | ||
3564 | break; | ||
3565 | |||
3566 | /* unexpected flag values */ | ||
3567 | case XLOG_UNMOUNT_TRANS: | ||
3568 | xfs_warn(log->l_mp, "%s: Unmount LR", __func__); | ||
3569 | error = 0; /* just skip trans */ | ||
3570 | break; | ||
3571 | case XLOG_START_TRANS: | ||
3572 | xfs_warn(log->l_mp, "%s: bad transaction", __func__); | ||
3573 | ASSERT(0); | ||
3574 | break; | ||
3575 | default: | ||
3576 | xfs_warn(log->l_mp, "%s: bad flag 0x%x", __func__, flags); | ||
3577 | ASSERT(0); | ||
3578 | break; | ||
3579 | } | ||
3580 | return error; | ||
3581 | } | ||
3582 | |||
3583 | STATIC struct xlog_recover * | ||
3584 | xlog_recover_ophdr_to_trans( | ||
3585 | struct hlist_head rhash[], | ||
3586 | struct xlog_rec_header *rhead, | ||
3587 | struct xlog_op_header *ohead) | ||
3588 | { | ||
3589 | struct xlog_recover *trans; | ||
3590 | xlog_tid_t tid; | ||
3591 | struct hlist_head *rhp; | ||
3592 | |||
3593 | tid = be32_to_cpu(ohead->oh_tid); | ||
3594 | rhp = &rhash[XLOG_RHASH(tid)]; | ||
3595 | trans = xlog_recover_find_tid(rhp, tid); | ||
3596 | if (trans) | ||
3597 | return trans; | ||
3598 | |||
3599 | /* | ||
3600 | * If this is a new transaction, the ophdr only contains the | ||
3601 | * start record. In that case, the only processing we need to do | ||
3602 | * on this opheader is allocate a new recovery container to hold | ||
3603 | * the recovery ops that will follow. | ||
3604 | */ | ||
3605 | if (ohead->oh_flags & XLOG_START_TRANS) { | ||
3606 | ASSERT(be32_to_cpu(ohead->oh_len) == 0); | ||
3607 | xlog_recover_new_tid(rhp, tid, be64_to_cpu(rhead->h_lsn)); | ||
3608 | } | ||
3609 | return NULL; | ||
3610 | } | ||
3611 | |||
3612 | STATIC int | ||
3613 | xlog_recover_process_ophdr( | ||
3614 | struct xlog *log, | ||
3615 | struct hlist_head rhash[], | ||
3616 | struct xlog_rec_header *rhead, | ||
3617 | struct xlog_op_header *ohead, | ||
3618 | xfs_caddr_t dp, | ||
3619 | xfs_caddr_t end, | ||
3620 | int pass) | ||
3621 | { | ||
3622 | struct xlog_recover *trans; | ||
3623 | int error; | ||
3624 | unsigned int len; | ||
3625 | |||
3626 | /* Do we understand who wrote this op? */ | ||
3627 | if (ohead->oh_clientid != XFS_TRANSACTION && | ||
3628 | ohead->oh_clientid != XFS_LOG) { | ||
3629 | xfs_warn(log->l_mp, "%s: bad clientid 0x%x", | ||
3630 | __func__, ohead->oh_clientid); | ||
3631 | ASSERT(0); | ||
3632 | return -EIO; | ||
3633 | } | ||
3634 | |||
3635 | /* | ||
3636 | * Check the ophdr contains all the data it is supposed to contain. | ||
3637 | */ | ||
3638 | len = be32_to_cpu(ohead->oh_len); | ||
3639 | if (dp + len > end) { | ||
3640 | xfs_warn(log->l_mp, "%s: bad length 0x%x", __func__, len); | ||
3641 | WARN_ON(1); | ||
3642 | return -EIO; | ||
3643 | } | ||
3644 | |||
3645 | trans = xlog_recover_ophdr_to_trans(rhash, rhead, ohead); | ||
3646 | if (!trans) { | ||
3647 | /* nothing to do, so skip over this ophdr */ | ||
3648 | return 0; | ||
3649 | } | ||
3650 | |||
3651 | error = xlog_recovery_process_trans(log, trans, dp, len, | ||
3652 | ohead->oh_flags, pass); | ||
3653 | if (error) | ||
3654 | xlog_recover_free_trans(trans); | ||
3655 | return error; | ||
3544 | } | 3656 | } |
3545 | 3657 | ||
3546 | /* | 3658 | /* |
@@ -3560,86 +3672,30 @@ xlog_recover_process_data( | |||
3560 | xfs_caddr_t dp, | 3672 | xfs_caddr_t dp, |
3561 | int pass) | 3673 | int pass) |
3562 | { | 3674 | { |
3563 | xfs_caddr_t lp; | 3675 | struct xlog_op_header *ohead; |
3676 | xfs_caddr_t end; | ||
3564 | int num_logops; | 3677 | int num_logops; |
3565 | xlog_op_header_t *ohead; | ||
3566 | xlog_recover_t *trans; | ||
3567 | xlog_tid_t tid; | ||
3568 | int error; | 3678 | int error; |
3569 | unsigned long hash; | ||
3570 | uint flags; | ||
3571 | 3679 | ||
3572 | lp = dp + be32_to_cpu(rhead->h_len); | 3680 | end = dp + be32_to_cpu(rhead->h_len); |
3573 | num_logops = be32_to_cpu(rhead->h_num_logops); | 3681 | num_logops = be32_to_cpu(rhead->h_num_logops); |
3574 | 3682 | ||
3575 | /* check the log format matches our own - else we can't recover */ | 3683 | /* check the log format matches our own - else we can't recover */ |
3576 | if (xlog_header_check_recover(log->l_mp, rhead)) | 3684 | if (xlog_header_check_recover(log->l_mp, rhead)) |
3577 | return -EIO; | 3685 | return -EIO; |
3578 | 3686 | ||
3579 | while ((dp < lp) && num_logops) { | 3687 | while ((dp < end) && num_logops) { |
3580 | ASSERT(dp + sizeof(xlog_op_header_t) <= lp); | 3688 | |
3581 | ohead = (xlog_op_header_t *)dp; | 3689 | ohead = (struct xlog_op_header *)dp; |
3582 | dp += sizeof(xlog_op_header_t); | 3690 | dp += sizeof(*ohead); |
3583 | if (ohead->oh_clientid != XFS_TRANSACTION && | 3691 | ASSERT(dp <= end); |
3584 | ohead->oh_clientid != XFS_LOG) { | 3692 | |
3585 | xfs_warn(log->l_mp, "%s: bad clientid 0x%x", | 3693 | /* errors will abort recovery */ |
3586 | __func__, ohead->oh_clientid); | 3694 | error = xlog_recover_process_ophdr(log, rhash, rhead, ohead, |
3587 | ASSERT(0); | 3695 | dp, end, pass); |
3588 | return -EIO; | 3696 | if (error) |
3589 | } | 3697 | return error; |
3590 | tid = be32_to_cpu(ohead->oh_tid); | 3698 | |
3591 | hash = XLOG_RHASH(tid); | ||
3592 | trans = xlog_recover_find_tid(&rhash[hash], tid); | ||
3593 | if (trans == NULL) { /* not found; add new tid */ | ||
3594 | if (ohead->oh_flags & XLOG_START_TRANS) | ||
3595 | xlog_recover_new_tid(&rhash[hash], tid, | ||
3596 | be64_to_cpu(rhead->h_lsn)); | ||
3597 | } else { | ||
3598 | if (dp + be32_to_cpu(ohead->oh_len) > lp) { | ||
3599 | xfs_warn(log->l_mp, "%s: bad length 0x%x", | ||
3600 | __func__, be32_to_cpu(ohead->oh_len)); | ||
3601 | WARN_ON(1); | ||
3602 | return -EIO; | ||
3603 | } | ||
3604 | flags = ohead->oh_flags & ~XLOG_END_TRANS; | ||
3605 | if (flags & XLOG_WAS_CONT_TRANS) | ||
3606 | flags &= ~XLOG_CONTINUE_TRANS; | ||
3607 | switch (flags) { | ||
3608 | case XLOG_COMMIT_TRANS: | ||
3609 | error = xlog_recover_commit_trans(log, | ||
3610 | trans, pass); | ||
3611 | break; | ||
3612 | case XLOG_UNMOUNT_TRANS: | ||
3613 | error = xlog_recover_unmount_trans(log); | ||
3614 | break; | ||
3615 | case XLOG_WAS_CONT_TRANS: | ||
3616 | error = xlog_recover_add_to_cont_trans(log, | ||
3617 | trans, dp, | ||
3618 | be32_to_cpu(ohead->oh_len)); | ||
3619 | break; | ||
3620 | case XLOG_START_TRANS: | ||
3621 | xfs_warn(log->l_mp, "%s: bad transaction", | ||
3622 | __func__); | ||
3623 | ASSERT(0); | ||
3624 | error = -EIO; | ||
3625 | break; | ||
3626 | case 0: | ||
3627 | case XLOG_CONTINUE_TRANS: | ||
3628 | error = xlog_recover_add_to_trans(log, trans, | ||
3629 | dp, be32_to_cpu(ohead->oh_len)); | ||
3630 | break; | ||
3631 | default: | ||
3632 | xfs_warn(log->l_mp, "%s: bad flag 0x%x", | ||
3633 | __func__, flags); | ||
3634 | ASSERT(0); | ||
3635 | error = -EIO; | ||
3636 | break; | ||
3637 | } | ||
3638 | if (error) { | ||
3639 | xlog_recover_free_trans(trans); | ||
3640 | return error; | ||
3641 | } | ||
3642 | } | ||
3643 | dp += be32_to_cpu(ohead->oh_len); | 3699 | dp += be32_to_cpu(ohead->oh_len); |
3644 | num_logops--; | 3700 | num_logops--; |
3645 | } | 3701 | } |