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

Reply via email to