f2fs_format.c revision cc9d9caeb6853d38297d97d3dd4731c452418f02
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 NULL 134}; 135 136static void configure_extension_list(void) 137{ 138 const char **extlist = media_ext_lists; 139 char *ext_str = config.extension_list; 140 char *ue; 141 int name_len; 142 int i = 0; 143 144 super_block.extension_count = 0; 145 memset(super_block.extension_list, 0, 146 sizeof(super_block.extension_list)); 147 148 while (*extlist) { 149 name_len = strlen(*extlist); 150 memcpy(super_block.extension_list[i++], *extlist, name_len); 151 extlist++; 152 } 153 super_block.extension_count = i - 1; 154 155 if (!ext_str) 156 return; 157 158 /* add user ext list */ 159 ue = strtok(ext_str, ","); 160 while (ue != NULL) { 161 name_len = strlen(ue); 162 memcpy(super_block.extension_list[i++], ue, name_len); 163 ue = strtok(NULL, ","); 164 if (i > F2FS_MAX_EXTENSION) 165 break; 166 } 167 168 super_block.extension_count = i - 1; 169 170 free(config.extension_list); 171} 172 173static int f2fs_prepare_super_block(void) 174{ 175 u_int32_t blk_size_bytes; 176 u_int32_t log_sectorsize, log_sectors_per_block; 177 u_int32_t log_blocksize, log_blks_per_seg; 178 u_int32_t segment_size_bytes, zone_size_bytes; 179 u_int32_t sit_segments; 180 u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa; 181 u_int32_t total_valid_blks_available; 182 u_int64_t zone_align_start_offset, diff, total_meta_segments; 183 u_int32_t sit_bitmap_size, max_nat_bitmap_size, max_nat_segments; 184 u_int32_t total_zones; 185 186 super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC); 187 super_block.major_ver = cpu_to_le16(F2FS_MAJOR_VERSION); 188 super_block.minor_ver = cpu_to_le16(F2FS_MINOR_VERSION); 189 190 log_sectorsize = log_base_2(config.sector_size); 191 log_sectors_per_block = log_base_2(config.sectors_per_blk); 192 log_blocksize = log_sectorsize + log_sectors_per_block; 193 log_blks_per_seg = log_base_2(config.blks_per_seg); 194 195 super_block.log_sectorsize = cpu_to_le32(log_sectorsize); 196 197 if (log_sectorsize < 0) { 198 MSG(1, "\tError: Failed to get the sector size: %u!\n", 199 config.sector_size); 200 return -1; 201 } 202 203 super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block); 204 205 if (log_sectors_per_block < 0) { 206 MSG(1, "\tError: Failed to get sectors per block: %u!\n", 207 config.sectors_per_blk); 208 return -1; 209 } 210 211 super_block.log_blocksize = cpu_to_le32(log_blocksize); 212 super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg); 213 214 if (log_blks_per_seg < 0) { 215 MSG(1, "\tError: Failed to get block per segment: %u!\n", 216 config.blks_per_seg); 217 return -1; 218 } 219 220 super_block.segs_per_sec = cpu_to_le32(config.segs_per_sec); 221 super_block.secs_per_zone = cpu_to_le32(config.secs_per_zone); 222 blk_size_bytes = 1 << log_blocksize; 223 segment_size_bytes = blk_size_bytes * config.blks_per_seg; 224 zone_size_bytes = 225 blk_size_bytes * config.secs_per_zone * 226 config.segs_per_sec * config.blks_per_seg; 227 228 super_block.checksum_offset = 0; 229 230 super_block.block_count = cpu_to_le64( 231 (config.total_sectors * DEFAULT_SECTOR_SIZE) / 232 blk_size_bytes); 233 234 zone_align_start_offset = 235 (config.start_sector * DEFAULT_SECTOR_SIZE + 236 2 * F2FS_BLKSIZE + zone_size_bytes - 1) / 237 zone_size_bytes * zone_size_bytes - 238 config.start_sector * DEFAULT_SECTOR_SIZE; 239 240 if (config.start_sector % DEFAULT_SECTORS_PER_BLOCK) { 241 MSG(1, "\tWARN: Align start sector number to the page unit\n"); 242 MSG(1, "\ti.e., start sector: %d, ofs:%d (sects/page: %d)\n", 243 config.start_sector, 244 config.start_sector % DEFAULT_SECTORS_PER_BLOCK, 245 DEFAULT_SECTORS_PER_BLOCK); 246 } 247 248 super_block.segment_count = cpu_to_le32( 249 ((config.total_sectors * DEFAULT_SECTOR_SIZE) - 250 zone_align_start_offset) / segment_size_bytes); 251 252 super_block.segment0_blkaddr = 253 cpu_to_le32(zone_align_start_offset / blk_size_bytes); 254 super_block.cp_blkaddr = super_block.segment0_blkaddr; 255 256 MSG(0, "Info: zone aligned segment0 blkaddr: %u\n", 257 le32_to_cpu(super_block.segment0_blkaddr)); 258 259 super_block.segment_count_ckpt = 260 cpu_to_le32(F2FS_NUMBER_OF_CHECKPOINT_PACK); 261 262 super_block.sit_blkaddr = cpu_to_le32( 263 le32_to_cpu(super_block.segment0_blkaddr) + 264 (le32_to_cpu(super_block.segment_count_ckpt) * 265 (1 << log_blks_per_seg))); 266 267 blocks_for_sit = (le32_to_cpu(super_block.segment_count) + 268 SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK; 269 270 sit_segments = (blocks_for_sit + config.blks_per_seg - 1) 271 / config.blks_per_seg; 272 273 super_block.segment_count_sit = cpu_to_le32(sit_segments * 2); 274 275 super_block.nat_blkaddr = cpu_to_le32( 276 le32_to_cpu(super_block.sit_blkaddr) + 277 (le32_to_cpu(super_block.segment_count_sit) * 278 config.blks_per_seg)); 279 280 total_valid_blks_available = (le32_to_cpu(super_block.segment_count) - 281 (le32_to_cpu(super_block.segment_count_ckpt) + 282 le32_to_cpu(super_block.segment_count_sit))) * 283 config.blks_per_seg; 284 285 blocks_for_nat = (total_valid_blks_available + NAT_ENTRY_PER_BLOCK - 1) 286 / NAT_ENTRY_PER_BLOCK; 287 288 super_block.segment_count_nat = cpu_to_le32( 289 (blocks_for_nat + config.blks_per_seg - 1) / 290 config.blks_per_seg); 291 /* 292 * The number of node segments should not be exceeded a "Threshold". 293 * This number resizes NAT bitmap area in a CP page. 294 * So the threshold is determined not to overflow one CP page 295 */ 296 sit_bitmap_size = ((le32_to_cpu(super_block.segment_count_sit) / 2) << 297 log_blks_per_seg) / 8; 298 max_nat_bitmap_size = 4096 - sizeof(struct f2fs_checkpoint) + 1 - 299 sit_bitmap_size; 300 max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg; 301 302 if (le32_to_cpu(super_block.segment_count_nat) > max_nat_segments) 303 super_block.segment_count_nat = cpu_to_le32(max_nat_segments); 304 305 super_block.segment_count_nat = cpu_to_le32( 306 le32_to_cpu(super_block.segment_count_nat) * 2); 307 308 super_block.ssa_blkaddr = cpu_to_le32( 309 le32_to_cpu(super_block.nat_blkaddr) + 310 le32_to_cpu(super_block.segment_count_nat) * 311 config.blks_per_seg); 312 313 total_valid_blks_available = (le32_to_cpu(super_block.segment_count) - 314 (le32_to_cpu(super_block.segment_count_ckpt) + 315 le32_to_cpu(super_block.segment_count_sit) + 316 le32_to_cpu(super_block.segment_count_nat))) * 317 config.blks_per_seg; 318 319 blocks_for_ssa = total_valid_blks_available / 320 config.blks_per_seg + 1; 321 322 super_block.segment_count_ssa = cpu_to_le32( 323 (blocks_for_ssa + config.blks_per_seg - 1) / 324 config.blks_per_seg); 325 326 total_meta_segments = le32_to_cpu(super_block.segment_count_ckpt) + 327 le32_to_cpu(super_block.segment_count_sit) + 328 le32_to_cpu(super_block.segment_count_nat) + 329 le32_to_cpu(super_block.segment_count_ssa); 330 diff = total_meta_segments % (config.segs_per_sec * 331 config.secs_per_zone); 332 if (diff) 333 super_block.segment_count_ssa = cpu_to_le32( 334 le32_to_cpu(super_block.segment_count_ssa) + 335 (config.segs_per_sec * config.secs_per_zone - 336 diff)); 337 338 super_block.main_blkaddr = cpu_to_le32( 339 le32_to_cpu(super_block.ssa_blkaddr) + 340 (le32_to_cpu(super_block.segment_count_ssa) * 341 config.blks_per_seg)); 342 343 super_block.segment_count_main = cpu_to_le32( 344 le32_to_cpu(super_block.segment_count) - 345 (le32_to_cpu(super_block.segment_count_ckpt) 346 + le32_to_cpu(super_block.segment_count_sit) + 347 le32_to_cpu(super_block.segment_count_nat) + 348 le32_to_cpu(super_block.segment_count_ssa))); 349 350 super_block.section_count = cpu_to_le32( 351 le32_to_cpu(super_block.segment_count_main) 352 / config.segs_per_sec); 353 354 super_block.segment_count_main = cpu_to_le32( 355 le32_to_cpu(super_block.section_count) * 356 config.segs_per_sec); 357 358 if ((le32_to_cpu(super_block.segment_count_main) - 2) < 359 config.reserved_segments) { 360 MSG(1, "\tError: Device size is not sufficient for F2FS volume,\ 361 more segment needed =%u", 362 config.reserved_segments - 363 (le32_to_cpu(super_block.segment_count_main) - 2)); 364 return -1; 365 } 366 367 uuid_generate(super_block.uuid); 368 369 ASCIIToUNICODE(super_block.volume_name, (u_int8_t *)config.vol_label); 370 371 super_block.node_ino = cpu_to_le32(1); 372 super_block.meta_ino = cpu_to_le32(2); 373 super_block.root_ino = cpu_to_le32(3); 374 375 total_zones = ((le32_to_cpu(super_block.segment_count_main) - 1) / 376 config.segs_per_sec) / 377 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 |= 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 if (S_ISREG(stat_buf.st_mode)) 921 return 0; 922 else if (S_ISBLK(stat_buf.st_mode)) { 923 if (ioctl(config.fd, BLKDISCARD, &range) < 0) 924 MSG(0, "Info: This device doesn't support TRIM\n"); 925 } else 926 return -1; 927 return 0; 928} 929 930static int f2fs_format_device(void) 931{ 932 int err = 0; 933 934 err= f2fs_prepare_super_block(); 935 if (err < 0) { 936 MSG(0, "\tError: Failed to prepare a super block!!!\n"); 937 goto exit; 938 } 939 940 err = f2fs_trim_device(); 941 if (err < 0) { 942 MSG(0, "\tError: Failed to trim whole device!!!\n"); 943 goto exit; 944 } 945 946 err = f2fs_init_sit_area(); 947 if (err < 0) { 948 MSG(0, "\tError: Failed to Initialise the SIT AREA!!!\n"); 949 goto exit; 950 } 951 952 err = f2fs_init_nat_area(); 953 if (err < 0) { 954 MSG(0, "\tError: Failed to Initialise the NAT AREA!!!\n"); 955 goto exit; 956 } 957 958 err = f2fs_create_root_dir(); 959 if (err < 0) { 960 MSG(0, "\tError: Failed to create the root directory!!!\n"); 961 goto exit; 962 } 963 964 err = f2fs_write_check_point_pack(); 965 if (err < 0) { 966 MSG(0, "\tError: Failed to write the check point pack!!!\n"); 967 goto exit; 968 } 969 970 err = f2fs_write_super_block(); 971 if (err < 0) { 972 MSG(0, "\tError: Failed to write the Super Block!!!\n"); 973 goto exit; 974 } 975exit: 976 if (err) 977 MSG(0, "\tError: Could not format the device!!!\n"); 978 979 /* 980 * We should call fsync() to flush out all the dirty pages 981 * in the block device page cache. 982 */ 983 if (fsync(config.fd) < 0) 984 MSG(0, "\tError: Could not conduct fsync!!!\n"); 985 986 if (close(config.fd) < 0) 987 MSG(0, "\tError: Failed to close device file!!!\n"); 988 989 return err; 990} 991 992int main(int argc, char *argv[]) 993{ 994 MSG(0, "\n\tF2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n", 995 F2FS_TOOLS_VERSION, 996 F2FS_TOOLS_DATE); 997 f2fs_init_configuration(&config); 998 999 f2fs_parse_options(argc, argv); 1000 1001 if (f2fs_dev_is_mounted(&config) < 0) 1002 return -1; 1003 1004 if (f2fs_get_device_info(&config) < 0) 1005 return -1; 1006 1007 if (f2fs_format_device() < 0) 1008 return -1; 1009 1010 MSG(0, "Info: format successful\n"); 1011 1012 return 0; 1013} 1014