fsck.f2fs: add hash conversion for encrypted dentries
authorJaegeuk Kim <jaegeuk@kernel.org>
Tue, 28 Apr 2015 21:27:18 +0000 (14:27 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Thu, 7 May 2015 22:50:49 +0000 (15:50 -0700)
If dentry is encrypted, we should convert its hash value.

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

index f3fbdfa..b15edbe 100644 (file)
@@ -583,7 +583,8 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
                        ret = fsck_chk_data_blk(sbi,
                                        le32_to_cpu(node_blk->i.i_addr[idx]),
                                        &child, (i_blocks == *blk_cnt),
-                                       ftype, nid, idx, ni->version);
+                                       ftype, nid, idx, ni->version,
+                                       file_is_encrypt(node_blk->i.i_advise));
                        if (!ret) {
                                *blk_cnt = *blk_cnt + 1;
                        } else if (config.fix_on) {
@@ -695,7 +696,8 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
                ret = fsck_chk_data_blk(sbi,
                        le32_to_cpu(node_blk->dn.addr[idx]),
                        child, le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype,
-                       nid, idx, ni->version);
+                       nid, idx, ni->version,
+                       file_is_encrypt(inode->i_advise));
                if (!ret) {
                        *blk_cnt = *blk_cnt + 1;
                } else if (config.fix_on) {
@@ -753,16 +755,37 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
        return 0;
 }
 
+static void convert_encrypted_name(unsigned char *name, int len,
+                               unsigned char *new, int encrypted)
+{
+       if (!encrypted) {
+               memcpy(new, name, len);
+               new[len] = 0;
+               return;
+       }
+
+       while (len--) {
+               *new = *name++;
+               if (*new > 128)
+                       *new -= 128;
+               if (*new < 32 || *new == 0x7f)
+                       *new ^= 0x40;   /* ^@, ^A, ^B; ^? for DEL */
+               new++;
+       }
+       *new = 0;
+}
+
 static void print_dentry(__u32 depth, __u8 *name,
                unsigned long *bitmap,
                struct f2fs_dir_entry *dentry,
-               int max, int idx, int last_blk)
+               int max, int idx, int last_blk, int encrypted)
 {
        int last_de = 0;
        int next_idx = 0;
        int name_len;
        unsigned int i;
        int bit_offset;
+       unsigned char new[F2FS_NAME_LEN + 1];
 
        if (config.dbg_lv != -1)
                return;
@@ -787,25 +810,49 @@ static void print_dentry(__u32 depth, __u8 *name,
        if (tree_mark[depth - 1] == '`')
                tree_mark[depth - 1] = ' ';
 
-
        for (i = 1; i < depth; i++)
                printf("%c   ", tree_mark[i]);
-       printf("%c-- %s 0x%x\n", last_de ? '`' : '|',
-                               name, le32_to_cpu(dentry[idx].ino));
+
+       convert_encrypted_name(name, name_len, new, encrypted);
+
+       printf("%c-- %s <ino = 0x%x>, <encrypted (%d)>\n",
+                       last_de ? '`' : '|',
+                       new, le32_to_cpu(dentry[idx].ino),
+                       encrypted);
+}
+
+static int f2fs_check_hash_code(struct f2fs_dir_entry *dentry,
+                       const unsigned char *name, u32 len, int encrypted)
+{
+       f2fs_hash_t hash_code = f2fs_dentry_hash(name, len);
+
+       /* fix hash_code made by old buggy code */
+       if (dentry->hash_code != hash_code) {
+               unsigned char new[F2FS_NAME_LEN + 1];
+
+               convert_encrypted_name((unsigned char *)name, len,
+                                                       new, encrypted);
+               FIX_MSG("Mismatch hash_code for \"%s\" [%x:%x]",
+                               new, le32_to_cpu(dentry->hash_code),
+                               hash_code);
+               dentry->hash_code = cpu_to_le32(hash_code);
+               return 1;
+       }
+       return 0;
 }
 
 static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child,
                        unsigned long *bitmap,
                        struct f2fs_dir_entry *dentry,
                        __u8 (*filenames)[F2FS_SLOT_LEN],
-                       int max, int last_blk)
+                       int max, int last_blk, int encrypted)
 {
        struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
        enum FILE_TYPE ftype;
        int dentries = 0;
        u32 blk_cnt;
        u8 *name;
-       u32 hash_code, ino;
+       u32 ino;
        u16 name_len;;
        int ret = 0;
        int fixed = 0;
@@ -875,20 +922,10 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child,
                        i++;
                        continue;
                }
-
                name = calloc(name_len + 1, 1);
                memcpy(name, filenames[i], name_len);
