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