aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2014-10-14 15:15:40 -0700
committerJP Abgrall <jpa@google.com>2014-11-07 15:32:19 -0800
commit3a8c9a69525f75a6c59bee0eb3d882ddc341b3f1 (patch)
treef5a70fd354832897bff441b0dbde054e7baf9c57
parent4c992fe23ae6739767f584a96157d0585282d8e2 (diff)
downloadandroid_external_f2fs-tools-3a8c9a69525f75a6c59bee0eb3d882ddc341b3f1.tar.gz
android_external_f2fs-tools-3a8c9a69525f75a6c59bee0eb3d882ddc341b3f1.tar.bz2
android_external_f2fs-tools-3a8c9a69525f75a6c59bee0eb3d882ddc341b3f1.zip
fsck.f2fs: support inline_dentry
This patch implements inline_dentry feature. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fsck/f2fs.h5
-rw-r--r--fsck/fsck.c123
-rw-r--r--fsck/fsck.h2
-rw-r--r--include/f2fs_fs.h20
4 files changed, 109 insertions, 41 deletions
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index cdd61b8..47f785d 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -191,6 +191,11 @@ static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
return (struct sit_info *)(SM_I(sbi)->sit_info);
}
+static inline void *inline_data_addr(struct f2fs_node *node_blk)
+{
+ return (void *)&(node_blk->i.i_addr[1]);
+}
+
static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
{
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
diff --git a/fsck/fsck.c b/fsck/fsck.c
index d0819c4..8e3ecc8 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -397,6 +397,12 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
DBG(3, "ino[0x%x] has inline data!\n", nid);
goto check;
}
+ if((node_blk->i.i_inline & F2FS_INLINE_DENTRY)){
+ DBG(3, "ino[0x%x] has inline dentry!\n", nid);
+ ret = fsck_chk_inline_dentries(sbi, node_blk,
+ &child_cnt, &child_files);
+ goto check;
+ }
/* check data blocks in inode */
for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i); idx++) {
@@ -546,7 +552,9 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
}
static void print_dentry(__u32 depth, __u8 *name,
- struct f2fs_dentry_block *de_blk, int idx, int last_blk)
+ unsigned long *bitmap,
+ struct f2fs_dir_entry *dentry,
+ int max, int idx, int last_blk)
{
int last_de = 0;
int next_idx = 0;
@@ -557,12 +565,11 @@ static void print_dentry(__u32 depth, __u8 *name,
if (config.dbg_lv != -1)
return;
- name_len = le16_to_cpu(de_blk->dentry[idx].name_len);
+ name_len = le16_to_cpu(dentry[idx].name_len);
next_idx = idx + (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
- bit_offset = find_next_bit((unsigned long *)de_blk->dentry_bitmap,
- NR_DENTRY_IN_BLOCK, next_idx);
- if (bit_offset >= NR_DENTRY_IN_BLOCK && last_blk)
+ bit_offset = find_next_bit(bitmap, max, next_idx);
+ if (bit_offset >= max && last_blk)
last_de = 1;
if (tree_mark_size <= depth) {
@@ -582,47 +589,41 @@ static void print_dentry(__u32 depth, __u8 *name,
for (i = 1; i < depth; i++)
printf("%c ", tree_mark[i]);
printf("%c-- %s 0x%x\n", last_de ? '`' : '|',
- name, le32_to_cpu(de_blk->dentry[idx].ino));
+ name, le32_to_cpu(dentry[idx].ino));
}
-int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
- u32 *child_cnt, u32 *child_files, int last_blk)
+static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
+ u32* child_files,
+ unsigned long *bitmap,
+ struct f2fs_dir_entry *dentry,
+ __u8 (*filenames)[F2FS_SLOT_LEN],
+ int max, int last_blk)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
- int i;
- int ret = 0;
+ enum FILE_TYPE ftype;
int dentries = 0;
+ u32 blk_cnt;
u8 *name;
u32 hash_code;
- u32 blk_cnt;
u16 name_len;;
+ int ret = 0;
+ int i;
- enum FILE_TYPE ftype;
- struct f2fs_dentry_block *de_blk;
-
- de_blk = (struct f2fs_dentry_block *)calloc(BLOCK_SZ, 1);
- ASSERT(de_blk != NULL);
-
- ret = dev_read_block(de_blk, blk_addr);
- ASSERT(ret >= 0);
-
- fsck->dentry_depth++;
-
- for (i = 0; i < NR_DENTRY_IN_BLOCK;) {
- if (test_bit(i, (unsigned long *)de_blk->dentry_bitmap) == 0) {
+ for (i = 0; i < max;) {
+ if (test_bit(i, bitmap) == 0) {
i++;
continue;
}
- name_len = le16_to_cpu(de_blk->dentry[i].name_len);
+ name_len = le16_to_cpu(dentry[i].name_len);
name = calloc(name_len + 1, 1);
- memcpy(name, de_blk->filename[i], name_len);
+ memcpy(name, filenames[i], name_len);
hash_code = f2fs_dentry_hash((const unsigned char *)name,
name_len);
- ASSERT(le32_to_cpu(de_blk->dentry[i].hash_code) == hash_code);
+ ASSERT(le32_to_cpu(dentry[i].hash_code) == hash_code);
- ftype = de_blk->dentry[i].file_type;
+ ftype = dentry[i].file_type;
/* Becareful. 'dentry.file_type' is not imode. */
if (ftype == F2FS_FT_DIR) {
@@ -638,30 +639,27 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
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(de_blk->dentry[i].ino),
- de_blk->dentry[i].file_type);
+ le32_to_cpu(dentry[i].ino),
+ dentry[i].file_type);
- print_dentry(fsck->dentry_depth, name, de_blk, i, last_blk);
+ print_dentry(fsck->dentry_depth, name, bitmap,
+ dentry, max, i, 1);
blk_cnt = 1;
ret = fsck_chk_node_blk(sbi,
- NULL,
- le32_to_cpu(de_blk->dentry[i].ino),
- ftype,
- TYPE_INODE,
- &blk_cnt);
+ NULL, le32_to_cpu(dentry[i].ino),
+ ftype, TYPE_INODE, &blk_cnt);
if (ret && config.fix_on) {
int j;
int slots = (name_len + F2FS_SLOT_LEN - 1) /
F2FS_SLOT_LEN;
for (j = 0; j < slots; j++)
- clear_bit(i + j,
- (unsigned long *)de_blk->dentry_bitmap);
+ clear_bit(i + j, bitmap);
FIX_MSG("Unlink [0x%x] - %s len[0x%x], type[0x%x]",
- le32_to_cpu(de_blk->dentry[i].ino),
+ le32_to_cpu(dentry[i].ino),
name, name_len,
- de_blk->dentry[i].file_type);
+ dentry[i].file_type);
i += slots;
free(name);
continue;
@@ -672,13 +670,56 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
*child_files = *child_files + 1;
free(name);
}
+ return dentries;
+}
+
+int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
+ struct f2fs_node *node_blk, u32 *child_cnt, u32 *child_files)
+{
+ struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+ struct f2fs_inline_dentry *de_blk;
+ int dentries;
+
+ de_blk = inline_data_addr(node_blk);
+ ASSERT(de_blk != NULL);
+
+ fsck->dentry_depth++;
+ dentries = __chk_dentries(sbi, child_cnt, child_files,
+ (unsigned long *)de_blk->dentry_bitmap,
+ de_blk->dentry, de_blk->filename,
+ NR_INLINE_DENTRY, 1);
+ DBG(1, "[%3d] Inline Dentry Block Done : "
+ "dentries:%d in %d slots (len:%d)\n\n",
+ fsck->dentry_depth, dentries,
+ (int)NR_INLINE_DENTRY, F2FS_NAME_LEN);
+ fsck->dentry_depth--;
+ return 0;
+}
+
+int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
+ u32 *child_cnt, u32 *child_files, int last_blk)
+{
+ struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+ struct f2fs_dentry_block *de_blk;
+ int dentries, ret;
+
+ de_blk = (struct f2fs_dentry_block *)calloc(BLOCK_SZ, 1);
+ ASSERT(de_blk != NULL);
+
+ ret = dev_read_block(de_blk, blk_addr);
+ ASSERT(ret >= 0);
+
+ fsck->dentry_depth++;
+ dentries = __chk_dentries(sbi, child_cnt, child_files,
+ (unsigned long *)de_blk->dentry_bitmap,
+ de_blk->dentry, de_blk->filename,
+ NR_DENTRY_IN_BLOCK, last_blk);
DBG(1, "[%3d] Dentry Block [0x%x] Done : "
"dentries:%d in %d slots (len:%d)\n\n",
fsck->dentry_depth, blk_addr, dentries,
NR_DENTRY_IN_BLOCK, F2FS_NAME_LEN);
fsck->dentry_depth--;
-
free(de_blk);
return 0;
}
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 64b9984..49d6d1d 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -93,6 +93,8 @@ extern int fsck_chk_didnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32, u32 *, u32 *,
int, enum FILE_TYPE, u32, u16, u8);
extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, u32, u32 *, u32 *, int);
+int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *,
+ u32 *, u32 *);
extern void print_node_info(struct f2fs_node *);
extern void print_inode_info(struct f2fs_inode *);
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index df37cdf..ed4abb1 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -425,6 +425,8 @@ struct f2fs_extent {
#define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */
#define F2FS_INLINE_DATA 0x02 /* file inline data flag */
+#define F2FS_INLINE_DENTRY 0x04 /* file inline dentry flag */
+
#define MAX_INLINE_DATA (sizeof(__le32) * (DEF_ADDRS_PER_INODE - \
F2FS_INLINE_XATTR_ADDRS - 1))
@@ -697,6 +699,24 @@ struct f2fs_dentry_block {
__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
} __attribute__((packed));
+/* for inline dir */
+#define NR_INLINE_DENTRY (MAX_INLINE_DATA * BITS_PER_BYTE / \
+ ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+ BITS_PER_BYTE + 1))
+#define INLINE_DENTRY_BITMAP_SIZE ((NR_INLINE_DENTRY + \
+ BITS_PER_BYTE - 1) / BITS_PER_BYTE)
+#define INLINE_RESERVED_SIZE (MAX_INLINE_DATA - \
+ ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+ NR_INLINE_DENTRY + INLINE_DENTRY_BITMAP_SIZE))
+
+/* inline directory entry structure */
+struct f2fs_inline_dentry {
+ __u8 dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE];
+ __u8 reserved[INLINE_RESERVED_SIZE];
+ struct f2fs_dir_entry dentry[NR_INLINE_DENTRY];
+ __u8 filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN];
+} __packed;
+
/* file types used in inode_info->flags */
enum FILE_TYPE {
F2FS_FT_UNKNOWN,