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