]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: check the CoW extent size hint
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 25 Oct 2016 22:14:35 +0000 (15:14 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 26 Oct 2016 23:41:08 +0000 (16:41 -0700)
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
repair/dinode.c

index d1da6d0ed30edac9de80f9e8df662dd459146907..8d014097bf8a966f34b35e20bec8a10c32efbbf5 100644 (file)
@@ -2529,6 +2529,38 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
                        goto clear_bad_out;
                }
 
+               if ((flags2 & XFS_DIFLAG2_COWEXTSIZE) &&
+                   !xfs_sb_version_hasreflink(&mp->m_sb)) {
+                       if (!uncertain) {
+                               do_warn(
+       _("inode %" PRIu64 " has CoW extent size hint but file system does not support reflink\n"),
+                                       lino);
+                       }
+                       flags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
+               }
+
+               if (flags2 & XFS_DIFLAG2_COWEXTSIZE) {
+                       /* must be a directory or file */
+                       if (di_mode && !S_ISDIR(di_mode) && !S_ISREG(di_mode)) {
+                               if (!uncertain) {
+                                       do_warn(
+       _("CoW extent size flag set on non-file, non-directory inode %" PRIu64 "\n" ),
+                                               lino);
+                               }
+                               flags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
+                       }
+               }
+
+               if ((flags2 & XFS_DIFLAG2_COWEXTSIZE) &&
+                   (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT))) {
+                       if (!uncertain) {
+                               do_warn(
+       _("Cannot have CoW extent size hint on a realtime inode %" PRIu64 "\n"),
+                                       lino);
+                       }
+                       flags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
+               }
+
                if (!verify_mode && flags2 != be64_to_cpu(dino->di_flags2)) {
                        if (!no_modify) {
                                do_warn(_("fixing bad flags2.\n"));
@@ -2621,6 +2653,29 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "),
                }
        }
 
+       /*
+        * Only (regular files and directories) with COWEXTSIZE flags
+        * set can have extsize set.
+        */
+       if (dino->di_version >= 3 &&
+           be32_to_cpu(dino->di_cowextsize) != 0) {
+               if ((type == XR_INO_DIR || type == XR_INO_DATA) &&
+                   (be64_to_cpu(dino->di_flags2) &
+                                       XFS_DIFLAG2_COWEXTSIZE)) {
+                       /* s'okay */ ;
+               } else {
+                       do_warn(
+_("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "),
+                                       be32_to_cpu(dino->di_cowextsize), lino);
+                       if (!no_modify)  {
+                               do_warn(_("resetting to zero\n"));
+                               dino->di_cowextsize = 0;
+                               *dirty = 1;
+                       } else
+                               do_warn(_("would reset to zero\n"));
+               }
+       }
+
        /*
         * general size/consistency checks:
         */