f2fs_format.c revision d2387723a8f47a3c860d2c67436232ccad764caf
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 <inttypes.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <fcntl.h>
17#include <string.h>
18#include <unistd.h>
19#include <errno.h>
20#include <mntent.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <sys/ioctl.h>
24#include <sys/mount.h>
25#include <linux/hdreg.h>
26#include <time.h>
27#include <linux/fs.h>
28#include <uuid/uuid.h>
29
30#include "f2fs_format.h"
31
32struct f2fs_global_parameters f2fs_params;
33struct f2fs_super_block super_block;
34
35/**
36 * @brief     	This function will change a given string from ASCII to UNICODE
37 * @param	out_buf Output UNICODE string
38 * @param	in_buf Input ASCII string
39 * @return	None
40 */
41void ASCIIToUNICODE(u_int16_t *out_buf, u_int8_t *in_buf)
42{
43	u_int8_t *pchTempPtr = in_buf;
44	u_int16_t *pwTempPtr = out_buf;
45
46	while (*pchTempPtr != '\0') {
47		/* Copy the string elements character by character
48		 * to the output string with typecasting the source.
49		 */
50		*pwTempPtr = (u_int16_t)*pchTempPtr;
51		pchTempPtr++;
52		pwTempPtr++;
53	}
54	*pwTempPtr = '\0';
55	return;
56}
57
58/**
59 * @brief     	This function will ntitlize f2fs global paramenters
60 * @param	None
61 * @return	None
62 */
63static void f2fs_init_global_parameters(void)
64{
65	f2fs_params.sector_size = DEFAULT_SECTOR_SIZE;
66	f2fs_params.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
67	f2fs_params.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
68	f2fs_params.reserved_segments = 48; /* calculated by overprovision ratio */
69	f2fs_params.overprovision = 5;
70	f2fs_params.segs_per_sec = 1;
71	f2fs_params.secs_per_zone = 1;
72	f2fs_params.heap = 1;
73	memset(f2fs_params.vol_label, 0, sizeof(f2fs_params.vol_label));
74
75	f2fs_params.vol_label[0] = 'F';
76	f2fs_params.vol_label[1] = '2';
77	f2fs_params.vol_label[2] = 'F';
78	f2fs_params.vol_label[3] = 'S';
79	f2fs_params.vol_label[4] = '\0';
80	f2fs_params.device_name = NULL;
81}
82
83static inline int f2fs_set_bit(unsigned int nr, unsigned char *addr)
84{
85	int mask;
86	int ret;
87
88	addr += (nr >> 3);
89	mask = 1 << (7 - (nr & 0x07));
90	ret = mask & *addr;
91	*addr |= mask;
92	return ret;
93}
94
95/**
96 * @brief     	This function calculates log base 2 of given number
97 * @param	num an integer number
98 * @return	an int log base 2 of given number
99 */
100static int8_t log_base_2(u_int32_t num)
101{
102	int8_t ret = 0;
103
104	if (num <= 0 || (num & (num - 1)) != 0) {
105		return -1;
106	}
107
108	while (num >>= 1) {
109		ret++;
110	}
111
112	return ret;
113}
114
115/**
116 * @brief     	This function shows error if user gives wrong parameters
117 * @param	None
118 * @return	None
119 */
120static void f2fs_usage(void)
121{
122	fprintf(stderr, "Usage: f2fs_format [options] device\n");
123	fprintf(stderr, "[options]\n");
124	fprintf(stderr, "-l label\n");
125	fprintf(stderr, "-a heap-based allocation [default:1]\n");
126	fprintf(stderr, "-o overprovision ratio [default:5]\n");
127	fprintf(stderr, "-s # of segments per section [default:1]\n");
128	fprintf(stderr, "-z # of sections per zone [default:1]\n");
129	fprintf(stderr, "-e [extension list] e.g. \"mp3,gif,mov\"\n");
130	exit(1);
131}
132
133/**
134 * @brief     	This function calculates log base 2 of given number
135 * @param	argc number of arguments
136 * @param	argv an array of arguments
137 * @return	None
138 */
139static void f2fs_parse_options(int argc, char *argv[])
140{
141	static const char *option_string = "l:o:z:a:s:e:";
142	int32_t option=0;
143
144	while ((option = getopt(argc,argv,option_string)) != EOF) {
145		switch (option) {
146		case 'l':		/*v: volume label */
147			if (strlen(optarg) > 512) {
148				printf("Error: Volume Label should be less than \
149						512 characters\n");
150				f2fs_usage();
151			}
152			sprintf((char *)f2fs_params.vol_label, "%s", optarg);
153			break;
154		case 'o':
155			f2fs_params.overprovision = atoi(optarg);
156			printf("Info: Overprovision ratio = %u%%\n", atoi(optarg));
157			break;
158		case 's':
159			f2fs_params.segs_per_sec = atoi(optarg);
160			printf("Info: segments per section = %d\n", atoi(optarg));
161			break;
162		case 'a':
163			f2fs_params.heap = atoi(optarg);
164			if (f2fs_params.heap == 0)
165				printf("Info: Allocate without heap-based policy\n");
166			break;
167		case 'z':
168			f2fs_params.secs_per_zone = atoi(optarg);
169			printf("Info: sections per zone = %d\n", atoi(optarg));
170			break;
171		case 'e':
172			f2fs_params.extension_list = strdup(optarg);
173			break;
174		default:
175			printf("Error: Unknown option %c\n",option);
176			f2fs_usage();
177			break;
178		}
179	}
180
181	if ((optind + 1) != argc) {
182		printf("Error: Device not specified\n");
183		f2fs_usage();
184	}
185
186	f2fs_params.reserved_segments  =
187			(2 * (100 / f2fs_params.overprovision + 1) + 6)
188			* f2fs_params.segs_per_sec;
189	f2fs_params.device_name = argv[optind];
190}
191
192/**
193 * @brief     	Routine to  check if the device is already mounted
194 * @param	None
195 * @return	0 if device is not mounted
196 * 		-1 if already mounted
197 */
198static int8_t f2fs_is_device_mounted()
199{
200	FILE *file;
201	struct mntent *mnt; /* mntent structure to retrieve mount info */
202
203	if ((file = setmntent(MOUNTED, "r")) == NULL)
204		return 0;
205
206	while ((mnt = getmntent(file)) != NULL) {
207		if (!strcmp(f2fs_params.device_name, mnt->mnt_fsname)) {
208			printf("Error: %s is already mounted\n",
209					f2fs_params.device_name);
210			return -1;
211		}
212	}
213	endmntent(file);
214	return 0;
215}
216
217/**
218 * @brief     	Get device info - sector size, number of sectors etc
219 * @param	None
220 * @return	0 if successfully got device info
221 */
222static int8_t f2fs_get_device_info()
223{
224	int32_t fd = 0;
225	int32_t sector_size;
226	struct stat stat_buf;
227	struct hd_geometry geom;
228
229	fd = open(f2fs_params.device_name, O_RDWR);
230	if (fd < 0) {
231		printf("\n\tError: Failed to open the device!!!\n");
232		return -1;
233	}
234	f2fs_params.fd = fd;
235
236	if (fstat(fd, &stat_buf) < 0 ) {
237		printf("\n\tError: Failed to get the device stat!!!\n");
238		return -1;
239	}
240
241	if (S_ISREG(stat_buf.st_mode)) {
242		f2fs_params.total_sectors = stat_buf.st_size /
243			f2fs_params.sector_size;
244	}
245	else if (S_ISBLK(stat_buf.st_mode)) {
246		if (ioctl(fd, BLKSSZGET, &sector_size) < 0 )
247			printf("\n\tError: Cannot get the sector size!!! \
248					Using the default Sector Size\n");
249		else {
250			if (f2fs_params.sector_size < sector_size) {
251				printf("\n\tError: Cannot set the sector size to: %d"
252					" as the device does not support"
253					"\nSetting the sector size to : %d\n",
254					f2fs_params.sector_size, sector_size);
255				f2fs_params.sector_size = sector_size;
256				f2fs_params.sectors_per_blk = PAGE_SIZE / sector_size;
257			}
258		}
259
260		if (ioctl(fd, BLKGETSIZE, &f2fs_params.total_sectors) < 0) {
261			printf("\n\tError: Cannot get the device size\n");
262			return -1;
263		}
264
265		if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
266			f2fs_params.start_sector = 0;
267		else
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 = %"PRIu64" (in 512bytes)\n",
277					f2fs_params.total_sectors);
278	if (f2fs_params.total_sectors <
279			(F2FS_MIN_VOLUME_SIZE / DEFAULT_SECTOR_SIZE)) {
280		printf("Error: Min volume size supported is %d\n",
281				F2FS_MIN_VOLUME_SIZE);
282		return -1;
283	}
284
285	return 0;
286}
287
288const char *media_ext_lists[] = {
289	"jpg",
290	"gif",
291	"png",
292	"avi",
293	"divx",
294	"mp4",
295	"mp3",
296	"3gp",
297	"wmv",
298	"wma",
299	"mpeg",
300	"mkv",
301	"mov",
302	"asx",
303	"asf",
304	"wmx",
305	"svi",
306	"wvx",
307	"wm",
308	"mpg",
309	"mpe",
310	"rm",
311	"ogg",
312	NULL
313};
314
315static void configure_extension_list(void)
316{
317	const char **extlist = media_ext_lists;
318	char *ext_str = f2fs_params.extension_list;
319	char *ue;
320	int name_len;
321	int i = 0;
322
323	super_block.extension_count = 0;
324	memset(super_block.extension_list, 0,
325			sizeof(super_block.extension_list));
326
327	while (*extlist) {
328		name_len = strlen(*extlist);
329		memcpy(super_block.extension_list[i++], *extlist, name_len);
330		extlist++;
331	}
332	super_block.extension_count = i - 1;
333
334	if (!ext_str)
335		return;
336
337	/* add user ext list */
338	ue = strtok(ext_str, ",");
339	while (ue != NULL) {
340		name_len = strlen(ue);
341		memcpy(super_block.extension_list[i++], ue, name_len);
342		ue = strtok(NULL, ",");
343		if (i > F2FS_MAX_EXTENSION)
344			break;
345	}
346
347	super_block.extension_count = i - 1;
348
349	free(f2fs_params.extension_list);
350}
351
352
353/**
354 * @brief     	It writes buffer to disk or storage meant to be formatted
355 *		with F2FS.
356 * @param	fd File descriptor for device
357 * @param	buf buffer to be written
358 * @param	offset where to bw written on the device
359 * @param	length length of the device
360 * @return	0 if success
361 */
362static int writetodisk(int32_t fd, void *buf, u_int64_t offset, size_t length)
363{
364	if (lseek64(fd, offset, SEEK_SET) < 0) {
365		printf("\n\tError: While lseek to the derised location!!!\n");
366		return -1;
367	}
368
369	if (write(fd, buf, length) < 0) {
370		printf("\n\tError: While writing data to the disk!!! Error Num : \
371				%d\n", errno);
372		return -1;
373	}
374
375	return 0;
376}
377
378/**
379 * @brief     	It initialize F2FS super block
380 * @param	None
381 * @return	None
382 */
383static int f2fs_prepare_super_block(void)
384{
385	u_int32_t blk_size_bytes;
386	u_int32_t log_sectorsize, log_sectors_per_block;
387	u_int32_t log_blocksize, log_blks_per_seg;
388	u_int32_t segment_size_bytes, zone_size_bytes;
389	u_int32_t sit_segments;
390	u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa;
391	u_int32_t total_valid_blks_available;
392	u_int64_t zone_align_start_offset, diff, total_meta_segments;
393	u_int32_t sit_bitmap_size, max_nat_bitmap_size, max_nat_segments;
394	u_int32_t total_zones;
395
396	super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC);
397	super_block.major_ver = cpu_to_le16(F2FS_MAJOR_VERSION);
398	super_block.minor_ver = cpu_to_le16(F2FS_MINOR_VERSION);
399
400	log_sectorsize = log_base_2(f2fs_params.sector_size);
401	log_sectors_per_block = log_base_2(f2fs_params.sectors_per_blk);
402	log_blocksize = log_sectorsize + log_sectors_per_block;
403	log_blks_per_seg = log_base_2(f2fs_params.blks_per_seg);
404
405	super_block.log_sectorsize = cpu_to_le32(log_sectorsize);
406
407	if (log_sectorsize < 0) {
408		printf("\n\tError: Failed to get the sector size: %u!\n",
409				f2fs_params.sector_size);
410		return -1;
411	}
412
413	super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block);
414
415	if (log_sectors_per_block < 0) {
416		printf("\n\tError: Failed to get sectors per block: %u!\n",
417				f2fs_params.sectors_per_blk);
418		return -1;
419	}
420
421	super_block.log_blocksize = cpu_to_le32(log_blocksize);
422	super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg);
423
424	if (log_blks_per_seg < 0) {
425		printf("\n\tError: Failed to get block per segment: %u!\n",
426				f2fs_params.blks_per_seg);
427		return -1;
428	}
429
430	super_block.segs_per_sec = cpu_to_le32(f2fs_params.segs_per_sec);
431	super_block.secs_per_zone = cpu_to_le32(f2fs_params.secs_per_zone);
432	blk_size_bytes = 1 << log_blocksize;
433	segment_size_bytes = blk_size_bytes * f2fs_params.blks_per_seg;
434	zone_size_bytes =
435		blk_size_bytes * f2fs_params.secs_per_zone *
436		f2fs_params.segs_per_sec * f2fs_params.blks_per_seg;
437
438	super_block.checksum_offset = 0;
439
440	super_block.block_count = cpu_to_le64(
441		(f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE) /
442			blk_size_bytes);
443
444	zone_align_start_offset =
445		(f2fs_params.start_sector * DEFAULT_SECTOR_SIZE +
446		2 * F2FS_BLKSIZE + zone_size_bytes - 1) /
447		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	super_block.cp_blkaddr = super_block.segment0_blkaddr;
465
466	printf("Info: zone aligned segment0 blkaddr: %u\n",
467				le32_to_cpu(super_block.segment0_blkaddr));
468
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.segment0_blkaddr) +
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	uuid_generate(super_block.uuid);
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	nat_seg_blk_offset *= 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->cur_data_blkoff[0] = cpu_to_le16(1);
791	ckp->valid_block_count = cpu_to_le64(2);
792	ckp->rsvd_segment_count = cpu_to_le32(f2fs_params.reserved_segments);
793	ckp->overprov_segment_count = cpu_to_le32(
794			(le32_to_cpu(super_block.segment_count_main) -
795			le32_to_cpu(ckp->rsvd_segment_count)) *
796			f2fs_params.overprovision / 100);
797	ckp->overprov_segment_count = cpu_to_le32(
798			le32_to_cpu(ckp->overprov_segment_count) +
799			le32_to_cpu(ckp->rsvd_segment_count));
800
801	/* main segments - reserved segments - (node + data segments) */
802	ckp->free_segment_count = cpu_to_le32(
803			le32_to_cpu(super_block.segment_count_main) - 6);
804	ckp->user_block_count = cpu_to_le64(
805			((le32_to_cpu(ckp->free_segment_count) + 6 -
806			le32_to_cpu(ckp->overprov_segment_count)) *
807			 f2fs_params.blks_per_seg));
808	ckp->cp_pack_total_block_count = cpu_to_le32(8);
809	ckp->ckpt_flags |= CP_UMOUNT_FLAG;
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 = le32_to_cpu(super_block.segment0_blkaddr);
833	cp_seg_blk_offset *= 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	memset(sum, 0, sizeof(struct f2fs_summary_block));
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	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
858
859	cp_seg_blk_offset += blk_size_bytes;
860	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
861				sizeof(struct f2fs_summary_block)) < 0) {
862		printf("\n\tError: While writing the sum_blk to disk!!!\n");
863		return -1;
864	}
865
866	/* 4. Fill segment summary for data block to zero. */
867	memset(sum, 0, sizeof(struct f2fs_summary_block));
868	SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
869
870	/* inode sit for root */
871	sum->n_sits = cpu_to_le16(6);
872	sum->sit_j.entries[0].segno = ckp->cur_node_segno[0];
873	sum->sit_j.entries[0].se.vblocks = cpu_to_le16((CURSEG_HOT_NODE << 10) | 1);
874	f2fs_set_bit(0, sum->sit_j.entries[0].se.valid_map);
875	sum->sit_j.entries[1].segno = ckp->cur_node_segno[1];
876	sum->sit_j.entries[1].se.vblocks = cpu_to_le16((CURSEG_WARM_NODE << 10));
877	sum->sit_j.entries[2].segno = ckp->cur_node_segno[2];
878	sum->sit_j.entries[2].se.vblocks = cpu_to_le16((CURSEG_COLD_NODE << 10));
879
880	/* data sit for root */
881	sum->sit_j.entries[3].segno = ckp->cur_data_segno[0];
882	sum->sit_j.entries[3].se.vblocks = cpu_to_le16((CURSEG_HOT_DATA << 10) | 1);
883	f2fs_set_bit(0, sum->sit_j.entries[3].se.valid_map);
884	sum->sit_j.entries[4].segno = ckp->cur_data_segno[1];
885	sum->sit_j.entries[4].se.vblocks = cpu_to_le16((CURSEG_WARM_DATA << 10));
886	sum->sit_j.entries[5].segno = ckp->cur_data_segno[2];
887	sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10));
888
889	cp_seg_blk_offset += blk_size_bytes;
890	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
891				sizeof(struct f2fs_summary_block)) < 0) {
892		printf("\n\tError: While writing the sum_blk to disk!!!\n");
893		return -1;
894	}
895
896	/* 5. Prepare and write Segment summary for node blocks */
897	memset(sum, 0, sizeof(struct f2fs_summary_block));
898	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
899
900	sum->entries[0].nid = super_block.root_ino;
901	sum->entries[0].ofs_in_node = 0;
902
903	cp_seg_blk_offset += blk_size_bytes;
904	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
905				sizeof(struct f2fs_summary_block)) < 0) {
906		printf("\n\tError: While writing the sum_blk to disk!!!\n");
907		return -1;
908	}
909
910	/* 6. Fill segment summary for data block to zero. */
911	memset(sum, 0, sizeof(struct f2fs_summary_block));
912	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
913
914	cp_seg_blk_offset += blk_size_bytes;
915	if (writetodisk(f2fs_params.fd, sum, cp_seg_blk_offset,
916				sizeof(struct f2fs_summary_block)) < 0) {
917		printf("\n\tError: While writing the sum_blk to disk!!!\n");
918		return -1;
919	}
920
921	/* 7. Fill segment summary for data block to zero. */
922	memset(sum, 0, sizeof(struct f2fs_summary_block));
923	SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
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. cp page2 */
932	cp_seg_blk_offset += blk_size_bytes;
933	if (writetodisk(f2fs_params.fd, ckp, cp_seg_blk_offset,
934				F2FS_CP_BLOCK_SIZE) < 0) {
935		printf("\n\tError: While writing the ckp to disk!!!\n");
936		return -1;
937	}
938
939	/* 9. cp page 1 of check point pack 2
940	 * Initiatialize other checkpoint pack with version zero
941	 */
942	ckp->checkpoint_ver = 0;
943
944	crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, ckp,
945					le32_to_cpu(ckp->checksum_offset));
946	*((u_int32_t *)((unsigned char *)ckp +
947				le32_to_cpu(ckp->checksum_offset))) = crc;
948
949	cp_seg_blk_offset = (le32_to_cpu(super_block.segment0_blkaddr) +
950				f2fs_params.blks_per_seg) *
951				blk_size_bytes;
952	if (writetodisk(f2fs_params.fd, ckp,
953				cp_seg_blk_offset, F2FS_CP_BLOCK_SIZE) < 0) {
954		printf("\n\tError: While writing the ckp to disk!!!\n");
955		return -1;
956	}
957
958	free(sum) ;
959	free(ckp) ;
960	return	0;
961}
962
963/**
964 * @brief     	It writes super block on device
965 * @param	None
966 * @return	0 if success
967 */
968static int8_t f2fs_write_super_block(void)
969{
970	u_int32_t index = 0;
971	u_int8_t *zero_buff;
972
973	zero_buff = calloc(F2FS_BLKSIZE, 1);
974
975	memcpy(zero_buff + F2FS_SUPER_OFFSET, &super_block,
976						sizeof(super_block));
977
978	for (index = 0; index < 2; index++) {
979		if (writetodisk(f2fs_params.fd, zero_buff,
980				index * F2FS_BLKSIZE, F2FS_BLKSIZE) < 0) {
981			printf("\n\tError: While while writing supe_blk \
982					on disk!!! index : %d\n", index);
983			return -1;
984		}
985	}
986
987	free(zero_buff);
988	return 0;
989}
990
991/**
992 * @brief     	It initializes and writes root inode on device.
993 * @param	None
994 * @return	0 if success
995 */
996static int8_t f2fs_write_root_inode(void)
997{
998	struct f2fs_node *raw_node = NULL;
999	u_int64_t blk_size_bytes, 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_int64_t blk_size_bytes, nat_seg_blk_offset = 0;
1076
1077	nat_blk = calloc(sizeof(struct f2fs_nat_block), 1);
1078	if(nat_blk == NULL) {
1079		printf("\n\tError: Calloc Failed for nat_blk!!!\n");
1080		return -1;
1081	}
1082
1083	/* update root */
1084	nat_blk->entries[super_block.root_ino].block_addr = cpu_to_le32(
1085		le32_to_cpu(super_block.main_blkaddr) +
1086		f2fs_params.cur_seg[CURSEG_HOT_NODE] * f2fs_params.blks_per_seg);
1087	nat_blk->entries[super_block.root_ino].ino = super_block.root_ino;
1088
1089	/* update node nat */
1090	nat_blk->entries[super_block.node_ino].block_addr = cpu_to_le32(1);
1091	nat_blk->entries[super_block.node_ino].ino = super_block.node_ino;
1092
1093	/* update meta nat */
1094	nat_blk->entries[super_block.meta_ino].block_addr = cpu_to_le32(1);
1095	nat_blk->entries[super_block.meta_ino].ino = super_block.meta_ino;
1096
1097	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
1098	nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr);
1099	nat_seg_blk_offset *= blk_size_bytes;
1100
1101	if (writetodisk(f2fs_params.fd, nat_blk, nat_seg_blk_offset,
1102				sizeof(struct f2fs_nat_block)) < 0) {
1103		printf("\n\tError: While writing the nat_blk set0 to disk!!!\n");
1104		return -1;
1105	}
1106
1107	free(nat_blk);
1108	return 0;
1109}
1110
1111/**
1112 * @brief     	It updates default dentries in Root Inode
1113 * @param	None
1114 * @return	0 if success
1115 */
1116static int8_t f2fs_add_default_dentry_root(void)
1117{
1118	struct f2fs_dentry_block *dent_blk = NULL;
1119	u_int64_t blk_size_bytes, data_blk_offset = 0;
1120
1121	dent_blk = calloc(sizeof(struct f2fs_dentry_block), 1);
1122	if(dent_blk == NULL) {
1123		printf("\n\tError: Calloc Failed for dent_blk!!!\n");
1124		return -1;
1125	}
1126
1127	dent_blk->dentry[0].hash_code = 0;
1128	dent_blk->dentry[0].ino = super_block.root_ino;
1129	dent_blk->dentry[0].name_len = cpu_to_le16(1);
1130	dent_blk->dentry[0].file_type = F2FS_FT_DIR;
1131	memcpy(dent_blk->filename[0], ".", 1);
1132
1133	dent_blk->dentry[1].hash_code = 0;
1134	dent_blk->dentry[1].ino = super_block.root_ino;
1135	dent_blk->dentry[1].name_len = cpu_to_le16(2);
1136	dent_blk->dentry[1].file_type = F2FS_FT_DIR;
1137	memcpy(dent_blk->filename[1], "..", 2);
1138
1139	/* bitmap for . and .. */
1140	dent_blk->dentry_bitmap[0] = (1 << 1) | (1 << 0);
1141	blk_size_bytes = 1 << le32_to_cpu(super_block.log_blocksize);
1142	data_blk_offset = le32_to_cpu(super_block.main_blkaddr);
1143	data_blk_offset += f2fs_params.cur_seg[CURSEG_HOT_DATA] *
1144				f2fs_params.blks_per_seg;
1145	data_blk_offset *= blk_size_bytes;
1146
1147	if (writetodisk(f2fs_params.fd, dent_blk, data_blk_offset,
1148				sizeof(struct f2fs_dentry_block)) < 0) {
1149		printf("\n\tError: While writing the dentry_blk to disk!!!\n");
1150		return -1;
1151	}
1152
1153	free(dent_blk);
1154	return 0;
1155}
1156
1157/**
1158 * @brief     	It creates root directory on device.
1159 * @param	None
1160 * @return	0 if success
1161 */
1162static int8_t f2fs_create_root_dir(void)
1163{
1164	int8_t err = 0;
1165
1166	err = f2fs_write_root_inode();
1167	if (err < 0) {
1168		printf("\n\tError: Failed to write root inode!!!\n");
1169		goto exit;
1170	}
1171
1172	err = f2fs_update_nat_root();
1173	if (err < 0) {
1174		printf("\n\tError: Failed to update NAT for root!!!\n");
1175		goto exit;
1176	}
1177
1178	err = f2fs_add_default_dentry_root();
1179	if (err < 0) {
1180		printf("\n\tError: Failed to add default dentries for root!!!\n");
1181		goto exit;
1182	}
1183exit:
1184	if (err)
1185		printf("\n\tError: Could not create the root directory!!!\n");
1186
1187	return err;
1188}
1189
1190int f2fs_trim_device()
1191{
1192	unsigned long long range[2];
1193	struct stat stat_buf;
1194
1195	range[0] = 0;
1196	range[1] = f2fs_params.total_sectors * DEFAULT_SECTOR_SIZE;
1197
1198	if (fstat(f2fs_params.fd, &stat_buf) < 0 ) {
1199		printf("\n\tError: Failed to get the device stat!!!\n");
1200		return -1;
1201	}
1202
1203	if (S_ISREG(stat_buf.st_mode))
1204		return 0;
1205	else if (S_ISBLK(stat_buf.st_mode)) {
1206		if (ioctl(f2fs_params.fd, BLKDISCARD, &range) < 0)
1207			printf("Info: This device doesn't support TRIM\n");
1208	} else
1209		return -1;
1210	return 0;
1211}
1212
1213/**
1214 * @brief     	It s a routine to fromat device with F2FS on-disk layout
1215 * @param	None
1216 * @return	0 if success
1217 */
1218static int8_t f2fs_format_device(void)
1219{
1220	int8_t err = 0;
1221
1222	err= f2fs_prepare_super_block();
1223	if (err < 0)
1224		goto exit;
1225
1226	err = f2fs_trim_device();
1227	if (err < 0) {
1228		printf("\n\tError: Failed to trim whole device!!!\n");
1229		goto exit;
1230	}
1231
1232	err = f2fs_init_sit_area();
1233	if (err < 0) {
1234		printf("\n\tError: Failed to Initialise the SIT AREA!!!\n");
1235		goto exit;
1236	}
1237
1238	err = f2fs_init_nat_area();
1239	if (err < 0) {
1240		printf("\n\tError: Failed to Initialise the NAT AREA!!!\n");
1241		goto exit;
1242	}
1243
1244	err = f2fs_create_root_dir();
1245	if (err < 0) {
1246		printf("\n\tError: Failed to create the root directory!!!\n");
1247		goto exit;
1248	}
1249
1250	err = f2fs_write_check_point_pack();
1251	if (err < 0) {
1252		printf("\n\tError: Failed to write the check point pack!!!\n");
1253		goto exit;
1254	}
1255
1256	err = f2fs_write_super_block();
1257	if (err < 0) {
1258		printf("\n\tError: Failed to write the Super Block!!!\n");
1259		goto exit;
1260	}
1261exit:
1262	if (err)
1263		printf("\n\tError: Could not format the device!!!\n");
1264
1265	/*
1266	 * We should call fsync() to flush out all the dirty pages
1267	 * in the block device page cache.
1268	 */
1269	if (fsync(f2fs_params.fd) < 0)
1270		printf("\n\tError: Could not conduct fsync!!!\n");
1271
1272	if (close(f2fs_params.fd) < 0)
1273		printf("\n\tError: Failed to close device file!!!\n");
1274
1275	return err;
1276}
1277
1278/**
1279 * @brief     	main function of F2Fs utility
1280 * @param	argc count of argument
1281 * @param	argv array of arguments
1282 * @return	0 if success
1283 */
1284int main(int argc, char *argv[])
1285{
1286	printf("\nF2FS-tools: Ver: %s (%s)\n",
1287				F2FS_TOOLS_VERSION,
1288				F2FS_TOOLS_DATE);
1289	f2fs_init_global_parameters();
1290
1291	f2fs_parse_options(argc, argv);
1292
1293	if (f2fs_is_device_mounted() < 0)
1294		return -1;
1295
1296	if (f2fs_get_device_info() < 0)
1297		return -1;
1298
1299	if (f2fs_format_device() < 0)
1300		return -1;
1301
1302	printf("Info: format successful\n");
1303
1304	return 0;
1305}
1306