]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_repair: reject unwritten shared extents
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:22:34 +0000 (14:22 -0700)
committerChristoph Hellwig <hch@lst.de>
Mon, 12 Aug 2024 11:53:51 +0000 (13:53 +0200)
We don't allow sharing of unwritten extents, which means that repair
should reject an unwritten extent if someone else has already claimed
the space.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
repair/dinode.c

index 3e41b2566ec0f3dcfdb209e8326c4cbd4e516670..1fa5482cbdd2ed21d4a7df8297a934c58ea734a7 100644 (file)
@@ -291,7 +291,8 @@ _("bad state in rt extent map %" PRIu64 "\n"),
                        break;
                case XR_E_INUSE:
                case XR_E_MULT:
-                       if (xfs_has_rtreflink(mp))
+                       if (xfs_has_rtreflink(mp) &&
+                           irec->br_state == XFS_EXT_NORM)
                                break;
                        set_rtbmap(ext, XR_E_MULT);
                        break;
@@ -367,8 +368,14 @@ _("data fork in rt inode %" PRIu64 " found rt metadata extent %" PRIu64 " in rt
                        return 1;
                case XR_E_INUSE:
                case XR_E_MULT:
-                       if (xfs_has_rtreflink(mp))
-                               break;
+                       if (xfs_has_rtreflink(mp)) {
+                               if (irec->br_state == XFS_EXT_NORM)
+                                       break;
+                               do_warn(
+_("data fork in rt inode %" PRIu64 " claims shared unwritten rt extent %" PRIu64 "\n"),
+                                       ino, b);
+                               return 1;
+                       }
                        do_warn(
 _("data fork in rt inode %" PRIu64 " claims used rt extent %" PRIu64 "\n"),
                                ino, b);
@@ -453,6 +460,18 @@ _("inode %" PRIu64 " - bad rt extent overflows - start %" PRIu64 ", "
        return 0;
 }
 
+static inline bool
+is_reflink_type(
+       struct xfs_mount        *mp,
+       int                     type)
+{
+       if (type == XR_INO_DATA && xfs_has_reflink(mp))
+               return true;
+       if (type == XR_INO_RTDATA && xfs_has_rtreflink(mp))
+               return true;
+       return false;
+}
+
 /*
  * return 1 if inode should be cleared, 0 otherwise
  * if check_dups should be set to 1, that implies that
@@ -707,9 +726,14 @@ _("%s fork in inode %" PRIu64 " claims metadata block %" PRIu64 "\n"),
 
                        case XR_E_INUSE:
                        case XR_E_MULT:
-                               if (type == XR_INO_DATA &&
-                                   xfs_has_reflink(mp))
-                                       break;
+                               if (is_reflink_type(mp, type)) {
+                                       if (irec.br_state == XFS_EXT_NORM)
+                                               break;
+                                       do_warn(
+_("%s fork in %s inode %" PRIu64 " claims shared unwritten block %" PRIu64 "\n"),
+                                               forkname, ftype, ino, b);
+                                       goto done;
+                               }
                                do_warn(
 _("%s fork in %s inode %" PRIu64 " claims used block %" PRIu64 "\n"),
                                        forkname, ftype, ino, b);