f2fs_format.c revision 0bdc381123301faf15867e8728f6dca34d6a78d6
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
24extern struct f2fs_configuration config;
25struct f2fs_super_block sb;
26struct 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
91const 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
121static 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
158static 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
370static 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
404static 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
438static 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
690free_cp_payload:
691	free(cp_payload);
692free_sum_compact:
693	free(sum_compact);
694free_sum:
695	free(sum);
696free_cp:
697	free(cp);
698	return ret;
699}
700
701static 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
724static 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
803static 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
843static 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
885static 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	}
906exit:
907	if (err)
908		MSG(1, "\tError: Could not create the root directory!!!\n");
909
910	return err;
911}
912
913int 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	}
958exit:
959	if (err)
960		MSG(0, "\tError: Could not format the device!!!\n");
961
962	return err;
963}
964