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