1/** 2 * f2fs_format.c 3 * 4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. 5 * http://www.samsung.com/ 6 * 7 * Dual licensed under the GPL or LGPL version 2 licenses. 8 */ 9#define _LARGEFILE64_SOURCE 10 11#include <stdio.h> 12#include <stdlib.h> 13#include <fcntl.h> 14#include <string.h> 15#include <unistd.h> 16#include <sys/stat.h> 17#include <sys/mount.h> 18#include <time.h> 19#include <uuid/uuid.h> 20 21#include "f2fs_fs.h" 22#include "f2fs_format_utils.h" 23 24extern struct f2fs_configuration config; 25struct f2fs_super_block super_block; 26 27const char *media_ext_lists[] = { 28 "jpg", 29 "gif", 30 "png", 31 "avi", 32 "divx", 33 "mp4", 34 "mp3", 35 "3gp", 36 "wmv", 37 "wma", 38 "mpeg", 39 "mkv", 40 "mov", 41 "asx", 42 "asf", 43 "wmx", 44 "svi", 45 "wvx", 46 "wm", 47 "mpg", 48 "mpe", 49 "rm", 50 "ogg", 51 "jpeg", 52 "video", 53 "apk", /* for android system */ 54 NULL 55}; 56 57static void configure_extension_list(void) 58{ 59 const char **extlist = media_ext_lists; 60 char *ext_str = config.extension_list; 61 char *ue; 62 int name_len; 63 int i = 0; 64 65 super_block.extension_count = 0; 66 memset(super_block.extension_list, 0, 67 sizeof(super_block.extension_list)); 68 69 while (*extlist) { 70 name_len = strlen(*extlist); 71 memcpy(super_block.extension_list[i++], *extlist, name_len); 72 extlist++; 73 } 74 super_block.extension_count = i; 75 76 if (!ext_str) 77 return; 78 79 /* add user ext list */ 80 ue = strtok(ext_str, ","); 81 while (ue != NULL) { 82 name_len = strlen(ue); 83 memcpy(super_block.extension_list[i++], ue, name_len); 84 ue = strtok(NULL, ","); 85 if (i >= F2FS_MAX_EXTENSION) 86 break; 87 } 88 89 super_block.extension_count = i; 90 91 free(config.extension_list); 92} 93 94static int f2fs_prepare_super_block(void) 95{ 96 u_int32_t blk_size_bytes; 97 u_int32_t log_sectorsize, log_sectors_per_block; 98 u_int32_t log_blocksize, log_blks_per_seg; 99 u_int32_t segment_size_bytes, zone_size_bytes; 100 u_int32_t sit_segments; 101 u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa; 102 u_int32_t total_valid_blks_available; 103 u_int64_t zone_align_start_offset, diff, total_meta_segments; 104 u_int32_t sit_bitmap_size, max_sit_bitmap_size; 105 u_int32_t max_nat_bitmap_size, max_nat_segments; 106 u_int32_t total_zones; 107 108 super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC); 109 super_block.major_ver = cpu_to_le16(F2FS_MAJOR_VERSION); 110 super_block.minor_ver = cpu_to_le16(F2FS_MINOR_VERSION); 111 112 log_sectorsize = log_base_2(config.sector_size); 113 log_sectors_per_block = log_base_2(config.sectors_per_blk); 114 log_blocksize = log_sectorsize + log_sectors_per_block; 115 log_blks_per_seg = log_base_2(config.blks_per_seg); 116 117 super_block.log_sectorsize = cpu_to_le32(log_sectorsize); 118 super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block); 119 120 super_block.log_blocksize = cpu_to_le32(log_blocksize); 121 super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg); 122 123 super_block.segs_per_sec = cpu_to_le32(config.segs_per_sec); 124 super_block.secs_per_zone = cpu_to_le32(config.secs_per_zone); 125 blk_size_bytes = 1 << log_blocksize; 126 segment_size_bytes = blk_size_bytes * config.blks_per_seg; 127 zone_size_bytes = 128 blk_size_bytes * config.secs_per_zone * 129 config.segs_per_sec * config.blks_per_seg; 130 131 super_block.checksum_offset = 0; 132 133 super_block.block_count = cpu_to_le64( 134 (config.total_sectors * DEFAULT_SECTOR_SIZE) / 135 blk_size_bytes); 136 137 zone_align_start_offset = 138 (config.start_sector * DEFAULT_SECTOR_SIZE + 139 2 * F2FS_BLKSIZE + zone_size_bytes - 1) / 140 zone_size_bytes * zone_size_bytes - 141 config.start_sector * DEFAULT_SECTOR_SIZE; 142 143 if (config.start_sector % DEFAULT_SECTORS_PER_BLOCK) { 144 MSG(1, "\tWARN: Align start sector number to the page unit\n"); 145 MSG(1, "\ti.e., start sector: %d, ofs:%d (sects/page: %d)\n", 146 config.start_sector, 147 config.start_sector % DEFAULT_SECTORS_PER_BLOCK, 148 DEFAULT_SECTORS_PER_BLOCK); 149 } 150 151 super_block.segment_count = cpu_to_le32( 152 ((config.total_sectors * DEFAULT_SECTOR_SIZE) - 153 zone_align_start_offset) / segment_size_bytes); 154 155 super_block.segment0_blkaddr = 156 cpu_to_le32(zone_align_start_offset / blk_size_bytes); 157 super_block.cp_blkaddr = super_block.segment0_blkaddr; 158 159 MSG(0, "Info: zone aligned segment0 blkaddr: %u\n", 160 le32_to_cpu(super_block.segment0_blkaddr)); 161 162 super_block.segment_count_ckpt = 163 cpu_to_le32(F2FS_NUMBER_OF_CHECKPOINT_PACK); 164 165 super_block.sit_blkaddr = cpu_to_le32( 166 le32_to_cpu(super_block.segment0_blkaddr) + 167 (le32_to_cpu(super_block.segment_count_ckpt) * 168 (1 << log_blks_per_seg))); 169 170 blocks_for_sit = (le32_to_cpu(super_block.segment_count) + 171 SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK; 172 173 sit_segments = (blocks_for_sit + config.blks_per_seg - 1) 174 / config.blks_per_seg; 175 176 super_block.segment_count_sit = cpu_to_le32(sit_segments * 2); 177 178 super_block.nat_blkaddr = cpu_to_le32( 179 le32_to_cpu(super_block.sit_blkaddr) + 180 (le32_to_cpu(super_block.segment_count_sit) * 181 config.blks_per_seg)); 182 183 total_valid_blks_available = (le32_to_cpu(super_block.segment_count) - 184 (le32_to_cpu(super_block.segment_count_ckpt) + 185 le32_to_cpu(super_block.segment_count_sit))) * 186 config.blks_per_seg; 187 188 blocks_for_nat = (total_valid_blks_available + NAT_ENTRY_PER_BLOCK - 1) 189 / NAT_ENTRY_PER_BLOCK; 190 191 super_block.segment_count_nat = cpu_to_le32( 192 (blocks_for_nat + config.blks_per_seg - 1) / 193 config.blks_per_seg); 194 /* 195 * The number of node segments should not be exceeded a "Threshold". 196 * This number resizes NAT bitmap area in a CP page. 197 * So the threshold is determined not to overflow one CP page 198 */ 199 sit_bitmap_size = ((le32_to_cpu(super_block.segment_count_sit) / 2) << 200 log_blks_per_seg) / 8; 201 202 if (sit_bitmap_size > MAX_SIT_BITMAP_SIZE) 203 max_sit_bitmap_size = MAX_SIT_BITMAP_SIZE; 204 else 205 max_sit_bitmap_size = sit_bitmap_size; 206 207 /* 208 * It should be reserved minimum 1 segment for nat. 209 * When sit is too large, we should expand cp area. It requires more pages for cp. 210 */ 211 if (max_sit_bitmap_size > 212 (CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 65)) { 213 max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1; 214 super_block.cp_payload = F2FS_BLK_ALIGN(max_sit_bitmap_size); 215 } else { 216 max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 217 - max_sit_bitmap_size; 218 super_block.cp_payload = 0; 219 } 220 221 max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg; 222 223 if (le32_to_cpu(super_block.segment_count_nat) > max_nat_segments) 224 super_block.segment_count_nat = cpu_to_le32(max_nat_segments); 225 226 super_block.segment_count_nat = cpu_to_le32( 227 le32_to_cpu(super_block.segment_count_nat) * 2); 228 229 super_block.ssa_blkaddr = cpu_to_le32( 230 le32_to_cpu(super_block.nat_blkaddr) + 231 le32_to_cpu(super_block.segment_count_nat) * 232 config.blks_per_seg); 233 234 total_valid_blks_available = (le32_to_cpu(super_block.segment_count) - 235 (le32_to_cpu(super_block.segment_count_ckpt) + 236 le32_to_cpu(super_block.segment_count_sit) + 237 le32_to_cpu(super_block.segment_count_nat))) * 238 config.blks_per_seg; 239 240 blocks_for_ssa = total_valid_blks_available / 241 config.blks_per_seg + 1; 242 243 super_block.segment_count_ssa = cpu_to_le32( 244 (blocks_for_ssa + config.blks_per_seg - 1) / 245 config.blks_per_seg); 246 247 total_meta_segments = le32_to_cpu(super_block.segment_count_ckpt) + 248 le32_to_cpu(super_block.segment_count_sit) + 249 le32_to_cpu(super_block.segment_count_nat) + 250 le32_to_cpu(super_block.segment_count_ssa); 251 diff = total_meta_segments % (config.segs_per_sec * 252 config.secs_per_zone); 253 if (diff) 254 super_block.segment_count_ssa = cpu_to_le32( 255 le32_to_cpu(super_block.segment_count_ssa) + 256 (config.segs_per_sec * config.secs_per_zone - 257 diff)); 258 259 super_block.main_blkaddr = cpu_to_le32( 260 le32_to_cpu(super_block.ssa_blkaddr) + 261 (le32_to_cpu(super_block.segment_count_ssa) * 262 config.blks_per_seg)); 263 264 super_block.segment_count_main = cpu_to_le32( 265 le32_to_cpu(super_block.segment_count) - 266 (le32_to_cpu(super_block.segment_count_ckpt) 267 + le32_to_cpu(super_block.segment_count_sit) + 268 le32_to_cpu(super_block.segment_count_nat) + 269 le32_to_cpu(super_block.segment_count_ssa))); 270 271 super_block.section_count = cpu_to_le32( 272 le32_to_cpu(super_block.segment_count_main) 273 / config.segs_per_sec); 274 275 super_block.segment_count_main = cpu_to_le32( 276 le32_to_cpu(super_block.section_count) * 277 config.segs_per_sec); 278 279 if ((le32_to_cpu(super_block.segment_count_main) - 2) < 280 config.reserved_segments) { 281 MSG(1, "\tError: Device size is not sufficient for F2FS volume,\ 282 more segment needed =%u", 283 config.reserved_segments - 284 (le32_to_cpu(super_block.segment_count_main) - 2)); 285 return -1; 286 } 287 288 uuid_generate(super_block.uuid); 289 290 ASCIIToUNICODE(super_block.volume_name, (u_int8_t *)config.vol_label); 291 292 super_block.node_ino = cpu_to_le32(1); 293 super_block.meta_ino = cpu_to_le32(2); 294 super_block.root_ino = cpu_to_le32(3); 295 296 total_zones = le32_to_cpu(super_block.segment_count_main) / 297 (config.segs_per_sec * config.secs_per_zone); 298 if (total_zones <= 6) { 299 MSG(1, "\tError: %d zones: Need more zones \ 300 by shrinking zone size\n", total_zones); 301 return -1; 302 } 303 304 if (config.heap) { 305 config.cur_seg[CURSEG_HOT_NODE] = (total_zones - 1) * 306 config.segs_per_sec * 307 config.secs_per_zone + 308 ((config.secs_per_zone - 1) * 309 config.segs_per_sec); 310 config.cur_seg[CURSEG_WARM_NODE] = 311 config.cur_seg[CURSEG_HOT_NODE] - 312 config.segs_per_sec * 313 config.secs_per_zone; 314 config.cur_seg[CURSEG_COLD_NODE] = 315 config.cur_seg[CURSEG_WARM_NODE] - 316 config.segs_per_sec * 317 config.secs_per_zone; 318 config.cur_seg[CURSEG_HOT_DATA] = 319 config.cur_seg[CURSEG_COLD_NODE] - 320 config.segs_per_sec * 321 config.secs_per_zone; 322 config.cur_seg[CURSEG_COLD_DATA] = 0; 323 config.cur_seg[CURSEG_WARM_DATA] = 324 config.cur_seg[CURSEG_COLD_DATA] + 325 config.segs_per_sec * 326 config.secs_per_zone; 327 } else { 328 config.cur_seg[CURSEG_HOT_NODE] = 0; 329 config.cur_seg[CURSEG_WARM_NODE] = 330 config.cur_seg[CURSEG_HOT_NODE] + 331 config.segs_per_sec * 332 config.secs_per_zone; 333 config.cur_seg[CURSEG_COLD_NODE] = 334 config.cur_seg[CURSEG_WARM_NODE] + 335 config.segs_per_sec * 336 config.secs_per_zone; 337 config.cur_seg[CURSEG_HOT_DATA] = 338 config.cur_seg[CURSEG_COLD_NODE] + 339 config.segs_per_sec * 340 config.secs_per_zone; 341 config.cur_seg[CURSEG_COLD_DATA] = 342 config.cur_seg[CURSEG_HOT_DATA] + 343 config.segs_per_sec * 344 config.secs_per_zone; 345 config.cur_seg[CURSEG_WARM_DATA] = 346 config.cur_seg[CURSEG_COLD_DATA] + 347 config.segs_per_sec * 348 config.secs_per_zone; 349 } 350 351 configure_extension_list(); 352 353 return 0; 354} 355 356static int f2fs_init_sit_area(void) 357{ 358 u_int32_t blk_size, seg_size; 359 u_int32_t index = 0; 360 u_int64_t sit_seg_addr = 0; 361 u_int8_t *zero_buf = NULL; 362 363 blk_size = 1 << le32_to_cpu(super_block.log_blocksize); 364 seg_size = (1 << le32_to_cpu(super_block.log_blocks_per_seg)) * 365 blk_size; 366 367 zero_buf = calloc(sizeof(u_int8_t), seg_size); 368 if(zero_buf == NULL) { 369 MSG(1, "\tError: Calloc Failed for sit_zero_buf!!!\n"); 370 return -1; 371 } 372 373 sit_seg_addr = le32_to_cpu(super_block.sit_blkaddr); 374 sit_seg_addr *= blk_size; 375 376 DBG(1, "\tFilling sit area at offset 0x%08"PRIx64"\n", sit_seg_addr); 377 for (index = 0; 378 index < (le32_to_cpu(super_block.segment_count_sit) / 2); 379 index++) { 380 if (dev_fill(zero_buf, sit_seg_addr, seg_size)) { 381 MSG(1, "\tError: While zeroing out the sit area \ 382 on disk!!!\n"); 383 return -1; 384 } 385 sit_seg_addr += seg_size; 386 } 387 388 free(zero_buf); 389 return 0 ; 390} 391 392static int f2fs_init_nat_area(void) 393{ 394 u_int32_t blk_size, seg_size; 395 u_int32_t index = 0; 396 u_int64_t nat_seg_addr = 0; 397 u_int8_t *nat_buf = NULL; 398 399 blk_size = 1 << le32_to_cpu(super_block.log_blocksize); 400 seg_size = (1 << le32_to_cpu(super_block.log_blocks_per_seg)) * 401 blk_size; 402 403 nat_buf = calloc(sizeof(u_int8_t), seg_size); 404 if (nat_buf == NULL) { 405 MSG(1, "\tError: Calloc Failed for nat_zero_blk!!!\n"); 406 return -1; 407 } 408 409 nat_seg_addr = le32_to_cpu(super_block.nat_blkaddr); 410 nat_seg_addr *= blk_size; 411 412 DBG(1, "\tFilling nat area at offset 0x%08"PRIx64"\n", nat_seg_addr); 413 for (index = 0; 414 index < (le32_to_cpu(super_block.segment_count_nat) / 2); 415 index++) { 416 if (dev_fill(nat_buf, nat_seg_addr, seg_size)) { 417 MSG(1, "\tError: While zeroing out the nat area \ 418 on disk!!!\n"); 419 return -1; 420 } 421 nat_seg_addr = nat_seg_addr + (2 * seg_size); 422 } 423 424 free(nat_buf); 425 return 0 ; 426} 427 428static int f2fs_write_check_point_pack(void) 429{ 430 struct f2fs_checkpoint *ckp = NULL; 431 struct f2fs_summary_block *sum = NULL; 432 u_int32_t blk_size_bytes; 433 u_int64_t cp_seg_blk_offset = 0; 434 u_int32_t crc = 0; 435 unsigned int i; 436 char *cp_payload = NULL; 437 438 ckp = calloc(F2FS_BLKSIZE, 1); 439 if (ckp == NULL) { 440 MSG(1, "\tError: Calloc Failed for f2fs_checkpoint!!!\n"); 441 return -1; 442 } 443 444 sum = calloc(F2FS_BLKSIZE, 1); 445 if (sum == NULL) { 446 MSG(1, "\tError: Calloc Failed for summay_node!!!\n"); 447 return -1; 448 } 449 450 cp_payload = calloc(F2FS_BLKSIZE, 1); 451 if (cp_payload == NULL) { 452 MSG(1, "\tError: Calloc Failed for cp_payload!!!\n"); 453 return -1; 454 } 455 456 /* 1. cp page 1 of checkpoint pack 1 */ 457 ckp->checkpoint_ver = cpu_to_le64(1); 458 ckp->cur_node_segno[0] = 459 cpu_to_le32(config.cur_seg[CURSEG_HOT_NODE]); 460 ckp->cur_node_segno[1] = 461 cpu_to_le32(config.cur_seg[CURSEG_WARM_NODE]); 462 ckp->cur_node_segno[2] = 463 cpu_to_le32(config.cur_seg[CURSEG_COLD_NODE]); 464 ckp->cur_data_segno[0] = 465 cpu_to_le32(config.cur_seg[CURSEG_HOT_DATA]); 466 ckp->cur_data_segno[1] = 467 cpu_to_le32(config.cur_seg[CURSEG_WARM_DATA]); 468 ckp->cur_data_segno[2] = 469 cpu_to_le32(config.cur_seg[CURSEG_COLD_DATA]); 470 for (i = 3; i < MAX_ACTIVE_NODE_LOGS; i++) { 471 ckp->cur_node_segno[i] = 0xffffffff; 472 ckp->cur_data_segno[i] = 0xffffffff; 473 } 474 475 ckp->cur_node_blkoff[0] = cpu_to_le16(1); 476 ckp->cur_data_blkoff[0] = cpu_to_le16(1); 477 ckp->valid_block_count = cpu_to_le64(2); 478 ckp->rsvd_segment_count = cpu_to_le32(config.reserved_segments); 479 ckp->overprov_segment_count = cpu_to_le32( 480 (le32_to_cpu(super_block.segment_count_main) - 481 le32_to_cpu(ckp->rsvd_segment_count)) * 482 config.overprovision / 100); 483 ckp->overprov_segment_count = cpu_to_le32( 484 le32_to_cpu(ckp->overprov_segment_count) + 485 le32_to_cpu(ckp->rsvd_segment_count)); 486 487 /* main segments - reserved segments - (node + data segments) */ 488 ckp->free_segment_count = cpu_to_le32( 489 le32_to_cpu(super_block.segment_count_main) - 6); 490 ckp->user_block_count = cpu_to_le64( 491 ((le32_to_cpu(ckp->free_segment_count) + 6 - 492 le32_to_cpu(ckp->overprov_segment_count)) * 493 config.blks_per_seg)); 494 ckp->cp_pack_total_block_count = 495 cpu_to_le32(8 + le32_to_cpu(super_block.cp_payload)); 496 ckp->ckpt_flags = cpu_to_le32(CP_UMOUNT_FLAG); 497 ckp->cp_pack_start_sum = cpu_to_le32(1 + le32_to_cpu(super_block.cp_payload)); 498 ckp->valid_node_count = cpu_to_le32(1); 499 ckp->valid_inode_count = cpu_to_le32(1); 500 ckp->next_free_nid = cpu_to_le32( 501 le32_to_cpu(super_block.root_ino) + 1); 502 ckp->sit_ver_bitmap_bytesize = cpu_to_le32( 503 ((le32_to_cpu(super_block.segment_count_sit) / 2) << 504 le32_to_cpu(super_block.log_blocks_per_seg)) / 8); 505 506 ckp->nat_ver_bitmap_bytesize = cpu_to_le32( 507 ((le32_to_cpu(super_block.segment_count_nat) / 2) << 508 le32_to_cpu(super_block.log_blocks_per_seg)) / 8); 509 510 ckp->checksum_offset = cpu_to_le32(CHECKSUM_OFFSET); 511 512 crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, CHECKSUM_OFFSET); 513 *((__le32 *)((unsigned char *)ckp + CHECKSUM_OFFSET)) = 514 cpu_to_le32(crc); 515 516 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 517 cp_seg_blk_offset = le32_to_cpu(super_block.segment0_blkaddr); 518 cp_seg_blk_offset *= blk_size_bytes; 519 520 DBG(1, "\tWriting main segments, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 521 if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) { 522 MSG(1, "\tError: While writing the ckp to disk!!!\n"); 523 return -1; 524 } 525 526 for (i = 0; i < le32_to_cpu(super_block.cp_payload); i++) { 527 cp_seg_blk_offset += blk_size_bytes; 528 if (dev_fill(cp_payload, cp_seg_blk_offset, blk_size_bytes)) { 529 MSG(1, "\tError: While zeroing out the sit bitmap area \ 530 on disk!!!\n"); 531 return -1; 532 } 533 } 534 535 /* 2. Prepare and write Segment summary for data blocks */ 536 memset(sum, 0, sizeof(struct f2fs_summary_block)); 537 SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); 538 539 sum->entries[0].nid = super_block.root_ino; 540 sum->entries[0].ofs_in_node = 0; 541 542 cp_seg_blk_offset += blk_size_bytes; 543 DBG(1, "\tWriting segment summary for data, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 544 if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { 545 MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); 546 return -1; 547 } 548 549 /* 3. Fill segment summary for data block to zero. */ 550 memset(sum, 0, sizeof(struct f2fs_summary_block)); 551 SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); 552 553 cp_seg_blk_offset += blk_size_bytes; 554 DBG(1, "\tWriting segment summary, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 555 if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { 556 MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); 557 return -1; 558 } 559 560 /* 4. Fill segment summary for data block to zero. */ 561 memset(sum, 0, sizeof(struct f2fs_summary_block)); 562 SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA); 563 564 /* inode sit for root */ 565 sum->n_sits = cpu_to_le16(6); 566 sum->sit_j.entries[0].segno = ckp->cur_node_segno[0]; 567 sum->sit_j.entries[0].se.vblocks = cpu_to_le16((CURSEG_HOT_NODE << 10) | 1); 568 f2fs_set_bit(0, (char *)sum->sit_j.entries[0].se.valid_map); 569 sum->sit_j.entries[1].segno = ckp->cur_node_segno[1]; 570 sum->sit_j.entries[1].se.vblocks = cpu_to_le16((CURSEG_WARM_NODE << 10)); 571 sum->sit_j.entries[2].segno = ckp->cur_node_segno[2]; 572 sum->sit_j.entries[2].se.vblocks = cpu_to_le16((CURSEG_COLD_NODE << 10)); 573 574 /* data sit for root */ 575 sum->sit_j.entries[3].segno = ckp->cur_data_segno[0]; 576 sum->sit_j.entries[3].se.vblocks = cpu_to_le16((CURSEG_HOT_DATA << 10) | 1); 577 f2fs_set_bit(0, (char *)sum->sit_j.entries[3].se.valid_map); 578 sum->sit_j.entries[4].segno = ckp->cur_data_segno[1]; 579 sum->sit_j.entries[4].se.vblocks = cpu_to_le16((CURSEG_WARM_DATA << 10)); 580 sum->sit_j.entries[5].segno = ckp->cur_data_segno[2]; 581 sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10)); 582 583 cp_seg_blk_offset += blk_size_bytes; 584 DBG(1, "\tWriting data sit for root, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 585 if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { 586 MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); 587 return -1; 588 } 589 590 /* 5. Prepare and write Segment summary for node blocks */ 591 memset(sum, 0, sizeof(struct f2fs_summary_block)); 592 SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); 593 594 sum->entries[0].nid = super_block.root_ino; 595 sum->entries[0].ofs_in_node = 0; 596 597 cp_seg_blk_offset += blk_size_bytes; 598 DBG(1, "\tWriting Segment summary for node blocks, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 599 if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { 600 MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); 601 return -1; 602 } 603 604 /* 6. Fill segment summary for data block to zero. */ 605 memset(sum, 0, sizeof(struct f2fs_summary_block)); 606 SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); 607 608 cp_seg_blk_offset += blk_size_bytes; 609 DBG(1, "\tWriting Segment summary for data block (1/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 610 if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { 611 MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); 612 return -1; 613 } 614 615 /* 7. Fill segment summary for data block to zero. */ 616 memset(sum, 0, sizeof(struct f2fs_summary_block)); 617 SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE); 618 cp_seg_blk_offset += blk_size_bytes; 619 DBG(1, "\tWriting Segment summary for data block (2/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 620 if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) { 621 MSG(1, "\tError: While writing the sum_blk to disk!!!\n"); 622 return -1; 623 } 624 625 /* 8. cp page2 */ 626 cp_seg_blk_offset += blk_size_bytes; 627 DBG(1, "\tWriting cp page2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 628 if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) { 629 MSG(1, "\tError: While writing the ckp to disk!!!\n"); 630 return -1; 631 } 632 633 /* 9. cp page 1 of check point pack 2 634 * Initiatialize other checkpoint pack with version zero 635 */ 636 ckp->checkpoint_ver = 0; 637 638 crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp, CHECKSUM_OFFSET); 639 *((__le32 *)((unsigned char *)ckp + CHECKSUM_OFFSET)) = 640 cpu_to_le32(crc); 641 cp_seg_blk_offset = (le32_to_cpu(super_block.segment0_blkaddr) + 642 config.blks_per_seg) * 643 blk_size_bytes; 644 DBG(1, "\tWriting cp page 1 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 645 if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) { 646 MSG(1, "\tError: While writing the ckp to disk!!!\n"); 647 return -1; 648 } 649 650 for (i = 0; i < le32_to_cpu(super_block.cp_payload); i++) { 651 cp_seg_blk_offset += blk_size_bytes; 652 if (dev_fill(cp_payload, cp_seg_blk_offset, blk_size_bytes)) { 653 MSG(1, "\tError: While zeroing out the sit bitmap area \ 654 on disk!!!\n"); 655 return -1; 656 } 657 } 658 659 /* 10. cp page 2 of check point pack 2 */ 660 cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(ckp->cp_pack_total_block_count) 661 - le32_to_cpu(super_block.cp_payload) - 1); 662 DBG(1, "\tWriting cp page 2 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset); 663 if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) { 664 MSG(1, "\tError: While writing the ckp to disk!!!\n"); 665 return -1; 666 } 667 668 free(sum) ; 669 free(ckp) ; 670 free(cp_payload); 671 return 0; 672} 673 674static int f2fs_write_super_block(void) 675{ 676 int index; 677 u_int8_t *zero_buff; 678 679 zero_buff = calloc(F2FS_BLKSIZE, 1); 680 681 memcpy(zero_buff + F2FS_SUPER_OFFSET, &super_block, 682 sizeof(super_block)); 683 DBG(1, "\tWriting super block, at offset 0x%08x\n", 0); 684 for (index = 0; index < 2; index++) { 685 if (dev_write(zero_buff, index * F2FS_BLKSIZE, F2FS_BLKSIZE)) { 686 MSG(1, "\tError: While while writing supe_blk \ 687 on disk!!! index : %d\n", index); 688 return -1; 689 } 690 } 691 692 free(zero_buff); 693 return 0; 694} 695 696static int f2fs_write_root_inode(void) 697{ 698 struct f2fs_node *raw_node = NULL; 699 u_int64_t blk_size_bytes, data_blk_nor; 700 u_int64_t main_area_node_seg_blk_offset = 0; 701 702 raw_node = calloc(F2FS_BLKSIZE, 1); 703 if (raw_node == NULL) { 704 MSG(1, "\tError: Calloc Failed for raw_node!!!\n"); 705 return -1; 706 } 707 708 raw_node->footer.nid = super_block.root_ino; 709 raw_node->footer.ino = super_block.root_ino; 710 raw_node->footer.cp_ver = cpu_to_le64(1); 711 raw_node->footer.next_blkaddr = cpu_to_le32( 712 le32_to_cpu(super_block.main_blkaddr) + 713 config.cur_seg[CURSEG_HOT_NODE] * 714 config.blks_per_seg + 1); 715 716 raw_node->i.i_mode = cpu_to_le16(0x41ed); 717 raw_node->i.i_links = cpu_to_le32(2); 718 raw_node->i.i_uid = cpu_to_le32(getuid()); 719 raw_node->i.i_gid = cpu_to_le32(getgid()); 720 721 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 722 raw_node->i.i_size = cpu_to_le64(1 * blk_size_bytes); /* dentry */ 723 raw_node->i.i_blocks = cpu_to_le64(2); 724 725 raw_node->i.i_atime = cpu_to_le32(time(NULL)); 726 raw_node->i.i_atime_nsec = 0; 727 raw_node->i.i_ctime = cpu_to_le32(time(NULL)); 728 raw_node->i.i_ctime_nsec = 0; 729 raw_node->i.i_mtime = cpu_to_le32(time(NULL)); 730 raw_node->i.i_mtime_nsec = 0; 731 raw_node->i.i_generation = 0; 732 raw_node->i.i_xattr_nid = 0; 733 raw_node->i.i_flags = 0; 734 raw_node->i.i_current_depth = cpu_to_le32(1); 735 raw_node->i.i_dir_level = DEF_DIR_LEVEL; 736 737 data_blk_nor = le32_to_cpu(super_block.main_blkaddr) + 738 config.cur_seg[CURSEG_HOT_DATA] * config.blks_per_seg; 739 raw_node->i.i_addr[0] = cpu_to_le32(data_blk_nor); 740 741 raw_node->i.i_ext.fofs = 0; 742 raw_node->i.i_ext.blk_addr = cpu_to_le32(data_blk_nor); 743 raw_node->i.i_ext.len = cpu_to_le32(1); 744 745 main_area_node_seg_blk_offset = le32_to_cpu(super_block.main_blkaddr); 746 main_area_node_seg_blk_offset += config.cur_seg[CURSEG_HOT_NODE] * 747 config.blks_per_seg; 748 main_area_node_seg_blk_offset *= blk_size_bytes; 749 750 DBG(1, "\tWriting root inode (hot node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset); 751 if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) { 752 MSG(1, "\tError: While writing the raw_node to disk!!!\n"); 753 return -1; 754 } 755 756 memset(raw_node, 0xff, sizeof(struct f2fs_node)); 757 758 /* avoid power-off-recovery based on roll-forward policy */ 759 main_area_node_seg_blk_offset = le32_to_cpu(super_block.main_blkaddr); 760 main_area_node_seg_blk_offset += config.cur_seg[CURSEG_WARM_NODE] * 761 config.blks_per_seg; 762 main_area_node_seg_blk_offset *= blk_size_bytes; 763 764 DBG(1, "\tWriting root inode (warm node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset); 765 if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) { 766 MSG(1, "\tError: While writing the raw_node to disk!!!\n"); 767 return -1; 768 } 769 free(raw_node); 770 return 0; 771} 772 773static int f2fs_update_nat_root(void) 774{ 775 struct f2fs_nat_block *nat_blk = NULL; 776 u_int64_t blk_size_bytes, nat_seg_blk_offset = 0; 777 778 nat_blk = calloc(F2FS_BLKSIZE, 1); 779 if(nat_blk == NULL) { 780 MSG(1, "\tError: Calloc Failed for nat_blk!!!\n"); 781 return -1; 782 } 783 784 /* update root */ 785 nat_blk->entries[le32_to_cpu(super_block.root_ino)].block_addr = cpu_to_le32( 786 le32_to_cpu(super_block.main_blkaddr) + 787 config.cur_seg[CURSEG_HOT_NODE] * config.blks_per_seg); 788 nat_blk->entries[le32_to_cpu(super_block.root_ino)].ino = super_block.root_ino; 789 790 /* update node nat */ 791 nat_blk->entries[le32_to_cpu(super_block.node_ino)].block_addr = cpu_to_le32(1); 792 nat_blk->entries[le32_to_cpu(super_block.node_ino)].ino = super_block.node_ino; 793 794 /* update meta nat */ 795 nat_blk->entries[le32_to_cpu(super_block.meta_ino)].block_addr = cpu_to_le32(1); 796 nat_blk->entries[le32_to_cpu(super_block.meta_ino)].ino = super_block.meta_ino; 797 798 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 799 nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr); 800 nat_seg_blk_offset *= blk_size_bytes; 801 802 DBG(1, "\tWriting nat root, at offset 0x%08"PRIx64"\n", nat_seg_blk_offset); 803 if (dev_write(nat_blk, nat_seg_blk_offset, F2FS_BLKSIZE)) { 804 MSG(1, "\tError: While writing the nat_blk set0 to disk!\n"); 805 return -1; 806 } 807 808 free(nat_blk); 809 return 0; 810} 811 812static int f2fs_add_default_dentry_root(void) 813{ 814 struct f2fs_dentry_block *dent_blk = NULL; 815 u_int64_t blk_size_bytes, data_blk_offset = 0; 816 817 dent_blk = calloc(F2FS_BLKSIZE, 1); 818 if(dent_blk == NULL) { 819 MSG(1, "\tError: Calloc Failed for dent_blk!!!\n"); 820 return -1; 821 } 822 823 dent_blk->dentry[0].hash_code = 0; 824 dent_blk->dentry[0].ino = super_block.root_ino; 825 dent_blk->dentry[0].name_len = cpu_to_le16(1); 826 dent_blk->dentry[0].file_type = F2FS_FT_DIR; 827 memcpy(dent_blk->filename[0], ".", 1); 828 829 dent_blk->dentry[1].hash_code = 0; 830 dent_blk->dentry[1].ino = super_block.root_ino; 831 dent_blk->dentry[1].name_len = cpu_to_le16(2); 832 dent_blk->dentry[1].file_type = F2FS_FT_DIR; 833 memcpy(dent_blk->filename[1], "..", 2); 834 835 /* bitmap for . and .. */ 836 dent_blk->dentry_bitmap[0] = (1 << 1) | (1 << 0); 837 blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize); 838 data_blk_offset = le32_to_cpu(super_block.main_blkaddr); 839 data_blk_offset += config.cur_seg[CURSEG_HOT_DATA] * 840 config.blks_per_seg; 841 data_blk_offset *= blk_size_bytes; 842 843 DBG(1, "\tWriting default dentry root, at offset 0x%08"PRIx64"\n", data_blk_offset); 844 if (dev_write(dent_blk, data_blk_offset, F2FS_BLKSIZE)) { 845 MSG(1, "\tError: While writing the dentry_blk to disk!!!\n"); 846 return -1; 847 } 848 849 free(dent_blk); 850 return 0; 851} 852 853static int f2fs_create_root_dir(void) 854{ 855 int err = 0; 856 857 err = f2fs_write_root_inode(); 858 if (err < 0) { 859 MSG(1, "\tError: Failed to write root inode!!!\n"); 860 goto exit; 861 } 862 863 err = f2fs_update_nat_root(); 864 if (err < 0) { 865 MSG(1, "\tError: Failed to update NAT for root!!!\n"); 866 goto exit; 867 } 868 869 err = f2fs_add_default_dentry_root(); 870 if (err < 0) { 871 MSG(1, "\tError: Failed to add default dentries for root!!!\n"); 872 goto exit; 873 } 874exit: 875 if (err) 876 MSG(1, "\tError: Could not create the root directory!!!\n"); 877 878 return err; 879} 880 881int f2fs_format_device(void) 882{ 883 int err = 0; 884 885 err= f2fs_prepare_super_block(); 886 if (err < 0) { 887 MSG(0, "\tError: Failed to prepare a super block!!!\n"); 888 goto exit; 889 } 890 891 err = f2fs_trim_device(); 892 if (err < 0) { 893 MSG(0, "\tError: Failed to trim whole device!!!\n"); 894 goto exit; 895 } 896 897 err = f2fs_init_sit_area(); 898 if (err < 0) { 899 MSG(0, "\tError: Failed to Initialise the SIT AREA!!!\n"); 900 goto exit; 901 } 902 903 err = f2fs_init_nat_area(); 904 if (err < 0) { 905 MSG(0, "\tError: Failed to Initialise the NAT AREA!!!\n"); 906 goto exit; 907 } 908 909 err = f2fs_create_root_dir(); 910 if (err < 0) { 911 MSG(0, "\tError: Failed to create the root directory!!!\n"); 912 goto exit; 913 } 914 915 err = f2fs_write_check_point_pack(); 916 if (err < 0) { 917 MSG(0, "\tError: Failed to write the check point pack!!!\n"); 918 goto exit; 919 } 920 921 err = f2fs_write_super_block(); 922 if (err < 0) { 923 MSG(0, "\tError: Failed to write the Super Block!!!\n"); 924 goto exit; 925 } 926exit: 927 if (err) 928 MSG(0, "\tError: Could not format the device!!!\n"); 929 930 return err; 931} 932