diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 108 |
1 files changed, 92 insertions, 16 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 3806088a8f77..140136cf2dc0 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -43,6 +43,8 @@ | |||
43 | #include "xfs_utils.h" | 43 | #include "xfs_utils.h" |
44 | #include "xfs_trace.h" | 44 | #include "xfs_trace.h" |
45 | #include "xfs_icache.h" | 45 | #include "xfs_icache.h" |
46 | #include "xfs_cksum.h" | ||
47 | #include "xfs_buf_item.h" | ||
46 | 48 | ||
47 | 49 | ||
48 | #ifdef HAVE_PERCPU_SB | 50 | #ifdef HAVE_PERCPU_SB |
@@ -109,6 +111,12 @@ static const struct { | |||
109 | { offsetof(xfs_sb_t, sb_logsunit), 0 }, | 111 | { offsetof(xfs_sb_t, sb_logsunit), 0 }, |
110 | { offsetof(xfs_sb_t, sb_features2), 0 }, | 112 | { offsetof(xfs_sb_t, sb_features2), 0 }, |
111 | { offsetof(xfs_sb_t, sb_bad_features2), 0 }, | 113 | { offsetof(xfs_sb_t, sb_bad_features2), 0 }, |
114 | { offsetof(xfs_sb_t, sb_features_compat), 0 }, | ||
115 | { offsetof(xfs_sb_t, sb_features_ro_compat), 0 }, | ||
116 | { offsetof(xfs_sb_t, sb_features_incompat), 0 }, | ||
117 | { offsetof(xfs_sb_t, sb_crc), 0 }, | ||
118 | { offsetof(xfs_sb_t, sb_pquotino), 0 }, | ||
119 | { offsetof(xfs_sb_t, sb_lsn), 0 }, | ||
112 | { sizeof(xfs_sb_t), 0 } | 120 | { sizeof(xfs_sb_t), 0 } |
113 | }; | 121 | }; |
114 | 122 | ||
@@ -319,11 +327,23 @@ xfs_mount_validate_sb( | |||
319 | return XFS_ERROR(EWRONGFS); | 327 | return XFS_ERROR(EWRONGFS); |
320 | } | 328 | } |
321 | 329 | ||
330 | |||
322 | if (!xfs_sb_good_version(sbp)) { | 331 | if (!xfs_sb_good_version(sbp)) { |
323 | xfs_warn(mp, "bad version"); | 332 | xfs_warn(mp, "bad version"); |
324 | return XFS_ERROR(EWRONGFS); | 333 | return XFS_ERROR(EWRONGFS); |
325 | } | 334 | } |
326 | 335 | ||
336 | /* | ||
337 | * Do not allow Version 5 superblocks to mount right now, even though | ||
338 | * support is in place. We need to implement the proper feature masks | ||
339 | * first. | ||
340 | */ | ||
341 | if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) { | ||
342 | xfs_alert(mp, | ||
343 | "Version 5 superblock detected. Experimental support not yet enabled!"); | ||
344 | return XFS_ERROR(EINVAL); | ||
345 | } | ||
346 | |||
327 | if (unlikely( | 347 | if (unlikely( |
328 | sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { | 348 | sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { |
329 | xfs_warn(mp, | 349 | xfs_warn(mp, |
@@ -557,6 +577,11 @@ xfs_sb_from_disk( | |||
557 | to->sb_logsunit = be32_to_cpu(from->sb_logsunit); | 577 | to->sb_logsunit = be32_to_cpu(from->sb_logsunit); |
558 | to->sb_features2 = be32_to_cpu(from->sb_features2); | 578 | to->sb_features2 = be32_to_cpu(from->sb_features2); |
559 | to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2); | 579 | to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2); |
580 | to->sb_features_compat = be32_to_cpu(from->sb_features_compat); | ||
581 | to->sb_features_ro_compat = be32_to_cpu(from->sb_features_ro_compat); | ||
582 | to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat); | ||
583 | to->sb_pquotino = be64_to_cpu(from->sb_pquotino); | ||
584 | to->sb_lsn = be64_to_cpu(from->sb_lsn); | ||
560 | } | 585 | } |
561 | 586 | ||
562 | /* | 587 | /* |
@@ -612,13 +637,12 @@ xfs_sb_to_disk( | |||
612 | } | 637 | } |
613 | } | 638 | } |
614 | 639 | ||
615 | static void | 640 | static int |
616 | xfs_sb_verify( | 641 | xfs_sb_verify( |
617 | struct xfs_buf *bp) | 642 | struct xfs_buf *bp) |
618 | { | 643 | { |
619 | struct xfs_mount *mp = bp->b_target->bt_mount; | 644 | struct xfs_mount *mp = bp->b_target->bt_mount; |
620 | struct xfs_sb sb; | 645 | struct xfs_sb sb; |
621 | int error; | ||
622 | 646 | ||
623 | xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp)); | 647 | xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp)); |
624 | 648 | ||
@@ -626,16 +650,46 @@ xfs_sb_verify( | |||
626 | * Only check the in progress field for the primary superblock as | 650 | * Only check the in progress field for the primary superblock as |
627 | * mkfs.xfs doesn't clear it from secondary superblocks. | 651 | * mkfs.xfs doesn't clear it from secondary superblocks. |
628 | */ | 652 | */ |
629 | error = xfs_mount_validate_sb(mp, &sb, bp->b_bn == XFS_SB_DADDR); | 653 | return xfs_mount_validate_sb(mp, &sb, bp->b_bn == XFS_SB_DADDR); |
630 | if (error) | ||
631 | xfs_buf_ioerror(bp, error); | ||
632 | } | 654 | } |
633 | 655 | ||
656 | /* | ||
657 | * If the superblock has the CRC feature bit set or the CRC field is non-null, | ||
658 | * check that the CRC is valid. We check the CRC field is non-null because a | ||
659 | * single bit error could clear the feature bit and unused parts of the | ||
660 | * superblock are supposed to be zero. Hence a non-null crc field indicates that | ||
661 | * we've potentially lost a feature bit and we should check it anyway. | ||
662 | */ | ||
634 | static void | 663 | static void |
635 | xfs_sb_read_verify( | 664 | xfs_sb_read_verify( |
636 | struct xfs_buf *bp) | 665 | struct xfs_buf *bp) |
637 | { | 666 | { |
638 | xfs_sb_verify(bp); | 667 | struct xfs_mount *mp = bp->b_target->bt_mount; |
668 | struct xfs_dsb *dsb = XFS_BUF_TO_SBP(bp); | ||
669 | int error; | ||
670 | |||
671 | /* | ||
672 | * open code the version check to avoid needing to convert the entire | ||
673 | * superblock from disk order just to check the version number | ||
674 | */ | ||
675 | if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC) && | ||
676 | (((be16_to_cpu(dsb->sb_versionnum) & XFS_SB_VERSION_NUMBITS) == | ||
677 | XFS_SB_VERSION_5) || | ||
678 | dsb->sb_crc != 0)) { | ||
679 | |||
680 | if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize), | ||
681 | offsetof(struct xfs_sb, sb_crc))) { | ||
682 | error = EFSCORRUPTED; | ||
683 | goto out_error; | ||
684 | } | ||
685 | } | ||
686 | error = xfs_sb_verify(bp); | ||
687 | |||
688 | out_error: | ||
689 | if (error) { | ||
690 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
691 | xfs_buf_ioerror(bp, error); | ||
692 | } | ||
639 | } | 693 | } |
640 | 694 | ||
641 | /* | 695 | /* |
@@ -648,11 +702,10 @@ static void | |||
648 | xfs_sb_quiet_read_verify( | 702 | xfs_sb_quiet_read_verify( |
649 | struct xfs_buf *bp) | 703 | struct xfs_buf *bp) |
650 | { | 704 | { |
651 | struct xfs_sb sb; | 705 | struct xfs_dsb *dsb = XFS_BUF_TO_SBP(bp); |
652 | 706 | ||
653 | xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp)); | ||
654 | 707 | ||
655 | if (sb.sb_magicnum == XFS_SB_MAGIC) { | 708 | if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) { |
656 | /* XFS filesystem, verify noisily! */ | 709 | /* XFS filesystem, verify noisily! */ |
657 | xfs_sb_read_verify(bp); | 710 | xfs_sb_read_verify(bp); |
658 | return; | 711 | return; |
@@ -663,9 +716,27 @@ xfs_sb_quiet_read_verify( | |||
663 | 716 | ||
664 | static void | 717 | static void |
665 | xfs_sb_write_verify( | 718 | xfs_sb_write_verify( |
666 | struct xfs_buf *bp) | 719 | struct xfs_buf *bp) |
667 | { | 720 | { |
668 | xfs_sb_verify(bp); | 721 | struct xfs_mount *mp = bp->b_target->bt_mount; |
722 | struct xfs_buf_log_item *bip = bp->b_fspriv; | ||
723 | int error; | ||
724 | |||
725 | error = xfs_sb_verify(bp); | ||
726 | if (error) { | ||
727 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
728 | xfs_buf_ioerror(bp, error); | ||
729 | return; | ||
730 | } | ||
731 | |||
732 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
733 | return; | ||
734 | |||
735 | if (bip) | ||
736 | XFS_BUF_TO_SBP(bp)->sb_lsn = cpu_to_be64(bip->bli_item.li_lsn); | ||
737 | |||
738 | xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
739 | offsetof(struct xfs_sb, sb_crc)); | ||
669 | } | 740 | } |
670 | 741 | ||
671 | const struct xfs_buf_ops xfs_sb_buf_ops = { | 742 | const struct xfs_buf_ops xfs_sb_buf_ops = { |
@@ -687,7 +758,8 @@ int | |||
687 | xfs_readsb(xfs_mount_t *mp, int flags) | 758 | xfs_readsb(xfs_mount_t *mp, int flags) |
688 | { | 759 | { |
689 | unsigned int sector_size; | 760 | unsigned int sector_size; |
690 | xfs_buf_t *bp; | 761 | struct xfs_buf *bp; |
762 | struct xfs_sb *sbp = &mp->m_sb; | ||
691 | int error; | 763 | int error; |
692 | int loud = !(flags & XFS_MFSI_QUIET); | 764 | int loud = !(flags & XFS_MFSI_QUIET); |
693 | 765 | ||
@@ -726,10 +798,10 @@ reread: | |||
726 | /* | 798 | /* |
727 | * We must be able to do sector-sized and sector-aligned IO. | 799 | * We must be able to do sector-sized and sector-aligned IO. |
728 | */ | 800 | */ |
729 | if (sector_size > mp->m_sb.sb_sectsize) { | 801 | if (sector_size > sbp->sb_sectsize) { |
730 | if (loud) | 802 | if (loud) |
731 | xfs_warn(mp, "device supports %u byte sectors (not %u)", | 803 | xfs_warn(mp, "device supports %u byte sectors (not %u)", |
732 | sector_size, mp->m_sb.sb_sectsize); | 804 | sector_size, sbp->sb_sectsize); |
733 | error = ENOSYS; | 805 | error = ENOSYS; |
734 | goto release_buf; | 806 | goto release_buf; |
735 | } | 807 | } |
@@ -738,15 +810,18 @@ reread: | |||
738 | * If device sector size is smaller than the superblock size, | 810 | * If device sector size is smaller than the superblock size, |
739 | * re-read the superblock so the buffer is correctly sized. | 811 | * re-read the superblock so the buffer is correctly sized. |
740 | */ | 812 | */ |
741 | if (sector_size < mp->m_sb.sb_sectsize) { | 813 | if (sector_size < sbp->sb_sectsize) { |
742 | xfs_buf_relse(bp); | 814 | xfs_buf_relse(bp); |
743 | sector_size = mp->m_sb.sb_sectsize; | 815 | sector_size = sbp->sb_sectsize; |
744 | goto reread; | 816 | goto reread; |
745 | } | 817 | } |
746 | 818 | ||
747 | /* Initialize per-cpu counters */ | 819 | /* Initialize per-cpu counters */ |
748 | xfs_icsb_reinit_counters(mp); | 820 | xfs_icsb_reinit_counters(mp); |
749 | 821 | ||
822 | /* no need to be quiet anymore, so reset the buf ops */ | ||
823 | bp->b_ops = &xfs_sb_buf_ops; | ||
824 | |||
750 | mp->m_sb_bp = bp; | 825 | mp->m_sb_bp = bp; |
751 | xfs_buf_unlock(bp); | 826 | xfs_buf_unlock(bp); |
752 | return 0; | 827 | return 0; |
@@ -1633,6 +1708,7 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) | |||
1633 | ASSERT((1LL << f) & XFS_SB_MOD_BITS); | 1708 | ASSERT((1LL << f) & XFS_SB_MOD_BITS); |
1634 | first = xfs_sb_info[f].offset; | 1709 | first = xfs_sb_info[f].offset; |
1635 | 1710 | ||
1711 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); | ||
1636 | xfs_trans_log_buf(tp, bp, first, last); | 1712 | xfs_trans_log_buf(tp, bp, first, last); |
1637 | } | 1713 | } |
1638 | 1714 | ||