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