-               hash_code = f2fs_dentry_hash((const unsigned char *)name,
-                                                               name_len);
                slots = (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
 
-               /* fix hash_code made by old buggy code */
-               if (le32_to_cpu(dentry[i].hash_code) != hash_code) {
-                       dentry[i].hash_code = hash_code;
-                       fixed = 1;
-                       FIX_MSG("hash_code[%d] of %s", i, name);
-               }
-
                /* Becareful. 'dentry.file_type' is not imode. */
                if (ftype == F2FS_FT_DIR) {
                        if ((name[0] == '.' && name_len == 1) ||
@@ -901,13 +938,16 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child,
                        }
                }
 
+               if (f2fs_check_hash_code(dentry + i, name, name_len, encrypted))
+                       fixed = 1;
+
                DBG(1, "[%3u]-[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n",
                                fsck->dentry_depth, i, name, name_len,
                                le32_to_cpu(dentry[i].ino),
                                dentry[i].file_type);
 
                print_dentry(fsck->dentry_depth, name, bitmap,
-                                               dentry, max, i, last_blk);
+                               dentry, max, i, last_blk, encrypted);
 
                blk_cnt = 1;
                ret = fsck_chk_node_blk(sbi,
@@ -951,7 +991,8 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
        dentries = __chk_dentries(sbi, child,
                        (unsigned long *)de_blk->dentry_bitmap,
                        de_blk->dentry, de_blk->filename,
-                       NR_INLINE_DENTRY, 1);
+                       NR_INLINE_DENTRY, 1,
+                       file_is_encrypt(node_blk->i.i_advise));
        if (dentries < 0) {
                DBG(1, "[%3d] Inline Dentry Block Fixed hash_codes\n\n",
                        fsck->dentry_depth);
@@ -966,7 +1007,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
 }
 
 int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
-               struct child_info *child, int last_blk)
+               struct child_info *child, int last_blk, int encrypted)
 {
        struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
        struct f2fs_dentry_block *de_blk;
@@ -982,7 +1023,7 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
        dentries = __chk_dentries(sbi, child,
                        (unsigned long *)de_blk->dentry_bitmap,
                        de_blk->dentry, de_blk->filename,
-                       NR_DENTRY_IN_BLOCK, last_blk);
+                       NR_DENTRY_IN_BLOCK, last_blk, encrypted);
 
        if (dentries < 0) {
                ret = dev_write_block(de_blk, blk_addr);
@@ -1002,7 +1043,8 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
 
 int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
                struct child_info *child, int last_blk,
-               enum FILE_TYPE ftype, u32 parent_nid, u16 idx_in_node, u8 ver)
+               enum FILE_TYPE ftype, u32 parent_nid, u16 idx_in_node, u8 ver,
+               int encrypted)
 {
        struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
 
@@ -1035,7 +1077,8 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
 
        if (ftype == F2FS_FT_DIR) {
                f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_HOT_DATA);
-               return fsck_chk_dentry_blk(sbi, blk_addr, child, last_blk);
+               return fsck_chk_dentry_blk(sbi, blk_addr, child,
+                                               last_blk, encrypted);
        } else {
                f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_WARM_DATA);
        }
index 5eac45c..37a25ba 100644 (file)
@@ -87,7 +87,8 @@ enum seg_type {
 
 extern void fsck_chk_orphan_node(struct f2fs_sb_info *);
 extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32,
-               u8 *, enum FILE_TYPE, enum NODE_TYPE, u32 *, struct child_info *);
+               u8 *, enum FILE_TYPE, enum NODE_TYPE, u32 *,
+               struct child_info *);
 extern void fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE,
                struct f2fs_node *, u32 *, struct node_info *);
 extern int fsck_chk_dnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
@@ -98,9 +99,9 @@ extern int fsck_chk_idnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
 extern int fsck_chk_didnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
                enum FILE_TYPE, struct f2fs_node *, u32 *, struct child_info *);
 extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32, struct child_info *,
-               int, enum FILE_TYPE, u32, u16, u8);
+               int, enum FILE_TYPE, u32, u16, u8, int);
 extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, u32, struct child_info *,
-               int);
+               int, int);
 int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *,
                struct child_info *);
 
index 6aefa5d..59cc0d1 100644 (file)
@@ -453,6 +453,15 @@ struct f2fs_extent {
 
 #define DEF_DIR_LEVEL          0
 
+/*
+ * i_advise uses FADVISE_XXX_BIT. We can add additional hints later.
+ */
+#define FADVISE_COLD_BIT       0x01
+#define FADVISE_LOST_PINO_BIT  0x02
+#define FADVISE_ENCRYPT_BIT    0x04
+
+#define file_is_encrypt(i_advise)      ((i_advise) & FADVISE_ENCRYPT_BIT)
+
 struct f2fs_inode {
        __le16 i_mode;                  /* file mode */
        __u8 i_advise;                  /* file hints */