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