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