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