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