If reflink is enabled, don't freak out if there are multiple owners of a given block; that's just a sign that each of those owners are reflink files. Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --- repair/dinode.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/scan.c | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 7766dea..2ff1476 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -722,6 +722,9 @@ _("Fatal error: inode %" PRIu64 " - blkmap_set_ext(): %s\n" * checking each entry without setting the * block bitmap */ + if (type == XR_INO_DATA && + xfs_sb_version_hasreflink(&mp->m_sb)) + goto skip_dup; if (search_dup_extent(agno, agbno, ebno)) { do_warn( _("%s fork in ino %" PRIu64 " claims dup extent, " @@ -731,6 +734,7 @@ _("%s fork in ino %" PRIu64 " claims dup extent, " irec.br_blockcount); goto done; } +skip_dup: *tot += irec.br_blockcount; continue; } @@ -770,6 +774,9 @@ _("%s fork in inode %" PRIu64 " claims metadata block %" PRIu64 "\n"), case XR_E_INUSE: case XR_E_MULT: set_bmap_ext(agno, agbno, blen, XR_E_MULT); + if (type == XR_INO_DATA && + xfs_sb_version_hasreflink(&mp->m_sb)) + break; do_warn( _("%s fork in %s inode %" PRIu64 " claims used block %" PRIu64 "\n"), forkname, ftype, ino, b); @@ -2460,6 +2467,52 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), } } + /* + * check that we only have valid flags2 set, and those that are set make + * sense. + */ + if (dino->di_version >= 3) { + uint16_t flags = be16_to_cpu(dino->di_flags); + uint64_t flags2 = be64_to_cpu(dino->di_flags2); + + if (flags2 & ~XFS_DIFLAG2_ANY) { + if (!uncertain) { + do_warn( + _("Bad flags2 set in inode %" PRIu64 "\n"), + lino); + } + flags2 &= XFS_DIFLAG2_ANY; + } + + if ((flags2 & XFS_DIFLAG2_REFLINK) && + (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT))) { + if (!uncertain) { + do_warn( + _("Cannot have a reflinked realtime inode %" PRIu64 "\n"), + lino); + } + goto clear_bad_out; + } + + if ((flags2 & XFS_DIFLAG2_REFLINK) && + !xfs_sb_version_hasreflink(&mp->m_sb)) { + if (!uncertain) { + do_warn( + _("inode %" PRIu64 " is marked reflinked but file system does not support reflink\n"), + lino); + } + goto clear_bad_out; + } + if (!verify_mode && flags2 != be64_to_cpu(dino->di_flags2)) { + if (!no_modify) { + do_warn(_("fixing bad flags2.\n")); + dino->di_flags2 = cpu_to_be64(flags2); + *dirty = 1; + } else + do_warn(_("would fix bad flags2.\n")); + } + } + if (verify_mode) return retval; diff --git a/repair/scan.c b/repair/scan.c index 4be02a6..54b9b68 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -783,7 +783,29 @@ ino_issparse( return xfs_inobt_is_sparse_disk(rp, offset); } - + +static bool +rmap_in_order( + xfs_agblock_t b, + xfs_agblock_t lastblock, + int64_t owner, + int64_t lastowner, + int64_t offset, + int64_t lastoffset) +{ + if (b > lastblock) + return true; + else if (b < lastblock) + return false; + + if (owner > lastowner) + return true; + else if (owner < lastowner) + return false; + + return offset > lastoffset; +} + static void scan_rmapbt( struct xfs_btree_block *block, @@ -910,7 +932,12 @@ advance: } else { bool bad; - bad = b <= lastblock; + if (xfs_sb_version_hasreflink(&mp->m_sb)) + bad = !rmap_in_order(b, lastblock, + owner, lastowner, + offset, lastoffset); + else + bad = b <= lastblock; if (bad) do_warn( _("out-of-order rmap btree record %d (%u %"PRId64" %"PRIx64" %u) block %u/%u\n"), @@ -997,6 +1024,15 @@ _("in use block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), * be caught later. */ break; + case XR_E_INUSE1: + /* + * multiple inode owners are ok with + * reflink enabled + */ + if (xfs_sb_version_hasreflink(&mp->m_sb) && + !XFS_RMAP_NON_INODE_OWNER(owner)) + break; + /* fall through */ default: do_warn( _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"), _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs