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 super_block;
26
27 const 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
configure_extension_list(void)57 static 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
f2fs_prepare_super_block(void)94 static 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
f2fs_init_sit_area(void)337 static 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
f2fs_init_nat_area(void)373 static 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
f2fs_write_check_point_pack(void)409 static 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(
474 le32_to_cpu(super_block.root_ino) + 1);
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
f2fs_write_super_block(void)627 static 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
f2fs_write_root_inode(void)649 static 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
f2fs_update_nat_root(void)726 static 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
f2fs_add_default_dentry_root(void)765 static 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
f2fs_create_root_dir(void)806 static 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 }
827 exit:
828 if (err)
829 MSG(1, "\tError: Could not create the root directory!!!\n");
830
831 return err;
832 }
833
f2fs_format_device(void)834 int 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 }
879 exit:
880 if (err)
881 MSG(0, "\tError: Could not format the device!!!\n");
882
883 return err;
884 }
885