aboutsummaryrefslogtreecommitdiffstats
path: root/fsck/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'fsck/mount.c')
-rw-r--r--fsck/mount.c518
1 files changed, 334 insertions, 184 deletions
diff --git a/fsck/mount.c b/fsck/mount.c
index e2f3ace..415f977 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -12,7 +12,7 @@
void print_inode_info(struct f2fs_inode *inode)
{
- int i = 0;
+ unsigned int i = 0;
int namelen = le32_to_cpu(inode->i_namelen);
DISP_u32(inode, i_mode);
@@ -53,7 +53,7 @@ void print_inode_info(struct f2fs_inode *inode)
for (i = 4; i < ADDRS_PER_INODE(inode); i++) {
if (inode->i_addr[i] != 0x0) {
- printf("i_addr[0x%x] points data block\r\t\t\t\t[0x%4x]\n",
+ printf("i_addr[0x%x] points data block\r\t\t[0x%4x]\n",
i, inode->i_addr[i]);
break;
}
@@ -79,9 +79,11 @@ void print_node_info(struct f2fs_node *node_block)
} else {
int i;
u32 *dump_blk = (u32 *)node_block;
- DBG(0, "Node ID [0x%x:%u] is direct node or indirect node.\n", nid, nid);
+ DBG(0, "Node ID [0x%x:%u] is direct node or indirect node.\n",
+ nid, nid);
for (i = 0; i <= 10; i++)
- MSG(0, "[%d]\t\t\t[0x%8x : %d]\n", i, dump_blk[i], dump_blk[i]);
+ MSG(0, "[%d]\t\t\t[0x%8x : %d]\n",
+ i, dump_blk[i], dump_blk[i]);
}
}
@@ -129,6 +131,7 @@ void print_raw_sb_info(struct f2fs_sb_info *sbi)
DISP_u32(sb, root_ino);
DISP_u32(sb, node_ino);
DISP_u32(sb, meta_ino);
+ DISP_u32(sb, cp_payload);
printf("\n");
}
@@ -210,7 +213,8 @@ int sanity_check_raw_super(struct f2fs_super_block *raw_super)
return -1;
}
- if (F2FS_LOG_SECTORS_PER_BLOCK != le32_to_cpu(raw_super->log_sectors_per_block)) {
+ if (F2FS_LOG_SECTORS_PER_BLOCK !=
+ le32_to_cpu(raw_super->log_sectors_per_block)) {
return -1;
}
@@ -229,7 +233,7 @@ int validate_super_block(struct f2fs_sb_info *sbi, int block)
return 0;
free(sbi->raw_super);
- MSG(0, "\tCan't find a valid F2FS filesystem in %d superblock\n", block);
+ MSG(0, "\tCan't find a valid F2FS superblock at 0x%x\n", block);
return -EINVAL;
}
@@ -257,7 +261,8 @@ int init_sb_info(struct f2fs_sb_info *sbi)
return 0;
}
-void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, unsigned long long *version)
+void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr,
+ unsigned long long *version)
{
void *cp_page_1, *cp_page_2;
struct f2fs_checkpoint *cp_block;
@@ -285,6 +290,7 @@ void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, unsigned lo
/* Read the 2nd cp block in this CP pack */
cp_page_2 = malloc(PAGE_SIZE);
cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
+
if (dev_read_block(cp_page_2, cp_addr) < 0)
goto invalid_cp2;
@@ -295,7 +301,7 @@ void *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, unsigned lo
crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
if (f2fs_crc_valid(crc, cp_block, crc_offset))
- goto invalid_cp1;
+ goto invalid_cp2;
cur_version = le64_to_cpu(cp_block->checkpoint_ver);
@@ -319,8 +325,10 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
unsigned long blk_size = sbi->blocksize;
unsigned long long cp1_version = 0, cp2_version = 0;
unsigned long long cp_start_blk_no;
+ unsigned int cp_blks = 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload);
+ int ret;
- sbi->ckpt = malloc(blk_size);
+ sbi->ckpt = malloc(cp_blks * blk_size);
if (!sbi->ckpt)
return -ENOMEM;
/*
@@ -335,14 +343,19 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
if (cp1 && cp2) {
- if (ver_after(cp2_version, cp1_version))
+ if (ver_after(cp2_version, cp1_version)) {
cur_page = cp2;
- else
+ sbi->cur_cp = 2;
+ } else {
cur_page = cp1;
+ sbi->cur_cp = 1;
+ }
} else if (cp1) {
cur_page = cp1;
+ sbi->cur_cp = 1;
} else if (cp2) {
cur_page = cp2;
+ sbi->cur_cp = 2;
} else {
free(cp1);
free(cp2);
@@ -351,6 +364,22 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
memcpy(sbi->ckpt, cur_page, blk_size);
+ if (cp_blks > 1) {
+ unsigned int i;
+ unsigned long long cp_blk_no;
+
+ cp_blk_no = le32_to_cpu(raw_sb->cp_blkaddr);
+ if (cur_page == cp2)
+ cp_blk_no += 1 <<
+ le32_to_cpu(raw_sb->log_blocks_per_seg);
+ /* copy sit bitmap */
+ for (i = 1; i < cp_blks; i++) {
+ unsigned char *ckpt = (unsigned char *)sbi->ckpt;
+ ret = dev_read_block(cur_page, cp_blk_no + i);
+ ASSERT(ret >= 0);
+ memcpy(ckpt + i * blk_size, cur_page, blk_size);
+ }
+ }
free(cp1);
free(cp2);
return 0;
@@ -470,199 +499,181 @@ int build_sit_info(struct f2fs_sb_info *sbi)
return 0;
}
-void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
+void reset_curseg(struct f2fs_sb_info *sbi, int type)
{
struct curseg_info *curseg = CURSEG_I(sbi, 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))
+ SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
+ if (IS_NODESEG(type))
+ SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
+ se = get_seg_entry(sbi, curseg->segno);
+ se->type = type;
}
-int read_compacted_summaries(struct f2fs_sb_info *sbi)
+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;
char *kaddr;
- unsigned int i, j, offset;
+ int ret;
start = start_sum_block(sbi);
kaddr = (char *)malloc(PAGE_SIZE);
- dev_read_block(kaddr, start++);
+ ret = dev_read_block(kaddr, start++);
+ ASSERT(ret >= 0);
curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
memcpy(&curseg->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE);
curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
- memcpy(&curseg->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE, SUM_JOURNAL_SIZE);
+ memcpy(&curseg->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE,
+ SUM_JOURNAL_SIZE);
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, 0);
- curseg->alloc_type = ckpt->alloc_type[i];
- curseg->next_blkoff = blk_off;
+ reset_curseg(sbi, i);
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;
s = (struct f2fs_summary *)(kaddr + offset);
curseg->sum_blk->entries[j] = *s;
offset += SUMMARY_SIZE;
- if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE - SUM_FOOTER_SIZE)
+ if (offset + SUMMARY_SIZE <=
+ PAGE_CACHE_SIZE - SUM_FOOTER_SIZE)
continue;
memset(kaddr, 0, PAGE_SIZE);
- dev_read_block(kaddr, start++);
+ ret = dev_read_block(kaddr, start++);
+ ASSERT(ret >= 0);
offset = 0;
}
}
-
free(kaddr);
- return 0;
}
-int restore_node_summary(struct f2fs_sb_info *sbi,
+static void restore_node_summary(struct f2fs_sb_info *sbi,
unsigned int segno, struct f2fs_summary_block *sum_blk)
{
struct f2fs_node *node_blk;
struct f2fs_summary *sum_entry;
- void *page;
block_t addr;
- int i;
+ unsigned int i;
+ int ret;
- page = malloc(PAGE_SIZE);
- if (!page)
- return -ENOMEM;
+ node_blk = malloc(F2FS_BLKSIZE);
+ ASSERT(node_blk);
/* scan the node segment */
addr = START_BLOCK(sbi, segno);
sum_entry = &sum_blk->entries[0];
for (i = 0; i < sbi->blocks_per_seg; i++, sum_entry++) {
- if (dev_read_block(page, addr))
- goto out;
-
- node_blk = (struct f2fs_node *)page;
+ ret = dev_read_block(node_blk, addr);
+ ASSERT(ret >= 0);
sum_entry->nid = node_blk->footer.nid;
- /* do not change original value */
-#if 0
- sum_entry->version = 0;
- sum_entry->ofs_in_node = 0;
-#endif
addr++;
-
}
-out:
- free(page);
- return 0;
+ free(node_blk);
}
-int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
+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
blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, 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]);
-
+ segno = le32_to_cpu(ckpt->cur_node_segno[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);
+ blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE,
+ type - CURSEG_HOT_NODE);
else
blk_addr = GET_SUM_BLKADDR(sbi, segno);
}
sum_blk = (struct f2fs_summary_block *)malloc(PAGE_SIZE);
- dev_read_block(sum_blk, blk_addr);
-
- if (IS_NODESEG(type)) {
- if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) {
- struct f2fs_summary *sum_entry = &sum_blk->entries[0];
- int i;
- for (i = 0; i < sbi->blocks_per_seg; i++, sum_entry++) {
- /* do not change original value */
-#if 0
- sum_entry->version = 0;
- sum_entry->ofs_in_node = 0;
-#endif
- }
- } else {
- if (restore_node_summary(sbi, segno, sum_blk)) {
- free(sum_blk);
- return -EINVAL;
- }
- }
- }
+ ret = dev_read_block(sum_blk, blk_addr);
+ ASSERT(ret >= 0);
+
+ if (IS_NODESEG(type) && !is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
+ restore_node_summary(sbi, segno, sum_blk);
curseg = CURSEG_I(sbi, type);
memcpy(curseg->sum_blk, sum_blk, PAGE_CACHE_SIZE);
- curseg->next_segno = segno;
- reset_curseg(sbi, type, 0);
- curseg->alloc_type = ckpt->alloc_type[type];
- curseg->next_blkoff = blk_off;
+ reset_curseg(sbi, type);
free(sum_blk);
-
- return 0;
}
-int restore_curseg_summaries(struct f2fs_sb_info *sbi)
+static void restore_curseg_summaries(struct f2fs_sb_info *sbi)
{
int type = CURSEG_HOT_DATA;
if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) {
- if (read_compacted_summaries(sbi))
- return -EINVAL;
+ read_compacted_summaries(sbi);
type = CURSEG_HOT_NODE;
}
- for (; type <= CURSEG_COLD_NODE; type++) {
- if (read_normal_summaries(sbi, type))
- return -EINVAL;
- }
- return 0;
+ for (; type <= CURSEG_COLD_NODE; type++)
+ read_normal_summaries(sbi, type);
}
-int build_curseg(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);
+ ASSERT(array);
SM_I(sbi)->curseg_array = array;
for (i = 0; i < NR_CURSEG_TYPE; i++) {
array[i].sum_blk = malloc(PAGE_CACHE_SIZE);
- if (!array[i].sum_blk)
- return -ENOMEM;
- array[i].segno = NULL_SEGNO;
- array[i].next_blkoff = 0;
+ ASSERT(array[i].sum_blk);
+ 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];
}
- return restore_curseg_summaries(sbi);
+ restore_curseg_summaries(sbi);
}
inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
@@ -671,12 +682,14 @@ inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
ASSERT(segno <= end_segno);
}
-struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi, unsigned int segno)
+static struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi,
+ unsigned int segno)
{
struct sit_info *sit_i = SIT_I(sbi);
unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno);
block_t blk_addr = sit_i->sit_base_addr + offset;
struct f2fs_sit_block *sit_blk = calloc(BLOCK_SZ, 1);
+ int ret;
check_seg_range(sbi, segno);
@@ -684,30 +697,56 @@ struct f2fs_sit_block *get_current_sit_page(struct f2fs_sb_info *sbi, unsigned i
if (f2fs_test_bit(offset, sit_i->sit_bitmap))
blk_addr += sit_i->sit_blocks;
- dev_read_block(sit_blk, blk_addr);
+ ret = dev_read_block(sit_blk, blk_addr);
+ ASSERT(ret >= 0);
return sit_blk;
}
+void rewrite_current_sit_page(struct f2fs_sb_info *sbi,
+ unsigned int segno, struct f2fs_sit_block *sit_blk)
+{
+ struct sit_info *sit_i = SIT_I(sbi);
+ unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno);
+ block_t blk_addr = sit_i->sit_base_addr + offset;
+ int ret;
+
+ /* calculate sit block address */
+ if (f2fs_test_bit(offset, sit_i->sit_bitmap))
+ blk_addr += sit_i->sit_blocks;
+
+ ret = dev_write_block(sit_blk, blk_addr);
+ ASSERT(ret >= 0);
+}
+
void check_block_count(struct f2fs_sb_info *sbi,
- int segno, struct f2fs_sit_entry *raw_sit)
+ unsigned int segno, struct f2fs_sit_entry *raw_sit)
{
struct f2fs_sm_info *sm_info = SM_I(sbi);
unsigned int end_segno = sm_info->segment_count - 1;
int valid_blocks = 0;
- int i;
+ unsigned int i;
/* check segment usage */
- ASSERT(GET_SIT_VBLOCKS(raw_sit) <= sbi->blocks_per_seg);
+ if (GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg)
+ ASSERT_MSG("Invalid SIT vblocks: segno=0x%x, %u",
+ segno, GET_SIT_VBLOCKS(raw_sit));
/* check boundary of a given segment number */
- ASSERT(segno <= end_segno);
+ if (segno > end_segno)
+ ASSERT_MSG("Invalid SEGNO: 0x%x", segno);
/* check bitmap with valid block count */
- for (i = 0; i < sbi->blocks_per_seg; i++)
- if (f2fs_test_bit(i, (char *)raw_sit->valid_map))
- valid_blocks++;
- ASSERT(GET_SIT_VBLOCKS(raw_sit) == valid_blocks);
+ for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++)
+ valid_blocks += get_bits_in_byte(raw_sit->valid_map[i]);
+
+ if (GET_SIT_VBLOCKS(raw_sit) != valid_blocks)
+ ASSERT_MSG("Wrong SIT valid blocks: segno=0x%x, %u vs. %u",
+ segno, GET_SIT_VBLOCKS(raw_sit), valid_blocks);
+
+ if (GET_SIT_TYPE(raw_sit) >= NO_CHECK_TYPE)
+ ASSERT_MSG("Wrong SIT type: segno=0x%x, %u",
+ segno, GET_SIT_TYPE(raw_sit));
}
void seg_info_from_raw_sit(struct seg_entry *se,
@@ -728,7 +767,8 @@ 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)
+int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno,
+ struct f2fs_summary_block *sum_blk)
{
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
struct curseg_info *curseg;
@@ -739,18 +779,30 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summ
for (type = 0; type < NR_CURSEG_NODE_TYPE; type++) {
if (segno == ckpt->cur_node_segno[type]) {
curseg = CURSEG_I(sbi, CURSEG_HOT_NODE + type);
+ if (!IS_SUM_NODE_SEG(curseg->sum_blk->footer)) {
+ ASSERT_MSG("segno [0x%x] indicates a data "
+ "segment, but should be node",
+ segno);
+ return -EINVAL;
+ }
memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ);
- return SEG_TYPE_CUR_NODE; /* current node seg was not stored */
+ return SEG_TYPE_CUR_NODE;
}
}
for (type = 0; type < NR_CURSEG_DATA_TYPE; type++) {
if (segno == ckpt->cur_data_segno[type]) {
curseg = CURSEG_I(sbi, type);
+ if (IS_SUM_NODE_SEG(curseg->sum_blk->footer)) {
+ ASSERT_MSG("segno [0x%x] indicates a node "
+ "segment, but should be data",
+ segno);
+ return -EINVAL;
+ }
+ DBG(2, "segno [0x%x] is current data seg[0x%x]\n",
+ segno, type);
memcpy(sum_blk, curseg->sum_blk, BLOCK_SZ);
- ASSERT(!IS_SUM_NODE_SEG(sum_blk->footer));
- DBG(2, "segno [0x%x] is current data seg[0x%x]\n", segno, type);
- return SEG_TYPE_CUR_DATA; /* current data seg was not stored */
+ return SEG_TYPE_CUR_DATA;
}
}
@@ -764,7 +816,8 @@ int get_sum_block(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summ
}
-int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, struct f2fs_summary *sum_entry)
+int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr,
+ struct f2fs_summary *sum_entry)
{
struct f2fs_summary_block *sum_blk;
u32 segno, offset;
@@ -776,16 +829,15 @@ int get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, struct f2fs_summary *s
sum_blk = calloc(BLOCK_SZ, 1);
ret = get_sum_block(sbi, segno, sum_blk);
-
- memcpy(sum_entry, &(sum_blk->entries[offset]), sizeof(struct f2fs_summary));
-
+ memcpy(sum_entry, &(sum_blk->entries[offset]),
+ sizeof(struct f2fs_summary));
free(sum_blk);
return ret;
}
-int get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, struct f2fs_nat_entry *raw_nat)
+static void get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
+ struct f2fs_nat_entry *raw_nat)
{
- struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct f2fs_nat_block *nat_block;
pgoff_t block_off;
@@ -793,13 +845,8 @@ int get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, struct f2fs_nat_entry *ra
int seg_off, entry_off;
int ret;
- if ((nid / NAT_ENTRY_PER_BLOCK) > fsck->nr_nat_entries) {
- DBG(0, "nid is over max nid\n");
- return -EINVAL;
- }
-
if (lookup_nat_in_journal(sbi, nid, raw_nat) >= 0)
- return 0;
+ return;
nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
@@ -817,21 +864,17 @@ int get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, struct f2fs_nat_entry *ra
ret = dev_read_block(nat_block, block_addr);
ASSERT(ret >= 0);
- memcpy(raw_nat, &nat_block->entries[entry_off], sizeof(struct f2fs_nat_entry));
+ memcpy(raw_nat, &nat_block->entries[entry_off],
+ sizeof(struct f2fs_nat_entry));
free(nat_block);
-
- return 0;
}
-int get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
+void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
{
struct f2fs_nat_entry raw_nat;
- int ret;
-
- ret = get_nat_entry(sbi, nid, &raw_nat);
+ get_nat_entry(sbi, nid, &raw_nat);
ni->nid = nid;
node_info_from_raw_nat(ni, &raw_nat);
- return ret;
}
void build_sit_entries(struct f2fs_sb_info *sbi)
@@ -892,17 +935,14 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
return 0;
}
-int build_sit_area_bitmap(struct f2fs_sb_info *sbi)
+void build_sit_area_bitmap(struct f2fs_sb_info *sbi)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
struct f2fs_sm_info *sm_i = SM_I(sbi);
- int segno = 0, j = 0;
+ unsigned int segno = 0;
char *ptr = NULL;
-
u32 sum_vblocks = 0;
u32 free_segs = 0;
- u32 vblocks = 0;
-
struct seg_entry *se;
fsck->sit_area_bitmap_sz = sm_i->main_segments * SIT_VBLOCK_MAP_SIZE;
@@ -911,20 +951,13 @@ int build_sit_area_bitmap(struct f2fs_sb_info *sbi)
ASSERT(fsck->sit_area_bitmap_sz == fsck->main_area_bitmap_sz);
- for (segno = 0; segno < sm_i->main_segments; segno++) {
+ for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) {
se = get_seg_entry(sbi, segno);
memcpy(ptr, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
ptr += SIT_VBLOCK_MAP_SIZE;
- vblocks = 0;
- for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++) {
- vblocks += get_bits_in_byte(se->cur_valid_map[j]);
- }
- ASSERT(vblocks == se->valid_blocks);
-
if (se->valid_blocks == 0x0) {
-
if (sbi->ckpt->cur_node_segno[0] == segno ||
sbi->ckpt->cur_data_segno[0] == segno ||
sbi->ckpt->cur_node_segno[1] == segno ||
@@ -935,22 +968,76 @@ int build_sit_area_bitmap(struct f2fs_sb_info *sbi)
} else {
free_segs++;
}
-
} else {
- ASSERT(se->valid_blocks <= 512);
sum_vblocks += se->valid_blocks;
}
}
-
fsck->chk.sit_valid_blocks = sum_vblocks;
fsck->chk.sit_free_segs = free_segs;
- DBG(1, "Blocks [0x%x : %d] Free Segs [0x%x : %d]\n\n", sum_vblocks, sum_vblocks,
+ DBG(1, "Blocks [0x%x : %d] Free Segs [0x%x : %d]\n\n",
+ sum_vblocks, sum_vblocks,
free_segs, free_segs);
- return 0;
}
-int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_entry *raw_nat)
+void rewrite_sit_area_bitmap(struct f2fs_sb_info *sbi)
+{
+ struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+ struct sit_info *sit_i = SIT_I(sbi);
+ unsigned int segno = 0;
+ struct f2fs_summary_block *sum = curseg->sum_blk;
+ char *ptr = NULL;
+
+ /* remove sit journal */
+ sum->n_sits = 0;
+
+ fsck->chk.free_segs = 0;
+
+ ptr = fsck->main_area_bitmap;
+
+ for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) {
+ struct f2fs_sit_block *sit_blk;
+ struct f2fs_sit_entry *sit;
+ struct seg_entry *se;
+ u16 valid_blocks = 0;
+ u16 type;
+ int i;
+
+ sit_blk = get_current_sit_page(sbi, segno);
+ sit = &sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)];
+ memcpy(sit->valid_map, ptr, SIT_VBLOCK_MAP_SIZE);
+
+ /* update valid block count */
+ for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++)
+ valid_blocks += get_bits_in_byte(sit->valid_map[i]);
+
+ se = get_seg_entry(sbi, segno);
+ type = se->type;
+ if (type >= NO_CHECK_TYPE) {
+ ASSERT(valid_blocks);
+ type = 0;
+ }
+ sit->vblocks = cpu_to_le16((type << SIT_VBLOCKS_SHIFT) |
+ valid_blocks);
+ rewrite_current_sit_page(sbi, segno, sit_blk);
+ free(sit_blk);
+
+ if (valid_blocks == 0 &&
+ sbi->ckpt->cur_node_segno[0] != segno &&
+ sbi->ckpt->cur_data_segno[0] != segno &&
+ sbi->ckpt->cur_node_segno[1] != segno &&
+ sbi->ckpt->cur_data_segno[1] != segno &&
+ sbi->ckpt->cur_node_segno[2] != segno &&
+ sbi->ckpt->cur_data_segno[2] != segno)
+ fsck->chk.free_segs++;
+
+ ptr += SIT_VBLOCK_MAP_SIZE;
+ }
+}
+
+int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid,
+ struct f2fs_nat_entry *raw_nat)
{
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
struct f2fs_summary_block *sum = curseg->sum_blk;
@@ -958,7 +1045,8 @@ int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_ent
for (i = 0; i < nats_in_cursum(sum); i++) {
if (le32_to_cpu(nid_in_journal(sum, i)) == nid) {
- memcpy(raw_nat, &nat_in_journal(sum, i), sizeof(struct f2fs_nat_entry));
+ memcpy(raw_nat, &nat_in_journal(sum, i),
+ sizeof(struct f2fs_nat_entry));
DBG(3, "==> Found nid [0x%x] in nat cache\n", nid);
return i;
}
@@ -966,6 +1054,51 @@ int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct f2fs_nat_ent
return -1;
}
+void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
+{
+ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+ struct f2fs_summary_block *sum = curseg->sum_blk;
+ struct f2fs_nm_info *nm_i = NM_I(sbi);
+ struct f2fs_nat_block *nat_block;
+ pgoff_t block_off;
+ pgoff_t block_addr;
+ int seg_off, entry_off;
+ int ret;
+ int i = 0;
+
+ /* check in journal */
+ for (i = 0; i < nats_in_cursum(sum); i++) {
+ if (le32_to_cpu(nid_in_journal(sum, i)) == nid) {
+ memset(&nat_in_journal(sum, i), 0,
+ sizeof(struct f2fs_nat_entry));
+ FIX_MSG("Remove nid [0x%x] in nat journal\n", nid);
+ return;
+ }
+ }
+ nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
+
+ block_off = nid / NAT_ENTRY_PER_BLOCK;
+ entry_off = nid % NAT_ENTRY_PER_BLOCK;
+
+ seg_off = block_off >> sbi->log_blocks_per_seg;
+ block_addr = (pgoff_t)(nm_i->nat_blkaddr +
+ (seg_off << sbi->log_blocks_per_seg << 1) +
+ (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
+
+ if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+ block_addr += sbi->blocks_per_seg;
+
+ ret = dev_read_block(nat_block, block_addr);
+ ASSERT(ret >= 0);
+
+ memset(&nat_block->entries[entry_off], 0,
+ sizeof(struct f2fs_nat_entry));
+
+ ret = dev_write_block(nat_block, block_addr);
+ ASSERT(ret >= 0);
+ free(nat_block);
+}
+
void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
@@ -973,17 +1106,18 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct f2fs_nat_block *nat_block;
u32 nid, nr_nat_blks;
-
pgoff_t block_off;
pgoff_t block_addr;
int seg_off;
- int ret, i;
-
+ int ret;
+ unsigned int i;
nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
+ ASSERT(nat_block);
/* Alloc & build nat entry bitmap */
- nr_nat_blks = (le32_to_cpu(raw_sb->segment_count_nat) / 2) << sbi->log_blocks_per_seg;
+ nr_nat_blks = (le32_to_cpu(raw_sb->segment_count_nat) / 2) <<
+ sbi->log_blocks_per_seg;
fsck->nr_nat_entries = nr_nat_blks * NAT_ENTRY_PER_BLOCK;
fsck->nat_area_bitmap_sz = (fsck->nr_nat_entries + 7) / 8;
@@ -994,8 +1128,8 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
seg_off = block_off >> sbi->log_blocks_per_seg;
block_addr = (pgoff_t)(nm_i->nat_blkaddr +
- (seg_off << sbi->log_blocks_per_seg << 1) +
- (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
+ (seg_off << sbi->log_blocks_per_seg << 1) +
+ (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
block_addr += sbi->blocks_per_seg;
@@ -1009,44 +1143,47 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
struct node_info ni;
ni.nid = nid + i;
- if ((nid + i) == F2FS_NODE_INO(sbi) || (nid + i) == F2FS_META_INO(sbi)) {
+ if ((nid + i) == F2FS_NODE_INO(sbi) ||
+ (nid + i) == F2FS_META_INO(sbi)) {
ASSERT(nat_block->entries[i].block_addr != 0x0);
continue;
}
- if (lookup_nat_in_journal(sbi, nid + i, &raw_nat) >= 0) {
+ if (lookup_nat_in_journal(sbi, nid + i,
+ &raw_nat) >= 0) {
node_info_from_raw_nat(&ni, &raw_nat);
if (ni.blk_addr != 0x0) {
- f2fs_set_bit(nid + i, fsck->nat_area_bitmap);
+ f2fs_set_bit(nid + i,
+ fsck->nat_area_bitmap);
fsck->chk.valid_nat_entry_cnt++;
- DBG(3, "nid[0x%x] in nat cache\n", nid + i);
+ DBG(3, "nid[0x%x] in nat cache\n",
+ nid + i);
}
} else {
- node_info_from_raw_nat(&ni, &nat_block->entries[i]);
- if (ni.blk_addr != 0) {
- ASSERT(nid + i != 0x0);
-
- DBG(3, "nid[0x%8x] in nat entry [0x%16x] [0x%8x]\n",
- nid + i,
- ni.blk_addr,
- ni.ino);
-
- f2fs_set_bit(nid + i, fsck->nat_area_bitmap);
- fsck->chk.valid_nat_entry_cnt++;
- }
+ node_info_from_raw_nat(&ni,
+ &nat_block->entries[i]);
+ if (ni.blk_addr == 0)
+ continue;
+ ASSERT(nid + i != 0x0);
+
+ DBG(3, "nid[0x%8x] addr[0x%16x] ino[0x%8x]\n",
+ nid + i, ni.blk_addr, ni.ino);
+ f2fs_set_bit(nid + i, fsck->nat_area_bitmap);
+ fsck->chk.valid_nat_entry_cnt++;
}
}
}
free(nat_block);
DBG(1, "valid nat entries (block_addr != 0x0) [0x%8x : %u]\n",
- fsck->chk.valid_nat_entry_cnt, fsck->chk.valid_nat_entry_cnt);
-
+ fsck->chk.valid_nat_entry_cnt,
+ fsck->chk.valid_nat_entry_cnt);
}
int f2fs_do_mount(struct f2fs_sb_info *sbi)
{
int ret;
+
sbi->active_logs = NR_CURSEG_TYPE;
ret = validate_super_block(sbi, 0);
if (ret) {
@@ -1072,10 +1209,23 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi)
print_ckpt_info(sbi);
+ if (config.auto_fix) {
+ u32 flag = le32_to_cpu(sbi->ckpt->ckpt_flags);
+
+ if (flag & CP_FSCK_FLAG)
+ config.fix_on = 1;
+ else
+ return 1;
+ }
+
+ config.bug_on = 0;
+
sbi->total_valid_node_count = le32_to_cpu(sbi->ckpt->valid_node_count);
- sbi->total_valid_inode_count = le32_to_cpu(sbi->ckpt->valid_inode_count);
+ sbi->total_valid_inode_count =
+ le32_to_cpu(sbi->ckpt->valid_inode_count);
sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count);
- sbi->total_valid_block_count = le64_to_cpu(sbi->ckpt->valid_block_count);
+ sbi->total_valid_block_count =
+ le64_to_cpu(sbi->ckpt->valid_block_count);
sbi->last_valid_block_count = sbi->total_valid_block_count;
sbi->alloc_valid_block_count = 0;
@@ -1089,7 +1239,7 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi)
return -1;
}
- return ret;
+ return 0;
}
void f2fs_do_umount(struct f2fs_sb_info *sbi)
@@ -1097,7 +1247,7 @@ void f2fs_do_umount(struct f2fs_sb_info *sbi)
struct sit_info *sit_i = SIT_I(sbi);
struct f2fs_sm_info *sm_i = SM_I(sbi);
struct f2fs_nm_info *nm_i = NM_I(sbi);
- int i;
+ unsigned int i;
/* free nm_info */
free(nm_i->nat_bitmap);