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