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