fsck.f2fs: fix corrupted dentries
authorJaegeuk Kim <jaegeuk@kernel.org>
Fri, 27 Mar 2015 20:32:17 +0000 (13:32 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Fri, 27 Mar 2015 23:34:48 +0000 (16:34 -0700)
This patch fixes corrupted dentries such as name_len == 0.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fsck/fsck.c

index ecb18f2..debae1c 100644 (file)
@@ -796,22 +796,24 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
        int i;
 
        /* readahead inode blocks */
-       for (i = 0; i < max;) {
-               if (test_bit(i, bitmap) == 0) {
-                       i++;
+       for (i = 0; i < max; i++) {
+               if (test_bit(i, bitmap) == 0)
                        continue;
-               }
+
                ino = le32_to_cpu(dentry[i].ino);
 
                if (IS_VALID_NID(sbi, ino)) {
                        struct node_info ni;
 
                        get_node_info(sbi, ino, &ni);
-                       if (IS_VALID_BLK_ADDR(sbi, ni.blk_addr))
+                       if (IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) {
                                dev_reada_block(ni.blk_addr);
+                               name_len = le16_to_cpu(dentry[i].name_len);
+                               if (name_len > 0)
+                                       i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN - 1;
+                               continue;
+                       }
                }
-               name_len = le16_to_cpu(dentry[i].name_len);
-               i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
        }
 
        for (i = 0; i < max;) {
@@ -820,31 +822,44 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
                        continue;
                }
                if (!IS_VALID_NID(sbi, le32_to_cpu(dentry[i].ino))) {
-                       DBG(1, "Bad dentry 0x%x with invalid NID/ino 0x%x",
-                           i, le32_to_cpu(dentry[i].ino));
+                       ASSERT_MSG("Bad dentry 0x%x with invalid NID/ino 0x%x",
+                                   i, le32_to_cpu(dentry[i].ino));
                        if (config.fix_on) {
                                FIX_MSG("Clear bad dentry 0x%x with bad ino 0x%x",
                                        i, le32_to_cpu(dentry[i].ino));
                                clear_bit(i, bitmap);
-                               i++;
                                fixed = 1;
-                               continue;
                        }
+                       i++;
+                       continue;
                }
+
                ftype = dentry[i].file_type;
-               if ((ftype <= F2FS_FT_UNKNOWN || ftype > F2FS_FT_LAST_FILE_TYPE) && config.fix_on) {
-                       DBG(1, "Bad dentry 0x%x with unexpected ftype 0x%x",
-                           i, ftype);
+               if ((ftype <= F2FS_FT_UNKNOWN || ftype > F2FS_FT_LAST_FILE_TYPE)) {
+                       ASSERT_MSG("Bad dentry 0x%x with unexpected ftype 0x%x", i, ftype);
                        if (config.fix_on) {
                                FIX_MSG("Clear bad dentry 0x%x with bad ftype 0x%x",
                                        i, ftype);
                                clear_bit(i, bitmap);
-                               i++;
                                fixed = 1;
-                               continue;
                        }
+                       i++;
+                       continue;
                }
+
                name_len = le16_to_cpu(dentry[i].name_len);
+
+               if (name_len == 0) {
+                       ASSERT_MSG("Bad dentry 0x%x with zero name_len", i);
+                       if (config.fix_on) {
+                               FIX_MSG("Clear bad dentry 0x%x", i);
+                               clear_bit(i, bitmap);
+                               fixed = 1;
+                       }
+                       i++;
+                       continue;
+               }
+
                name = calloc(name_len + 1, 1);
                memcpy(name, filenames[i], name_len);
                hash_code = f2fs_dentry_hash((const unsigned char *)name,