f2fs_format.c revision 036d45e551ca5405c726f8ccb51f446620cd4af4
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 <errno.h>
19#include <mntent.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <sys/ioctl.h>
23#include <sys/mount.h>
24#include <linux/hdreg.h>
25#include <time.h>
26#include <linux/fs.h>
27
28#include "f2fs_format.h"
29
30struct f2fs_global_parameters f2fs_params;
31struct f2fs_super_block super_block;
32
33/**
34 * @brief     	This function will change a given string from ASCII to UNICODE
35 * @param	out_buf Output UNICODE string
36 * @param	in_buf Input ASCII string
37 * @return	None
38 */
39void ASCIIToUNICODE(u_int16_t *out_buf, u_int8_t *in_buf)
40{
41	u_int8_t *pchTempPtr = in_buf;
42	u_int16_t *pwTempPtr = out_buf;
43
44	while (*pchTempPtr != '\0') {
45		/* Copy the string elements character by character
46		 * to the output string with typecasting the source.
47		 */
48		*pwTempPtr = (u_int16_t)*pchTempPtr;
49		pchTempPtr++;
50		pwTempPtr++;
51	}
52	*pwTempPtr = '\0';
53	return;
54}
55
56/**
57 * @brief     	This function will ntitlize f2fs global paramenters
58 * @param	None
59 * @return	None
60 */
61static void f2fs_init_global_parameters(void)
62{
63	f2fs_params.sector_size = DEFAULT_SECTOR_SIZE;
64	f2fs_params.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
65	f2fs_params.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
66	f2fs_params.reserved_segments = 20; /* calculated by overprovision ratio */
67	f2fs_params.overprovision = 5;
68	f2fs_params.segs_per_sec = 1;
69	f2fs_params.secs_per_zone = 1;
70	f2fs_params.heap = 1;
71	memset(f2fs_params.vol_label, 0, sizeof(f2fs_params.vol_label));
72
73	f2fs_params.vol_label[0] = 'F';
74	f2fs_params.vol_label[1] = '2';
75	f2fs_params.vol_label[2] = 'F';
76	f2fs_params.vol_label[3] = 'S';
77	f2fs_params.vol_label[4] = '\0';
78	f2fs_params.device_name = NULL;
79}
80
81static inline int f2fs_set_bit(unsigned int nr, unsigned char *addr)
82{
83	int mask;
84	int ret;
85
86	addr += (nr >> 3);
87	mask = 1 << (7 - (nr & 0x07));
88	ret = mask & *addr;
89	*addr |= mask;
90	return ret;
91}
92
93/**
94 * @brief     	This function calculates log base 2 of given number
95 * @param	num an integer number
96 * @return	an int log base 2 of given number
97 */
98static int8_t log_base_2(u_int32_t num)
99{
100	int8_t ret = 0;
101
102	if (num <= 0 || (num & (num - 1)) != 0) {
103		return -1;
104	}
105
106	while (num >>= 1) {
107		ret++;
108	}
109
110	return ret;
111}
112
113/**
114 * @brief     	This function shows error if user gives wrong parameters
115 * @param	None
116 * @return	None
117 */
118static void f2fs_usage(void)
119{
120	fprintf(stderr, "Usage: f2fs_format [options] device\n");
121	fprintf(stderr, "[options]\n");
122	fprintf(stderr, "-l label\n");
123	fprintf(stderr, "-a heap-based allocation [default:1]\n");
124	fprintf(stderr, "-o overprovision ratio [default:5]\n");
125	fprintf(stderr, "-s # of segments per section [default:1]\n");
126	fprintf(stderr, "-z # of sections per zone [default:1]\n");
127	fprintf(stderr, "-e [extension list] e.g. \"mp3,gif,mov\"\n");
128	exit(1);
129}
130
131/**
132 * @brief     	This function calculates log base 2 of given number
133 * @param	argc number of arguments
134 * @param	argv an array of arguments
135 * @return	None
136 */
137static void f2fs_parse_options(int argc, char *argv[])
138{
139	static const char *option_string = "l:o:z:a:s:e:";
140	int32_t option=0;
141
142	while ((option = getopt(argc,argv,option_string)) != EOF) {
143		switch (option) {
144		case 'l':		/*v: volume label */
145			if (strlen(optarg) > 512) {
146				printf("Error: Volume Label should be less than \
147						512 characters\n");
148				f2fs_usage();
149			}
150			sprintf((char *)f2fs_params.vol_label, "%s", optarg);
151			break;
152		case 'o':
153			f2fs_params.overprovision = atoi(optarg);
154			printf("Info: Overprovision ratio = %u%%\n", atoi(optarg));
155			break;
156		case 's':
157			f2fs_params.segs_per_sec = atoi(optarg);
158			printf("Info: segments per section = %d\n", atoi(optarg));
159			break;
160		case 'a':
161			f2fs_params.heap = atoi(optarg);
162			if (f2fs_params.heap == 0)
163				printf("Info: Allocate without heap-based policy\n");
164			break;
165		case 'z':
166			f2fs_params.secs_per_zone = atoi(optarg);
167			printf("Info: sections per zone = %d\n", atoi(optarg));
168			break;
169		case 'e':
170			f2fs_params.extension_list = strdup(optarg);
171			break;
172		default:
173			printf("Error: Unknown option %c\n",option);
174			f2fs_usage();
175			break;
176		}
177	}
178
179	if ((optind + 1) != argc) {
180		printf("Error: Device not specified\n");
181		f2fs_usage();
182	}
183
184	f2fs_params.reserved_segments  =
185			(100 / f2fs_params.overprovision + 5)
186			* f2fs_params.segs_per_sec;
187	f2fs_params.device_name = argv[optind];
188}
189
190/**
191 * @brief     	Routine to  check if the device is already mounted
192 * @param	None
193 * @return	0 if device is not mounted
194 * 		-1 if already mounted
195 */
196static int8_t f2fs_is_device_mounted()
197{
198	FILE *file;
199	struct mntent *mnt; /* mntent structure to retrieve mount info */
200
201	if ((file = setmntent(MOUNTED, "r")) == NULL)
202		return 0;
203
204	while ((mnt = getmntent(file)) != NULL) {
205		if (!strcmp(f2fs_params.device_name, mnt->mnt_fsname)) {
206			printf("Error: %s is already mounted\n",
207					f2fs_params.device_name);
208			return -1;
209		}
210	}
211	endmntent(file);
212	return 0;
213}
214
215/**
216 * @brief     	Get device info - sector size, number of sectors etc
217 * @param	None
218 * @return	0 if successfully got device info
219 */
220static int8_t f2fs_get_device_info()
221{
222	int32_t fd = 0;
223	int32_t sector_size;
224	struct stat stat_buf;
225	struct hd_geometry geom;
226
227	fd = open(f2fs_params.device_name, O_RDWR);
228	if (fd < 0) {
229		printf("\n\tError: Failed to open the device!!!\n");
230		return -1;
231	}
232	f2fs_params.fd = fd;
233
234	if (fstat(fd, &stat_buf) < 0 ) {
235		printf("\n\tError: Failed to get the device stat!!!\n");
236		return -1;
237	}
238
239	if (S_ISREG(stat_buf.st_mode)) {
240		f2fs_params.total_sectors = stat_buf.st_size /
241			f2fs_params.sector_size;
242	}
243	else if (S_ISBLK(stat_buf.st_mode)) {
244		if (ioctl(fd, BLKSSZGET, &sector_size) < 0 )
245			printf("\n\tError: Cannot get the sector size!!! \
246					Using the default Sector Size\n");
247		else {
248			if (f2fs_params.sector_size < sector_size) {
249				printf("\n\tError: Cannot set the sector size to: %d"
250					" as the device does not support"
251					"\nSetting the sector size to : %d\n",
252					f2fs_params.sector_size, sector_size);
253				f2fs_params.sector_size = sector_size;
254				f2fs_params.sectors_per_blk = PAGE_SIZE / sector_size;
255			}
256		}
257
258		if (ioctl(fd, BLKGETSIZE, &f2fs_params.total_sectors) < 0) {
259			printf("\n\tError: Cannot get the device size\n");
260			return -1;
261		}
262
263		if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
264			printf("\n\tError: Cannot get the device geometry\n");
265			return -1;
266		}
267		f2fs_params.start_sector = geom.start;
268	}
269	else {
270		printf("\n\n\tError: Volume type is not supported!!!\n");
271		return -1;
272	}
273
274	printf("Info: sector size = %u\n", f2fs_params.sector_size);
275	printf("Info: total sectors = %llu (in 512bytes)\n", f2fs_params.total_sectors);
276	if (f2fs_params.total_sectors <
277			(F2FS_MIN_VOLUME_SIZE / DEFAULT_SECTOR_SIZE)) {
278		printf("Error: Min volume size supported is %d\n",
279				F2FS_MIN_VOLUME_SIZE);
280		return -1;
281	}
282
283	return 0;
284}
285
286const char *media_ext_lists[] = {
287	"jpg",
288	"gif",
289	"png",
290	"avi",
291	"divx",
292	"mp4",
293	"mp3",
294	"3gp",
295	"wmv",
296	"wma",
297	"mpeg",
298	"mkv",
299	"mov",
300	"asx",
301	"asf",
302	"wmx",
303	"svi",
304	"wvx",
305	"wm",
306	"mpg",
307	"mpe",
308	"rm",
309	"ogg",
310	NULL
311};
312
313static void configure_extension_list(void)
314{
315	const char **extlist = media_ext_lists;
316	char *ext_str = f2fs_params.extension_list;
317	char *ue;
318	int name_len;
319	int i = 0;
320
321	super_block.extension_count = 0;
322	memset(super_block.extension_list, 0,
323			sizeof(super_block.extension_list));
324
325	while (*extlist) {
326		name_len = strlen(*extlist);
327		memcpy(super_block.extension_list[i++], *extlist, name_len);
328		extlist++;
329	}
330	super_block.extension_count = i - 1;
331
332	if (!ext_str)
333		return;
334
335	/* add user ext list */
336	ue = strtok(ext_str, ",");
337	while (ue != NULL) {
338		name_len = strlen(ue);
339		memcpy(super_block.extension_list[i++], ue, name_len);
340		ue = strtok(NULL, ",");
341		if (i > F2FS_MAX_EXTENSION)
342			break;
343	}
344
345	super_block.extension_count = i - 1;
346
347	free(f2fs_params.extension_list);
348}
349
350
351/**
352 * @brief     	It writes buffer to disk or storage meant to be formatted
353 *		with F2FS.
354 * @param	fd File descriptor for device
355 * @param	buf buffer to be written
356 * @param	offset where to bw written on the device
357 * @param	length length of the device
358 * @return	0 if success
359 */
360static int writetodisk(int32_t fd, void *buf, u_int64_t offset, size_t length)
361{
362	if (lseek64(fd, offset, SEEK_SET) < 0) {
363		printf("\n\tError: While lseek to the derised location!!!\n");
364		return -1;
365	}
366
367	if (write(fd, buf, length) < 0) {
368		printf("\n\tError: While writing data to the disk!!! Error Num : \
369				%d\n", errno);
370		return -1;
371	}
372
373	return 0;
374}
375
376/**
377 * @brief     	It initialize F2FS super block
378 * @param	None
379 * @return	None
380 */
381static int f2fs_prepare_super_block(void)
382{
383	u_int32_t blk_size_bytes;
384	u_int32_t log_sectorsize, log_sectors_per_block;
385	u_int32_t log_blocksize, log_blks_per_seg;
386	u_int32_t segment_size_bytes, zone_size_bytes;
387	u_int32_t sit_segments;
388	u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa;
389	u_int32_t total_valid_blks_available;
390	u_int64_t zone_align_start_offset, diff, total_meta_segments;
391	u_int32_t sit_bitmap_size, max_nat_bitmap_size, max_nat_segments;
392	u_int32_t total_zones;
393
394	super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC);
395	super_block.major_ver = cpu_to_le16(F2FS_MAJOR_VERSION);
396	super_block.minor_ver = cpu_to_le16(F2FS_MINOR_VERSION);
397
398	log_sectorsize = log_base_2(f2fs_params.sector_size);
399	log_sectors_per_block = log_base_2(f2fs_params.sectors_per_blk);
400	log_blocksize = log_sectorsize + log_sectors_per_block;
401	log_blks_per_seg = log_base_2(f2fs_params.blks_per_seg);
402
403	super_block.log_sectorsize = cpu_to_le32(log_sectorsize);
404
405	if (log_sectorsize < 0) {
406		printf("\n\tError: Failed to get the sector size: %u!\n",
407				f2fs_params.sector_size);
408		return -1;
409	}
410
411	super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block);
412
413	if (log_sectors_per_block < 0) {
414		printf("\n\tError: Failed to get sectors per block: %u!\n",
415				f2fs_params.sectors_per_blk);
416		return -1;
417	}
418
419	super_block.log_blocksize = cpu_to_le32(log_blocksize);
420	super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg);
421
422	if (log_blks_per_seg < 0) {
423		printf("\n\tError: Failed to get block per segment: %u!\n",
424				f2fs_params.blks_per_seg);
425		return -1;
426	}
427
428	super_block.segs_per_sec = cpu_to_le32(f2fs_params.segs_per_sec);
429	super_block.secs_per_zone = cpu_to_le32(f2fs_params.secs_per_zone);
430	blk_size_bytes = 1 << log_blocksize;
431	segment_size_bytes = blk_size_bytes * f2fs_params.blks_per_seg;
432	zone_size_bytes =
433		blk_size_bytes * f2fs_params.secs_per_zone *
434		f2fs_params.segs_per_sec * f2fs_params.blks_per_seg;
435
436	super_block.checksum_offset = 0;
437
438	super_block.block_count = cpu_to_le64(
439		(f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE) /
440			blk_size_bytes);
441
442	zone_align_start_offset =
443		(f2fs_params.start_sector * DEFAULT_SECTOR_SIZE +
444		F2FS_SUPER_OFFSET * F2FS_BLKSIZE +
445		sizeof(struct f2fs_super_block) * 2 +
446		zone_size_bytes - 1) / zone_size_bytes * zone_size_bytes -
447		f2fs_params.start_sector * DEFAULT_SECTOR_SIZE;
448
449	if (f2fs_params.start_sector % DEFAULT_SECTORS_PER_BLOCK) {
450		printf("WARN: Align start sector number in a unit of pages\n");
451		printf("\ti.e., start sector: %d, ofs:%d (sectors per page: %d)\n",
452				f2fs_params.start_sector,
453				f2fs_params.start_sector % DEFAULT_SECTORS_PER_BLOCK,
454				DEFAULT_SECTORS_PER_BLOCK);
455	}
456
457	super_block.segment_count = cpu_to_le32(
458		((f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE) -
459		zone_align_start_offset) / segment_size_bytes);
460
461	super_block.segment0_blkaddr =
462		cpu_to_le32(zone_align_start_offset / blk_size_bytes);
463
464	printf("Info: zone aligned segment0 blkaddr: %u\n",
465				le32_to_cpu(super_block.segment0_blkaddr));
466
467	super_block.start_segment_checkpoint = super_block.segment0_blkaddr;
468	super_block.segment_count_ckpt =
469				cpu_to_le32(F2FS_NUMBER_OF_CHECKPOINT_PACK);
470
471	super_block.sit_blkaddr = cpu_to_le32(
472		le32_to_cpu(super_block.start_segment_checkpoint) +
473		(le32_to_cpu(super_block.segment_count_ckpt) *
474		(1 << log_blks_per_seg)));
475
476	blocks_for_sit = (le32_to_cpu(super_block.segment_count) +
477			SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK;
478
479	sit_segments = (blocks_for_sit + f2fs_params.blks_per_seg - 1)
480			/ f2fs_params.blks_per_seg;
481
482	super_block.segment_count_sit = cpu_to_le32(sit_segments * 2);
483
484	super_block.nat_blkaddr = cpu_to_le32(
485			le32_to_cpu(super_block.sit_blkaddr) +
486			(le32_to_cpu(super_block.segment_count_sit) *
487			 f2fs_params.blks_per_seg));
488
489	total_valid_blks_available = (le32_to_cpu(super_block.segment_count) -
490			(le32_to_cpu(super_block.segment_count_ckpt) +
491			 le32_to_cpu(super_block.segment_count_sit))) *
492			f2fs_params.blks_per_seg;
493
494	blocks_for_nat = (total_valid_blks_available + NAT_ENTRY_PER_BLOCK - 1)
495				/ NAT_ENTRY_PER_BLOCK;
496
497	super_block.segment_count_nat = cpu_to_le32(
498				(blocks_for_nat + f2fs_params.blks_per_seg - 1) /
499				f2fs_params.blks_per_seg);
500	/*
501	 * The number of node segments should not be exceeded a "Threshold".
502	 * This number resizes NAT bitmap area in a CP page.
503	 * So the threshold is determined not to overflow one CP page
504	 */
505	sit_bitmap_size = ((le32_to_cpu(super_block.segment_count_sit) / 2) <<
506				log_blks_per_seg) / 8;
507	max_nat_bitmap_size = 4096 - sizeof(struct f2fs_checkpoint) + 1 -
508			sit_bitmap_size;
509	max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg;
510
511	if (le32_to_cpu(super_block.segment_count_nat) > max_nat_segments)
512		super_block.segment_count_nat = cpu_to_le32(max_nat_segments);
513
514	super_block.segment_count_nat = cpu_to_le32(
515			le32_to_cpu(super_block.segment_count_nat) * 2);
516
517	super_block.ssa_blkaddr = cpu_to_le32(
518			le32_to_cpu(super_block.nat_blkaddr) +
519			le32_to_cpu(super_block.segment_count_nat) *
520			f2fs_params.blks_per_seg);
521
522	total_valid_blks_available = (le32_to_cpu(super_block.segment_count) -
523			(le32_to_cpu(super_block.segment_count_ckpt) +
524			le32_to_cpu(super_block.segment_count_sit) +
525			le32_to_cpu(super_block.segment_count_nat))) *
526			f2fs_params.blks_per_seg;
527
528	blocks_for_ssa = total_valid_blks_available /
529				f2fs_params.blks_per_seg + 1;
530
531	super_block.segment_count_ssa = cpu_to_le32(
532			(blocks_for_ssa + f2fs_params.blks_per_seg - 1) /
533			f2fs_params.blks_per_seg);
534
535	total_meta_segments = le32_to_cpu(super_block.segment_count_ckpt) +
536		le32_to_cpu(super_block.segment_count_sit) +
537		le32_to_cpu(super_block.segment_count_nat) +
538		le32_to_cpu(super_block.segment_count_ssa);
539	diff = total_meta_segments % (f2fs_params.segs_per_sec *
540						f2fs_params.secs_per_zone);
541	if (diff)
542		super_block.segment_count_ssa = cpu_to_le32(
543			le32_to_cpu(super_block.segment_count_ssa) +
544			(f2fs_params.segs_per_sec * f2fs_params.secs_per_zone -
545			 diff));
546
547	super_block.main_blkaddr = cpu_to_le32(
548			le32_to_cpu(super_block.ssa_blkaddr) +
549			(le32_to_cpu(super_block.segment_count_ssa) *
550			 f2fs_params.blks_per_seg));
551
552	super_block.segment_count_main = cpu_to_le32(
553			le32_to_cpu(super_block.segment_count) -
554			(le32_to_cpu(super_block.segment_count_ckpt)
555			 + le32_to_cpu(super_block.segment_count_sit) +
556			 le32_to_cpu(super_block.segment_count_nat) +
557			 le32_to_cpu(super_block.segment_count_ssa)));
558
559	super_block.section_count = cpu_to_le32(
560			le32_to_cpu(super_block.segment_count_main)
561			/ f2fs_params.segs_per_sec);
562
563	super_block.segment_count_main = cpu_to_le32(
564			le32_to_cpu(super_block.section_count) *
565			f2fs_params.segs_per_sec);
566
567	if ((le32_to_cpu(super_block.segment_count_main) - 2) <
568					f2fs_params.reserved_segments) {
569		printf("Error: Device size is not sufficient for F2FS volume, \
570			more segment needed =%u",
571			f2fs_params.reserved_segments -
572			(le32_to_cpu(super_block.segment_count_main) - 2));
573		return -1;
574	}
575
576	super_block.failure_safe_block_distance = 0;
577	super_block.volume_serial_number = 0;
578
579	ASCIIToUNICODE(super_block.volume_name, f2fs_params.vol_label);
580
581	super_block.node_ino = cpu_to_le32(1);
582	super_block.meta_ino = cpu_to_le32(2);
583	super_block.root_ino = cpu_to_le32(3);
584
585	total_zones = ((le32_to_cpu(super_block.segment_count_main) - 1) /
586			f2fs_params.segs_per_sec) /
587			f2fs_params.secs_per_zone;
588	if (total_zones <= 6) {
589		printf("\n\tError: %d zones: Need more zones \
590			by shrinking zone size\n", total_zones);
591		return -1;
592	}
593
594	if (f2fs_params.heap) {
595		f2fs_params.cur_seg[CURSEG_HOT_NODE] = (total_zones - 1) *
596					f2fs_params.segs_per_sec *
597					f2fs_params.secs_per_zone +
598					((f2fs_params.secs_per_zone - 1) *
599					f2fs_params.segs_per_sec);
600		f2fs_params.cur_seg[CURSEG_WARM_NODE] =
601					f2fs_params.cur_seg[CURSEG_HOT_NODE] -
602					f2fs_params.segs_per_sec *
603					f2fs_params.secs_per_zone;
604		f2fs_params.cur_seg[CURSEG_COLD_NODE] =
605					f2fs_params.cur_seg[CURSEG_WARM_NODE] -
606					f2fs_params.segs_per_sec *
607					f2fs_params.secs_per_zone;
608		f2fs_params.cur_seg[CURSEG_HOT_DATA] =
609					f2fs_params.cur_seg[CURSEG_COLD_NODE] -
610					f2fs_params.segs_per_sec *
611					f2fs_params.secs_per_zone;
612		f2fs_params.cur_seg[CURSEG_COLD_DATA] = 0;
613		f2fs_params.cur_seg[CURSEG_WARM_DATA] =
614					f2fs_params.cur_seg[CURSEG_COLD_DATA] +
615					f2fs_params.segs_per_sec *
616					f2fs_params.secs_per_zone;
617	} else {
618		f2fs_params.cur_seg[CURSEG_HOT_NODE] = 0;
619		f2fs_params.cur_seg[CURSEG_WARM_NODE] =
620					f2fs_params.cur_seg[CURSEG_HOT_NODE] +
621					f2fs_params.segs_per_sec *
622					f2fs_params.secs_per_zone;
623		f2fs_params.cur_seg[CURSEG_COLD_NODE] =
624					f2fs_params.cur_seg[CURSEG_WARM_NODE] +
625					f2fs_params.segs_per_sec *
626					f2fs_params.secs_per_zone;
627		f2fs_params.cur_seg[CURSEG_HOT_DATA] =
628					f2fs_params.cur_seg[CURSEG_COLD_NODE] +
629					f2fs_params.segs_per_sec *
630					f2fs_params.secs_per_zone;
631		f2fs_params.cur_seg[CURSEG_COLD_DATA] =
632					f2fs_params.cur_seg[CURSEG_HOT_DATA] +
633					f2fs_params.segs_per_sec *
634					f2fs_params.secs_per_zone;
635		f2fs_params.cur_seg[CURSEG_WARM_DATA] =
636					f2fs_params.cur_seg[CURSEG_COLD_DATA] +
637					f2fs_params.segs_per_sec *
638					f2fs_params.secs_per_zone;
639	}
640
641	configure_extension_list();
642
643	return 0;
644}
645
646/**
647 * @brief     	It initialize SIT Data structure
648 * @param	None
649 * @return	0 if success
650 */
651static int8_t f2fs_init_sit_area(void)
652{
653	u_int32_t blk_size_bytes;
654	u_int32_t seg_size_bytes;
655	u_int32_t index = 0;
656	u_int64_t sit_seg_blk_offset = 0;
657	u_int8_t *zero_buf = NULL;
658
659	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
660	seg_size_bytes = (1 << le32_to_cpu(super_block.log_blocks_per_seg)) *
661				blk_size_bytes;
662
663	zero_buf = calloc(sizeof(u_int8_t), seg_size_bytes);
664	if(zero_buf == NULL) {
665		printf("\n\tError: Calloc Failed for sit_zero_buf!!!\n");
666		return -1;
667	}
668
669	sit_seg_blk_offset = le32_to_cpu(super_block.sit_blkaddr) *
670						blk_size_bytes;
671
672	for (index = 0;
673		index < (le32_to_cpu(super_block.segment_count_sit) / 2);
674								index++) {
675		if (writetodisk(f2fs_params.fd, zero_buf, sit_seg_blk_offset,
676					seg_size_bytes) < 0) {
677			printf("\n\tError: While zeroing out the sit area \
678					on disk!!!\n");
679			return -1;
680		}
681		sit_seg_blk_offset = sit_seg_blk_offset + seg_size_bytes;
682	}
683
684	free(zero_buf);
685	return 0 ;
686}
687
688/**
689 * @brief     	It initialize NAT Area
690 * @param	None
691 * @return	0 if success
692 */
693static int8_t f2fs_init_nat_area(void)
694{
695	u_int32_t blk_size_bytes;
696	u_int32_t seg_size_bytes;
697	u_int32_t index = 0;
698	u_int64_t nat_seg_blk_offset = 0;
699	u_int8_t *nat_buf = NULL;
700
701	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
702	seg_size_bytes = (1 << le32_to_cpu(super_block.log_blocks_per_seg)) *
703					blk_size_bytes;
704
705	nat_buf = calloc(sizeof(u_int8_t), seg_size_bytes);
706	if (nat_buf == NULL) {
707		printf("\n\tError: Calloc Failed for nat_zero_blk!!!\n");
708		return -1;
709	}
710
711	nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr) *
712							blk_size_bytes;
713
714	for (index = 0;
715		index < (le32_to_cpu(super_block.segment_count_nat) / 2);
716								index++) {
717		if (writetodisk(f2fs_params.fd, nat_buf, nat_seg_blk_offset,
718					seg_size_bytes) < 0) {
719			printf("\n\tError: While zeroing out the nat area \
720					on disk!!!\n");
721			return -1;
722		}
723		nat_seg_blk_offset = nat_seg_blk_offset + (2 * seg_size_bytes);
724	}
725
726	free(nat_buf);
727	return 0 ;
728}
729
730#define CRCPOLY_LE 0xedb88320
731
732unsigned int f2fs_cal_crc32(unsigned int crc, void *buff, unsigned int len)
733{
734	int i;
735	unsigned char *p = (unsigned char *)buff;
736	while (len--) {
737		crc ^= *p++;
738		for (i = 0; i < 8; i++)
739			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
740	}
741	return crc;
742}
743
744/**
745 * @brief     	It writes check poiint pack on Check point Area
746 * @param	None
747 * @return	0 if succes
748 */
749static int8_t f2fs_write_check_point_pack(void)
750{
751	struct f2fs_checkpoint *ckp = NULL;
752	struct f2fs_summary_block *sum = NULL;
753	u_int32_t blk_size_bytes;
754	u_int64_t cp_seg_blk_offset = 0;
755	u_int32_t crc = 0;
756	int i;
757
758	ckp = calloc(F2FS_CP_BLOCK_SIZE, 1);
759	if (ckp == NULL) {
760		printf("\n\tError: Calloc Failed for f2fs_checkpoint!!!\n");
761		return -1;
762	}
763
764	sum = calloc(sizeof(struct f2fs_summary_block), 1);
765	if (sum == NULL) {
766		printf("\n\tError: Calloc Failed for summay_node!!!\n");
767		return -1;
768	}
769
770	/* 1. cp page 1 of checkpoint pack 1 */
771	ckp->checkpoint_ver = 1;
772	ckp->cur_node_segno[0] =
773		cpu_to_le32(f2fs_params.cur_seg[CURSEG_HOT_NODE]);
774	ckp->cur_node_segno[1] =
775		cpu_to_le32(f2fs_params.cur_seg[CURSEG_WARM_NODE]);
776	ckp->cur_node_segno[2] =
777		cpu_to_le32(f2fs_params.cur_seg[CURSEG_COLD_NODE]);
778	ckp->cur_data_segno[0] =
779		cpu_to_le32(f2fs_params.cur_seg[CURSEG_HOT_DATA]);
780	ckp->cur_data_segno[1] =
781		cpu_to_le32(f2fs_params.cur_seg[CURSEG_WARM_DATA]);
782	ckp->cur_data_segno[2] =
783		cpu_to_le32(f2fs_params.cur_seg[CURSEG_COLD_DATA]);
784	for (i = 3; i < MAX_ACTIVE_NODE_LOGS; i++) {
785		ckp->cur_node_segno[i] = 0xffffffff;
786		ckp->cur_data_segno[i] = 0xffffffff;
787	}
788
789	ckp->cur_node_blkoff[0] = cpu_to_le16(1);
790	ckp->nat_upd_blkoff[0] = cpu_to_le16(1);
791	ckp->cur_data_blkoff[0] = cpu_to_le16(1);
792	ckp->valid_block_count = cpu_to_le64(2);
793	ckp->rsvd_segment_count = cpu_to_le32(f2fs_params.reserved_segments);
794	ckp->overprov_segment_count = cpu_to_le32(
795			(le32_to_cpu(super_block.segment_count_main) -
796			le32_to_cpu(ckp->rsvd_segment_count)) *
797			f2fs_params.overprovision / 100);
798	ckp->overprov_segment_count = cpu_to_le32(
799			le32_to_cpu(ckp->overprov_segment_count) +
800			le32_to_cpu(ckp->rsvd_segment_count));
801
802	/* main segments - reserved segments - (node + data segments) */
803	ckp->free_segment_count = cpu_to_le32(
804			le32_to_cpu(super_block.segment_count_main) - 6);
805	ckp->user_block_count = cpu_to_le64(
806			((le32_to_cpu(ckp->free_segment_count) + 6 -
807			le32_to_cpu(ckp->overprov_segment_count)) *
808			 f2fs_params.blks_per_seg));
809	ckp->cp_pack_total_block_count = cpu_to_le32(5);
810	ckp->cp_pack_start_sum = cpu_to_le32(1);
811	ckp->valid_node_count = cpu_to_le32(1);
812	ckp->valid_inode_count = cpu_to_le32(1);
813	ckp->next_free_nid = cpu_to_le32(
814			le32_to_cpu(super_block.root_ino) + 1);
815
816	ckp->sit_ver_bitmap_bytesize = cpu_to_le32(
817			((le32_to_cpu(super_block.segment_count_sit) / 2) <<
818			 le32_to_cpu(super_block.log_blocks_per_seg)) / 8);
819
820	ckp->nat_ver_bitmap_bytesize = cpu_to_le32(
821			((le32_to_cpu(super_block.segment_count_nat) / 2) <<
822			 le32_to_cpu(super_block.log_blocks_per_seg)) / 8);
823
824	ckp->checksum_offset = cpu_to_le32(4092);
825
826	crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp,
827					le32_to_cpu(ckp->checksum_offset));
828	*((u_int32_t *)((unsigned char *)ckp +
829				le32_to_cpu(ckp->checksum_offset))) = crc;
830
831	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
832	cp_seg_blk_offset =
833		le32_to_cpu(super_block.start_segment_checkpoint) * blk_size_bytes;
834
835	if (writetodisk(f2fs_params.fd, ckp, cp_seg_blk_offset,
836				F2FS_CP_BLOCK_SIZE) < 0) {
837		printf("\n\tError: While writing the ckp to disk!!!\n");
838		return -1;
839	}
840
841	/* 2. Prepare and write Segment summary for data blocks */
842	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
843
844	sum->entries[0].nid = super_block.root_ino;
845	sum->entries[0].bidx = 0;
846
847	cp_seg_blk_offset += blk_size_bytes;
848	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
849				sizeof(struct f2fs_summary_block)) < 0) {
850		printf("\n\tError: While writing the sum_blk to disk!!!\n");
851		return -1;
852	}
853
854	/* 3. Fill segment summary for data block to zero. */
855	memset(sum, 0, sizeof(struct f2fs_summary_block));
856
857	cp_seg_blk_offset += blk_size_bytes;
858	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
859				sizeof(struct f2fs_summary_block)) < 0) {
860		printf("\n\tError: While writing the sum_blk to disk!!!\n");
861		return -1;
862	}
863
864	/* 4. Fill segment summary for data block to zero. */
865	memset(sum, 0, sizeof(struct f2fs_summary_block));
866
867	/* inode sit for root */
868	sum->n_sits = cpu_to_le16(6);
869	sum->sit_j.entries[0].segno = ckp->cur_node_segno[0];
870	sum->sit_j.entries[0].se.vblocks = cpu_to_le16((CURSEG_HOT_NODE << 10) | 1);
871	f2fs_set_bit(0, sum->sit_j.entries[0].se.valid_map);
872	sum->sit_j.entries[1].segno = ckp->cur_node_segno[1];
873	sum->sit_j.entries[1].se.vblocks = cpu_to_le16((CURSEG_WARM_NODE << 10));
874	sum->sit_j.entries[2].segno = ckp->cur_node_segno[2];
875	sum->sit_j.entries[2].se.vblocks = cpu_to_le16((CURSEG_COLD_NODE << 10));
876
877	/* data sit for root */
878	sum->sit_j.entries[3].segno = ckp->cur_data_segno[0];
879	sum->sit_j.entries[3].se.vblocks = cpu_to_le16((CURSEG_HOT_DATA << 10) | 1);
880	f2fs_set_bit(0, sum->sit_j.entries[3].se.valid_map);
881	sum->sit_j.entries[4].segno = ckp->cur_data_segno[1];
882	sum->sit_j.entries[4].se.vblocks = cpu_to_le16((CURSEG_WARM_DATA << 10));
883	sum->sit_j.entries[5].segno = ckp->cur_data_segno[2];
884	sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10));
885
886	cp_seg_blk_offset += blk_size_bytes;
887	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
888				sizeof(struct f2fs_summary_block)) < 0) {
889		printf("\n\tError: While writing the sum_blk to disk!!!\n");
890		return -1;
891	}
892
893	/* 5. cp page2 */
894	cp_seg_blk_offset += blk_size_bytes;
895	if (writetodisk(f2fs_params.fd, ckp, cp_seg_blk_offset,
896				F2FS_CP_BLOCK_SIZE) < 0) {
897		printf("\n\tError: While writing the ckp to disk!!!\n");
898		return -1;
899	}
900
901	/* 6. cp page 1 of check point pack 2
902	 * Initiatialize other checkpoint pack with version zero
903	 */
904	ckp->checkpoint_ver = 0;
905
906	crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp,
907					le32_to_cpu(ckp->checksum_offset));
908	*((u_int32_t *)((unsigned char *)ckp +
909				le32_to_cpu(ckp->checksum_offset))) = crc;
910
911	cp_seg_blk_offset = (le32_to_cpu(super_block.start_segment_checkpoint) +
912				f2fs_params.blks_per_seg) *
913				blk_size_bytes;
914	if (writetodisk(f2fs_params.fd, ckp,
915				cp_seg_blk_offset, F2FS_CP_BLOCK_SIZE) < 0) {
916		printf("\n\tError: While writing the ckp to disk!!!\n");
917		return -1;
918	}
919
920	/* 7. */
921	memset(sum, 0, sizeof(struct f2fs_summary_block));
922	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
923	cp_seg_blk_offset += blk_size_bytes;
924	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
925				sizeof(struct f2fs_summary_block)) < 0) {
926		printf("\n\tError: While writing the sum_blk to disk!!!\n");
927		return -1;
928	}
929
930	/* 8. */
931	memset(sum, 0, sizeof(struct f2fs_summary_block));
932	cp_seg_blk_offset += blk_size_bytes;
933	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
934				sizeof(struct f2fs_summary_block)) < 0) {
935		printf("\n\tError: While writing the sum_blk to disk!!!\n");
936		return -1;
937	}
938
939	/* 9. */
940	memset(sum, 0, sizeof(struct f2fs_summary_block));
941	cp_seg_blk_offset += blk_size_bytes;
942	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
943				sizeof(struct f2fs_summary_block)) < 0) {
944		printf("\n\tError: While writing the sum_blk to disk!!!\n");
945		return -1;
946	}
947
948	/* 10. cp page 2 of check point pack 2 */
949	cp_seg_blk_offset += blk_size_bytes;
950	if (writetodisk(f2fs_params.fd, ckp, cp_seg_blk_offset,
951				F2FS_CP_BLOCK_SIZE) < 0) {
952		printf("\n\tError: While writing the ckp to disk!!!\n");
953		return -1;
954	}
955
956	free(sum) ;
957	free(ckp) ;
958	return	0;
959}
960
961/**
962 * @brief     	It writes super block on device
963 * @param	None
964 * @return	0 if success
965 */
966static int8_t f2fs_write_super_block(void)
967{
968	u_int32_t index = 0;
969	u_int64_t super_blk_offset;
970	u_int8_t *zero_buff;
971
972	zero_buff = calloc(f2fs_params.sector_size, 1);
973	super_blk_offset = F2FS_SUPER_OFFSET * F2FS_BLKSIZE;
974
975	for (index = 0; index < 2; index++) {
976		if (writetodisk(f2fs_params.fd, &super_block, super_blk_offset,
977					sizeof(struct f2fs_super_block)) < 0) {
978			printf("\n\tError: While while writing supe_blk \
979					on disk!!! index : %d\n", index);
980			return -1;
981		}
982		super_blk_offset += F2FS_BLKSIZE;
983	}
984
985	free(zero_buff);
986	return 0;
987}
988
989/**
990 * @brief     	It initializes and writes root inode on device.
991 * @param	None
992 * @return	0 if success
993 */
994static int8_t f2fs_write_root_inode(void)
995{
996	struct f2fs_node *raw_node = NULL;
997	u_int32_t blk_size_bytes;
998	u_int64_t data_blk_nor;
999	u_int64_t main_area_node_seg_blk_offset = 0;
1000
1001	raw_node = calloc(sizeof(struct f2fs_node), 1);
1002	if (raw_node == NULL) {
1003		printf("\n\tError: Calloc Failed for raw_node!!!\n");
1004		return -1;
1005	}
1006
1007	raw_node->footer.nid = super_block.root_ino;
1008	raw_node->footer.ino = super_block.root_ino;
1009	raw_node->footer.cp_ver = cpu_to_le64(1);
1010	raw_node->footer.next_blkaddr = cpu_to_le32(
1011			le32_to_cpu(super_block.main_blkaddr) +
1012			f2fs_params.cur_seg[CURSEG_HOT_NODE] *
1013			f2fs_params.blks_per_seg + 1);
1014
1015	raw_node->i.i_mode = cpu_to_le16(0x41ed);
1016	raw_node->i.i_links = cpu_to_le32(2);
1017	raw_node->i.i_uid = cpu_to_le32(getuid());
1018	raw_node->i.i_gid = cpu_to_le32(getgid());
1019
1020	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
1021	raw_node->i.i_size = cpu_to_le64(1 * blk_size_bytes); /* dentry */
1022	raw_node->i.i_blocks = cpu_to_le64(2);
1023
1024	raw_node->i.i_ctime = cpu_to_le32(time(NULL));
1025	raw_node->i.i_ctime_nsec = 0;
1026	raw_node->i.i_mtime = cpu_to_le32(time(NULL));
1027	raw_node->i.i_mtime_nsec = 0;
1028	raw_node->i.i_xattr_nid = 0;
1029	raw_node->i.i_flags = 0;
1030	raw_node->i.current_depth = cpu_to_le32(1);
1031
1032	data_blk_nor = le32_to_cpu(super_block.main_blkaddr) +
1033		f2fs_params.cur_seg[CURSEG_HOT_DATA] * f2fs_params.blks_per_seg;
1034	raw_node->i.i_addr[0] = cpu_to_le32(data_blk_nor);
1035
1036	raw_node->i.i_ext.fofs = 0;
1037	raw_node->i.i_ext.blk_addr = cpu_to_le32(data_blk_nor);
1038	raw_node->i.i_ext.len = cpu_to_le32(1);
1039
1040	main_area_node_seg_blk_offset = le32_to_cpu(super_block.main_blkaddr);
1041	main_area_node_seg_blk_offset += f2fs_params.cur_seg[CURSEG_HOT_NODE] *
1042					f2fs_params.blks_per_seg;
1043        main_area_node_seg_blk_offset *= blk_size_bytes;
1044
1045	if (writetodisk(f2fs_params.fd, raw_node, main_area_node_seg_blk_offset,
1046				sizeof(struct f2fs_node)) < 0) {
1047		printf("\n\tError: While writing the raw_node to disk!!!\n");
1048		return -1;
1049	}
1050
1051	memset(raw_node, 0xff, sizeof(struct f2fs_node));
1052
1053	if (writetodisk(f2fs_params.fd, raw_node,
1054				main_area_node_seg_blk_offset + 4096,
1055				sizeof(struct f2fs_node)) < 0) {
1056		printf("\n\tError: While writing the raw_node to disk!!!\n");
1057		return -1;
1058	}
1059	free(raw_node);
1060	return 0;
1061}
1062
1063/**
1064 * @brief     	It updates NAT for root Inode
1065 * @param	None
1066 * @return	0 if success
1067 */
1068static int8_t f2fs_update_nat_root(void)
1069{
1070	struct f2fs_nat_block *nat_blk = NULL;
1071	u_int32_t blk_size_bytes;
1072	u_int64_t nat_seg_blk_offset = 0;
1073
1074	nat_blk = calloc(sizeof(struct f2fs_nat_block), 1);
1075	if(nat_blk == NULL) {
1076		printf("\n\tError: Calloc Failed for nat_blk!!!\n");
1077		return -1;
1078	}
1079
1080	/* update root */
1081	nat_blk->entries[super_block.root_ino].block_addr = cpu_to_le32(
1082		le32_to_cpu(super_block.main_blkaddr) +
1083		f2fs_params.cur_seg[CURSEG_HOT_NODE] * f2fs_params.blks_per_seg);
1084	nat_blk->entries[super_block.root_ino].ino = super_block.root_ino;
1085
1086	/* update node nat */
1087	nat_blk->entries[super_block.node_ino].block_addr = cpu_to_le32(1);
1088	nat_blk->entries[super_block.node_ino].ino = super_block.node_ino;
1089
1090	/* update meta nat */
1091	nat_blk->entries[super_block.meta_ino].block_addr = cpu_to_le32(1);
1092	nat_blk->entries[super_block.meta_ino].ino = super_block.meta_ino;
1093
1094	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
1095
1096	nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr) *
1097							blk_size_bytes;
1098
1099	if (writetodisk(f2fs_params.fd, nat_blk, nat_seg_blk_offset,
1100				sizeof(struct f2fs_nat_block)) < 0) {
1101		printf("\n\tError: While writing the nat_blk set0 to disk!!!\n");
1102		return -1;
1103	}
1104
1105	free(nat_blk);
1106	return 0;
1107}
1108
1109/**
1110 * @brief     	It updates default dentries in Root Inode
1111 * @param	None
1112 * @return	0 if success
1113 */
1114static int8_t f2fs_add_default_dentry_root(void)
1115{
1116	struct f2fs_dentry_block *dent_blk = NULL;
1117	u_int32_t blk_size_bytes;
1118	u_int64_t data_blk_offset = 0;
1119
1120	dent_blk = calloc(sizeof(struct f2fs_dentry_block), 1);
1121	if(dent_blk == NULL) {
1122		printf("\n\tError: Calloc Failed for dent_blk!!!\n");
1123		return -1;
1124	}
1125
1126	dent_blk->dentry[0].hash_code = 0;
1127	dent_blk->dentry[0].ino = super_block.root_ino;
1128	dent_blk->dentry[0].name_len = cpu_to_le16(1);
1129	dent_blk->dentry[0].file_type = F2FS_FT_DIR;
1130	memcpy(dent_blk->filename[0], ".", 1);
1131
1132	dent_blk->dentry[1].hash_code = 0;
1133	dent_blk->dentry[1].ino = super_block.root_ino;
1134	dent_blk->dentry[1].name_len = cpu_to_le16(2);
1135	dent_blk->dentry[1].file_type = F2FS_FT_DIR;
1136	memcpy(dent_blk->filename[1], "..", 2);
1137
1138	/* bitmap for . and .. */
1139	dent_blk->dentry_bitmap[0] = (1 << 1) | (1 << 0);
1140	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
1141	data_blk_offset = (le32_to_cpu(super_block.main_blkaddr) +
1142			f2fs_params.cur_seg[CURSEG_HOT_DATA] *
1143			f2fs_params.blks_per_seg) * blk_size_bytes;
1144
1145	if (writetodisk(f2fs_params.fd, dent_blk, data_blk_offset,
1146				sizeof(struct f2fs_dentry_block)) < 0) {
1147		printf("\n\tError: While writing the dentry_blk to disk!!!\n");
1148		return -1;
1149	}
1150
1151	free(dent_blk);
1152	return 0;
1153}
1154
1155/**
1156 * @brief     	It creates root directory on device.
1157 * @param	None
1158 * @return	0 if success
1159 */
1160static int8_t f2fs_create_root_dir(void)
1161{
1162	int8_t err = 0;
1163
1164	err = f2fs_write_root_inode();
1165	if (err < 0) {
1166		printf("\n\tError: Failed to write root inode!!!\n");
1167		goto exit;
1168	}
1169
1170	err = f2fs_update_nat_root();
1171	if (err < 0) {
1172		printf("\n\tError: Failed to update NAT for root!!!\n");
1173		goto exit;
1174	}
1175
1176	err = f2fs_add_default_dentry_root();
1177	if (err < 0) {
1178		printf("\n\tError: Failed to add default dentries for root!!!\n");
1179		goto exit;
1180	}
1181exit:
1182	if (err)
1183		printf("\n\tError: Could not create the root directory!!!\n");
1184
1185	return err;
1186}
1187
1188int f2fs_trim_device()
1189{
1190	unsigned long long range[2];
1191	struct stat stat_buf;
1192
1193	range[0] = 0;
1194	range[1] = f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE;
1195
1196	if (fstat(f2fs_params.fd, &stat_buf) < 0 ) {
1197		printf("\n\tError: Failed to get the device stat!!!\n");
1198		return -1;
1199	}
1200
1201	if (S_ISREG(stat_buf.st_mode))
1202		return 0;
1203	else if (S_ISBLK(stat_buf.st_mode)) {
1204		if (ioctl(f2fs_params.fd, BLKDISCARD, &range) < 0)
1205			printf("Info: This device doesn't support TRIM\n");
1206	} else
1207		return -1;
1208	return 0;
1209}
1210
1211/**
1212 * @brief     	It s a routine to fromat device with F2FS on-disk layout
1213 * @param	None
1214 * @return	0 if success
1215 */
1216static int8_t f2fs_format_device(void)
1217{
1218	int8_t err = 0;
1219
1220	err= f2fs_prepare_super_block();
1221	if (err < 0)
1222		goto exit;
1223
1224	err = f2fs_trim_device();
1225	if (err < 0) {
1226		printf("\n\tError: Failed to trim whole device!!!\n");
1227		goto exit;
1228	}
1229
1230	err = f2fs_init_sit_area();
1231	if (err < 0) {
1232		printf("\n\tError: Failed to Initialise the SIT AREA!!!\n");
1233		goto exit;
1234	}
1235
1236	err = f2fs_init_nat_area();
1237	if (err < 0) {
1238		printf("\n\tError: Failed to Initialise the NAT AREA!!!\n");
1239		goto exit;
1240	}
1241
1242	err = f2fs_create_root_dir();
1243	if (err < 0) {
1244		printf("\n\tError: Failed to create the root directory!!!\n");
1245		goto exit;
1246	}
1247
1248	err = f2fs_write_check_point_pack();
1249	if (err < 0) {
1250		printf("\n\tError: Failed to write the check point pack!!!\n");
1251		goto exit;
1252	}
1253
1254	err = f2fs_write_super_block();
1255	if (err < 0) {
1256		printf("\n\tError: Failed to write the Super Block!!!\n");
1257		goto exit;
1258	}
1259exit:
1260	if (err)
1261		printf("\n\tError: Could not format the device!!!\n");
1262
1263	/*
1264	 * We should call fsync() to flush out all the dirty pages
1265	 * in the block device page cache.
1266	 */
1267	if (fsync(f2fs_params.fd) < 0)
1268		printf("\n\tError: Could not conduct fsync!!!\n");
1269
1270	if (close(f2fs_params.fd) < 0)
1271		printf("\n\tError: Failed to close device file!!!\n");
1272
1273	return err;
1274}
1275
1276/**
1277 * @brief     	main function of F2Fs utility
1278 * @param	argc count of argument
1279 * @param	argv array of arguments
1280 * @return	0 if success
1281 */
1282int main(int argc, char *argv[])
1283{
1284	f2fs_init_global_parameters();
1285
1286	f2fs_parse_options(argc, argv);
1287
1288	if (f2fs_is_device_mounted() < 0)
1289		return -1;
1290
1291	if (f2fs_get_device_info() < 0)
1292		return -1;
1293
1294	if (f2fs_format_device() < 0)
1295		return -1;
1296
1297	printf("Info: format successful\n");
1298
1299	return 0;
1300}
1301