f2fs_format.c revision 036d45e551ca5405c726f8ccb51f446620cd4af4
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 <errno.h> 19#include <mntent.h> 20#include <sys/types.h> 21#include <sys/stat.h> 22#include <sys/ioctl.h> 23#include <sys/mount.h> 24#include <linux/hdreg.h> 25#include <time.h> 26#include <linux/fs.h> 27 28#include "f2fs_format.h" 29 30struct f2fs_global_parameters f2fs_params; 31struct f2fs_super_block super_block; 32 33/** 34 * @brief This function will change a given string from ASCII to UNICODE 35 * @param out_buf Output UNICODE string 36 * @param in_buf Input ASCII string 37 * @return None 38 */ 39void ASCIIToUNICODE(u_int16_t *out_buf, u_int8_t *in_buf) 40{ 41 u_int8_t *pchTempPtr = in_buf; 42 u_int16_t *pwTempPtr = out_buf; 43 44 while (*pchTempPtr != '\0') { 45 /* Copy the string elements character by character 46 * to the output string with typecasting the source. 47 */ 48 *pwTempPtr = (u_int16_t)*pchTempPtr; 49 pchTempPtr++; 50 pwTempPtr++; 51 } 52 *pwTempPtr = '\0'; 53 return; 54} 55 56/** 57 * @brief This function will ntitlize f2fs global paramenters 58 * @param None 59 * @return None 60 */ 61static void f2fs_init_global_parameters(void) 62{ 63 f2fs_params.sector_size = DEFAULT_SECTOR_SIZE; 64 f2fs_params.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK; 65 f2fs_params.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT; 66 f2fs_params.reserved_segments = 20; /* calculated by overprovision ratio */ 67 f2fs_params.overprovision = 5; 68 f2fs_params.segs_per_sec = 1; 69 f2fs_params.secs_per_zone = 1; 70 f2fs_params.heap = 1; 71 memset(f2fs_params.vol_label, 0, sizeof(f2fs_params.vol_label)); 72 73 f2fs_params.vol_label[0] = 'F'; 74 f2fs_params.vol_label[1] = '2'; 75 f2fs_params.vol_label[2] = 'F'; 76 f2fs_params.vol_label[3] = 'S'; 77 f2fs_params.vol_label[4] = '\0'; 78 f2fs_params.device_name = NULL; 79} 80 81static inline int f2fs_set_bit(unsigned int nr, unsigned char *addr) 82{ 83 int mask; 84 int ret; 85 86 addr += (nr >> 3); 87 mask = 1 << (7 - (nr & 0x07)); 88 ret = mask & *addr; 89 *addr |= mask; 90 return ret; 91} 92 93/** 94 * @brief This function calculates log base 2 of given number 95 * @param num an integer number 96 * @return an int log base 2 of given number 97 */ 98static int8_t log_base_2(u_int32_t num) 99{ 100 int8_t ret = 0; 101 102 if (num <= 0 || (num & (num - 1)) != 0) { 103 return -1; 104 } 105 106 while (num >>= 1) { 107 ret++; 108 } 109 110 return ret; 111} 112 113/** 114 * @brief This function shows error if user gives wrong parameters 115 * @param None 116 * @return None 117 */ 118static void f2fs_usage(void) 119{ 120 fprintf(stderr, "Usage: f2fs_format [options] device\n"); 121 fprintf(stderr, "[options]\n"); 122 fprintf(stderr, "-l label\n"); 123 fprintf(stderr, "-a heap-based allocation [default:1]\n"); 124 fprintf(stderr, "-o overprovision ratio [default:5]\n"); 125 fprintf(stderr, "-s # of segments per section [default:1]\n"); 126 fprintf(stderr, "-z # of sections per zone [default:1]\n"); 127 fprintf(stderr, "-e [extension list] e.g. \"mp3,gif,mov\"\n"); 128 exit(1); 129} 130 131/** 132 * @brief This function calculates log base 2 of given number 133 * @param argc number of arguments 134 * @param argv an array of arguments 135 * @return None 136 */ 137static void f2fs_parse_options(int argc, char *argv[]) 138{ 139 static const char *option_string = "l:o:z:a:s:e:"; 140 int32_t option=0; 141 142 while ((option = getopt(argc,argv,option_string)) != EOF) { 143 switch (option) { 144 case 'l': /*v: volume label */ 145 if (strlen(optarg) > 512) { 146 printf("Error: Volume Label should be less than \ 147 512 characters\n"); 148 f2fs_usage(); 149 } 150 sprintf((char *)f2fs_params.vol_label, "%s", optarg); 151 break; 152 case 'o': 153 f2fs_params.overprovision = atoi(optarg); 154 printf("Info: Overprovision ratio = %u%%\n", atoi(optarg)); 155 break; 156 case 's': 157 f2fs_params.segs_per_sec = atoi(optarg); 158 printf("Info: segments per section = %d\n", atoi(optarg)); 159 break; 160 case 'a': 161 f2fs_params.heap = atoi(optarg); 162 if (f2fs_params.heap == 0) 163 printf("Info: Allocate without heap-based policy\n"); 164 break; 165 case 'z': 166 f2fs_params.secs_per_zone = atoi(optarg); 167 printf("Info: sections per zone = %d\n", atoi(optarg)); 168 break; 169 case 'e': 170 f2fs_params.extension_list = strdup(optarg); 171 break; 172 default: 173 printf("Error: Unknown option %c\n",option); 174 f2fs_usage(); 175 break; 176 } 177 } 178 179 if ((optind + 1) != argc) { 180 printf("Error: Device not specified\n"); 181 f2fs_usage(); 182 } 183 184 f2fs_params.reserved_segments = 185 (100 / f2fs_params.overprovision + 5) 186 * f2fs_params.segs_per_sec; 187 f2fs_params.device_name = argv[optind]; 188} 189 190/** 191 * @brief Routine to check if the device is already mounted 192 * @param None 193 * @return 0 if device is not mounted 194 * -1 if already mounted 195 */ 196static int8_t f2fs_is_device_mounted() 197{ 198 FILE *file; 199 struct mntent *mnt; /* mntent structure to retrieve mount info */ 200 201 if ((file = setmntent(MOUNTED, "r")) == NULL) 202 return 0; 203 204 while ((mnt = getmntent(file)) != NULL) { 205 if (!strcmp(f2fs_params.device_name, mnt->mnt_fsname)) { 206 printf("Error: %s is already mounted\n", 207 f2fs_params.device_name); 208 return -1; 209 } 210 } 211 endmntent(file); 212 return 0; 213} 214 215/** 216 * @brief Get device info - sector size, number of sectors etc 217 * @param None 218 * @return 0 if successfully got device info 219 */ 220static int8_t f2fs_get_device_info() 221{ 222 int32_t fd = 0; 223 int32_t sector_size; 224 struct stat stat_buf; 225 struct hd_geometry geom; 226 227 fd = open(f2fs_params.device_name, O_RDWR); 228 if (fd < 0) { 229 printf("\n\tError: Failed to open the device!!!\n"); 230 return -1; 231 } 232 f2fs_params.fd = fd; 233 234 if (fstat(fd, &stat_buf) < 0 ) { 235 printf("\n\tError: Failed to get the device stat!!!\n"); 236 return -1; 237 } 238 239 if (S_ISREG(stat_buf.st_mode)) { 240 f2fs_params.total_sectors = stat_buf.st_size / 241 f2fs_params.sector_size; 242 } 243 else if (S_ISBLK(stat_buf.st_mode)) { 244 if (ioctl(fd, BLKSSZGET, §or_size) < 0 ) 245 printf("\n\tError: Cannot get the sector size!!! \ 246 Using the default Sector Size\n"); 247 else { 248 if (f2fs_params.sector_size < sector_size) { 249 printf("\n\tError: Cannot set the sector size to: %d" 250 " as the device does not support" 251 "\nSetting the sector size to : %d\n", 252 f2fs_params.sector_size, sector_size); 253 f2fs_params.sector_size = sector_size; 254 f2fs_params.sectors_per_blk = PAGE_SIZE / sector_size; 255 } 256 } 257 258 if (ioctl(fd, BLKGETSIZE, &f2fs_params.total_sectors) < 0) { 259 printf("\n\tError: Cannot get the device size\n"); 260 return -1; 261 } 262 263 if (ioctl(fd, HDIO_GETGEO, &geom) < 0) { 264 printf("\n\tError: Cannot get the device geometry\n"); 265 return -1; 266 } 267 f2fs_params.start_sector = geom.start; 268 } 269 else { 270 printf("\n\n\tError: Volume type is not supported!!!\n"); 271 return -1; 272 } 273 274 printf("Info: sector size = %u\n", f2fs_params.sector_size); 275 printf("Info: total sectors = %llu (in 512bytes)\n", f2fs_params.total_sectors); 276 if (f2fs_params.total_sectors < 277 (F2FS_MIN_VOLUME_SIZE / DEFAULT_SECTOR_SIZE)) { 278 printf("Error: Min volume size supported is %d\n", 279 F2FS_MIN_VOLUME_SIZE); 280 return -1; 281 } 282 283 return 0; 284} 285 286const char *media_ext_lists[] = { 287 "jpg", 288 "gif", 289 "png", 290 "avi", 291 "divx", 292 "mp4", 293 "mp3", 294 "3gp", 295 "wmv", 296 "wma", 297 "mpeg", 298 "mkv", 299 "mov", 300 "asx", 301 "asf", 302 "wmx", 303 "svi", 304 "wvx", 305 "wm", 306 "mpg", 307 "mpe", 308 "rm", 309 "ogg", 310 NULL 311}; 312 313static void configure_extension_list(void) 314{ 315 const char **extlist = media_ext_lists; 316 char *ext_str = f2fs_params.extension_list; 317 char *ue; 318 int name_len; 319 int i = 0; 320 321 super_block.extension_count = 0; 322 memset(super_block.extension_list, 0, 323 sizeof(super_block.extension_list)); 324 325 while (*extlist) { 326 name_len = strlen(*extlist); 327 memcpy(super_block.extension_list[i++], *extlist, name_len); 328 extlist++; 329 } 330 super_block.extension_count = i - 1; 331 332 if (!ext_str) 333 return; 334 335 /* add user ext list */ 336 ue = strtok(ext_str, ","); 337 while (ue != NULL) { 338 name_len = strlen(ue); 339 memcpy(super_block.extension_list[i++], ue, name_len); 340 ue = strtok(NULL, ","); 341 if (i > F2FS_MAX_EXTENSION) 342 break; 343 } 344 345 super_block.extension_count = i - 1; 346 347 free(f2fs_params.extension_list); 348} 349 350 351/** 352 * @brief It writes buffer to disk or storage meant to be formatted 353 * with F2FS. 354 * @param fd File descriptor for device 355 * @param buf buffer to be written 356 * @param offset where to bw written on the device 357 * @param length length of the device 358 * @return 0 if success 359 */ 360static int writetodisk(int32_t fd, void *buf, u_int64_t offset, size_t length) 361{ 362 if (lseek64(fd, offset, SEEK_SET) < 0) { 363 printf("\n\tError: While lseek to the derised location!!!\n"); 364 return -1; 365 } 366 367 if (write(fd, buf, length) < 0) { 368 printf("\n\tError: While writing data to the disk!!! Error Num : \ 369 %d\n", errno); 370 return -1; 371 } 372 373 return 0; 374} 375 376/** 377 * @brief It initialize F2FS super block 378 * @param None 379 * @return None 380 */ 381static int f2fs_prepare_super_block(void) 382{ 383 u_int32_t blk_size_bytes; 384 u_int32_t log_sectorsize, log_sectors_per_block; 385 u_int32_t log_blocksize, log_blks_per_seg; 386 u_int32_t segment_size_bytes, zone_size_bytes; 387 u_int32_t sit_segments; 388 u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa; 389 u_int32_t total_valid_blks_available; 390 u_int64_t zone_align_start_offset, diff, total_meta_segments; 391 u_int32_t sit_bitmap_size, max_nat_bitmap_size, max_nat_segments; 392 u_int32_t total_zones; 393 394 super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC); 395 super_block.major_ver = cpu_to_le16(F2FS_MAJOR_VERSION); 396 super_block.minor_ver = cpu_to_le16(F2FS_MINOR_VERSION); 397 398 log_sectorsize = log_base_2(f2fs_params.sector_size); 399 log_sectors_per_block = log_base_2(f2fs_params.sectors_per_blk); 400 log_blocksize = log_sectorsize + log_sectors_per_block; 401 log_blks_per_seg = log_base_2(f2fs_params.blks_per_seg); 402 403 super_block.log_sectorsize = cpu_to_le32(log_sectorsize); 404 405 if (log_sectorsize < 0) { 406 printf("\n\tError: Failed to get the sector size: %u!\n", 407 f2fs_params.sector_size); 408 return -1; 409 } 410 411 super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block); 412 413 if (log_sectors_per_block < 0) { 414 printf("\n\tError: Failed to get sectors per block: %u!\n", 415 f2fs_params.sectors_per_blk); 416 return -1; 417 } 418 419 super_block.log_blocksize = cpu_to_le32(log_blocksize); 420 super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg); 421 422 if (log_blks_per_seg < 0) { 423 printf("\n\tError: Failed to get block per segment: %u!\n", 424 f2fs_params.blks_per_seg); 425 return -1; 426 } 427 428 super_block.segs_per_sec = cpu_to_le32(f2fs_params.segs_per_sec); 429 super_block.secs_per_zone = cpu_to_le32(f2fs_params.secs_per_zone); 430 blk_size_bytes = 1 << log_blocksize; 431 segment_size_bytes = blk_size_bytes * f2fs_params.blks_per_seg; 432 zone_size_bytes = 433 blk_size_bytes * f2fs_params.secs_per_zone * 434 f2fs_params.segs_per_sec * f2fs_params.blks_per_seg; 435 436 super_block.checksum_offset = 0; 437 438 super_block.block_count = cpu_to_le64( 439 (f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE) / 440 blk_size_bytes); 441 442 zone_align_start_offset = 443 (f2fs_params.start_sector * DEFAULT_SECTOR_SIZE + 444 F2FS_SUPER_OFFSET * F2FS_BLKSIZE + 445 sizeof(struct f2fs_super_block) * 2 + 446 zone_size_bytes - 1) / zone_size_bytes * zone_size_bytes - 447 f2fs_params.start_sector * DEFAULT_SECTOR_SIZE; 448 449 if (f2fs_params.start_sector % DEFAULT_SECTORS_PER_BLOCK) { 450 printf("WARN: Align start sector number in a unit of pages\n"); 451 printf("\ti.e., start sector: %d, ofs:%d (sectors per page: %d)\n", 452 f2fs_params.start_sector, 453 f2fs_params.start_sector % DEFAULT_SECTORS_PER_BLOCK, 454 DEFAULT_SECTORS_PER_BLOCK); 455 } 456 457 super_block.segment_count = cpu_to_le32( 458 ((f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE) - 459 zone_align_start_offset) / segment_size_bytes); 460 461 super_block.segment0_blkaddr = 462 cpu_to_le32(zone_align_start_offset / blk_size_bytes); 463 464 printf("Info: zone aligned segment0 blkaddr: %u\n", 465 le32_to_cpu(super_block.segment0_blkaddr)); 466 467 super_block.start_segment_checkpoint = super_block.segment0_blkaddr; 468 super_block.segment_count_ckpt = 469 cpu_to_le32(F2FS_NUMBER_OF_CHECKPOINT_PACK); 470 471 super_block.sit_blkaddr = cpu_to_le32( 472 le32_to_cpu(super_block.start_segment_checkpoint) + 473 (le32_to_cpu(super_block.segment_count_ckpt) * 474 (1 << log_blks_per_seg))); 475 476 blocks_for_sit = (le32_to_cpu(super_block.segment_count) + 477 SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK; 478 479 sit_segments = (blocks_for_sit + f2fs_params.blks_per_seg - 1) 480 / f2fs_params.blks_per_seg; 481 482 super_block.segment_count_sit = cpu_to_le32(sit_segments * 2); 483 484 super_block.nat_blkaddr = cpu_to_le32( 485 le32_to_cpu(super_block.sit_blkaddr) + 486 (le32_to_cpu(super_block.segment_count_sit) * 487 f2fs_params.blks_per_seg)); 488 489 total_valid_blks_available = (le32_to_cpu(super_block.segment_count) - 490 (le32_to_cpu(super_block.segment_count_ckpt) + 491 le32_to_cpu(super_block.segment_count_sit))) * 492 f2fs_params.blks_per_seg; 493 494 blocks_for_nat = (total_valid_blks_available + NAT_ENTRY_PER_BLOCK - 1) 495 / NAT_ENTRY_PER_BLOCK; 496 497 super_block.segment_count_nat = cpu_to_le32( 498 (blocks_for_nat + f2fs_params.blks_per_seg - 1) / 499 f2fs_params.blks_per_seg); 500 /* 501 * The number of node segments should not be exceeded a "Threshold". 502 * This number resizes NAT bitmap area in a CP page. 503 * So the threshold is determined not to overflow one CP page 504 */ 505 sit_bitmap_size = ((le32_to_cpu(super_block.segment_count_sit) / 2) << 506 log_blks_per_seg) / 8; 507 max_nat_bitmap_size = 4096 - sizeof(struct f2fs_checkpoint) + 1 - 508 sit_bitmap_size; 509 max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg; 510 511 if (le32_to_cpu(super_block.segment_count_nat) > max_nat_segments) 512 super_block.segment_count_nat = cpu_to_le32(max_nat_segments); 513 514 super_block.segment_count_nat = cpu_to_le32( 515 le32_to_cpu(super_block.segment_count_nat) * 2); 516 517 super_block.ssa_blkaddr = cpu_to_le32( 518 le32_to_cpu(super_block.nat_blkaddr) + 519 le32_to_cpu(super_block.segment_count_nat) * 520 f2fs_params.blks_per_seg); 521 522 total_valid_blks_available = (le32_to_cpu(super_block.segment_count) - 523 (le32_to_cpu(super_block.segment_count_ckpt) + 524 le32_to_cpu(super_block.segment_count_sit) + 525 le32_to_cpu(super_block.segment_count_nat))) * 526 f2fs_params.blks_per_seg; 527 528 blocks_for_ssa = total_valid_blks_available / 529 f2fs_params.blks_per_seg + 1; 530 531 super_block.segment_count_ssa = cpu_to_le32( 532 (blocks_for_ssa + f2fs_params.blks_per_seg - 1) / 533 f2fs_params.blks_per_seg); 534 535 total_meta_segments = le32_to_cpu(super_block.segment_count_ckpt) + 536 le32_to_cpu(super_block.segment_count_sit) + 537 le32_to_cpu(super_block.segment_count_nat) + 538 le32_to_cpu(super_block.segment_count_ssa); 539 diff = total_meta_segments % (f2fs_params.segs_per_sec * 540 f2fs_params.secs_per_zone); 541 if (diff) 542 super_block.segment_count_ssa = cpu_to_le32( 543 le32_to_cpu(super_block.segment_count_ssa) + 544 (f2fs_params.segs_per_sec * f2fs_params.secs_per_zone - 545 diff)); 546 547 super_block.main_blkaddr = cpu_to_le32( 548 le32_to_cpu(super_block.ssa_blkaddr) + 549 (le32_to_cpu(super_block.segment_count_ssa) * 550 f2fs_params.blks_per_seg)); 551 552 super_block.segment_count_main = cpu_to_le32( 553 le32_to_cpu(super_block.segment_count) - 554 (le32_to_cpu(super_block.segment_count_ckpt) 555 + le32_to_cpu(super_block.segment_count_sit) + 556 le32_to_cpu(super_block.segment_count_nat) + 557 le32_to_cpu(super_block.segment_count_ssa))); 558 559 super_block.section_count = cpu_to_le32( 560 le32_to_cpu(super_block.segment_count_main) 561 / f2fs_params.segs_per_sec); 562 563 super_block.segment_count_main = cpu_to_le32( 564 le32_to_cpu(super_block.section_count) * 565 f2fs_params.segs_per_sec); 566 567 if ((le32_to_cpu(super_block.segment_count_main) - 2) < 568 f2fs_params.reserved_segments) { 569 printf("Error: Device size is not sufficient for F2FS volume, \ 570 more segment needed =%u", 571 f2fs_params.reserved_segments - 572 (le32_to_cpu(super_block.segment_count_main) - 2)); 573 return -1; 574 } 575 576 super_block.failure_safe_block_distance = 0; 577 super_block.volume_serial_number = 0; 578 579 ASCIIToUNICODE(super_block.volume_name, f2fs_params.vol_label); 580 581 super_block.node_ino = cpu_to_le32(1); 582 super_block.meta_ino = cpu_to_le32(2); 583 super_block.root_ino = cpu_to_le32(3); 584 585 total_zones = ((le32_to_cpu(super_block.segment_count_main) - 1) / 586 f2fs_params.segs_per_sec) / 587 f2fs_params.secs_per_zone; 588 if (total_zones <= 6) { 589 printf("\n\tError: %d zones: Need more zones \ 590 by shrinking zone size\n", total_zones); 591 return -1; 592 } 593 594 if (f2fs_params.heap) { 595 f2fs_params.cur_seg[CURSEG_HOT_NODE] = (total_zones - 1) * 596 f2fs_params.segs_per_sec * 597 f2fs_params.secs_per_zone + 598 ((f2fs_params.secs_per_zone - 1) * 599 f2fs_params.segs_per_sec); 600 f2fs_params.cur_seg[CURSEG_WARM_NODE] = 601 f2fs_params.cur_seg[CURSEG_HOT_NODE] - 602 f2fs_params.segs_per_sec * 603 f2fs_params.secs_per_zone; 604 f2fs_params.cur_seg[CURSEG_COLD_NODE] = 605 f2fs_params.cur_seg[CURSEG_WARM_NODE] - 606 f2fs_params.segs_per_sec * 607 f2fs_params.secs_per_zone; 608 f2fs_params.cur_seg[CURSEG_HOT_DATA] = 609 f2fs_params.cur_seg[CURSEG_COLD_NODE] - 610 f2fs_params.segs_per_sec * 611 f2fs_params.secs_per_zone; 612 f2fs_params.cur_seg[CURSEG_COLD_DATA] = 0; 613 f2fs_params.cur_seg[CURSEG_WARM_DATA] = 614 f2fs_params.cur_seg[CURSEG_COLD_DATA] + 615 f2fs_params.segs_per_sec * 616 f2fs_params.secs_per_zone; 617 } else { 618 f2fs_params.cur_seg[CURSEG_HOT_NODE] = 0; 619 f2fs_params.cur_seg[CURSEG_WARM_NODE] = 620 f2fs_params.cur_seg[CURSEG_HOT_NODE] + 621 f2fs_params.segs_per_sec * 622 f2fs_params.secs_per_zone; 623 f2fs_params.cur_seg[CURSEG_COLD_NODE] = 624 f2fs_params.cur_seg[CURSEG_WARM_NODE] + 625 f2fs_params.segs_per_sec * 626 f2fs_params.secs_per_zone; 627 f2fs_params.cur_seg[CURSEG_HOT_DATA] = 628 f2fs_params.cur_seg[CURSEG_COLD_NODE] + 629 f2fs_params.segs_per_sec * 630 f2fs_params.secs_per_zone; 631 f2fs_params.cur_seg[CURSEG_COLD_DATA] = 632 f2fs_params.cur_seg[CURSEG_HOT_DATA] + 633 f2fs_params.segs_per_sec * 634 f2fs_params.secs_per_zone; 635 f2fs_params.cur_seg[CURSEG_WARM_DATA] = 636 f2fs_params.cur_seg[CURSEG_COLD_DATA] + 637 f2fs_params.segs_per_sec * 638 f2fs_params.secs_per_zone; 639 } 640 641 configure_extension_list(); 642 643 return 0; 644} 645 646/** 647 * @brief It initialize SIT Data structure 648 * @param None 649 * @return 0 if success 650 */ 651static int8_t f2fs_init_sit_area(void) 652{ 653 u_int32_t blk_size_bytes; 654 u_int32_t seg_size_bytes; 655 u_int32_t index = 0; 656 u_int64_t sit_seg_blk_offset = 0; 657 u_int8_t *zero_buf = NULL; 658 659 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 660 seg_size_bytes = (1 << le32_to_cpu(super_block.log_blocks_per_seg)) * 661 blk_size_bytes; 662 663 zero_buf = calloc(sizeof(u_int8_t), seg_size_bytes); 664 if(zero_buf == NULL) { 665 printf("\n\tError: Calloc Failed for sit_zero_buf!!!\n"); 666 return -1; 667 } 668 669 sit_seg_blk_offset = le32_to_cpu(super_block.sit_blkaddr) * 670 blk_size_bytes; 671 672 for (index = 0; 673 index < (le32_to_cpu(super_block.segment_count_sit) / 2); 674 index++) { 675 if (writetodisk(f2fs_params.fd, zero_buf, sit_seg_blk_offset, 676 seg_size_bytes) < 0) { 677 printf("\n\tError: While zeroing out the sit area \ 678 on disk!!!\n"); 679 return -1; 680 } 681 sit_seg_blk_offset = sit_seg_blk_offset + seg_size_bytes; 682 } 683 684 free(zero_buf); 685 return 0 ; 686} 687 688/** 689 * @brief It initialize NAT Area 690 * @param None 691 * @return 0 if success 692 */ 693static int8_t f2fs_init_nat_area(void) 694{ 695 u_int32_t blk_size_bytes; 696 u_int32_t seg_size_bytes; 697 u_int32_t index = 0; 698 u_int64_t nat_seg_blk_offset = 0; 699 u_int8_t *nat_buf = NULL; 700 701 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 702 seg_size_bytes = (1 << le32_to_cpu(super_block.log_blocks_per_seg)) * 703 blk_size_bytes; 704 705 nat_buf = calloc(sizeof(u_int8_t), seg_size_bytes); 706 if (nat_buf == NULL) { 707 printf("\n\tError: Calloc Failed for nat_zero_blk!!!\n"); 708 return -1; 709 } 710 711 nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr) * 712 blk_size_bytes; 713 714 for (index = 0; 715 index < (le32_to_cpu(super_block.segment_count_nat) / 2); 716 index++) { 717 if (writetodisk(f2fs_params.fd, nat_buf, nat_seg_blk_offset, 718 seg_size_bytes) < 0) { 719 printf("\n\tError: While zeroing out the nat area \ 720 on disk!!!\n"); 721 return -1; 722 } 723 nat_seg_blk_offset = nat_seg_blk_offset + (2 * seg_size_bytes); 724 } 725 726 free(nat_buf); 727 return 0 ; 728} 729 730#define CRCPOLY_LE 0xedb88320 731 732unsigned int f2fs_cal_crc32(unsigned int crc, void *buff, unsigned int len) 733{ 734 int i; 735 unsigned char *p = (unsigned char *)buff; 736 while (len--) { 737 crc ^= *p++; 738 for (i = 0; i < 8; i++) 739 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); 740 } 741 return crc; 742} 743 744/** 745 * @brief It writes check poiint pack on Check point Area 746 * @param None 747 * @return 0 if succes 748 */ 749static int8_t f2fs_write_check_point_pack(void) 750{ 751 struct f2fs_checkpoint *ckp = NULL; 752 struct f2fs_summary_block *sum = NULL; 753 u_int32_t blk_size_bytes; 754 u_int64_t cp_seg_blk_offset = 0; 755 u_int32_t crc = 0; 756 int i; 757 758 ckp = calloc(F2FS_CP_BLOCK_SIZE, 1); 759 if (ckp == NULL) { 760 printf("\n\tError: Calloc Failed for f2fs_checkpoint!!!\n"); 761 return -1; 762 } 763 764 sum = calloc(sizeof(struct f2fs_summary_block), 1); 765 if (sum == NULL) { 766 printf("\n\tError: Calloc Failed for summay_node!!!\n"); 767 return -1; 768 } 769 770 /* 1. cp page 1 of checkpoint pack 1 */ 771 ckp->checkpoint_ver = 1; 772 ckp->cur_node_segno[0] = 773 cpu_to_le32(f2fs_params.cur_seg[CURSEG_HOT_NODE]); 774 ckp->cur_node_segno[1] = 775 cpu_to_le32(f2fs_params.cur_seg[CURSEG_WARM_NODE]); 776 ckp->cur_node_segno[2] = 777 cpu_to_le32(f2fs_params.cur_seg[CURSEG_COLD_NODE]); 778 ckp->cur_data_segno[0] = 779 cpu_to_le32(f2fs_params.cur_seg[CURSEG_HOT_DATA]); 780 ckp->cur_data_segno[1] = 781 cpu_to_le32(f2fs_params.cur_seg[CURSEG_WARM_DATA]); 782 ckp->cur_data_segno[2] = 783 cpu_to_le32(f2fs_params.cur_seg[CURSEG_COLD_DATA]); 784 for (i = 3; i < MAX_ACTIVE_NODE_LOGS; i++) { 785 ckp->cur_node_segno[i] = 0xffffffff; 786 ckp->cur_data_segno[i] = 0xffffffff; 787 } 788 789 ckp->cur_node_blkoff[0] = cpu_to_le16(1); 790 ckp->nat_upd_blkoff[0] = cpu_to_le16(1); 791 ckp->cur_data_blkoff[0] = cpu_to_le16(1); 792 ckp->valid_block_count = cpu_to_le64(2); 793 ckp->rsvd_segment_count = cpu_to_le32(f2fs_params.reserved_segments); 794 ckp->overprov_segment_count = cpu_to_le32( 795 (le32_to_cpu(super_block.segment_count_main) - 796 le32_to_cpu(ckp->rsvd_segment_count)) * 797 f2fs_params.overprovision / 100); 798 ckp->overprov_segment_count = cpu_to_le32( 799 le32_to_cpu(ckp->overprov_segment_count) + 800 le32_to_cpu(ckp->rsvd_segment_count)); 801 802 /* main segments - reserved segments - (node + data segments) */ 803 ckp->free_segment_count = cpu_to_le32( 804 le32_to_cpu(super_block.segment_count_main) - 6); 805 ckp->user_block_count = cpu_to_le64( 806 ((le32_to_cpu(ckp->free_segment_count) + 6 - 807 le32_to_cpu(ckp->overprov_segment_count)) * 808 f2fs_params.blks_per_seg)); 809 ckp->cp_pack_total_block_count = cpu_to_le32(5); 810 ckp->cp_pack_start_sum = cpu_to_le32(1); 811 ckp->valid_node_count = cpu_to_le32(1); 812 ckp->valid_inode_count = cpu_to_le32(1); 813 ckp->next_free_nid = cpu_to_le32( 814 le32_to_cpu(super_block.root_ino) + 1); 815 816 ckp->sit_ver_bitmap_bytesize = cpu_to_le32( 817 ((le32_to_cpu(super_block.segment_count_sit) / 2) << 818 le32_to_cpu(super_block.log_blocks_per_seg)) / 8); 819 820 ckp->nat_ver_bitmap_bytesize = cpu_to_le32( 821 ((le32_to_cpu(super_block.segment_count_nat) / 2) << 822 le32_to_cpu(super_block.log_blocks_per_seg)) / 8); 823 824 ckp->checksum_offset = cpu_to_le32(4092); 825 826 crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, 827 le32_to_cpu(ckp->checksum_offset)); 828 *((u_int32_t *)((unsigned char *)ckp + 829 le32_to_cpu(ckp->checksum_offset))) = crc; 830 831 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 832 cp_seg_blk_offset = 833 le32_to_cpu(super_block.start_segment_checkpoint) * blk_size_bytes; 834 835 if (writetodisk(f2fs_params.fd, ckp, cp_seg_blk_offset, 836 F2FS_CP_BLOCK_SIZE) < 0) { 837 printf("\n\tError: While writing the ckp to disk!!!\n"); 838 return -1; 839 } 840 841 /* 2. Prepare and write Segment summary for data blocks */ 842 SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); 843 844 sum->entries[0].nid = super_block.root_ino; 845 sum->entries[0].bidx = 0; 846 847 cp_seg_blk_offset += blk_size_bytes; 848 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 849 sizeof(struct f2fs_summary_block)) < 0) { 850 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 851 return -1; 852 } 853 854 /* 3. Fill segment summary for data block to zero. */ 855 memset(sum, 0, sizeof(struct f2fs_summary_block)); 856 857 cp_seg_blk_offset += blk_size_bytes; 858 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 859 sizeof(struct f2fs_summary_block)) < 0) { 860 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 861 return -1; 862 } 863 864 /* 4. Fill segment summary for data block to zero. */ 865 memset(sum, 0, sizeof(struct f2fs_summary_block)); 866 867 /* inode sit for root */ 868 sum->n_sits = cpu_to_le16(6); 869 sum->sit_j.entries[0].segno = ckp->cur_node_segno[0]; 870 sum->sit_j.entries[0].se.vblocks = cpu_to_le16((CURSEG_HOT_NODE << 10) | 1); 871 f2fs_set_bit(0, sum->sit_j.entries[0].se.valid_map); 872 sum->sit_j.entries[1].segno = ckp->cur_node_segno[1]; 873 sum->sit_j.entries[1].se.vblocks = cpu_to_le16((CURSEG_WARM_NODE << 10)); 874 sum->sit_j.entries[2].segno = ckp->cur_node_segno[2]; 875 sum->sit_j.entries[2].se.vblocks = cpu_to_le16((CURSEG_COLD_NODE << 10)); 876 877 /* data sit for root */ 878 sum->sit_j.entries[3].segno = ckp->cur_data_segno[0]; 879 sum->sit_j.entries[3].se.vblocks = cpu_to_le16((CURSEG_HOT_DATA << 10) | 1); 880 f2fs_set_bit(0, sum->sit_j.entries[3].se.valid_map); 881 sum->sit_j.entries[4].segno = ckp->cur_data_segno[1]; 882 sum->sit_j.entries[4].se.vblocks = cpu_to_le16((CURSEG_WARM_DATA << 10)); 883 sum->sit_j.entries[5].segno = ckp->cur_data_segno[2]; 884 sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10)); 885 886 cp_seg_blk_offset += blk_size_bytes; 887 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 888 sizeof(struct f2fs_summary_block)) < 0) { 889 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 890 return -1; 891 } 892 893 /* 5. cp page2 */ 894 cp_seg_blk_offset += blk_size_bytes; 895 if (writetodisk(f2fs_params.fd, ckp, cp_seg_blk_offset, 896 F2FS_CP_BLOCK_SIZE) < 0) { 897 printf("\n\tError: While writing the ckp to disk!!!\n"); 898 return -1; 899 } 900 901 /* 6. cp page 1 of check point pack 2 902 * Initiatialize other checkpoint pack with version zero 903 */ 904 ckp->checkpoint_ver = 0; 905 906 crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, 907 le32_to_cpu(ckp->checksum_offset)); 908 *((u_int32_t *)((unsigned char *)ckp + 909 le32_to_cpu(ckp->checksum_offset))) = crc; 910 911 cp_seg_blk_offset = (le32_to_cpu(super_block.start_segment_checkpoint) + 912 f2fs_params.blks_per_seg) * 913 blk_size_bytes; 914 if (writetodisk(f2fs_params.fd, ckp, 915 cp_seg_blk_offset, F2FS_CP_BLOCK_SIZE) < 0) { 916 printf("\n\tError: While writing the ckp to disk!!!\n"); 917 return -1; 918 } 919 920 /* 7. */ 921 memset(sum, 0, sizeof(struct f2fs_summary_block)); 922 SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); 923 cp_seg_blk_offset += blk_size_bytes; 924 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 925 sizeof(struct f2fs_summary_block)) < 0) { 926 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 927 return -1; 928 } 929 930 /* 8. */ 931 memset(sum, 0, sizeof(struct f2fs_summary_block)); 932 cp_seg_blk_offset += blk_size_bytes; 933 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 934 sizeof(struct f2fs_summary_block)) < 0) { 935 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 936 return -1; 937 } 938 939 /* 9. */ 940 memset(sum, 0, sizeof(struct f2fs_summary_block)); 941 cp_seg_blk_offset += blk_size_bytes; 942 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 943 sizeof(struct f2fs_summary_block)) < 0) { 944 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 945 return -1; 946 } 947 948 /* 10. cp page 2 of check point pack 2 */ 949 cp_seg_blk_offset += blk_size_bytes; 950 if (writetodisk(f2fs_params.fd, ckp, cp_seg_blk_offset, 951 F2FS_CP_BLOCK_SIZE) < 0) { 952 printf("\n\tError: While writing the ckp to disk!!!\n"); 953 return -1; 954 } 955 956 free(sum) ; 957 free(ckp) ; 958 return 0; 959} 960 961/** 962 * @brief It writes super block on device 963 * @param None 964 * @return 0 if success 965 */ 966static int8_t f2fs_write_super_block(void) 967{ 968 u_int32_t index = 0; 969 u_int64_t super_blk_offset; 970 u_int8_t *zero_buff; 971 972 zero_buff = calloc(f2fs_params.sector_size, 1); 973 super_blk_offset = F2FS_SUPER_OFFSET * F2FS_BLKSIZE; 974 975 for (index = 0; index < 2; index++) { 976 if (writetodisk(f2fs_params.fd, &super_block, super_blk_offset, 977 sizeof(struct f2fs_super_block)) < 0) { 978 printf("\n\tError: While while writing supe_blk \ 979 on disk!!! index : %d\n", index); 980 return -1; 981 } 982 super_blk_offset += F2FS_BLKSIZE; 983 } 984 985 free(zero_buff); 986 return 0; 987} 988 989/** 990 * @brief It initializes and writes root inode on device. 991 * @param None 992 * @return 0 if success 993 */ 994static int8_t f2fs_write_root_inode(void) 995{ 996 struct f2fs_node *raw_node = NULL; 997 u_int32_t blk_size_bytes; 998 u_int64_t data_blk_nor; 999 u_int64_t main_area_node_seg_blk_offset = 0; 1000 1001 raw_node = calloc(sizeof(struct f2fs_node), 1); 1002 if (raw_node == NULL) { 1003 printf("\n\tError: Calloc Failed for raw_node!!!\n"); 1004 return -1; 1005 } 1006 1007 raw_node->footer.nid = super_block.root_ino; 1008 raw_node->footer.ino = super_block.root_ino; 1009 raw_node->footer.cp_ver = cpu_to_le64(1); 1010 raw_node->footer.next_blkaddr = cpu_to_le32( 1011 le32_to_cpu(super_block.main_blkaddr) + 1012 f2fs_params.cur_seg[CURSEG_HOT_NODE] * 1013 f2fs_params.blks_per_seg + 1); 1014 1015 raw_node->i.i_mode = cpu_to_le16(0x41ed); 1016 raw_node->i.i_links = cpu_to_le32(2); 1017 raw_node->i.i_uid = cpu_to_le32(getuid()); 1018 raw_node->i.i_gid = cpu_to_le32(getgid()); 1019 1020 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 1021 raw_node->i.i_size = cpu_to_le64(1 * blk_size_bytes); /* dentry */ 1022 raw_node->i.i_blocks = cpu_to_le64(2); 1023 1024 raw_node->i.i_ctime = cpu_to_le32(time(NULL)); 1025 raw_node->i.i_ctime_nsec = 0; 1026 raw_node->i.i_mtime = cpu_to_le32(time(NULL)); 1027 raw_node->i.i_mtime_nsec = 0; 1028 raw_node->i.i_xattr_nid = 0; 1029 raw_node->i.i_flags = 0; 1030 raw_node->i.current_depth = cpu_to_le32(1); 1031 1032 data_blk_nor = le32_to_cpu(super_block.main_blkaddr) + 1033 f2fs_params.cur_seg[CURSEG_HOT_DATA] * f2fs_params.blks_per_seg; 1034 raw_node->i.i_addr[0] = cpu_to_le32(data_blk_nor); 1035 1036 raw_node->i.i_ext.fofs = 0; 1037 raw_node->i.i_ext.blk_addr = cpu_to_le32(data_blk_nor); 1038 raw_node->i.i_ext.len = cpu_to_le32(1); 1039 1040 main_area_node_seg_blk_offset = le32_to_cpu(super_block.main_blkaddr); 1041 main_area_node_seg_blk_offset += f2fs_params.cur_seg[CURSEG_HOT_NODE] * 1042 f2fs_params.blks_per_seg; 1043 main_area_node_seg_blk_offset *= blk_size_bytes; 1044 1045 if (writetodisk(f2fs_params.fd, raw_node, main_area_node_seg_blk_offset, 1046 sizeof(struct f2fs_node)) < 0) { 1047 printf("\n\tError: While writing the raw_node to disk!!!\n"); 1048 return -1; 1049 } 1050 1051 memset(raw_node, 0xff, sizeof(struct f2fs_node)); 1052 1053 if (writetodisk(f2fs_params.fd, raw_node, 1054 main_area_node_seg_blk_offset + 4096, 1055 sizeof(struct f2fs_node)) < 0) { 1056 printf("\n\tError: While writing the raw_node to disk!!!\n"); 1057 return -1; 1058 } 1059 free(raw_node); 1060 return 0; 1061} 1062 1063/** 1064 * @brief It updates NAT for root Inode 1065 * @param None 1066 * @return 0 if success 1067 */ 1068static int8_t f2fs_update_nat_root(void) 1069{ 1070 struct f2fs_nat_block *nat_blk = NULL; 1071 u_int32_t blk_size_bytes; 1072 u_int64_t nat_seg_blk_offset = 0; 1073 1074 nat_blk = calloc(sizeof(struct f2fs_nat_block), 1); 1075 if(nat_blk == NULL) { 1076 printf("\n\tError: Calloc Failed for nat_blk!!!\n"); 1077 return -1; 1078 } 1079 1080 /* update root */ 1081 nat_blk->entries[super_block.root_ino].block_addr = cpu_to_le32( 1082 le32_to_cpu(super_block.main_blkaddr) + 1083 f2fs_params.cur_seg[CURSEG_HOT_NODE] * f2fs_params.blks_per_seg); 1084 nat_blk->entries[super_block.root_ino].ino = super_block.root_ino; 1085 1086 /* update node nat */ 1087 nat_blk->entries[super_block.node_ino].block_addr = cpu_to_le32(1); 1088 nat_blk->entries[super_block.node_ino].ino = super_block.node_ino; 1089 1090 /* update meta nat */ 1091 nat_blk->entries[super_block.meta_ino].block_addr = cpu_to_le32(1); 1092 nat_blk->entries[super_block.meta_ino].ino = super_block.meta_ino; 1093 1094 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 1095 1096 nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr) * 1097 blk_size_bytes; 1098 1099 if (writetodisk(f2fs_params.fd, nat_blk, nat_seg_blk_offset, 1100 sizeof(struct f2fs_nat_block)) < 0) { 1101 printf("\n\tError: While writing the nat_blk set0 to disk!!!\n"); 1102 return -1; 1103 } 1104 1105 free(nat_blk); 1106 return 0; 1107} 1108 1109/** 1110 * @brief It updates default dentries in Root Inode 1111 * @param None 1112 * @return 0 if success 1113 */ 1114static int8_t f2fs_add_default_dentry_root(void) 1115{ 1116 struct f2fs_dentry_block *dent_blk = NULL; 1117 u_int32_t blk_size_bytes; 1118 u_int64_t data_blk_offset = 0; 1119 1120 dent_blk = calloc(sizeof(struct f2fs_dentry_block), 1); 1121 if(dent_blk == NULL) { 1122 printf("\n\tError: Calloc Failed for dent_blk!!!\n"); 1123 return -1; 1124 } 1125 1126 dent_blk->dentry[0].hash_code = 0; 1127 dent_blk->dentry[0].ino = super_block.root_ino; 1128 dent_blk->dentry[0].name_len = cpu_to_le16(1); 1129 dent_blk->dentry[0].file_type = F2FS_FT_DIR; 1130 memcpy(dent_blk->filename[0], ".", 1); 1131 1132 dent_blk->dentry[1].hash_code = 0; 1133 dent_blk->dentry[1].ino = super_block.root_ino; 1134 dent_blk->dentry[1].name_len = cpu_to_le16(2); 1135 dent_blk->dentry[1].file_type = F2FS_FT_DIR; 1136 memcpy(dent_blk->filename[1], "..", 2); 1137 1138 /* bitmap for . and .. */ 1139 dent_blk->dentry_bitmap[0] = (1 << 1) | (1 << 0); 1140 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 1141 data_blk_offset = (le32_to_cpu(super_block.main_blkaddr) + 1142 f2fs_params.cur_seg[CURSEG_HOT_DATA] * 1143 f2fs_params.blks_per_seg) * blk_size_bytes; 1144 1145 if (writetodisk(f2fs_params.fd, dent_blk, data_blk_offset, 1146 sizeof(struct f2fs_dentry_block)) < 0) { 1147 printf("\n\tError: While writing the dentry_blk to disk!!!\n"); 1148 return -1; 1149 } 1150 1151 free(dent_blk); 1152 return 0; 1153} 1154 1155/** 1156 * @brief It creates root directory on device. 1157 * @param None 1158 * @return 0 if success 1159 */ 1160static int8_t f2fs_create_root_dir(void) 1161{ 1162 int8_t err = 0; 1163 1164 err = f2fs_write_root_inode(); 1165 if (err < 0) { 1166 printf("\n\tError: Failed to write root inode!!!\n"); 1167 goto exit; 1168 } 1169 1170 err = f2fs_update_nat_root(); 1171 if (err < 0) { 1172 printf("\n\tError: Failed to update NAT for root!!!\n"); 1173 goto exit; 1174 } 1175 1176 err = f2fs_add_default_dentry_root(); 1177 if (err < 0) { 1178 printf("\n\tError: Failed to add default dentries for root!!!\n"); 1179 goto exit; 1180 } 1181exit: 1182 if (err) 1183 printf("\n\tError: Could not create the root directory!!!\n"); 1184 1185 return err; 1186} 1187 1188int f2fs_trim_device() 1189{ 1190 unsigned long long range[2]; 1191 struct stat stat_buf; 1192 1193 range[0] = 0; 1194 range[1] = f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE; 1195 1196 if (fstat(f2fs_params.fd, &stat_buf) < 0 ) { 1197 printf("\n\tError: Failed to get the device stat!!!\n"); 1198 return -1; 1199 } 1200 1201 if (S_ISREG(stat_buf.st_mode)) 1202 return 0; 1203 else if (S_ISBLK(stat_buf.st_mode)) { 1204 if (ioctl(f2fs_params.fd, BLKDISCARD, &range) < 0) 1205 printf("Info: This device doesn't support TRIM\n"); 1206 } else 1207 return -1; 1208 return 0; 1209} 1210 1211/** 1212 * @brief It s a routine to fromat device with F2FS on-disk layout 1213 * @param None 1214 * @return 0 if success 1215 */ 1216static int8_t f2fs_format_device(void) 1217{ 1218 int8_t err = 0; 1219 1220 err= f2fs_prepare_super_block(); 1221 if (err < 0) 1222 goto exit; 1223 1224 err = f2fs_trim_device(); 1225 if (err < 0) { 1226 printf("\n\tError: Failed to trim whole device!!!\n"); 1227 goto exit; 1228 } 1229 1230 err = f2fs_init_sit_area(); 1231 if (err < 0) { 1232 printf("\n\tError: Failed to Initialise the SIT AREA!!!\n"); 1233 goto exit; 1234 } 1235 1236 err = f2fs_init_nat_area(); 1237 if (err < 0) { 1238 printf("\n\tError: Failed to Initialise the NAT AREA!!!\n"); 1239 goto exit; 1240 } 1241 1242 err = f2fs_create_root_dir(); 1243 if (err < 0) { 1244 printf("\n\tError: Failed to create the root directory!!!\n"); 1245 goto exit; 1246 } 1247 1248 err = f2fs_write_check_point_pack(); 1249 if (err < 0) { 1250 printf("\n\tError: Failed to write the check point pack!!!\n"); 1251 goto exit; 1252 } 1253 1254 err = f2fs_write_super_block(); 1255 if (err < 0) { 1256 printf("\n\tError: Failed to write the Super Block!!!\n"); 1257 goto exit; 1258 } 1259exit: 1260 if (err) 1261 printf("\n\tError: Could not format the device!!!\n"); 1262 1263 /* 1264 * We should call fsync() to flush out all the dirty pages 1265 * in the block device page cache. 1266 */ 1267 if (fsync(f2fs_params.fd) < 0) 1268 printf("\n\tError: Could not conduct fsync!!!\n"); 1269 1270 if (close(f2fs_params.fd) < 0) 1271 printf("\n\tError: Failed to close device file!!!\n"); 1272 1273 return err; 1274} 1275 1276/** 1277 * @brief main function of F2Fs utility 1278 * @param argc count of argument 1279 * @param argv array of arguments 1280 * @return 0 if success 1281 */ 1282int main(int argc, char *argv[]) 1283{ 1284 f2fs_init_global_parameters(); 1285 1286 f2fs_parse_options(argc, argv); 1287 1288 if (f2fs_is_device_mounted() < 0) 1289 return -1; 1290 1291 if (f2fs_get_device_info() < 0) 1292 return -1; 1293 1294 if (f2fs_format_device() < 0) 1295 return -1; 1296 1297 printf("Info: format successful\n"); 1298 1299 return 0; 1300} 1301