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