* [PATCH 1/8] fsck.f2fs: return summary block pointer and types
@ 2015-04-02 17:50 Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 2/8] fsck.f2fs: fix summary block Jaegeuk Kim
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Jaegeuk Kim @ 2015-04-02 17:50 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: Jaegeuk Kim
This patch adds to return summry_block pointer to callers, which will be used
when fixing them.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fsck/dump.c | 16 +++++++++++-----
fsck/f2fs.h | 1 +
fsck/fsck.h | 4 ++--
fsck/mount.c | 45 ++++++++++++++++++++++++++-------------------
4 files changed, 40 insertions(+), 26 deletions(-)
diff --git a/fsck/dump.c b/fsck/dump.c
index 3c4a8d1..8698b28 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -15,11 +15,12 @@
#define BUF_SZ 80
-const char *seg_type_name[SEG_TYPE_MAX] = {
+const char *seg_type_name[SEG_TYPE_MAX + 1] = {
"SEG_TYPE_DATA",
"SEG_TYPE_CUR_DATA",
"SEG_TYPE_NODE",
"SEG_TYPE_CUR_NODE",
+ "SEG_TYPE_NONE",
};
void sit_dump(struct f2fs_sb_info *sbi, int start_sit, int end_sit)
@@ -65,7 +66,7 @@ void sit_dump(struct f2fs_sb_info *sbi, int start_sit, int end_sit)
void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa)
{
- struct f2fs_summary_block sum_blk;
+ struct f2fs_summary_block *sum_blk;
char buf[BUF_SZ];
int segno, i, ret;
int fd;
@@ -80,7 +81,7 @@ void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa)
ASSERT(ret >= 0);
for (segno = start_ssa; segno < end_ssa; segno++) {
- ret = get_sum_block(sbi, segno, &sum_blk);
+ sum_blk = get_sum_block(sbi, segno, &ret);
memset(buf, 0, BUF_SZ);
switch (ret) {
@@ -108,10 +109,13 @@ void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa)
ASSERT(ret >= 0);
}
snprintf(buf, BUF_SZ, "[%3d: %6x]", i,
- le32_to_cpu(sum_blk.entries[i].nid));
+ le32_to_cpu(sum_blk->entries[i].nid));
ret = write(fd, buf, strlen(buf));
ASSERT(ret >= 0);
}
+ if (ret == SEG_TYPE_NODE || ret == SEG_TYPE_DATA ||
+ ret == SEG_TYPE_MAX)
+ free(sum_blk);
}
close(fd);
}
@@ -418,7 +422,9 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
DBG(1, " - Segno [0x%x]\n", GET_SEGNO(sbi, blk_addr));
DBG(1, " - Offset [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr));
DBG(1, "SUM.nid [0x%x]\n", nid);
- DBG(1, "SUM.type [%s]\n", seg_type_name[type]);
+ DBG(1, "SUM.type [%s]\n", type >= 0 ?
+ seg_type_name[type] :
+ "Broken");
DBG(1, "SUM.version [%d]\n", sum_entry.version);
DBG(1, "SUM.ofs_in_node [0x%x]\n", sum_entry.ofs_in_node);
DBG(1, "NAT.blkaddr [0x%x]\n", ni.blk_addr);
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index e59bb0b..100854e 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -382,5 +382,6 @@ static inline void node_info_from_raw_nat(struct node_info *ni,
extern int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_entry *ne);
#define IS_SUM_NODE_SEG(footer) (footer.entry_type == SUM_TYPE_NODE)
+#define IS_SUM_DATA_SEG(footer) (footer.entry_type == SUM_TYPE_DATA)
#endif /* _F2FS_H_ */
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 1c2ef94..ffb3ae2 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -101,8 +101,8 @@ void print_cp_state(u32);
extern void print_node_info(struct f2fs_node *);
extern void print_inode_info(struct f2fs_inode *, int);
extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
-extern int get_sum_block(struct f2fs_sb_info *, unsigned int,
- struct f2fs_summary_block *);
+extern struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *,
+ unsigned int, int *);
extern int get_sum_entry(struct f2fs_sb_info *, u32, struct f2fs_summary *);
extern void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
extern void nullify_nat_entry(struct f2fs_sb_info *, u32);
diff --git a/fsck/mount.c b/fsck/mount.c
index dfaa596..f900dd7 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -845,14 +845,17 @@ struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
return &sit_i->sentries[segno];
}
-int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno,
- struct f2fs_summary_block *sum_blk)
+struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *sbi,
+ unsigned int segno, int *ret_type)
{
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+ struct f2fs_summary_block *sum_blk;
struct curseg_info *curseg;
int type, ret;
u64 ssa_blk;
+ *ret_type= SEG_TYPE_MAX;
+
ssa_blk = GET_SUM_BLKADDR(sbi, segno);
for (type = 0; type < NR_CURSEG_NODE_TYPE; type++) {
if (segno == ckpt->cur_node_segno[type]) {
@@ -861,10 +864,11 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno,
ASSERT_MSG("segno [0x%x] indicates a data "
"segment, but should be node",
segno);
- return -EINVAL;
+ *ret_type = -SEG_TYPE_CUR_NODE;
+ } else {
+ *ret_type = SEG_TYPE_CUR_NODE;
}
- memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ);
- return SEG_TYPE_CUR_NODE;
+ return curseg->sum_blk;
}
}
@@ -875,23 +879,26 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno,
ASSERT_MSG("segno [0x%x] indicates a node "
"segment, but should be data",
segno);
- return -EINVAL;
+ *ret_type = -SEG_TYPE_CUR_DATA;
+ } else {
+ *ret_type = SEG_TYPE_CUR_DATA;
}
- DBG(2, "segno [0x%x] is current data seg[0x%x]\n",
- segno, type);
- memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ);
- return SEG_TYPE_CUR_DATA;
+ return curseg->sum_blk;
}
}
+ sum_blk = calloc(BLOCK_SZ, 1);
+ ASSERT(sum_blk);
+
ret = dev_read_block(sum_blk, ssa_blk);
ASSERT(ret >= 0);
if (IS_SUM_NODE_SEG(sum_blk->footer))
- return SEG_TYPE_NODE;
- else
- return SEG_TYPE_DATA;
+ *ret_type = SEG_TYPE_NODE;
+ else if (IS_SUM_DATA_SEG(sum_blk->footer))
+ *ret_type = SEG_TYPE_DATA;
+ return sum_blk;
}
int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr,
@@ -899,18 +906,18 @@ int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr,
{
struct f2fs_summary_block *sum_blk;
u32 segno, offset;
- int ret;
+ int type;
segno = GET_SEGNO(sbi, blk_addr);
offset = OFFSET_IN_SEG(sbi, blk_addr);
- sum_blk = calloc(BLOCK_SZ, 1);
-
- ret = get_sum_block(sbi, segno, sum_blk);
+ sum_blk = get_sum_block(sbi, segno, &type);
memcpy(sum_entry, &(sum_blk->entries[offset]),
sizeof(struct f2fs_summary));
- free(sum_blk);
- return ret;
+ if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
+ type == SEG_TYPE_MAX)
+ free(sum_blk);
+ return type;
}
static void get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
--
2.1.1
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/8] fsck.f2fs: fix summary block
2015-04-02 17:50 [PATCH 1/8] fsck.f2fs: return summary block pointer and types Jaegeuk Kim
@ 2015-04-02 17:50 ` Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 3/8] fsck.f2fs: fix corrupted dentries Jaegeuk Kim
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Jaegeuk Kim @ 2015-04-02 17:50 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: Jaegeuk Kim
Previously, if data and node summary was corrupted, the block was deallocated.
But, this patch fixes their summary first, so that we can keep their blocks.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fsck/fsck.c | 166 ++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 118 insertions(+), 48 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index a3029ba..ecb18f2 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -129,66 +129,137 @@ static int find_and_dec_hard_link_list(struct f2fs_sb_info *sbi, u32 nid)
static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid,
u32 blk_addr)
{
- int ret = 0;
- struct f2fs_summary sum_entry;
-
- ret = get_sum_entry(sbi, blk_addr, &sum_entry);
+ struct f2fs_summary_block *sum_blk;
+ struct f2fs_summary *sum_entry;
+ u32 segno, offset;
+ int need_fix = 0, ret = 0;
+ int type;
+
+ segno = GET_SEGNO(sbi, blk_addr);
+ offset = OFFSET_IN_SEG(sbi, blk_addr);
+
+ sum_blk = get_sum_block(sbi, segno, &type);
+
+ if (type != SEG_TYPE_NODE && type != SEG_TYPE_CUR_NODE) {
+ /* can't fix current summary, then drop the block */
+ if (!config.fix_on || type < 0) {
+ ASSERT_MSG("Summary footer is not for node segment");
+ ret = -EINVAL;
+ goto out;
+ }
+ FIX_MSG("Summary footer indicates a node segment: 0x%x", segno);
+ sum_blk->footer.entry_type = SUM_TYPE_NODE;
+ need_fix = 1;
+ }
- if (ret != SEG_TYPE_NODE && ret != SEG_TYPE_CUR_NODE) {
- ASSERT_MSG("Summary footer is not for node segment");
- return -EINVAL;
+ sum_entry = &(sum_blk->entries[offset]);
+
+ if (le32_to_cpu(sum_entry->nid) != nid) {
+ if (!config.fix_on || type < 0) {
+ DBG(0, "nid [0x%x]\n", nid);
+ DBG(0, "target blk_addr [0x%x]\n", blk_addr);
+ DBG(0, "summary blk_addr [0x%x]\n",
+ GET_SUM_BLKADDR(sbi,
+ GET_SEGNO(sbi, blk_addr)));
+ DBG(0, "seg no / offset [0x%x / 0x%x]\n",
+ GET_SEGNO(sbi, blk_addr),
+ OFFSET_IN_SEG(sbi, blk_addr));
+ DBG(0, "summary_entry.nid [0x%x]\n",
+ le32_to_cpu(sum_entry->nid));
+ DBG(0, "--> node block's nid [0x%x]\n", nid);
+ ASSERT_MSG("Invalid node seg summary\n");
+ ret = -EINVAL;
+ } else {
+ FIX_MSG("Set node summary 0x%x -> [0x%x] [0x%x]",
+ segno, nid, blk_addr);
+ sum_entry->nid = cpu_to_le32(nid);
+ need_fix = 1;
+ }
}
+ if (need_fix) {
+ u64 ssa_blk;
+ int ret2;
- if (le32_to_cpu(sum_entry.nid) != nid) {
- DBG(0, "nid [0x%x]\n", nid);
- DBG(0, "target blk_addr [0x%x]\n", blk_addr);
- DBG(0, "summary blk_addr [0x%x]\n",
- GET_SUM_BLKADDR(sbi,
- GET_SEGNO(sbi, blk_addr)));
- DBG(0, "seg no / offset [0x%x / 0x%x]\n",
- GET_SEGNO(sbi, blk_addr),
- OFFSET_IN_SEG(sbi, blk_addr));
- DBG(0, "summary_entry.nid [0x%x]\n",
- le32_to_cpu(sum_entry.nid));
- DBG(0, "--> node block's nid [0x%x]\n", nid);
- ASSERT_MSG("Invalid node seg summary\n");
- return -EINVAL;
+ ssa_blk = GET_SUM_BLKADDR(sbi, segno);
+ ret2 = dev_write_block(sum_blk, ssa_blk);
+ ASSERT(ret2 >= 0);
}
- return 0;
+out:
+ if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
+ type == SEG_TYPE_MAX)
+ free(sum_blk);
+ return ret;
}
static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
u32 parent_nid, u16 idx_in_node, u8 version)
{
- int ret = 0;
- struct f2fs_summary sum_entry;
-
- ret = get_sum_entry(sbi, blk_addr, &sum_entry);
-
- if (ret != SEG_TYPE_DATA && ret != SEG_TYPE_CUR_DATA) {
- ASSERT_MSG("Summary footer is not for data segment");
- return -EINVAL;
+ struct f2fs_summary_block *sum_blk;
+ struct f2fs_summary *sum_entry;
+ u32 segno, offset;
+ int need_fix = 0, ret = 0;
+ int type;
+
+ segno = GET_SEGNO(sbi, blk_addr);
+ offset = OFFSET_IN_SEG(sbi, blk_addr);
+
+ sum_blk = get_sum_block(sbi, segno, &type);
+
+ if (type != SEG_TYPE_DATA && type != SEG_TYPE_CUR_DATA) {
+ /* can't fix current summary, then drop the block */
+ if (!config.fix_on || type < 0) {
+ ASSERT_MSG("Summary footer is not for data segment");
+ ret = -EINVAL;
+ goto out;
+ }
+ FIX_MSG("Summary footer indicates a data segment: 0x%x", segno);
+ sum_blk->footer.entry_type = SUM_TYPE_DATA;
+ need_fix = 1;
}
- if (le32_to_cpu(sum_entry.nid) != parent_nid ||
- sum_entry.version != version ||
- le16_to_cpu(sum_entry.ofs_in_node) != idx_in_node) {
-
- DBG(0, "summary_entry.nid [0x%x]\n",
- le32_to_cpu(sum_entry.nid));
- DBG(0, "summary_entry.version [0x%x]\n",
- sum_entry.version);
- DBG(0, "summary_entry.ofs_in_node [0x%x]\n",
- le16_to_cpu(sum_entry.ofs_in_node));
- DBG(0, "parent nid [0x%x]\n", parent_nid);
- DBG(0, "version from nat [0x%x]\n", version);
- DBG(0, "idx in parent node [0x%x]\n", idx_in_node);
+ sum_entry = &(sum_blk->entries[offset]);
+
+ if (le32_to_cpu(sum_entry->nid) != parent_nid ||
+ sum_entry->version != version ||
+ le16_to_cpu(sum_entry->ofs_in_node) != idx_in_node) {
+ if (!config.fix_on || type < 0) {
+ DBG(0, "summary_entry.nid [0x%x]\n",
+ le32_to_cpu(sum_entry->nid));
+ DBG(0, "summary_entry.version [0x%x]\n",
+ sum_entry->version);
+ DBG(0, "summary_entry.ofs_in_node [0x%x]\n",
+ le16_to_cpu(sum_entry->ofs_in_node));
+ DBG(0, "parent nid [0x%x]\n",
+ parent_nid);
+ DBG(0, "version from nat [0x%x]\n", version);
+ DBG(0, "idx in parent node [0x%x]\n",
+ idx_in_node);
+
+ DBG(0, "Target data block addr [0x%x]\n", blk_addr);
+ ASSERT_MSG("Invalid data seg summary\n");
+ ret = -EINVAL;
+ } else {
+ FIX_MSG("Set data summary 0x%x -> [0x%x] [0x%x] [0x%x]",
+ segno, parent_nid, version, idx_in_node);
+ sum_entry->nid = cpu_to_le32(parent_nid);
+ sum_entry->version = version;
+ sum_entry->ofs_in_node = cpu_to_le16(idx_in_node);
+ need_fix = 1;
+ }
+ }
+ if (need_fix) {
+ u64 ssa_blk;
+ int ret2;
- DBG(0, "Target data block addr [0x%x]\n", blk_addr);
- ASSERT_MSG("Invalid data seg summary\n");
- return -EINVAL;
+ ssa_blk = GET_SUM_BLKADDR(sbi, segno);
+ ret2 = dev_write_block(sum_blk, ssa_blk);
+ ASSERT(ret2 >= 0);
}
- return 0;
+out:
+ if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
+ type == SEG_TYPE_MAX)
+ free(sum_blk);
+ return ret;
}
static int __check_inode_mode(u32 nid, enum FILE_TYPE ftype, u32 mode)
@@ -929,7 +1000,6 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
ASSERT_MSG("Duplicated data [0x%x]. pnid[0x%x] idx[0x%x]",
blk_addr, parent_nid, idx_in_node);
-
fsck->chk.valid_blk_cnt++;
if (ftype == F2FS_FT_DIR) {
--
2.1.1
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/8] fsck.f2fs: fix corrupted dentries
2015-04-02 17:50 [PATCH 1/8] fsck.f2fs: return summary block pointer and types Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 2/8] fsck.f2fs: fix summary block Jaegeuk Kim
@ 2015-04-02 17:50 ` Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 4/8] fsck.f2fs: count child directories correctly for i_links Jaegeuk Kim
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Jaegeuk Kim @ 2015-04-02 17:50 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: Jaegeuk Kim
This patch fixes corrupted dentries such as name_len == 0.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fsck/fsck.c | 47 +++++++++++++++++++++++++++++++----------------
1 file changed, 31 insertions(+), 16 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index ecb18f2..debae1c 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -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,
--
2.1.1
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/8] fsck.f2fs: count child directories correctly for i_links
2015-04-02 17:50 [PATCH 1/8] fsck.f2fs: return summary block pointer and types Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 2/8] fsck.f2fs: fix summary block Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 3/8] fsck.f2fs: fix corrupted dentries Jaegeuk Kim
@ 2015-04-02 17:50 ` Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 5/8] fsck.f2fs: fix missing i_links Jaegeuk Kim
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Jaegeuk Kim @ 2015-04-02 17:50 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: Jaegeuk Kim
If some of children including directories are corrupted, we should not include
them into i_links of their parent.
This patch fixes that.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fsck/fsck.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index debae1c..828d889 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -793,7 +793,7 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
u16 name_len;;
int ret = 0;
int fixed = 0;
- int i;
+ int i, slots;
/* readahead inode blocks */
for (i = 0; i < max; i++) {
@@ -864,6 +864,7 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
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) {
@@ -874,12 +875,12 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
/* Becareful. 'dentry.file_type' is not imode. */
if (ftype == F2FS_FT_DIR) {
- *child_cnt = *child_cnt + 1;
if ((name[0] == '.' && name_len == 1) ||
(name[0] == '.' && name[1] == '.' &&
name_len == 2)) {
i++;
free(name);
+ *child_cnt = *child_cnt + 1;
continue;
}
}
@@ -899,23 +900,22 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_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, bitmap);
FIX_MSG("Unlink [0x%x] - %s len[0x%x], type[0x%x]",
le32_to_cpu(dentry[i].ino),
name, name_len,
dentry[i].file_type);
- i += slots;
- free(name);
fixed = 1;
- continue;
+ } else if (ret == 0) {
+ if (ftype == F2FS_FT_DIR)
+ *child_cnt = *child_cnt + 1;
+ dentries++;
+ *child_files = *child_files + 1;
}
- i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
- dentries++;
- *child_files = *child_files + 1;
+ i += slots;
free(name);
}
return fixed ? -1 : dentries;
--
2.1.1
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/8] fsck.f2fs: fix missing i_links
2015-04-02 17:50 [PATCH 1/8] fsck.f2fs: return summary block pointer and types Jaegeuk Kim
` (2 preceding siblings ...)
2015-04-02 17:50 ` [PATCH 4/8] fsck.f2fs: count child directories correctly for i_links Jaegeuk Kim
@ 2015-04-02 17:50 ` Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 6/8] fsck.f2fs: clean up child information Jaegeuk Kim
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Jaegeuk Kim @ 2015-04-02 17:50 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: Jaegeuk Kim
If a child is a directory, we should increase parent's i_links.
Previously, it counts direct dentry blocks excluding indirect blocks.
This patch fixes to count child_cnt correctly in order to get precise i_links.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fsck/fsck.c | 34 ++++++++++++++++++++--------------
fsck/fsck.h | 8 ++++----
fsck/main.c | 2 +-
3 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 828d889..2325e4a 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -426,7 +426,7 @@ out:
int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
u32 nid, u8 *name, enum FILE_TYPE ftype, enum NODE_TYPE ntype,
- u32 *blk_cnt)
+ u32 *blk_cnt, u32 *child_cnt, u32 *child_files)
{
struct node_info ni;
struct f2fs_node *node_blk = NULL;
@@ -445,19 +445,19 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
f2fs_set_main_bitmap(sbi, ni.blk_addr,
CURSEG_WARM_NODE);
fsck_chk_dnode_blk(sbi, inode, nid, ftype, node_blk,
- blk_cnt, &ni);
+ blk_cnt, child_cnt, child_files, &ni);
break;
case TYPE_INDIRECT_NODE:
f2fs_set_main_bitmap(sbi, ni.blk_addr,
CURSEG_COLD_NODE);
fsck_chk_idnode_blk(sbi, inode, ftype, node_blk,
- blk_cnt);
+ blk_cnt, child_cnt, child_files);
break;
case TYPE_DOUBLE_INDIRECT_NODE:
f2fs_set_main_bitmap(sbi, ni.blk_addr,
CURSEG_COLD_NODE);
fsck_chk_didnode_blk(sbi, inode, ftype, node_blk,
- blk_cnt);
+ blk_cnt, child_cnt, child_files);
break;
default:
ASSERT(0);
@@ -610,7 +610,8 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
if (le32_to_cpu(node_blk->i.i_nid[idx]) != 0) {
ret = fsck_chk_node_blk(sbi, &node_blk->i,
le32_to_cpu(node_blk->i.i_nid[idx]),
- NULL, ftype, ntype, blk_cnt);
+ NULL, ftype, ntype, blk_cnt,
+ &child_cnt, &child_files);
if (!ret) {
*blk_cnt = *blk_cnt + 1;
} else if (config.fix_on) {
@@ -667,10 +668,10 @@ skip_blkcnt_fix:
int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk,
- u32 *blk_cnt, struct node_info *ni)
+ u32 *blk_cnt, u32 *child_cnt, u32 *child_files,
+ struct node_info *ni)
{
int idx, ret;
- u32 child_cnt = 0, child_files = 0;
int need_fix = 0;
for (idx = 0; idx < ADDRS_PER_BLOCK; idx++) {
@@ -678,7 +679,7 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
continue;
ret = fsck_chk_data_blk(sbi,
le32_to_cpu(node_blk->dn.addr[idx]),
- &child_cnt, &child_files,
+ child_cnt, child_files,
le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype,
nid, idx, ni->version);
if (!ret) {
@@ -697,7 +698,8 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
}
int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
- enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt)
+ enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt,
+ u32 *child_cnt, u32 *child_files)
{
int ret;
int i = 0;
@@ -707,7 +709,8 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
continue;
ret = fsck_chk_node_blk(sbi, inode,
le32_to_cpu(node_blk->in.nid[i]), NULL,
- ftype, TYPE_DIRECT_NODE, blk_cnt);
+ ftype, TYPE_DIRECT_NODE, blk_cnt,
+ child_cnt, child_files);
if (!ret)
*blk_cnt = *blk_cnt + 1;
else if (ret == -EINVAL)
@@ -717,7 +720,8 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
}
int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
- enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt)
+ enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt,
+ u32 *child_cnt, u32 *child_files)
{
int i = 0;
int ret = 0;
@@ -727,7 +731,8 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
continue;
ret = fsck_chk_node_blk(sbi, inode,
le32_to_cpu(node_blk->in.nid[i]), NULL,
- ftype, TYPE_INDIRECT_NODE, blk_cnt);
+ ftype, TYPE_INDIRECT_NODE, blk_cnt,
+ child_cnt, child_files);
if (!ret)
*blk_cnt = *blk_cnt + 1;
else if (ret == -EINVAL)
@@ -896,7 +901,7 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
blk_cnt = 1;
ret = fsck_chk_node_blk(sbi,
NULL, le32_to_cpu(dentry[i].ino), name,
- ftype, TYPE_INODE, &blk_cnt);
+ ftype, TYPE_INODE, &blk_cnt, NULL, NULL);
if (ret && config.fix_on) {
int j;
@@ -1060,7 +1065,8 @@ void fsck_chk_orphan_node(struct f2fs_sb_info *sbi)
DBG(1, "[%3d] ino [0x%x]\n", i, ino);
blk_cnt = 1;
ret = fsck_chk_node_blk(sbi, NULL, ino, NULL,
- F2FS_FT_ORPHAN, TYPE_INODE, &blk_cnt);
+ F2FS_FT_ORPHAN, TYPE_INODE, &blk_cnt,
+ NULL, NULL);
if (!ret)
new_blk->ino[new_entry_count++] =
orphan_blk->ino[j];
diff --git a/fsck/fsck.h b/fsck/fsck.h
index ffb3ae2..a640ccf 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -81,16 +81,16 @@ 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 *);
+ u8 *, enum FILE_TYPE, enum NODE_TYPE, u32 *, u32 *, u32 *);
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 *,
- u32, enum FILE_TYPE, struct f2fs_node *, u32 *,
+ u32, enum FILE_TYPE, struct f2fs_node *, u32 *, u32 *, u32 *,
struct node_info *);
extern int fsck_chk_idnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
- enum FILE_TYPE, struct f2fs_node *, u32 *);
+ enum FILE_TYPE, struct f2fs_node *, u32 *, u32 *, u32 *);
extern int fsck_chk_didnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
- enum FILE_TYPE, struct f2fs_node *, u32 *);
+ enum FILE_TYPE, struct f2fs_node *, u32 *, u32 *, u32 *);
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);
diff --git a/fsck/main.c b/fsck/main.c
index e0b126b..ba76bf8 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -153,7 +153,7 @@ static void do_fsck(struct f2fs_sb_info *sbi)
/* Traverse all block recursively from root inode */
blk_cnt = 1;
fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num, (u8 *)"/",
- F2FS_FT_DIR, TYPE_INODE, &blk_cnt);
+ F2FS_FT_DIR, TYPE_INODE, &blk_cnt, NULL, NULL);
fsck_verify(sbi);
fsck_free(sbi);
}
--
2.1.1
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/8] fsck.f2fs: clean up child information
2015-04-02 17:50 [PATCH 1/8] fsck.f2fs: return summary block pointer and types Jaegeuk Kim
` (3 preceding siblings ...)
2015-04-02 17:50 ` [PATCH 5/8] fsck.f2fs: fix missing i_links Jaegeuk Kim
@ 2015-04-02 17:50 ` Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 7/8] fsck.f2fs: fix missing dentries Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 8/8] fsck.f2fs: fix orphan inode's link count Jaegeuk Kim
6 siblings, 0 replies; 8+ messages in thread
From: Jaegeuk Kim @ 2015-04-02 17:50 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: Jaegeuk Kim
This patch adds a child_info data structure to clean up dirty parameters.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fsck/fsck.c | 71 +++++++++++++++++++++++++++----------------------------------
fsck/fsck.h | 22 ++++++++++++-------
fsck/main.c | 2 +-
3 files changed, 46 insertions(+), 49 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 2325e4a..d83f5a8 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -426,7 +426,7 @@ out:
int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
u32 nid, u8 *name, enum FILE_TYPE ftype, enum NODE_TYPE ntype,
- u32 *blk_cnt, u32 *child_cnt, u32 *child_files)
+ u32 *blk_cnt, struct child_info *child)
{
struct node_info ni;
struct f2fs_node *node_blk = NULL;
@@ -445,19 +445,19 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
f2fs_set_main_bitmap(sbi, ni.blk_addr,
CURSEG_WARM_NODE);
fsck_chk_dnode_blk(sbi, inode, nid, ftype, node_blk,
- blk_cnt, child_cnt, child_files, &ni);
+ blk_cnt, child, &ni);
break;
case TYPE_INDIRECT_NODE:
f2fs_set_main_bitmap(sbi, ni.blk_addr,
CURSEG_COLD_NODE);
fsck_chk_idnode_blk(sbi, inode, ftype, node_blk,
- blk_cnt, child_cnt, child_files);
+ blk_cnt, child);
break;
case TYPE_DOUBLE_INDIRECT_NODE:
f2fs_set_main_bitmap(sbi, ni.blk_addr,
CURSEG_COLD_NODE);
fsck_chk_didnode_blk(sbi, inode, ftype, node_blk,
- blk_cnt, child_cnt, child_files);
+ blk_cnt, child);
break;
default:
ASSERT(0);
@@ -476,7 +476,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
u32 *blk_cnt, struct node_info *ni)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
- u32 child_cnt = 0, child_files = 0;
+ struct child_info child = {0, 0};
enum NODE_TYPE ntype;
u32 i_links = le32_to_cpu(node_blk->i.i_links);
u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks);
@@ -556,8 +556,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
}
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);
+ ret = fsck_chk_inline_dentries(sbi, node_blk, &child);
if (ret < 0) {
/* should fix this bug all the time */
need_fix = 1;
@@ -583,8 +582,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
if (le32_to_cpu(node_blk->i.i_addr[idx]) != 0) {
ret = fsck_chk_data_blk(sbi,
le32_to_cpu(node_blk->i.i_addr[idx]),
- &child_cnt, &child_files,
- (i_blocks == *blk_cnt),
+ &child, (i_blocks == *blk_cnt),
ftype, nid, idx, ni->version);
if (!ret) {
*blk_cnt = *blk_cnt + 1;
@@ -610,8 +608,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
if (le32_to_cpu(node_blk->i.i_nid[idx]) != 0) {
ret = fsck_chk_node_blk(sbi, &node_blk->i,
le32_to_cpu(node_blk->i.i_nid[idx]),
- NULL, ftype, ntype, blk_cnt,
- &child_cnt, &child_files);
+ NULL, ftype, ntype, blk_cnt, &child);
if (!ret) {
*blk_cnt = *blk_cnt + 1;
} else if (config.fix_on) {
@@ -639,21 +636,21 @@ skip_blkcnt_fix:
le32_to_cpu(node_blk->footer.ino),
node_blk->i.i_name,
le32_to_cpu(node_blk->i.i_current_depth),
- child_files);
+ child.files);
if (ftype == F2FS_FT_ORPHAN)
DBG(1, "Orphan Inode: 0x%x [%s] i_blocks: %u\n\n",
le32_to_cpu(node_blk->footer.ino),
node_blk->i.i_name,
(u32)i_blocks);
- if (ftype == F2FS_FT_DIR && i_links != child_cnt) {
+ if (ftype == F2FS_FT_DIR && i_links != child.links) {
ASSERT_MSG("ino: 0x%x has i_links: %u but real links: %u",
- nid, i_links, child_cnt);
+ nid, i_links, child.links);
if (config.fix_on) {
- node_blk->i.i_links = cpu_to_le32(child_cnt);
+ node_blk->i.i_links = cpu_to_le32(child.links);
need_fix = 1;
FIX_MSG("Dir: 0x%x i_links= 0x%x -> 0x%x",
- nid, i_links, child_cnt);
+ nid, i_links, child.links);
}
}
@@ -668,8 +665,7 @@ skip_blkcnt_fix:
int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk,
- u32 *blk_cnt, u32 *child_cnt, u32 *child_files,
- struct node_info *ni)
+ u32 *blk_cnt, struct child_info *child, struct node_info *ni)
{
int idx, ret;
int need_fix = 0;
@@ -679,8 +675,7 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
continue;
ret = fsck_chk_data_blk(sbi,
le32_to_cpu(node_blk->dn.addr[idx]),
- child_cnt, child_files,
- le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype,
+ child, le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype,
nid, idx, ni->version);
if (!ret) {
*blk_cnt = *blk_cnt + 1;
@@ -699,7 +694,7 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt,
- u32 *child_cnt, u32 *child_files)
+ struct child_info *child)
{
int ret;
int i = 0;
@@ -709,8 +704,7 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
continue;
ret = fsck_chk_node_blk(sbi, inode,
le32_to_cpu(node_blk->in.nid[i]), NULL,
- ftype, TYPE_DIRECT_NODE, blk_cnt,
- child_cnt, child_files);
+ ftype, TYPE_DIRECT_NODE, blk_cnt, child);
if (!ret)
*blk_cnt = *blk_cnt + 1;
else if (ret == -EINVAL)
@@ -721,7 +715,7 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt,
- u32 *child_cnt, u32 *child_files)
+ struct child_info *child)
{
int i = 0;
int ret = 0;
@@ -731,8 +725,7 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
continue;
ret = fsck_chk_node_blk(sbi, inode,
le32_to_cpu(node_blk->in.nid[i]), NULL,
- ftype, TYPE_INDIRECT_NODE, blk_cnt,
- child_cnt, child_files);
+ ftype, TYPE_INDIRECT_NODE, blk_cnt, child);
if (!ret)
*blk_cnt = *blk_cnt + 1;
else if (ret == -EINVAL)
@@ -782,8 +775,7 @@ static void print_dentry(__u32 depth, __u8 *name,
name, le32_to_cpu(dentry[idx].ino));
}
-static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
- u32* child_files,
+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],
@@ -885,7 +877,7 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
name_len == 2)) {
i++;
free(name);
- *child_cnt = *child_cnt + 1;
+ child->links++;
continue;
}
}
@@ -901,7 +893,7 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
blk_cnt = 1;
ret = fsck_chk_node_blk(sbi,
NULL, le32_to_cpu(dentry[i].ino), name,
- ftype, TYPE_INODE, &blk_cnt, NULL, NULL);
+ ftype, TYPE_INODE, &blk_cnt, NULL);
if (ret && config.fix_on) {
int j;
@@ -915,9 +907,9 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
fixed = 1;
} else if (ret == 0) {
if (ftype == F2FS_FT_DIR)
- *child_cnt = *child_cnt + 1;
+ child->links++;
dentries++;
- *child_files = *child_files + 1;
+ child->files++;
}
i += slots;
@@ -927,7 +919,7 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, u32 *child_cnt,
}
int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
- struct f2fs_node *node_blk, u32 *child_cnt, u32 *child_files)
+ struct f2fs_node *node_blk, struct child_info *child)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
struct f2fs_inline_dentry *de_blk;
@@ -937,7 +929,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
ASSERT(de_blk != NULL);
fsck->dentry_depth++;
- dentries = __chk_dentries(sbi, child_cnt, child_files,
+ dentries = __chk_dentries(sbi, child,
(unsigned long *)de_blk->dentry_bitmap,
de_blk->dentry, de_blk->filename,
NR_INLINE_DENTRY, 1);
@@ -955,7 +947,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
}
int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
- u32 *child_cnt, u32 *child_files, int last_blk)
+ struct child_info *child, int last_blk)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
struct f2fs_dentry_block *de_blk;
@@ -968,7 +960,7 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
ASSERT(ret >= 0);
fsck->dentry_depth++;
- dentries = __chk_dentries(sbi, child_cnt, child_files,
+ dentries = __chk_dentries(sbi, child,
(unsigned long *)de_blk->dentry_bitmap,
de_blk->dentry, de_blk->filename,
NR_DENTRY_IN_BLOCK, last_blk);
@@ -990,7 +982,7 @@ 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,
- u32 *child_cnt, u32 *child_files, int last_blk,
+ struct child_info *child, int last_blk,
enum FILE_TYPE ftype, u32 parent_nid, u16 idx_in_node, u8 ver)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
@@ -1024,8 +1016,7 @@ 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_cnt,
- child_files, last_blk);
+ return fsck_chk_dentry_blk(sbi, blk_addr, child, last_blk);
} else {
f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_WARM_DATA);
}
@@ -1066,7 +1057,7 @@ void fsck_chk_orphan_node(struct f2fs_sb_info *sbi)
blk_cnt = 1;
ret = fsck_chk_node_blk(sbi, NULL, ino, NULL,
F2FS_FT_ORPHAN, TYPE_INODE, &blk_cnt,
- NULL, NULL);
+ NULL);
if (!ret)
new_blk->ino[new_entry_count++] =
orphan_blk->ino[j];
diff --git a/fsck/fsck.h b/fsck/fsck.h
index a640ccf..97e2385 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -19,6 +19,11 @@ struct orphan_info {
u32 *ino_list;
};
+struct child_info {
+ u32 links;
+ u32 files;
+};
+
struct f2fs_fsck {
struct f2fs_sb_info sbi;
@@ -81,21 +86,22 @@ 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 *, u32 *, u32 *);
+ 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 *,
- u32, enum FILE_TYPE, struct f2fs_node *, u32 *, u32 *, u32 *,
- struct node_info *);
+ u32, enum FILE_TYPE, struct f2fs_node *, u32 *,
+ struct child_info *, struct node_info *);
extern int fsck_chk_idnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
- enum FILE_TYPE, struct f2fs_node *, u32 *, u32 *, u32 *);
+ enum FILE_TYPE, struct f2fs_node *, u32 *, struct child_info *);
extern int fsck_chk_didnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
- enum FILE_TYPE, struct f2fs_node *, u32 *, u32 *, u32 *);
-extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32, u32 *, u32 *,
+ 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);
-extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, u32, u32 *, u32 *, int);
+extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, u32, struct child_info *,
+ int);
int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *,
- u32 *, u32 *);
+ struct child_info *);
void print_cp_state(u32);
extern void print_node_info(struct f2fs_node *);
diff --git a/fsck/main.c b/fsck/main.c
index ba76bf8..b5ad46e 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -153,7 +153,7 @@ static void do_fsck(struct f2fs_sb_info *sbi)
/* Traverse all block recursively from root inode */
blk_cnt = 1;
fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num, (u8 *)"/",
- F2FS_FT_DIR, TYPE_INODE, &blk_cnt, NULL, NULL);
+ F2FS_FT_DIR, TYPE_INODE, &blk_cnt, NULL);
fsck_verify(sbi);
fsck_free(sbi);
}
--
2.1.1
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 7/8] fsck.f2fs: fix missing dentries
2015-04-02 17:50 [PATCH 1/8] fsck.f2fs: return summary block pointer and types Jaegeuk Kim
` (4 preceding siblings ...)
2015-04-02 17:50 ` [PATCH 6/8] fsck.f2fs: clean up child information Jaegeuk Kim
@ 2015-04-02 17:50 ` Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 8/8] fsck.f2fs: fix orphan inode's link count Jaegeuk Kim
6 siblings, 0 replies; 8+ messages in thread
From: Jaegeuk Kim @ 2015-04-02 17:50 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: Jaegeuk Kim
If a directory has no dot and dotdot dentries, fsck.f2fs sets inline_dots for
the inode so that f2fs module can handle that properly.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fsck/fsck.c | 42 +++++++++++++++++++++++++++---------------
fsck/fsck.h | 1 +
include/f2fs_fs.h | 1 +
3 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index d83f5a8..8211159 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -476,7 +476,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
u32 *blk_cnt, struct node_info *ni)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
- struct child_info child = {0, 0};
+ struct child_info child = {2, 0, 0};
enum NODE_TYPE ntype;
u32 i_links = le32_to_cpu(node_blk->i.i_links);
u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks);
@@ -631,26 +631,38 @@ check:
}
}
skip_blkcnt_fix:
- if (ftype == F2FS_FT_DIR)
- DBG(1, "Directory Inode: 0x%x [%s] depth: %d has %d files\n\n",
- le32_to_cpu(node_blk->footer.ino),
- node_blk->i.i_name,
- le32_to_cpu(node_blk->i.i_current_depth),
- child.files);
if (ftype == F2FS_FT_ORPHAN)
DBG(1, "Orphan Inode: 0x%x [%s] i_blocks: %u\n\n",
le32_to_cpu(node_blk->footer.ino),
node_blk->i.i_name,
(u32)i_blocks);
- if (ftype == F2FS_FT_DIR && i_links != child.links) {
- ASSERT_MSG("ino: 0x%x has i_links: %u but real links: %u",
- nid, i_links, child.links);
- if (config.fix_on) {
- node_blk->i.i_links = cpu_to_le32(child.links);
- need_fix = 1;
- FIX_MSG("Dir: 0x%x i_links= 0x%x -> 0x%x",
+ if (ftype == F2FS_FT_DIR) {
+ DBG(1, "Directory Inode: 0x%x [%s] depth: %d has %d files\n\n",
+ le32_to_cpu(node_blk->footer.ino),
+ node_blk->i.i_name,
+ le32_to_cpu(node_blk->i.i_current_depth),
+ child.files);
+
+ if (i_links != child.links) {
+ ASSERT_MSG("ino: 0x%x i_links: %u, real links: %u",
+ nid, i_links, child.links);
+ if (config.fix_on) {
+ node_blk->i.i_links = cpu_to_le32(child.links);
+ need_fix = 1;
+ FIX_MSG("Dir: 0x%x i_links= 0x%x -> 0x%x",
nid, i_links, child.links);
+ }
+ }
+ if (child.dots < 2 &&
+ !(node_blk->i.i_inline & F2FS_INLINE_DOTS)) {
+ ASSERT_MSG("ino: 0x%x dots: %u",
+ nid, child.dots);
+ if (config.fix_on) {
+ node_blk->i.i_inline |= F2FS_INLINE_DOTS;
+ need_fix = 1;
+ FIX_MSG("Dir: 0x%x set inline_dots", nid);
+ }
}
}
@@ -877,7 +889,7 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child,
name_len == 2)) {
i++;
free(name);
- child->links++;
+ child->dots++;
continue;
}
}
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 97e2385..5eac45c 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -22,6 +22,7 @@ struct orphan_info {
struct child_info {
u32 links;
u32 files;
+ u8 dots;
};
struct f2fs_fsck {
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 6ce58c2..d23ae1b 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -436,6 +436,7 @@ struct f2fs_extent {
#define F2FS_INLINE_DATA 0x02 /* file inline data flag */
#define F2FS_INLINE_DENTRY 0x04 /* file inline dentry flag */
#define F2FS_DATA_EXIST 0x08 /* file inline data exist flag */
+#define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries */
#define MAX_INLINE_DATA (sizeof(__le32) * (DEF_ADDRS_PER_INODE - \
F2FS_INLINE_XATTR_ADDRS - 1))
--
2.1.1
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 8/8] fsck.f2fs: fix orphan inode's link count
2015-04-02 17:50 [PATCH 1/8] fsck.f2fs: return summary block pointer and types Jaegeuk Kim
` (5 preceding siblings ...)
2015-04-02 17:50 ` [PATCH 7/8] fsck.f2fs: fix missing dentries Jaegeuk Kim
@ 2015-04-02 17:50 ` Jaegeuk Kim
6 siblings, 0 replies; 8+ messages in thread
From: Jaegeuk Kim @ 2015-04-02 17:50 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: Jaegeuk Kim
This patch fixes orphan inode's link count as 0.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
fsck/fsck.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 8211159..f3fbdfa 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -493,7 +493,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) {
f2fs_set_main_bitmap(sbi, ni->blk_addr,
CURSEG_WARM_NODE);
- if (i_links > 1) {
+ if (i_links > 1 && ftype != F2FS_FT_ORPHAN) {
/* First time. Create new hard link node */
add_into_hard_link_list(sbi, nid, i_links);
fsck->chk.multi_hard_link_files++;
@@ -666,9 +666,16 @@ skip_blkcnt_fix:
}
}
- if (ftype == F2FS_FT_ORPHAN && i_links)
+ if (ftype == F2FS_FT_ORPHAN && i_links) {
ASSERT_MSG("ino: 0x%x is orphan inode, but has i_links: %u",
nid, i_links);
+ if (config.fix_on) {
+ node_blk->i.i_links = 0;
+ need_fix = 1;
+ FIX_MSG("ino: 0x%x orphan_inode, i_links= 0x%x -> 0",
+ nid, i_links);
+ }
+ }
if (need_fix) {
ret = dev_write_block(node_blk, ni->blk_addr);
ASSERT(ret >= 0);
--
2.1.1
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-04-02 17:51 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-02 17:50 [PATCH 1/8] fsck.f2fs: return summary block pointer and types Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 2/8] fsck.f2fs: fix summary block Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 3/8] fsck.f2fs: fix corrupted dentries Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 4/8] fsck.f2fs: count child directories correctly for i_links Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 5/8] fsck.f2fs: fix missing i_links Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 6/8] fsck.f2fs: clean up child information Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 7/8] fsck.f2fs: fix missing dentries Jaegeuk Kim
2015-04-02 17:50 ` [PATCH 8/8] fsck.f2fs: fix orphan inode's link count Jaegeuk Kim
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).