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