f2fs_format.c revision d2387723a8f47a3c860d2c67436232ccad764caf
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 = 48; /* 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 (2 * (100 / f2fs_params.overprovision + 1) + 6) 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 f2fs_params.start_sector = 0; 267 else 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 = %"PRIu64" (in 512bytes)\n", 277 f2fs_params.total_sectors); 278 if (f2fs_params.total_sectors < 279 (F2FS_MIN_VOLUME_SIZE / DEFAULT_SECTOR_SIZE)) { 280 printf("Error: Min volume size supported is %d\n", 281 F2FS_MIN_VOLUME_SIZE); 282 return -1; 283 } 284 285 return 0; 286} 287 288const char *media_ext_lists[] = { 289 "jpg", 290 "gif", 291 "png", 292 "avi", 293 "divx", 294 "mp4", 295 "mp3", 296 "3gp", 297 "wmv", 298 "wma", 299 "mpeg", 300 "mkv", 301 "mov", 302 "asx", 303 "asf", 304 "wmx", 305 "svi", 306 "wvx", 307 "wm", 308 "mpg", 309 "mpe", 310 "rm", 311 "ogg", 312 NULL 313}; 314 315static void configure_extension_list(void) 316{ 317 const char **extlist = media_ext_lists; 318 char *ext_str = f2fs_params.extension_list; 319 char *ue; 320 int name_len; 321 int i = 0; 322 323 super_block.extension_count = 0; 324 memset(super_block.extension_list, 0, 325 sizeof(super_block.extension_list)); 326 327 while (*extlist) { 328 name_len = strlen(*extlist); 329 memcpy(super_block.extension_list[i++], *extlist, name_len); 330 extlist++; 331 } 332 super_block.extension_count = i - 1; 333 334 if (!ext_str) 335 return; 336 337 /* add user ext list */ 338 ue = strtok(ext_str, ","); 339 while (ue != NULL) { 340 name_len = strlen(ue); 341 memcpy(super_block.extension_list[i++], ue, name_len); 342 ue = strtok(NULL, ","); 343 if (i > F2FS_MAX_EXTENSION) 344 break; 345 } 346 347 super_block.extension_count = i - 1; 348 349 free(f2fs_params.extension_list); 350} 351 352 353/** 354 * @brief It writes buffer to disk or storage meant to be formatted 355 * with F2FS. 356 * @param fd File descriptor for device 357 * @param buf buffer to be written 358 * @param offset where to bw written on the device 359 * @param length length of the device 360 * @return 0 if success 361 */ 362static int writetodisk(int32_t fd, void *buf, u_int64_t offset, size_t length) 363{ 364 if (lseek64(fd, offset, SEEK_SET) < 0) { 365 printf("\n\tError: While lseek to the derised location!!!\n"); 366 return -1; 367 } 368 369 if (write(fd, buf, length) < 0) { 370 printf("\n\tError: While writing data to the disk!!! Error Num : \ 371 %d\n", errno); 372 return -1; 373 } 374 375 return 0; 376} 377 378/** 379 * @brief It initialize F2FS super block 380 * @param None 381 * @return None 382 */ 383static int f2fs_prepare_super_block(void) 384{ 385 u_int32_t blk_size_bytes; 386 u_int32_t log_sectorsize, log_sectors_per_block; 387 u_int32_t log_blocksize, log_blks_per_seg; 388 u_int32_t segment_size_bytes, zone_size_bytes; 389 u_int32_t sit_segments; 390 u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa; 391 u_int32_t total_valid_blks_available; 392 u_int64_t zone_align_start_offset, diff, total_meta_segments; 393 u_int32_t sit_bitmap_size, max_nat_bitmap_size, max_nat_segments; 394 u_int32_t total_zones; 395 396 super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC); 397 super_block.major_ver = cpu_to_le16(F2FS_MAJOR_VERSION); 398 super_block.minor_ver = cpu_to_le16(F2FS_MINOR_VERSION); 399 400 log_sectorsize = log_base_2(f2fs_params.sector_size); 401 log_sectors_per_block = log_base_2(f2fs_params.sectors_per_blk); 402 log_blocksize = log_sectorsize + log_sectors_per_block; 403 log_blks_per_seg = log_base_2(f2fs_params.blks_per_seg); 404 405 super_block.log_sectorsize = cpu_to_le32(log_sectorsize); 406 407 if (log_sectorsize < 0) { 408 printf("\n\tError: Failed to get the sector size: %u!\n", 409 f2fs_params.sector_size); 410 return -1; 411 } 412 413 super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block); 414 415 if (log_sectors_per_block < 0) { 416 printf("\n\tError: Failed to get sectors per block: %u!\n", 417 f2fs_params.sectors_per_blk); 418 return -1; 419 } 420 421 super_block.log_blocksize = cpu_to_le32(log_blocksize); 422 super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg); 423 424 if (log_blks_per_seg < 0) { 425 printf("\n\tError: Failed to get block per segment: %u!\n", 426 f2fs_params.blks_per_seg); 427 return -1; 428 } 429 430 super_block.segs_per_sec = cpu_to_le32(f2fs_params.segs_per_sec); 431 super_block.secs_per_zone = cpu_to_le32(f2fs_params.secs_per_zone); 432 blk_size_bytes = 1 << log_blocksize; 433 segment_size_bytes = blk_size_bytes * f2fs_params.blks_per_seg; 434 zone_size_bytes = 435 blk_size_bytes * f2fs_params.secs_per_zone * 436 f2fs_params.segs_per_sec * f2fs_params.blks_per_seg; 437 438 super_block.checksum_offset = 0; 439 440 super_block.block_count = cpu_to_le64( 441 (f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE) / 442 blk_size_bytes); 443 444 zone_align_start_offset = 445 (f2fs_params.start_sector * DEFAULT_SECTOR_SIZE + 446 2 * F2FS_BLKSIZE + zone_size_bytes - 1) / 447 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 super_block.cp_blkaddr = super_block.segment0_blkaddr; 465 466 printf("Info: zone aligned segment0 blkaddr: %u\n", 467 le32_to_cpu(super_block.segment0_blkaddr)); 468 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.segment0_blkaddr) + 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 uuid_generate(super_block.uuid); 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 nat_seg_blk_offset *= 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->cur_data_blkoff[0] = cpu_to_le16(1); 791 ckp->valid_block_count = cpu_to_le64(2); 792 ckp->rsvd_segment_count = cpu_to_le32(f2fs_params.reserved_segments); 793 ckp->overprov_segment_count = cpu_to_le32( 794 (le32_to_cpu(super_block.segment_count_main) - 795 le32_to_cpu(ckp->rsvd_segment_count)) * 796 f2fs_params.overprovision / 100); 797 ckp->overprov_segment_count = cpu_to_le32( 798 le32_to_cpu(ckp->overprov_segment_count) + 799 le32_to_cpu(ckp->rsvd_segment_count)); 800 801 /* main segments - reserved segments - (node + data segments) */ 802 ckp->free_segment_count = cpu_to_le32( 803 le32_to_cpu(super_block.segment_count_main) - 6); 804 ckp->user_block_count = cpu_to_le64( 805 ((le32_to_cpu(ckp->free_segment_count) + 6 - 806 le32_to_cpu(ckp->overprov_segment_count)) * 807 f2fs_params.blks_per_seg)); 808 ckp->cp_pack_total_block_count = cpu_to_le32(8); 809 ckp->ckpt_flags |= CP_UMOUNT_FLAG; 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 = le32_to_cpu(super_block.segment0_blkaddr); 833 cp_seg_blk_offset *= 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 memset(sum, 0, sizeof(struct f2fs_summary_block)); 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 SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); 858 859 cp_seg_blk_offset += blk_size_bytes; 860 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 861 sizeof(struct f2fs_summary_block)) < 0) { 862 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 863 return -1; 864 } 865 866 /* 4. Fill segment summary for data block to zero. */ 867 memset(sum, 0, sizeof(struct f2fs_summary_block)); 868 SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); 869 870 /* inode sit for root */ 871 sum->n_sits = cpu_to_le16(6); 872 sum->sit_j.entries[0].segno = ckp->cur_node_segno[0]; 873 sum->sit_j.entries[0].se.vblocks = cpu_to_le16((CURSEG_HOT_NODE << 10) | 1); 874 f2fs_set_bit(0, sum->sit_j.entries[0].se.valid_map); 875 sum->sit_j.entries[1].segno = ckp->cur_node_segno[1]; 876 sum->sit_j.entries[1].se.vblocks = cpu_to_le16((CURSEG_WARM_NODE << 10)); 877 sum->sit_j.entries[2].segno = ckp->cur_node_segno[2]; 878 sum->sit_j.entries[2].se.vblocks = cpu_to_le16((CURSEG_COLD_NODE << 10)); 879 880 /* data sit for root */ 881 sum->sit_j.entries[3].segno = ckp->cur_data_segno[0]; 882 sum->sit_j.entries[3].se.vblocks = cpu_to_le16((CURSEG_HOT_DATA << 10) | 1); 883 f2fs_set_bit(0, sum->sit_j.entries[3].se.valid_map); 884 sum->sit_j.entries[4].segno = ckp->cur_data_segno[1]; 885 sum->sit_j.entries[4].se.vblocks = cpu_to_le16((CURSEG_WARM_DATA << 10)); 886 sum->sit_j.entries[5].segno = ckp->cur_data_segno[2]; 887 sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10)); 888 889 cp_seg_blk_offset += blk_size_bytes; 890 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 891 sizeof(struct f2fs_summary_block)) < 0) { 892 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 893 return -1; 894 } 895 896 /* 5. Prepare and write Segment summary for node blocks */ 897 memset(sum, 0, sizeof(struct f2fs_summary_block)); 898 SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); 899 900 sum->entries[0].nid = super_block.root_ino; 901 sum->entries[0].ofs_in_node = 0; 902 903 cp_seg_blk_offset += blk_size_bytes; 904 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 905 sizeof(struct f2fs_summary_block)) < 0) { 906 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 907 return -1; 908 } 909 910 /* 6. Fill segment summary for data block to zero. */ 911 memset(sum, 0, sizeof(struct f2fs_summary_block)); 912 SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); 913 914 cp_seg_blk_offset += blk_size_bytes; 915 if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset, 916 sizeof(struct f2fs_summary_block)) < 0) { 917 printf("\n\tError: While writing the sum_blk to disk!!!\n"); 918 return -1; 919 } 920 921 /* 7. Fill segment summary for data block to zero. */ 922 memset(sum, 0, sizeof(struct f2fs_summary_block)); 923 SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); 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. cp page2 */ 932 cp_seg_blk_offset += blk_size_bytes; 933 if (writetodisk(f2fs_params.fd, ckp, cp_seg_blk_offset, 934 F2FS_CP_BLOCK_SIZE) < 0) { 935 printf("\n\tError: While writing the ckp to disk!!!\n"); 936 return -1; 937 } 938 939 /* 9. cp page 1 of check point pack 2 940 * Initiatialize other checkpoint pack with version zero 941 */ 942 ckp->checkpoint_ver = 0; 943 944 crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, 945 le32_to_cpu(ckp->checksum_offset)); 946 *((u_int32_t *)((unsigned char *)ckp + 947 le32_to_cpu(ckp->checksum_offset))) = crc; 948 949 cp_seg_blk_offset = (le32_to_cpu(super_block.segment0_blkaddr) + 950 f2fs_params.blks_per_seg) * 951 blk_size_bytes; 952 if (writetodisk(f2fs_params.fd, ckp, 953 cp_seg_blk_offset, F2FS_CP_BLOCK_SIZE) < 0) { 954 printf("\n\tError: While writing the ckp to disk!!!\n"); 955 return -1; 956 } 957 958 free(sum) ; 959 free(ckp) ; 960 return 0; 961} 962 963/** 964 * @brief It writes super block on device 965 * @param None 966 * @return 0 if success 967 */ 968static int8_t f2fs_write_super_block(void) 969{ 970 u_int32_t index = 0; 971 u_int8_t *zero_buff; 972 973 zero_buff = calloc(F2FS_BLKSIZE, 1); 974 975 memcpy(zero_buff + F2FS_SUPER_OFFSET, &super_block, 976 sizeof(super_block)); 977 978 for (index = 0; index < 2; index++) { 979 if (writetodisk(f2fs_params.fd, zero_buff, 980 index * F2FS_BLKSIZE, F2FS_BLKSIZE) < 0) { 981 printf("\n\tError: While while writing supe_blk \ 982 on disk!!! index : %d\n", index); 983 return -1; 984 } 985 } 986 987 free(zero_buff); 988 return 0; 989} 990 991/** 992 * @brief It initializes and writes root inode on device. 993 * @param None 994 * @return 0 if success 995 */ 996static int8_t f2fs_write_root_inode(void) 997{ 998 struct f2fs_node *raw_node = NULL; 999 u_int64_t blk_size_bytes, 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_int64_t blk_size_bytes, nat_seg_blk_offset = 0; 1076 1077 nat_blk = calloc(sizeof(struct f2fs_nat_block), 1); 1078 if(nat_blk == NULL) { 1079 printf("\n\tError: Calloc Failed for nat_blk!!!\n"); 1080 return -1; 1081 } 1082 1083 /* update root */ 1084 nat_blk->entries[super_block.root_ino].block_addr = cpu_to_le32( 1085 le32_to_cpu(super_block.main_blkaddr) + 1086 f2fs_params.cur_seg[CURSEG_HOT_NODE] * f2fs_params.blks_per_seg); 1087 nat_blk->entries[super_block.root_ino].ino = super_block.root_ino; 1088 1089 /* update node nat */ 1090 nat_blk->entries[super_block.node_ino].block_addr = cpu_to_le32(1); 1091 nat_blk->entries[super_block.node_ino].ino = super_block.node_ino; 1092 1093 /* update meta nat */ 1094 nat_blk->entries[super_block.meta_ino].block_addr = cpu_to_le32(1); 1095 nat_blk->entries[super_block.meta_ino].ino = super_block.meta_ino; 1096 1097 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 1098 nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr); 1099 nat_seg_blk_offset *= blk_size_bytes; 1100 1101 if (writetodisk(f2fs_params.fd, nat_blk, nat_seg_blk_offset, 1102 sizeof(struct f2fs_nat_block)) < 0) { 1103 printf("\n\tError: While writing the nat_blk set0 to disk!!!\n"); 1104 return -1; 1105 } 1106 1107 free(nat_blk); 1108 return 0; 1109} 1110 1111/** 1112 * @brief It updates default dentries in Root Inode 1113 * @param None 1114 * @return 0 if success 1115 */ 1116static int8_t f2fs_add_default_dentry_root(void) 1117{ 1118 struct f2fs_dentry_block *dent_blk = NULL; 1119 u_int64_t blk_size_bytes, data_blk_offset = 0; 1120 1121 dent_blk = calloc(sizeof(struct f2fs_dentry_block), 1); 1122 if(dent_blk == NULL) { 1123 printf("\n\tError: Calloc Failed for dent_blk!!!\n"); 1124 return -1; 1125 } 1126 1127 dent_blk->dentry[0].hash_code = 0; 1128 dent_blk->dentry[0].ino = super_block.root_ino; 1129 dent_blk->dentry[0].name_len = cpu_to_le16(1); 1130 dent_blk->dentry[0].file_type = F2FS_FT_DIR; 1131 memcpy(dent_blk->filename[0], ".", 1); 1132 1133 dent_blk->dentry[1].hash_code = 0; 1134 dent_blk->dentry[1].ino = super_block.root_ino; 1135 dent_blk->dentry[1].name_len = cpu_to_le16(2); 1136 dent_blk->dentry[1].file_type = F2FS_FT_DIR; 1137 memcpy(dent_blk->filename[1], "..", 2); 1138 1139 /* bitmap for . and .. */ 1140 dent_blk->dentry_bitmap[0] = (1 << 1) | (1 << 0); 1141 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 1142 data_blk_offset = le32_to_cpu(super_block.main_blkaddr); 1143 data_blk_offset += f2fs_params.cur_seg[CURSEG_HOT_DATA] * 1144 f2fs_params.blks_per_seg; 1145 data_blk_offset *= blk_size_bytes; 1146 1147 if (writetodisk(f2fs_params.fd, dent_blk, data_blk_offset, 1148 sizeof(struct f2fs_dentry_block)) < 0) { 1149 printf("\n\tError: While writing the dentry_blk to disk!!!\n"); 1150 return -1; 1151 } 1152 1153 free(dent_blk); 1154 return 0; 1155} 1156 1157/** 1158 * @brief It creates root directory on device. 1159 * @param None 1160 * @return 0 if success 1161 */ 1162static int8_t f2fs_create_root_dir(void) 1163{ 1164 int8_t err = 0; 1165 1166 err = f2fs_write_root_inode(); 1167 if (err < 0) { 1168 printf("\n\tError: Failed to write root inode!!!\n"); 1169 goto exit; 1170 } 1171 1172 err = f2fs_update_nat_root(); 1173 if (err < 0) { 1174 printf("\n\tError: Failed to update NAT for root!!!\n"); 1175 goto exit; 1176 } 1177 1178 err = f2fs_add_default_dentry_root(); 1179 if (err < 0) { 1180 printf("\n\tError: Failed to add default dentries for root!!!\n"); 1181 goto exit; 1182 } 1183exit: 1184 if (err) 1185 printf("\n\tError: Could not create the root directory!!!\n"); 1186 1187 return err; 1188} 1189 1190int f2fs_trim_device() 1191{ 1192 unsigned long long range[2]; 1193 struct stat stat_buf; 1194 1195 range[0] = 0; 1196 range[1] = f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE; 1197 1198 if (fstat(f2fs_params.fd, &stat_buf) < 0 ) { 1199 printf("\n\tError: Failed to get the device stat!!!\n"); 1200 return -1; 1201 } 1202 1203 if (S_ISREG(stat_buf.st_mode)) 1204 return 0; 1205 else if (S_ISBLK(stat_buf.st_mode)) { 1206 if (ioctl(f2fs_params.fd, BLKDISCARD, &range) < 0) 1207 printf("Info: This device doesn't support TRIM\n"); 1208 } else 1209 return -1; 1210 return 0; 1211} 1212 1213/** 1214 * @brief It s a routine to fromat device with F2FS on-disk layout 1215 * @param None 1216 * @return 0 if success 1217 */ 1218static int8_t f2fs_format_device(void) 1219{ 1220 int8_t err = 0; 1221 1222 err= f2fs_prepare_super_block(); 1223 if (err < 0) 1224 goto exit; 1225 1226 err = f2fs_trim_device(); 1227 if (err < 0) { 1228 printf("\n\tError: Failed to trim whole device!!!\n"); 1229 goto exit; 1230 } 1231 1232 err = f2fs_init_sit_area(); 1233 if (err < 0) { 1234 printf("\n\tError: Failed to Initialise the SIT AREA!!!\n"); 1235 goto exit; 1236 } 1237 1238 err = f2fs_init_nat_area(); 1239 if (err < 0) { 1240 printf("\n\tError: Failed to Initialise the NAT AREA!!!\n"); 1241 goto exit; 1242 } 1243 1244 err = f2fs_create_root_dir(); 1245 if (err < 0) { 1246 printf("\n\tError: Failed to create the root directory!!!\n"); 1247 goto exit; 1248 } 1249 1250 err = f2fs_write_check_point_pack(); 1251 if (err < 0) { 1252 printf("\n\tError: Failed to write the check point pack!!!\n"); 1253 goto exit; 1254 } 1255 1256 err = f2fs_write_super_block(); 1257 if (err < 0) { 1258 printf("\n\tError: Failed to write the Super Block!!!\n"); 1259 goto exit; 1260 } 1261exit: 1262 if (err) 1263 printf("\n\tError: Could not format the device!!!\n"); 1264 1265 /* 1266 * We should call fsync() to flush out all the dirty pages 1267 * in the block device page cache. 1268 */ 1269 if (fsync(f2fs_params.fd) < 0) 1270 printf("\n\tError: Could not conduct fsync!!!\n"); 1271 1272 if (close(f2fs_params.fd) < 0) 1273 printf("\n\tError: Failed to close device file!!!\n"); 1274 1275 return err; 1276} 1277 1278/** 1279 * @brief main function of F2Fs utility 1280 * @param argc count of argument 1281 * @param argv array of arguments 1282 * @return 0 if success 1283 */ 1284int main(int argc, char *argv[]) 1285{ 1286 printf("\nF2FS-tools: Ver: %s (%s)\n", 1287 F2FS_TOOLS_VERSION, 1288 F2FS_TOOLS_DATE); 1289 f2fs_init_global_parameters(); 1290 1291 f2fs_parse_options(argc, argv); 1292 1293 if (f2fs_is_device_mounted() < 0) 1294 return -1; 1295 1296 if (f2fs_get_device_info() < 0) 1297 return -1; 1298 1299 if (f2fs_format_device() < 0) 1300 return -1; 1301 1302 printf("Info: format successful\n"); 1303 1304 return 0; 1305} 1306