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