This patch adds a check to function basic_dentry_checks for a
special case where a GFS1 dirent points to a non-inode. Since
GFS1 marked all its metadata as "metadata" (not just dinodes as
GFS2 does), we need to verify that GFS1 dirents actually point
to GFS1 dinodes. If they point to a different kind of metadata
block, we need to treat it as an error.
rhbz#1257625
---
gfs2/fsck/pass2.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 900d4e1..11777eb 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -611,6 +611,27 @@ static int basic_dentry_checks(struct gfs2_inode *ip,
struct gfs2_dirent *dent,
(unsigned long long)ii->di_num.no_formal_ino);
return 1;
}
+ /* Check for a special case where a (bad) GFS1 dirent points to what
+ * is not a known inode. It could be other GFS1 metadata, such as an
+ * eattr or indirect block, but marked "dinode" in the bitmap because
+ * gfs1 marked all gfs1 metadata that way. */
+ if (ii == NULL && sdp->gfs1) {
+ struct gfs2_buffer_head *tbh;
+
+ tbh = bread(sdp, entry->no_addr);
+ if (gfs2_check_meta(tbh, GFS2_METATYPE_DI)) { /* not dinode */
+ log_err( _("Directory entry '%s' pointing to block "
+ "%llu (0x%llx) in directory %llu (0x%llx) "
+ "is not really a GFS1 dinode.\n"), tmp_name,
+ (unsigned long long)entry->no_addr,
+ (unsigned long long)entry->no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
+ brelse(tbh);
+ return 1;
+ }
+ brelse(tbh);
+ }
return 0;
}
--
2.4.3