@@ -662,16 +662,46 @@ xchk_bmap_want_check_rmaps(
* The inode repair code zaps broken inode forks by resetting them back
* to EXTENTS format and zero extent records. If we encounter a fork
* in this state along with evidence that the fork isn't supposed to be
- * empty, we need to scan the reverse mappings to decide if we're going
- * to rebuild the fork. Data forks with nonzero file size are scanned.
- * xattr forks are never empty of content, so they are always scanned.
+ * empty, we might want scan the reverse mappings to decide if we're
+ * going to rebuild the fork.
*/
ifp = xfs_ifork_ptr(sc->ip, info->whichfork);
if (ifp->if_format == XFS_DINODE_FMT_EXTENTS && ifp->if_nextents == 0) {
- if (info->whichfork == XFS_DATA_FORK &&
- i_size_read(VFS_I(sc->ip)) == 0)
- return false;
-
+ switch (info->whichfork) {
+ case XFS_DATA_FORK:
+ /*
+ * Data forks with zero file size are presumed not to
+ * have any written data blocks. Skip the scan.
+ */
+ if (i_size_read(VFS_I(sc->ip)) == 0)
+ return false;
+ break;
+ case XFS_ATTR_FORK:
+ /*
+ * Files can have an attr fork in EXTENTS format with
+ * zero records for several reasons:
+ *
+ * a) an attr set created a fork but ran out of space
+ * b) attr replace deleted an old attr but failed
+ * during the set step
+ * c) the data fork was in btree format when all attrs
+ * were deleted, so the fork was left in place
+ * d) the inode repair code zapped the fork
+ *
+ * Only in case (d) do we want to scan the rmapbt to
+ * see if we need to rebuild the attr fork. The fork
+ * zap code clears all DAC permission bits and zeroes
+ * the uid and gid, so avoid the scan if any of those
+ * three conditions are not met.
+ */
+ if ((VFS_I(sc->ip)->i_mode & 0777) != 0)
+ return false;
+ if (!uid_eq(VFS_I(sc->ip)->i_uid, GLOBAL_ROOT_UID))
+ return false;
+ if (!gid_eq(VFS_I(sc->ip)->i_gid, GLOBAL_ROOT_GID))
+ return false;
+ break;
+ }
return true;
}