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