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