Home | History | Annotate | Download | only in mkfs
      1 /**
      2  * f2fs_format.c
      3  *
      4  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
      5  *             http://www.samsung.com/
      6  *
      7  * Dual licensed under the GPL or LGPL version 2 licenses.
      8  */
      9 #define _LARGEFILE64_SOURCE
     10 
     11 #include <stdio.h>
     12 #include <stdlib.h>
     13 #include <fcntl.h>
     14 #include <string.h>
     15 #include <unistd.h>
     16 #include <sys/stat.h>
     17 #include <sys/mount.h>
     18 #include <time.h>
     19 #include <uuid/uuid.h>
     20 
     21 #include "f2fs_fs.h"
     22 #include "f2fs_format_utils.h"
     23 
     24 extern struct f2fs_configuration config;
     25 struct f2fs_super_block super_block;
     26 
     27 const char *media_ext_lists[] = {
     28 	"jpg",
     29 	"gif",
     30 	"png",
     31 	"avi",
     32 	"divx",
     33 	"mp4",
     34 	"mp3",
     35 	"3gp",
     36 	"wmv",
     37 	"wma",
     38 	"mpeg",
     39 	"mkv",
     40 	"mov",
     41 	"asx",
     42 	"asf",
     43 	"wmx",
     44 	"svi",
     45 	"wvx",
     46 	"wm",
     47 	"mpg",
     48 	"mpe",
     49 	"rm",
     50 	"ogg",
     51 	"jpeg",
     52 	"video",
     53 	"apk",	/* for android system */
     54 	NULL
     55 };
     56 
     57 static void configure_extension_list(void)
     58 {
     59 	const char **extlist = media_ext_lists;
     60 	char *ext_str = config.extension_list;
     61 	char *ue;
     62 	int name_len;
     63 	int i = 0;
     64 
     65 	super_block.extension_count = 0;
     66 	memset(super_block.extension_list, 0,
     67 			sizeof(super_block.extension_list));
     68 
     69 	while (*extlist) {
     70 		name_len = strlen(*extlist);
     71 		memcpy(super_block.extension_list[i++], *extlist, name_len);
     72 		extlist++;
     73 	}
     74 	super_block.extension_count = i;
     75 
     76 	if (!ext_str)
     77 		return;
     78 
     79 	/* add user ext list */
     80 	ue = strtok(ext_str, ",");
     81 	while (ue != NULL) {
     82 		name_len = strlen(ue);
     83 		memcpy(super_block.extension_list[i++], ue, name_len);
     84 		ue = strtok(NULL, ",");
     85 		if (i >= F2FS_MAX_EXTENSION)
     86 			break;
     87 	}
     88 
     89 	super_block.extension_count = i;
     90 
     91 	free(config.extension_list);
     92 }
     93 
     94 static int f2fs_prepare_super_block(void)
     95 {
     96 	u_int32_t blk_size_bytes;
     97 	u_int32_t log_sectorsize, log_sectors_per_block;
     98 	u_int32_t log_blocksize, log_blks_per_seg;
     99 	u_int32_t segment_size_bytes, zone_size_bytes;
    100 	u_int32_t sit_segments;
    101 	u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa;
    102 	u_int32_t total_valid_blks_available;
    103 	u_int64_t zone_align_start_offset, diff, total_meta_segments;
    104 	u_int32_t sit_bitmap_size, max_nat_bitmap_size, max_nat_segments;
    105 	u_int32_t total_zones;
    106 
    107 	super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC);
    108 	super_block.major_ver = cpu_to_le16(F2FS_MAJOR_VERSION);
    109 	super_block.minor_ver = cpu_to_le16(F2FS_MINOR_VERSION);
    110 
    111 	log_sectorsize = log_base_2(config.sector_size);
    112 	log_sectors_per_block = log_base_2(config.sectors_per_blk);
    113 	log_blocksize = log_sectorsize + log_sectors_per_block;
    114 	log_blks_per_seg = log_base_2(config.blks_per_seg);
    115 
    116 	super_block.log_sectorsize = cpu_to_le32(log_sectorsize);
    117 	super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block);
    118 
    119 	super_block.log_blocksize = cpu_to_le32(log_blocksize);
    120 	super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg);
    121 
    122 	super_block.segs_per_sec = cpu_to_le32(config.segs_per_sec);
    123 	super_block.secs_per_zone = cpu_to_le32(config.secs_per_zone);
    124 	blk_size_bytes = 1 << log_blocksize;
    125 	segment_size_bytes = blk_size_bytes * config.blks_per_seg;
    126 	zone_size_bytes =
    127 		blk_size_bytes * config.secs_per_zone *
    128 		config.segs_per_sec * config.blks_per_seg;
    129 
    130 	super_block.checksum_offset = 0;
    131 
    132 	super_block.block_count = cpu_to_le64(
    133 		(config.total_sectors * DEFAULT_SECTOR_SIZE) /
    134 			blk_size_bytes);
    135 
    136 	zone_align_start_offset =
    137 		(config.start_sector * DEFAULT_SECTOR_SIZE +
    138 		2 * F2FS_BLKSIZE + zone_size_bytes - 1) /
    139 		zone_size_bytes * zone_size_bytes -
    140 		config.start_sector * DEFAULT_SECTOR_SIZE;
    141 
    142 	if (config.start_sector % DEFAULT_SECTORS_PER_BLOCK) {
    143 		MSG(1, "\tWARN: Align start sector number to the page unit\n");
    144 		MSG(1, "\ti.e., start sector: %d, ofs:%d (sects/page: %d)\n",
    145 				config.start_sector,
    146 				config.start_sector % DEFAULT_SECTORS_PER_BLOCK,
    147 				DEFAULT_SECTORS_PER_BLOCK);
    148 	}
    149 
    150 	super_block.segment_count = cpu_to_le32(
    151 		((config.total_sectors * DEFAULT_SECTOR_SIZE) -
    152 		zone_align_start_offset) / segment_size_bytes);
    153 
    154 	super_block.segment0_blkaddr =
    155 		cpu_to_le32(zone_align_start_offset / blk_size_bytes);
    156 	super_block.cp_blkaddr = super_block.segment0_blkaddr;
    157 
    158 	MSG(0, "Info: zone aligned segment0 blkaddr: %u\n",
    159 				le32_to_cpu(super_block.segment0_blkaddr));
    160 
    161 	super_block.segment_count_ckpt =
    162 				cpu_to_le32(F2FS_NUMBER_OF_CHECKPOINT_PACK);
    163 
    164 	super_block.sit_blkaddr = cpu_to_le32(
    165 		le32_to_cpu(super_block.segment0_blkaddr) +
    166 		(le32_to_cpu(super_block.segment_count_ckpt) *
    167 		(1 << log_blks_per_seg)));
    168 
    169 	blocks_for_sit = (le32_to_cpu(super_block.segment_count) +
    170 			SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK;
    171 
    172 	sit_segments = (blocks_for_sit + config.blks_per_seg - 1)
    173 			/ config.blks_per_seg;
    174 
    175 	super_block.segment_count_sit = cpu_to_le32(sit_segments * 2);
    176 
    177 	super_block.nat_blkaddr = cpu_to_le32(
    178 			le32_to_cpu(super_block.sit_blkaddr) +
    179 			(le32_to_cpu(super_block.segment_count_sit) *
    180 			 config.blks_per_seg));
    181 
    182 	total_valid_blks_available = (le32_to_cpu(super_block.segment_count) -
    183 			(le32_to_cpu(super_block.segment_count_ckpt) +
    184 			 le32_to_cpu(super_block.segment_count_sit))) *
    185 			config.blks_per_seg;
    186 
    187 	blocks_for_nat = (total_valid_blks_available + NAT_ENTRY_PER_BLOCK - 1)
    188 				/ NAT_ENTRY_PER_BLOCK;
    189 
    190 	super_block.segment_count_nat = cpu_to_le32(
    191 				(blocks_for_nat + config.blks_per_seg - 1) /
    192 				config.blks_per_seg);
    193 	/*
    194 	 * The number of node segments should not be exceeded a "Threshold".
    195 	 * This number resizes NAT bitmap area in a CP page.
    196 	 * So the threshold is determined not to overflow one CP page
    197 	 */
    198 	sit_bitmap_size = ((le32_to_cpu(super_block.segment_count_sit) / 2) <<
    199 				log_blks_per_seg) / 8;
    200 	max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 -
    201 			sit_bitmap_size;
    202 	max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg;
    203 
    204 	if (le32_to_cpu(super_block.segment_count_nat) > max_nat_segments)
    205 		super_block.segment_count_nat = cpu_to_le32(max_nat_segments);
    206 
    207 	super_block.segment_count_nat = cpu_to_le32(
    208 			le32_to_cpu(super_block.segment_count_nat) * 2);
    209 
    210 	super_block.ssa_blkaddr = cpu_to_le32(
    211 			le32_to_cpu(super_block.nat_blkaddr) +
    212 			le32_to_cpu(super_block.segment_count_nat) *
    213 			config.blks_per_seg);
    214 
    215 	total_valid_blks_available = (le32_to_cpu(super_block.segment_count) -
    216 			(le32_to_cpu(super_block.segment_count_ckpt) +
    217 			le32_to_cpu(super_block.segment_count_sit) +
    218 			le32_to_cpu(super_block.segment_count_nat))) *
    219 			config.blks_per_seg;
    220 
    221 	blocks_for_ssa = total_valid_blks_available /
    222 				config.blks_per_seg + 1;
    223 
    224 	super_block.segment_count_ssa = cpu_to_le32(
    225 			(blocks_for_ssa + config.blks_per_seg - 1) /
    226 			config.blks_per_seg);
    227 
    228 	total_meta_segments = le32_to_cpu(super_block.segment_count_ckpt) +
    229 		le32_to_cpu(super_block.segment_count_sit) +
    230 		le32_to_cpu(super_block.segment_count_nat) +
    231 		le32_to_cpu(super_block.segment_count_ssa);
    232 	diff = total_meta_segments % (config.segs_per_sec *
    233 						config.secs_per_zone);
    234 	if (diff)
    235 		super_block.segment_count_ssa = cpu_to_le32(
    236 			le32_to_cpu(super_block.segment_count_ssa) +
    237 			(config.segs_per_sec * config.secs_per_zone -
    238 			 diff));
    239 
    240 	super_block.main_blkaddr = cpu_to_le32(
    241 			le32_to_cpu(super_block.ssa_blkaddr) +
    242 			(le32_to_cpu(super_block.segment_count_ssa) *
    243 			 config.blks_per_seg));
    244 
    245 	super_block.segment_count_main = cpu_to_le32(
    246 			le32_to_cpu(super_block.segment_count) -
    247 			(le32_to_cpu(super_block.segment_count_ckpt)
    248 			 + le32_to_cpu(super_block.segment_count_sit) +
    249 			 le32_to_cpu(super_block.segment_count_nat) +
    250 			 le32_to_cpu(super_block.segment_count_ssa)));
    251 
    252 	super_block.section_count = cpu_to_le32(
    253 			le32_to_cpu(super_block.segment_count_main)
    254 			/ config.segs_per_sec);
    255 
    256 	super_block.segment_count_main = cpu_to_le32(
    257 			le32_to_cpu(super_block.section_count) *
    258 			config.segs_per_sec);
    259 
    260 	if ((le32_to_cpu(super_block.segment_count_main) - 2) <
    261 					config.reserved_segments) {
    262 		MSG(1, "\tError: Device size is not sufficient for F2FS volume,\
    263 			more segment needed =%u",
    264 			config.reserved_segments -
    265 			(le32_to_cpu(super_block.segment_count_main) - 2));
    266 		return -1;
    267 	}
    268 
    269 	uuid_generate(super_block.uuid);
    270 
    271 	ASCIIToUNICODE(super_block.volume_name, (u_int8_t *)config.vol_label);
    272 
    273 	super_block.node_ino = cpu_to_le32(1);
    274 	super_block.meta_ino = cpu_to_le32(2);
    275 	super_block.root_ino = cpu_to_le32(3);
    276 
    277 	total_zones = le32_to_cpu(super_block.segment_count_main) /
    278 			(config.segs_per_sec * config.secs_per_zone);
    279 	if (total_zones <= 6) {
    280 		MSG(1, "\tError: %d zones: Need more zones \
    281 			by shrinking zone size\n", total_zones);
    282 		return -1;
    283 	}
    284 
    285 	if (config.heap) {
    286 		config.cur_seg[CURSEG_HOT_NODE] = (total_zones - 1) *
    287 					config.segs_per_sec *
    288 					config.secs_per_zone +
    289 					((config.secs_per_zone - 1) *
    290 					config.segs_per_sec);
    291 		config.cur_seg[CURSEG_WARM_NODE] =
    292 					config.cur_seg[CURSEG_HOT_NODE] -
    293 					config.segs_per_sec *
    294 					config.secs_per_zone;
    295 		config.cur_seg[CURSEG_COLD_NODE] =
    296 					config.cur_seg[CURSEG_WARM_NODE] -
    297 					config.segs_per_sec *
    298 					config.secs_per_zone;
    299 		config.cur_seg[CURSEG_HOT_DATA] =
    300 					config.cur_seg[CURSEG_COLD_NODE] -
    301 					config.segs_per_sec *
    302 					config.secs_per_zone;
    303 		config.cur_seg[CURSEG_COLD_DATA] = 0;
    304 		config.cur_seg[CURSEG_WARM_DATA] =
    305 					config.cur_seg[CURSEG_COLD_DATA] +
    306 					config.segs_per_sec *
    307 					config.secs_per_zone;
    308 	} else {
    309 		config.cur_seg[CURSEG_HOT_NODE] = 0;
    310 		config.cur_seg[CURSEG_WARM_NODE] =
    311 					config.cur_seg[CURSEG_HOT_NODE] +
    312 					config.segs_per_sec *
    313 					config.secs_per_zone;
    314 		config.cur_seg[CURSEG_COLD_NODE] =
    315 					config.cur_seg[CURSEG_WARM_NODE] +
    316 					config.segs_per_sec *
    317 					config.secs_per_zone;
    318 		config.cur_seg[CURSEG_HOT_DATA] =
    319 					config.cur_seg[CURSEG_COLD_NODE] +
    320 					config.segs_per_sec *
    321 					config.secs_per_zone;
    322 		config.cur_seg[CURSEG_COLD_DATA] =
    323 					config.cur_seg[CURSEG_HOT_DATA] +
    324 					config.segs_per_sec *
    325 					config.secs_per_zone;
    326 		config.cur_seg[CURSEG_WARM_DATA] =
    327 					config.cur_seg[CURSEG_COLD_DATA] +
    328 					config.segs_per_sec *
    329 					config.secs_per_zone;
    330 	}
    331 
    332 	configure_extension_list();
    333 
    334 	return 0;
    335 }
    336 
    337 static int f2fs_init_sit_area(void)
    338 {
    339 	u_int32_t blk_size, seg_size;
    340 	u_int32_t index = 0;
    341 	u_int64_t sit_seg_addr = 0;
    342 	u_int8_t *zero_buf = NULL;
    343 
    344 	blk_size = 1 << le32_to_cpu(super_block.log_blocksize);
    345 	seg_size = (1 << le32_to_cpu(super_block.log_blocks_per_seg)) *
    346 							blk_size;
    347 
    348 	zero_buf = calloc(sizeof(u_int8_t), seg_size);
    349 	if(zero_buf == NULL) {
    350 		MSG(1, "\tError: Calloc Failed for sit_zero_buf!!!\n");
    351 		return -1;
    352 	}
    353 
    354 	sit_seg_addr = le32_to_cpu(super_block.sit_blkaddr);
    355 	sit_seg_addr *= blk_size;
    356 
    357 	DBG(1, "\tFilling sit area at offset 0x%08"PRIx64"\n", sit_seg_addr);
    358 	for (index = 0;
    359 		index < (le32_to_cpu(super_block.segment_count_sit) / 2);
    360 								index++) {
    361 		if (dev_fill(zero_buf, sit_seg_addr, seg_size)) {
    362 			MSG(1, "\tError: While zeroing out the sit area \
    363 					on disk!!!\n");
    364 			return -1;
    365 		}
    366 		sit_seg_addr += seg_size;
    367 	}
    368 
    369 	free(zero_buf);
    370 	return 0 ;
    371 }
    372 
    373 static int f2fs_init_nat_area(void)
    374 {
    375 	u_int32_t blk_size, seg_size;
    376 	u_int32_t index = 0;
    377 	u_int64_t nat_seg_addr = 0;
    378 	u_int8_t *nat_buf = NULL;
    379 
    380 	blk_size = 1 << le32_to_cpu(super_block.log_blocksize);
    381 	seg_size = (1 << le32_to_cpu(super_block.log_blocks_per_seg)) *
    382 							blk_size;
    383 
    384 	nat_buf = calloc(sizeof(u_int8_t), seg_size);
    385 	if (nat_buf == NULL) {
    386 		MSG(1, "\tError: Calloc Failed for nat_zero_blk!!!\n");
    387 		return -1;
    388 	}
    389 
    390 	nat_seg_addr = le32_to_cpu(super_block.nat_blkaddr);
    391 	nat_seg_addr *= blk_size;
    392 
    393 	DBG(1, "\tFilling nat area at offset 0x%08"PRIx64"\n", nat_seg_addr);
    394 	for (index = 0;
    395 		index < (le32_to_cpu(super_block.segment_count_nat) / 2);
    396 								index++) {
    397 		if (dev_fill(nat_buf, nat_seg_addr, seg_size)) {
    398 			MSG(1, "\tError: While zeroing out the nat area \
    399 					on disk!!!\n");
    400 			return -1;
    401 		}
    402 		nat_seg_addr = nat_seg_addr + (2 * seg_size);
    403 	}
    404 
    405 	free(nat_buf);
    406 	return 0 ;
    407 }
    408 
    409 static int f2fs_write_check_point_pack(void)
    410 {
    411 	struct f2fs_checkpoint *ckp = NULL;
    412 	struct f2fs_summary_block *sum = NULL;
    413 	u_int32_t blk_size_bytes;
    414 	u_int64_t cp_seg_blk_offset = 0;
    415 	u_int32_t crc = 0;
    416 	int i;
    417 
    418 	ckp = calloc(F2FS_BLKSIZE, 1);
    419 	if (ckp == NULL) {
    420 		MSG(1, "\tError: Calloc Failed for f2fs_checkpoint!!!\n");
    421 		return -1;
    422 	}
    423 
    424 	sum = calloc(F2FS_BLKSIZE, 1);
    425 	if (sum == NULL) {
    426 		MSG(1, "\tError: Calloc Failed for summay_node!!!\n");
    427 		return -1;
    428 	}
    429 
    430 	/* 1. cp page 1 of checkpoint pack 1 */
    431 	ckp->checkpoint_ver = cpu_to_le64(1);
    432 	ckp->cur_node_segno[0] =
    433 		cpu_to_le32(config.cur_seg[CURSEG_HOT_NODE]);
    434 	ckp->cur_node_segno[1] =
    435 		cpu_to_le32(config.cur_seg[CURSEG_WARM_NODE]);
    436 	ckp->cur_node_segno[2] =
    437 		cpu_to_le32(config.cur_seg[CURSEG_COLD_NODE]);
    438 	ckp->cur_data_segno[0] =
    439 		cpu_to_le32(config.cur_seg[CURSEG_HOT_DATA]);
    440 	ckp->cur_data_segno[1] =
    441 		cpu_to_le32(config.cur_seg[CURSEG_WARM_DATA]);
    442 	ckp->cur_data_segno[2] =
    443 		cpu_to_le32(config.cur_seg[CURSEG_COLD_DATA]);
    444 	for (i = 3; i < MAX_ACTIVE_NODE_LOGS; i++) {
    445 		ckp->cur_node_segno[i] = 0xffffffff;
    446 		ckp->cur_data_segno[i] = 0xffffffff;
    447 	}
    448 
    449 	ckp->cur_node_blkoff[0] = cpu_to_le16(1);
    450 	ckp->cur_data_blkoff[0] = cpu_to_le16(1);
    451 	ckp->valid_block_count = cpu_to_le64(2);
    452 	ckp->rsvd_segment_count = cpu_to_le32(config.reserved_segments);
    453 	ckp->overprov_segment_count = cpu_to_le32(
    454 			(le32_to_cpu(super_block.segment_count_main) -
    455 			le32_to_cpu(ckp->rsvd_segment_count)) *
    456 			config.overprovision / 100);
    457 	ckp->overprov_segment_count = cpu_to_le32(
    458 			le32_to_cpu(ckp->overprov_segment_count) +
    459 			le32_to_cpu(ckp->rsvd_segment_count));
    460 
    461 	/* main segments - reserved segments - (node + data segments) */
    462 	ckp->free_segment_count = cpu_to_le32(
    463 			le32_to_cpu(super_block.segment_count_main) - 6);
    464 	ckp->user_block_count = cpu_to_le64(
    465 			((le32_to_cpu(ckp->free_segment_count) + 6 -
    466 			le32_to_cpu(ckp->overprov_segment_count)) *
    467 			 config.blks_per_seg));
    468 	ckp->cp_pack_total_block_count = cpu_to_le32(8);
    469 	ckp->ckpt_flags = cpu_to_le32(CP_UMOUNT_FLAG);
    470 	ckp->cp_pack_start_sum = cpu_to_le32(1);
    471 	ckp->valid_node_count = cpu_to_le32(1);
    472 	ckp->valid_inode_count = cpu_to_le32(1);
    473 	ckp->next_free_nid = cpu_to_le32(
    474 			le32_to_cpu(super_block.root_ino) + 1);
    475 	ckp->sit_ver_bitmap_bytesize = cpu_to_le32(
    476 			((le32_to_cpu(super_block.segment_count_sit) / 2) <<
    477 			 le32_to_cpu(super_block.log_blocks_per_seg)) / 8);
    478 
    479 	ckp->nat_ver_bitmap_bytesize = cpu_to_le32(
    480 			((le32_to_cpu(super_block.segment_count_nat) / 2) <<
    481 			 le32_to_cpu(super_block.log_blocks_per_seg)) / 8);
    482 
    483 	ckp->checksum_offset = cpu_to_le32(CHECKSUM_OFFSET);
    484 
    485 	crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, CHECKSUM_OFFSET);
    486 	*((__le32 *)((unsigned char *)ckp + CHECKSUM_OFFSET)) =
    487 							cpu_to_le32(crc);
    488 
    489 	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
    490 	cp_seg_blk_offset = le32_to_cpu(super_block.segment0_blkaddr);
    491 	cp_seg_blk_offset *= blk_size_bytes;
    492 
    493 	DBG(1, "\tWriting main segments, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    494 	if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    495 		MSG(1, "\tError: While writing the ckp to disk!!!\n");
    496 		return -1;
    497 	}
    498 
    499 	/* 2. Prepare and write Segment summary for data blocks */
    500 	memset(sum, 0, sizeof(struct f2fs_summary_block));
    501 	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
    502 
    503 	sum->entries[0].nid = super_block.root_ino;
    504 	sum->entries[0].ofs_in_node = 0;
    505 
    506 	cp_seg_blk_offset += blk_size_bytes;
    507 	DBG(1, "\tWriting segment summary for data, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    508 	if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    509 		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
    510 		return -1;
    511 	}
    512 
    513 	/* 3. Fill segment summary for data block to zero. */
    514 	memset(sum, 0, sizeof(struct f2fs_summary_block));
    515 	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
    516 
    517 	cp_seg_blk_offset += blk_size_bytes;
    518 	DBG(1, "\tWriting segment summary, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    519 	if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    520 		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
    521 		return -1;
    522 	}
    523 
    524 	/* 4. Fill segment summary for data block to zero. */
    525 	memset(sum, 0, sizeof(struct f2fs_summary_block));
    526 	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
    527 
    528 	/* inode sit for root */
    529 	sum->n_sits = cpu_to_le16(6);
    530 	sum->sit_j.entries[0].segno = ckp->cur_node_segno[0];
    531 	sum->sit_j.entries[0].se.vblocks = cpu_to_le16((CURSEG_HOT_NODE << 10) | 1);
    532 	f2fs_set_bit(0, (char *)sum->sit_j.entries[0].se.valid_map);
    533 	sum->sit_j.entries[1].segno = ckp->cur_node_segno[1];
    534 	sum->sit_j.entries[1].se.vblocks = cpu_to_le16((CURSEG_WARM_NODE << 10));
    535 	sum->sit_j.entries[2].segno = ckp->cur_node_segno[2];
    536 	sum->sit_j.entries[2].se.vblocks = cpu_to_le16((CURSEG_COLD_NODE << 10));
    537 
    538 	/* data sit for root */
    539 	sum->sit_j.entries[3].segno = ckp->cur_data_segno[0];
    540 	sum->sit_j.entries[3].se.vblocks = cpu_to_le16((CURSEG_HOT_DATA << 10) | 1);
    541 	f2fs_set_bit(0, (char *)sum->sit_j.entries[3].se.valid_map);
    542 	sum->sit_j.entries[4].segno = ckp->cur_data_segno[1];
    543 	sum->sit_j.entries[4].se.vblocks = cpu_to_le16((CURSEG_WARM_DATA << 10));
    544 	sum->sit_j.entries[5].segno = ckp->cur_data_segno[2];
    545 	sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10));
    546 
    547 	cp_seg_blk_offset += blk_size_bytes;
    548 	DBG(1, "\tWriting data sit for root, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    549 	if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    550 		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
    551 		return -1;
    552 	}
    553 
    554 	/* 5. Prepare and write Segment summary for node blocks */
    555 	memset(sum, 0, sizeof(struct f2fs_summary_block));
    556 	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
    557 
    558 	sum->entries[0].nid = super_block.root_ino;
    559 	sum->entries[0].ofs_in_node = 0;
    560 
    561 	cp_seg_blk_offset += blk_size_bytes;
    562 	DBG(1, "\tWriting Segment summary for node blocks, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    563 	if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    564 		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
    565 		return -1;
    566 	}
    567 
    568 	/* 6. Fill segment summary for data block to zero. */
    569 	memset(sum, 0, sizeof(struct f2fs_summary_block));
    570 	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
    571 
    572 	cp_seg_blk_offset += blk_size_bytes;
    573 	DBG(1, "\tWriting Segment summary for data block (1/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    574 	if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    575 		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
    576 		return -1;
    577 	}
    578 
    579 	/* 7. Fill segment summary for data block to zero. */
    580 	memset(sum, 0, sizeof(struct f2fs_summary_block));
    581 	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
    582 	cp_seg_blk_offset += blk_size_bytes;
    583 	DBG(1, "\tWriting Segment summary for data block (2/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    584 	if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    585 		MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
    586 		return -1;
    587 	}
    588 
    589 	/* 8. cp page2 */
    590 	cp_seg_blk_offset += blk_size_bytes;
    591 	DBG(1, "\tWriting cp page2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    592 	if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    593 		MSG(1, "\tError: While writing the ckp to disk!!!\n");
    594 		return -1;
    595 	}
    596 
    597 	/* 9. cp page 1 of check point pack 2
    598 	 * Initiatialize other checkpoint pack with version zero
    599 	 */
    600 	ckp->checkpoint_ver = 0;
    601 
    602 	crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, CHECKSUM_OFFSET);
    603 	*((__le32 *)((unsigned char *)ckp + CHECKSUM_OFFSET)) =
    604 							cpu_to_le32(crc);
    605 	cp_seg_blk_offset = (le32_to_cpu(super_block.segment0_blkaddr) +
    606 				config.blks_per_seg) *
    607 				blk_size_bytes;
    608 	DBG(1, "\tWriting cp page 1 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    609 	if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    610 		MSG(1, "\tError: While writing the ckp to disk!!!\n");
    611 		return -1;
    612 	}
    613 
    614 	/* 10. cp page 2 of check point pack 2 */
    615 	cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(ckp->cp_pack_total_block_count) - 1);
    616 	DBG(1, "\tWriting cp page 2 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
    617 	if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) {
    618 		MSG(1, "\tError: While writing the ckp to disk!!!\n");
    619 		return -1;
    620 	}
    621 
    622 	free(sum) ;
    623 	free(ckp) ;
    624 	return	0;
    625 }
    626 
    627 static int f2fs_write_super_block(void)
    628 {
    629 	int index;
    630 	u_int8_t *zero_buff;
    631 
    632 	zero_buff = calloc(F2FS_BLKSIZE, 1);
    633 
    634 	memcpy(zero_buff + F2FS_SUPER_OFFSET, &super_block,
    635 						sizeof(super_block));
    636 	DBG(1, "\tWriting super block, at offset 0x%08x\n", 0);
    637 	for (index = 0; index < 2; index++) {
    638 		if (dev_write(zero_buff, index * F2FS_BLKSIZE, F2FS_BLKSIZE)) {
    639 			MSG(1, "\tError: While while writing supe_blk \
    640 					on disk!!! index : %d\n", index);
    641 			return -1;
    642 		}
    643 	}
    644 
    645 	free(zero_buff);
    646 	return 0;
    647 }
    648 
    649 static int f2fs_write_root_inode(void)
    650 {
    651 	struct f2fs_node *raw_node = NULL;
    652 	u_int64_t blk_size_bytes, data_blk_nor;
    653 	u_int64_t main_area_node_seg_blk_offset = 0;
    654 
    655 	raw_node = calloc(F2FS_BLKSIZE, 1);
    656 	if (raw_node == NULL) {
    657 		MSG(1, "\tError: Calloc Failed for raw_node!!!\n");
    658 		return -1;
    659 	}
    660 
    661 	raw_node->footer.nid = super_block.root_ino;
    662 	raw_node->footer.ino = super_block.root_ino;
    663 	raw_node->footer.cp_ver = cpu_to_le64(1);
    664 	raw_node->footer.next_blkaddr = cpu_to_le32(
    665 			le32_to_cpu(super_block.main_blkaddr) +
    666 			config.cur_seg[CURSEG_HOT_NODE] *
    667 			config.blks_per_seg + 1);
    668 
    669 	raw_node->i.i_mode = cpu_to_le16(0x41ed);
    670 	raw_node->i.i_links = cpu_to_le32(2);
    671 	raw_node->i.i_uid = cpu_to_le32(getuid());
    672 	raw_node->i.i_gid = cpu_to_le32(getgid());
    673 
    674 	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
    675 	raw_node->i.i_size = cpu_to_le64(1 * blk_size_bytes); /* dentry */
    676 	raw_node->i.i_blocks = cpu_to_le64(2);
    677 
    678 	raw_node->i.i_atime = cpu_to_le32(time(NULL));
    679 	raw_node->i.i_atime_nsec = 0;
    680 	raw_node->i.i_ctime = cpu_to_le32(time(NULL));
    681 	raw_node->i.i_ctime_nsec = 0;
    682 	raw_node->i.i_mtime = cpu_to_le32(time(NULL));
    683 	raw_node->i.i_mtime_nsec = 0;
    684 	raw_node->i.i_generation = 0;
    685 	raw_node->i.i_xattr_nid = 0;
    686 	raw_node->i.i_flags = 0;
    687 	raw_node->i.i_current_depth = cpu_to_le32(1);
    688 	raw_node->i.i_dir_level = DEF_DIR_LEVEL;
    689 
    690 	data_blk_nor = le32_to_cpu(super_block.main_blkaddr) +
    691 		config.cur_seg[CURSEG_HOT_DATA] * config.blks_per_seg;
    692 	raw_node->i.i_addr[0] = cpu_to_le32(data_blk_nor);
    693 
    694 	raw_node->i.i_ext.fofs = 0;
    695 	raw_node->i.i_ext.blk_addr = cpu_to_le32(data_blk_nor);
    696 	raw_node->i.i_ext.len = cpu_to_le32(1);
    697 
    698 	main_area_node_seg_blk_offset = le32_to_cpu(super_block.main_blkaddr);
    699 	main_area_node_seg_blk_offset += config.cur_seg[CURSEG_HOT_NODE] *
    700 					config.blks_per_seg;
    701         main_area_node_seg_blk_offset *= blk_size_bytes;
    702 
    703 	DBG(1, "\tWriting root inode (hot node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset);
    704 	if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) {
    705 		MSG(1, "\tError: While writing the raw_node to disk!!!\n");
    706 		return -1;
    707 	}
    708 
    709 	memset(raw_node, 0xff, sizeof(struct f2fs_node));
    710 
    711 	/* avoid power-off-recovery based on roll-forward policy */
    712 	main_area_node_seg_blk_offset = le32_to_cpu(super_block.main_blkaddr);
    713 	main_area_node_seg_blk_offset += config.cur_seg[CURSEG_WARM_NODE] *
    714 					config.blks_per_seg;
    715         main_area_node_seg_blk_offset *= blk_size_bytes;
    716 
    717 	DBG(1, "\tWriting root inode (warm node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset);
    718 	if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) {
    719 		MSG(1, "\tError: While writing the raw_node to disk!!!\n");
    720 		return -1;
    721 	}
    722 	free(raw_node);
    723 	return 0;
    724 }
    725 
    726 static int f2fs_update_nat_root(void)
    727 {
    728 	struct f2fs_nat_block *nat_blk = NULL;
    729 	u_int64_t blk_size_bytes, nat_seg_blk_offset = 0;
    730 
    731 	nat_blk = calloc(F2FS_BLKSIZE, 1);
    732 	if(nat_blk == NULL) {
    733 		MSG(1, "\tError: Calloc Failed for nat_blk!!!\n");
    734 		return -1;
    735 	}
    736 
    737 	/* update root */
    738 	nat_blk->entries[le32_to_cpu(super_block.root_ino)].block_addr = cpu_to_le32(
    739 		le32_to_cpu(super_block.main_blkaddr) +
    740 		config.cur_seg[CURSEG_HOT_NODE] * config.blks_per_seg);
    741 	nat_blk->entries[le32_to_cpu(super_block.root_ino)].ino = super_block.root_ino;
    742 
    743 	/* update node nat */
    744 	nat_blk->entries[le32_to_cpu(super_block.node_ino)].block_addr = cpu_to_le32(1);
    745 	nat_blk->entries[le32_to_cpu(super_block.node_ino)].ino = super_block.node_ino;
    746 
    747 	/* update meta nat */
    748 	nat_blk->entries[le32_to_cpu(super_block.meta_ino)].block_addr = cpu_to_le32(1);
    749 	nat_blk->entries[le32_to_cpu(super_block.meta_ino)].ino = super_block.meta_ino;
    750 
    751 	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
    752 	nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr);
    753 	nat_seg_blk_offset *= blk_size_bytes;
    754 
    755 	DBG(1, "\tWriting nat root, at offset 0x%08"PRIx64"\n", nat_seg_blk_offset);
    756 	if (dev_write(nat_blk, nat_seg_blk_offset, F2FS_BLKSIZE)) {
    757 		MSG(1, "\tError: While writing the nat_blk set0 to disk!\n");
    758 		return -1;
    759 	}
    760 
    761 	free(nat_blk);
    762 	return 0;
    763 }
    764 
    765 static int f2fs_add_default_dentry_root(void)
    766 {
    767 	struct f2fs_dentry_block *dent_blk = NULL;
    768 	u_int64_t blk_size_bytes, data_blk_offset = 0;
    769 
    770 	dent_blk = calloc(F2FS_BLKSIZE, 1);
    771 	if(dent_blk == NULL) {
    772 		MSG(1, "\tError: Calloc Failed for dent_blk!!!\n");
    773 		return -1;
    774 	}
    775 
    776 	dent_blk->dentry[0].hash_code = 0;
    777 	dent_blk->dentry[0].ino = super_block.root_ino;
    778 	dent_blk->dentry[0].name_len = cpu_to_le16(1);
    779 	dent_blk->dentry[0].file_type = F2FS_FT_DIR;
    780 	memcpy(dent_blk->filename[0], ".", 1);
    781 
    782 	dent_blk->dentry[1].hash_code = 0;
    783 	dent_blk->dentry[1].ino = super_block.root_ino;
    784 	dent_blk->dentry[1].name_len = cpu_to_le16(2);
    785 	dent_blk->dentry[1].file_type = F2FS_FT_DIR;
    786 	memcpy(dent_blk->filename[1], "..", 2);
    787 
    788 	/* bitmap for . and .. */
    789 	dent_blk->dentry_bitmap[0] = (1 << 1) | (1 << 0);
    790 	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
    791 	data_blk_offset = le32_to_cpu(super_block.main_blkaddr);
    792 	data_blk_offset += config.cur_seg[CURSEG_HOT_DATA] *
    793 				config.blks_per_seg;
    794 	data_blk_offset *= blk_size_bytes;
    795 
    796 	DBG(1, "\tWriting default dentry root, at offset 0x%08"PRIx64"\n", data_blk_offset);
    797 	if (dev_write(dent_blk, data_blk_offset, F2FS_BLKSIZE)) {
    798 		MSG(1, "\tError: While writing the dentry_blk to disk!!!\n");
    799 		return -1;
    800 	}
    801 
    802 	free(dent_blk);
    803 	return 0;
    804 }
    805 
    806 static int f2fs_create_root_dir(void)
    807 {
    808 	int err = 0;
    809 
    810 	err = f2fs_write_root_inode();
    811 	if (err < 0) {
    812 		MSG(1, "\tError: Failed to write root inode!!!\n");
    813 		goto exit;
    814 	}
    815 
    816 	err = f2fs_update_nat_root();
    817 	if (err < 0) {
    818 		MSG(1, "\tError: Failed to update NAT for root!!!\n");
    819 		goto exit;
    820 	}
    821 
    822 	err = f2fs_add_default_dentry_root();
    823 	if (err < 0) {
    824 		MSG(1, "\tError: Failed to add default dentries for root!!!\n");
    825 		goto exit;
    826 	}
    827 exit:
    828 	if (err)
    829 		MSG(1, "\tError: Could not create the root directory!!!\n");
    830 
    831 	return err;
    832 }
    833 
    834 int f2fs_format_device(void)
    835 {
    836 	int err = 0;
    837 
    838 	err= f2fs_prepare_super_block();
    839 	if (err < 0) {
    840 		MSG(0, "\tError: Failed to prepare a super block!!!\n");
    841 		goto exit;
    842 	}
    843 
    844 	err = f2fs_trim_device();
    845 	if (err < 0) {
    846 		MSG(0, "\tError: Failed to trim whole device!!!\n");
    847 		goto exit;
    848 	}
    849 
    850 	err = f2fs_init_sit_area();
    851 	if (err < 0) {
    852 		MSG(0, "\tError: Failed to Initialise the SIT AREA!!!\n");
    853 		goto exit;
    854 	}
    855 
    856 	err = f2fs_init_nat_area();
    857 	if (err < 0) {
    858 		MSG(0, "\tError: Failed to Initialise the NAT AREA!!!\n");
    859 		goto exit;
    860 	}
    861 
    862 	err = f2fs_create_root_dir();
    863 	if (err < 0) {
    864 		MSG(0, "\tError: Failed to create the root directory!!!\n");
    865 		goto exit;
    866 	}
    867 
    868 	err = f2fs_write_check_point_pack();
    869 	if (err < 0) {
    870 		MSG(0, "\tError: Failed to write the check point pack!!!\n");
    871 		goto exit;
    872 	}
    873 
    874 	err = f2fs_write_super_block();
    875 	if (err < 0) {
    876 		MSG(0, "\tError: Failed to write the Super Block!!!\n");
    877 		goto exit;
    878 	}
    879 exit:
    880 	if (err)
    881 		MSG(0, "\tError: Could not format the device!!!\n");
    882 
    883 	return err;
    884 }
    885