aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2014-08-28 16:55:45 -0700
committerJaegeuk Kim <jaegeuk@kernel.org>2014-08-29 16:37:46 -0700
commita6b2870ddb760ab2e2f662db0c09f220d02c6d9e (patch)
tree9056660ef37f7d2a746007e36c625a125148ebe6
parentb700e313b4ad390fce7f610c51d0bb2dc52661bb (diff)
downloadandroid_external_f2fs-tools-a6b2870ddb760ab2e2f662db0c09f220d02c6d9e.tar.gz
android_external_f2fs-tools-a6b2870ddb760ab2e2f662db0c09f220d02c6d9e.tar.bz2
android_external_f2fs-tools-a6b2870ddb760ab2e2f662db0c09f220d02c6d9e.zip
fsck.f2fs: check next block is free or not
If block allocation is made to the next block offset, we should drop that block. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fsck/f2fs.h19
-rw-r--r--fsck/fsck.c27
-rw-r--r--fsck/mount.c46
3 files changed, 65 insertions, 27 deletions
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index 8c31981..f674ede 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -266,10 +266,15 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
#define GET_SEGNO_FROM_SEG0(sbi, blk_addr) \
(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg)
-#define FREE_I_START_SEGNO(sbi) GET_SEGNO_FROM_SEG0(sbi, SM_I(sbi)->main_blkaddr)
+#define GET_BLKOFF_FROM_SEG0(sbi, blk_addr) \
+ (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & (sbi->blocks_per_seg - 1))
+
+#define FREE_I_START_SEGNO(sbi) \
+ GET_SEGNO_FROM_SEG0(sbi, SM_I(sbi)->main_blkaddr)
#define GET_R2L_SEGNO(sbi, segno) (segno + FREE_I_START_SEGNO(sbi))
-#define START_BLOCK(sbi, segno) (SM_I(sbi)->main_blkaddr + (segno << sbi->log_blocks_per_seg))
+#define START_BLOCK(sbi, segno) (SM_I(sbi)->main_blkaddr + \
+ (segno << sbi->log_blocks_per_seg))
static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
{
@@ -311,6 +316,8 @@ static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
{
+ int i;
+
if (addr >= F2FS_RAW_SUPER(sbi)->block_count ||
addr < SM_I(sbi)->main_blkaddr) {
DBG(0, "block addr [0x%x]\n", addr);
@@ -318,6 +325,14 @@ static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
ASSERT(addr >= SM_I(sbi)->main_blkaddr);
return 0;
}
+
+ for (i = 0; i < NO_CHECK_TYPE; i++) {
+ struct curseg_info *curseg = CURSEG_I(sbi, i);
+
+ if (START_BLOCK(sbi, curseg->segno) +
+ curseg->next_blkoff == addr)
+ return 0;
+ }
return 1;
}
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 8df489d..560b541 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -843,6 +843,24 @@ static void fix_checkpoint(struct f2fs_sb_info *sbi)
ASSERT(ret >= 0);
}
+int check_curseg_offset(struct f2fs_sb_info *sbi)
+{
+ int i;
+
+ for (i = 0; i < NO_CHECK_TYPE; i++) {
+ struct curseg_info *curseg = CURSEG_I(sbi, i);
+ struct seg_entry *se;
+
+ se = get_seg_entry(sbi, curseg->segno);
+ if (f2fs_test_bit(curseg->next_blkoff,
+ (const char *)se->cur_valid_map) == 1) {
+ ASSERT_MSG("Next block offset is not free, type:%d", i);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
int fsck_verify(struct f2fs_sb_info *sbi)
{
unsigned int i = 0;
@@ -944,6 +962,15 @@ int fsck_verify(struct f2fs_sb_info *sbi)
config.bug_on = 1;
}
+ printf("[FSCK] next block offset is free ");
+ if (check_curseg_offset(sbi) == 0) {
+ printf(" [Ok..]\n");
+ } else {
+ printf(" [Fail]\n");
+ ret = EXIT_ERR_CODE;
+ config.bug_on = 1;
+ }
+
printf("[FSCK] other corrupted bugs ");
if (config.bug_on == 0) {
printf(" [Ok..]\n");
diff --git a/fsck/mount.c b/fsck/mount.c
index a41320f..2bbd3c5 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -505,11 +505,6 @@ void reset_curseg(struct f2fs_sb_info *sbi, int type)
struct summary_footer *sum_footer;
struct seg_entry *se;
- curseg->segno = curseg->next_segno;
- curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno);
- curseg->next_blkoff = 0;
- curseg->next_segno = NULL_SEGNO;
-
sum_footer = &(curseg->sum_blk->footer);
memset(sum_footer, 0, sizeof(struct summary_footer));
if (IS_DATASEG(type))
@@ -522,7 +517,6 @@ void reset_curseg(struct f2fs_sb_info *sbi, int type)
static void read_compacted_summaries(struct f2fs_sb_info *sbi)
{
- struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
struct curseg_info *curseg;
unsigned int i, j, offset;
block_t start;
@@ -545,18 +539,14 @@ static void read_compacted_summaries(struct f2fs_sb_info *sbi)
offset = 2 * SUM_JOURNAL_SIZE;
for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
unsigned short blk_off;
- unsigned int segno;
+ struct curseg_info *curseg = CURSEG_I(sbi, i);
- curseg = CURSEG_I(sbi, i);
- segno = le32_to_cpu(ckpt->cur_data_segno[i]);
- blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]);
- curseg->next_segno = segno;
reset_curseg(sbi, i);
- curseg->alloc_type = ckpt->alloc_type[i];
- curseg->next_blkoff = blk_off;
if (curseg->alloc_type == SSR)
blk_off = sbi->blocks_per_seg;
+ else
+ blk_off = curseg->next_blkoff;
for (j = 0; j < blk_off; j++) {
struct f2fs_summary *s;
@@ -605,16 +595,12 @@ static void read_normal_summaries(struct f2fs_sb_info *sbi, int type)
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
struct f2fs_summary_block *sum_blk;
struct curseg_info *curseg;
- unsigned short blk_off;
unsigned int segno = 0;
block_t blk_addr = 0;
int ret;
if (IS_DATASEG(type)) {
segno = le32_to_cpu(ckpt->cur_data_segno[type]);
- blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
- CURSEG_HOT_DATA]);
-
if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
else
@@ -622,9 +608,6 @@ static void read_normal_summaries(struct f2fs_sb_info *sbi, int type)
} else {
segno = le32_to_cpu(ckpt->cur_node_segno[type -
CURSEG_HOT_NODE]);
- blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type -
- CURSEG_HOT_NODE]);
-
if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE,
type - CURSEG_HOT_NODE);
@@ -641,10 +624,7 @@ static void read_normal_summaries(struct f2fs_sb_info *sbi, int type)
curseg = CURSEG_I(sbi, type);
memcpy(curseg->sum_blk, sum_blk, PAGE_CACHE_SIZE);
- curseg->next_segno = segno;
reset_curseg(sbi, type);
- curseg->alloc_type = ckpt->alloc_type[type];
- curseg->next_blkoff = blk_off;
free(sum_blk);
}
@@ -663,7 +643,10 @@ static void restore_curseg_summaries(struct f2fs_sb_info *sbi)
static void build_curseg(struct f2fs_sb_info *sbi)
{
+ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
struct curseg_info *array;
+ unsigned short blk_off;
+ unsigned int segno;
int i;
array = malloc(sizeof(*array) * NR_CURSEG_TYPE);
@@ -674,8 +657,21 @@ static void build_curseg(struct f2fs_sb_info *sbi)
for (i = 0; i < NR_CURSEG_TYPE; i++) {
array[i].sum_blk = malloc(PAGE_CACHE_SIZE);
ASSERT(array[i].sum_blk);
- array[i].segno = NULL_SEGNO;
- array[i].next_blkoff = 0;
+ if (i <= CURSEG_COLD_DATA) {
+ blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]);
+ segno = le32_to_cpu(ckpt->cur_data_segno[i]);
+ }
+ if (i > CURSEG_COLD_DATA) {
+ blk_off = le16_to_cpu(ckpt->cur_node_blkoff[i -
+ CURSEG_HOT_NODE]);
+ segno = le32_to_cpu(ckpt->cur_node_segno[i -
+ CURSEG_HOT_NODE]);
+ }
+ array[i].segno = segno;
+ array[i].zone = GET_ZONENO_FROM_SEGNO(sbi, segno);
+ array[i].next_segno = NULL_SEGNO;
+ array[i].next_blkoff = blk_off;
+ array[i].alloc_type = ckpt->alloc_type[i];
}
restore_curseg_summaries(sbi);
}