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