aboutsummaryrefslogtreecommitdiffstats
path: root/mkfs
diff options
context:
space:
mode:
Diffstat (limited to 'mkfs')
-rw-r--r--mkfs/Makefile.am4
-rw-r--r--mkfs/f2fs_format.c326
-rw-r--r--mkfs/f2fs_format_main.c146
-rw-r--r--mkfs/f2fs_format_utils.c33
-rw-r--r--mkfs/f2fs_format_utils.h13
5 files changed, 304 insertions, 218 deletions
diff --git a/mkfs/Makefile.am b/mkfs/Makefile.am
index 79cbec2..fa48699 100644
--- a/mkfs/Makefile.am
+++ b/mkfs/Makefile.am
@@ -1,7 +1,7 @@
## Makefile.am
AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include
-AM_CFLAGS = -Wall
+AM_CFLAGS = -Wall -DWITH_BLKDISCARD
sbin_PROGRAMS = mkfs.f2fs
-mkfs_f2fs_SOURCES = f2fs_format.c f2fs_format_utils.c
+mkfs_f2fs_SOURCES = f2fs_format_main.c f2fs_format.c f2fs_format_utils.c
mkfs_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la
diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index 3dd534c..e09baf5 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -4,9 +4,7 @@
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * Dual licensed under the GPL or LGPL version 2 licenses.
*/
#define _LARGEFILE64_SOURCE
@@ -18,131 +16,19 @@
#include <sys/stat.h>
#include <sys/mount.h>
#include <time.h>
-#include <linux/fs.h>
-//#include <uuid/uuid.h>
+#ifndef ANDROID
+#include <uuid/uuid.h>
+#include "f2fs_fs.h"
+#else
#include "include/f2fs_fs.h"
-#include "f2fs_format_utils.h"
+#endif
-#define BLKDISCARD _IO(0x12,119)
+#include "f2fs_format_utils.h"
extern struct f2fs_configuration config;
struct f2fs_super_block super_block;
-/*
- This generates a version 4 universally unique identifier (UUID).
- The format is: xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx
- where each x is 4 bits populated by /dev/urandom.
- The algorithm is derived from Theodore T'so's original e2fsprogs source.
-
- 16 bytes will be written to the passed pointer, so allocate
- at least that much space before calling uuid_generate.
-*/
-#define RANDOM "/dev/urandom"
-void uuid_generate(unsigned char *uuid)
-{
- int fd;
-
- fd = open(RANDOM, O_RDONLY);
- if(-1 == fd)
- {
- perror("Error while opening " RANDOM);
- return;
- }
-
- if(16 != read(fd, uuid, 16))
- {
- perror("Error while reading from " RANDOM);
- }
-
- uuid[6] &= 0x0F;
- uuid[6] |= 0x40;
-
- uuid[8] &= 0x3F;
- uuid[8] |= 0x80;
-
- close(fd);
-}
-
-static void mkfs_usage()
-{
- MSG(0, "\nUsage: mkfs.f2fs [options] device\n");
- MSG(0, "[options]:\n");
- MSG(0, " -a heap-based allocation [default:1]\n");
- MSG(0, " -d debug level [default:0]\n");
- MSG(0, " -e [extension list] e.g. \"mp3,gif,mov\"\n");
- MSG(0, " -l label\n");
- MSG(0, " -o overprovision ratio [default:5]\n");
- MSG(0, " -s # of segments per section [default:1]\n");
- MSG(0, " -z # of sections per zone [default:1]\n");
- MSG(0, " -t 0: nodiscard, 1: discard [default:1]\n");
- exit(1);
-}
-
-static void f2fs_parse_options(int argc, char *argv[])
-{
- static const char *option_string = "a:d:e:l:o:s:z:t:";
- int32_t option=0;
-
- while ((option = getopt(argc,argv,option_string)) != EOF) {
- switch (option) {
- case 'a':
- config.heap = atoi(optarg);
- if (config.heap == 0)
- MSG(0, "Info: Disable heap-based policy\n");
- break;
- case 'd':
- config.dbg_lv = atoi(optarg);
- MSG(0, "Info: Debug level = %d\n", config.dbg_lv);
- break;
- case 'e':
- config.extension_list = strdup(optarg);
- MSG(0, "Info: Add new extension list\n");
- break;
- case 'l': /*v: volume label */
- if (strlen(optarg) > 512) {
- MSG(0, "Error: Volume Label should be less than\
- 512 characters\n");
- mkfs_usage();
- }
- config.vol_label = optarg;
- MSG(0, "Info: Label = %s\n", config.vol_label);
- break;
- case 'o':
- config.overprovision = atoi(optarg);
- MSG(0, "Info: Overprovision ratio = %u%%\n",
- atoi(optarg));
- break;
- case 's':
- config.segs_per_sec = atoi(optarg);
- MSG(0, "Info: Segments per section = %d\n",
- atoi(optarg));
- break;
- case 'z':
- config.secs_per_zone = atoi(optarg);
- MSG(0, "Info: Sections per zone = %d\n", atoi(optarg));
- break;
- case 't':
- config.trim = atoi(optarg);
- MSG(0, "Info: Trim is %s\n", config.trim ? "enabled": "disabled");
- break;
- default:
- mkfs_usage();
- break;
- }
- }
-
- if ((optind + 1) != argc) {
- MSG(0, "\tError: Device not specified\n");
- mkfs_usage();
- }
-
- config.reserved_segments =
- (2 * (100 / config.overprovision + 1) + 6)
- * config.segs_per_sec;
- config.device_name = argv[optind];
-}
-
const char *media_ext_lists[] = {
"jpg",
"gif",
@@ -190,7 +76,7 @@ static void configure_extension_list(void)
memcpy(super_block.extension_list[i++], *extlist, name_len);
extlist++;
}
- super_block.extension_count = i - 1;
+ super_block.extension_count = i;
if (!ext_str)
return;
@@ -201,15 +87,52 @@ static void configure_extension_list(void)
name_len = strlen(ue);
memcpy(super_block.extension_list[i++], ue, name_len);
ue = strtok(NULL, ",");
- if (i > F2FS_MAX_EXTENSION)
+ if (i >= F2FS_MAX_EXTENSION)
break;
}
- super_block.extension_count = i - 1;
+ super_block.extension_count = i;
free(config.extension_list);
}
+#ifdef ANDROID
+/*
+ This generates a version 4 universally unique identifier (UUID).
+ The format is: xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx
+ where each x is 4 bits populated by /dev/urandom.
+ The algorithm is derived from Theodore T'so's original e2fsprogs source.
+
+ 16 bytes will be written to the passed pointer, so allocate
+ at least that much space before calling uuid_generate.
+*/
+#define RANDOM "/dev/urandom"
+void uuid_generate(unsigned char *uuid)
+{
+ int fd;
+
+ fd = open(RANDOM, O_RDONLY);
+ if(-1 == fd)
+ {
+ perror("Error while opening " RANDOM);
+ return;
+ }
+
+ if(16 != read(fd, uuid, 16))
+ {
+ perror("Error while reading from " RANDOM);
+ }
+
+ uuid[6] &= 0x0F;
+ uuid[6] |= 0x40;
+
+ uuid[8] &= 0x3F;
+ uuid[8] |= 0x80;
+
+ close(fd);
+}
+#endif
+
static int f2fs_prepare_super_block(void)
{
u_int32_t blk_size_bytes;
@@ -220,7 +143,8 @@ static int f2fs_prepare_super_block(void)
u_int32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa;
u_int32_t total_valid_blks_available;
u_int64_t zone_align_start_offset, diff, total_meta_segments;
- u_int32_t sit_bitmap_size, max_nat_bitmap_size, max_nat_segments;
+ u_int32_t sit_bitmap_size, max_sit_bitmap_size;
+ u_int32_t max_nat_bitmap_size, max_nat_segments;
u_int32_t total_zones;
super_block.magic = cpu_to_le32(F2FS_SUPER_MAGIC);
@@ -233,30 +157,11 @@ static int f2fs_prepare_super_block(void)
log_blks_per_seg = log_base_2(config.blks_per_seg);
super_block.log_sectorsize = cpu_to_le32(log_sectorsize);
-
- if (log_sectorsize < 0) {
- MSG(1, "\tError: Failed to get the sector size: %u!\n",
- config.sector_size);
- return -1;
- }
-
super_block.log_sectors_per_block = cpu_to_le32(log_sectors_per_block);
- if (log_sectors_per_block < 0) {
- MSG(1, "\tError: Failed to get sectors per block: %u!\n",
- config.sectors_per_blk);
- return -1;
- }
-
super_block.log_blocksize = cpu_to_le32(log_blocksize);
super_block.log_blocks_per_seg = cpu_to_le32(log_blks_per_seg);
- if (log_blks_per_seg < 0) {
- MSG(1, "\tError: Failed to get block per segment: %u!\n",
- config.blks_per_seg);
- return -1;
- }
-
super_block.segs_per_sec = cpu_to_le32(config.segs_per_sec);
super_block.secs_per_zone = cpu_to_le32(config.secs_per_zone);
blk_size_bytes = 1 << log_blocksize;
@@ -335,8 +240,26 @@ static int f2fs_prepare_super_block(void)
*/
sit_bitmap_size = ((le32_to_cpu(super_block.segment_count_sit) / 2) <<
log_blks_per_seg) / 8;
- max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 -
- sit_bitmap_size;
+
+ if (sit_bitmap_size > MAX_SIT_BITMAP_SIZE)
+ max_sit_bitmap_size = MAX_SIT_BITMAP_SIZE;
+ else
+ max_sit_bitmap_size = sit_bitmap_size;
+
+ /*
+ * It should be reserved minimum 1 segment for nat.
+ * When sit is too large, we should expand cp area. It requires more pages for cp.
+ */
+ if (max_sit_bitmap_size >
+ (CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 65)) {
+ max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1;
+ super_block.cp_payload = F2FS_BLK_ALIGN(max_sit_bitmap_size);
+ } else {
+ max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1
+ - max_sit_bitmap_size;
+ super_block.cp_payload = 0;
+ }
+
max_nat_segments = (max_nat_bitmap_size * 8) >> log_blks_per_seg;
if (le32_to_cpu(super_block.segment_count_nat) > max_nat_segments)
@@ -492,10 +415,11 @@ static int f2fs_init_sit_area(void)
sit_seg_addr = le32_to_cpu(super_block.sit_blkaddr);
sit_seg_addr *= blk_size;
+ DBG(1, "\tFilling sit area at offset 0x%08"PRIx64"\n", sit_seg_addr);
for (index = 0;
index < (le32_to_cpu(super_block.segment_count_sit) / 2);
index++) {
- if (dev_write(zero_buf, sit_seg_addr, seg_size)) {
+ if (dev_fill(zero_buf, sit_seg_addr, seg_size)) {
MSG(1, "\tError: While zeroing out the sit area \
on disk!!!\n");
return -1;
@@ -527,10 +451,11 @@ static int f2fs_init_nat_area(void)
nat_seg_addr = le32_to_cpu(super_block.nat_blkaddr);
nat_seg_addr *= blk_size;
+ DBG(1, "\tFilling nat area at offset 0x%08"PRIx64"\n", nat_seg_addr);
for (index = 0;
index < (le32_to_cpu(super_block.segment_count_nat) / 2);
index++) {
- if (dev_write(nat_buf, nat_seg_addr, seg_size)) {
+ if (dev_fill(nat_buf, nat_seg_addr, seg_size)) {
MSG(1, "\tError: While zeroing out the nat area \
on disk!!!\n");
return -1;
@@ -549,7 +474,8 @@ static int f2fs_write_check_point_pack(void)
u_int32_t blk_size_bytes;
u_int64_t cp_seg_blk_offset = 0;
u_int32_t crc = 0;
- int i;
+ unsigned int i;
+ char *cp_payload = NULL;
ckp = calloc(F2FS_BLKSIZE, 1);
if (ckp == NULL) {
@@ -563,6 +489,12 @@ static int f2fs_write_check_point_pack(void)
return -1;
}
+ cp_payload = calloc(F2FS_BLKSIZE, 1);
+ if (cp_payload == NULL) {
+ MSG(1, "\tError: Calloc Failed for cp_payload!!!\n");
+ return -1;
+ }
+
/* 1. cp page 1 of checkpoint pack 1 */
ckp->checkpoint_ver = cpu_to_le64(1);
ckp->cur_node_segno[0] =
@@ -601,13 +533,14 @@ static int f2fs_write_check_point_pack(void)
((le32_to_cpu(ckp->free_segment_count) + 6 -
le32_to_cpu(ckp->overprov_segment_count)) *
config.blks_per_seg));
- ckp->cp_pack_total_block_count = cpu_to_le32(8);
+ ckp->cp_pack_total_block_count =
+ cpu_to_le32(8 + le32_to_cpu(super_block.cp_payload));
ckp->ckpt_flags = cpu_to_le32(CP_UMOUNT_FLAG);
- ckp->cp_pack_start_sum = cpu_to_le32(1);
+ ckp->cp_pack_start_sum = cpu_to_le32(1 + le32_to_cpu(super_block.cp_payload));
ckp->valid_node_count = cpu_to_le32(1);
ckp->valid_inode_count = cpu_to_le32(1);
- ckp->next_free_nid = cpu_to_le32(0xc00000);
-
+ ckp->next_free_nid = cpu_to_le32(
+ le32_to_cpu(super_block.root_ino) + 1);
ckp->sit_ver_bitmap_bytesize = cpu_to_le32(
((le32_to_cpu(super_block.segment_count_sit) / 2) <<
le32_to_cpu(super_block.log_blocks_per_seg)) / 8);
@@ -626,11 +559,21 @@ static int f2fs_write_check_point_pack(void)
cp_seg_blk_offset = le32_to_cpu(super_block.segment0_blkaddr);
cp_seg_blk_offset *= blk_size_bytes;
- if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting main segments, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the ckp to disk!!!\n");
return -1;
}
+ for (i = 0; i < le32_to_cpu(super_block.cp_payload); i++) {
+ cp_seg_blk_offset += blk_size_bytes;
+ if (dev_fill(cp_payload, cp_seg_blk_offset, blk_size_bytes)) {
+ MSG(1, "\tError: While zeroing out the sit bitmap area \
+ on disk!!!\n");
+ return -1;
+ }
+ }
+
/* 2. Prepare and write Segment summary for data blocks */
memset(sum, 0, sizeof(struct f2fs_summary_block));
SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
@@ -639,7 +582,8 @@ static int f2fs_write_check_point_pack(void)
sum->entries[0].ofs_in_node = 0;
cp_seg_blk_offset += blk_size_bytes;
- if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting segment summary for data, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
return -1;
}
@@ -649,7 +593,8 @@ static int f2fs_write_check_point_pack(void)
SET_SUM_TYPE((&sum->footer), SUM_TYPE_DATA);
cp_seg_blk_offset += blk_size_bytes;
- if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting segment summary, ckp at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
return -1;
}
@@ -678,7 +623,8 @@ static int f2fs_write_check_point_pack(void)
sum->sit_j.entries[5].se.vblocks = cpu_to_le16((CURSEG_COLD_DATA << 10));
cp_seg_blk_offset += blk_size_bytes;
- if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting data sit for root, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
return -1;
}
@@ -691,7 +637,8 @@ static int f2fs_write_check_point_pack(void)
sum->entries[0].ofs_in_node = 0;
cp_seg_blk_offset += blk_size_bytes;
- if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting Segment summary for node blocks, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
return -1;
}
@@ -701,7 +648,8 @@ static int f2fs_write_check_point_pack(void)
SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
cp_seg_blk_offset += blk_size_bytes;
- if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting Segment summary for data block (1/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
return -1;
}
@@ -710,14 +658,16 @@ static int f2fs_write_check_point_pack(void)
memset(sum, 0, sizeof(struct f2fs_summary_block));
SET_SUM_TYPE((&sum->footer), SUM_TYPE_NODE);
cp_seg_blk_offset += blk_size_bytes;
- if (dev_write(sum, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting Segment summary for data block (2/2), at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(sum, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the sum_blk to disk!!!\n");
return -1;
}
/* 8. cp page2 */
cp_seg_blk_offset += blk_size_bytes;
- if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting cp page2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the ckp to disk!!!\n");
return -1;
}
@@ -733,20 +683,33 @@ static int f2fs_write_check_point_pack(void)
cp_seg_blk_offset = (le32_to_cpu(super_block.segment0_blkaddr) +
config.blks_per_seg) *
blk_size_bytes;
- if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ DBG(1, "\tWriting cp page 1 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the ckp to disk!!!\n");
return -1;
}
+ for (i = 0; i < le32_to_cpu(super_block.cp_payload); i++) {
+ cp_seg_blk_offset += blk_size_bytes;
+ if (dev_fill(cp_payload, cp_seg_blk_offset, blk_size_bytes)) {
+ MSG(1, "\tError: While zeroing out the sit bitmap area \
+ on disk!!!\n");
+ return -1;
+ }
+ }
+
/* 10. cp page 2 of check point pack 2 */
- cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(ckp->cp_pack_total_block_count) - 1);
- if (dev_write(ckp, cp_seg_blk_offset, F2FS_BLKSIZE)) {
+ cp_seg_blk_offset += blk_size_bytes * (le32_to_cpu(ckp->cp_pack_total_block_count)
+ - le32_to_cpu(super_block.cp_payload) - 1);
+ DBG(1, "\tWriting cp page 2 of checkpoint pack 2, at offset 0x%08"PRIx64"\n", cp_seg_blk_offset);
+ if (dev_write(ckp, cp_seg_blk_offset, blk_size_bytes)) {
MSG(1, "\tError: While writing the ckp to disk!!!\n");
return -1;
}
free(sum) ;
free(ckp) ;
+ free(cp_payload);
return 0;
}
@@ -759,6 +722,7 @@ static int f2fs_write_super_block(void)
memcpy(zero_buff + F2FS_SUPER_OFFSET, &super_block,
sizeof(super_block));
+ DBG(1, "\tWriting super block, at offset 0x%08x\n", 0);
for (index = 0; index < 2; index++) {
if (dev_write(zero_buff, index * F2FS_BLKSIZE, F2FS_BLKSIZE)) {
MSG(1, "\tError: While while writing supe_blk \
@@ -810,6 +774,7 @@ static int f2fs_write_root_inode(void)
raw_node->i.i_xattr_nid = 0;
raw_node->i.i_flags = 0;
raw_node->i.i_current_depth = cpu_to_le32(1);
+ raw_node->i.i_dir_level = DEF_DIR_LEVEL;
data_blk_nor = le32_to_cpu(super_block.main_blkaddr) +
config.cur_seg[CURSEG_HOT_DATA] * config.blks_per_seg;
@@ -824,6 +789,7 @@ static int f2fs_write_root_inode(void)
config.blks_per_seg;
main_area_node_seg_blk_offset *= blk_size_bytes;
+ DBG(1, "\tWriting root inode (hot node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset);
if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) {
MSG(1, "\tError: While writing the raw_node to disk!!!\n");
return -1;
@@ -837,6 +803,7 @@ static int f2fs_write_root_inode(void)
config.blks_per_seg;
main_area_node_seg_blk_offset *= blk_size_bytes;
+ DBG(1, "\tWriting root inode (warm node), at offset 0x%08"PRIx64"\n", main_area_node_seg_blk_offset);
if (dev_write(raw_node, main_area_node_seg_blk_offset, F2FS_BLKSIZE)) {
MSG(1, "\tError: While writing the raw_node to disk!!!\n");
return -1;
@@ -874,6 +841,7 @@ static int f2fs_update_nat_root(void)
nat_seg_blk_offset = le32_to_cpu(super_block.nat_blkaddr);
nat_seg_blk_offset *= blk_size_bytes;
+ DBG(1, "\tWriting nat root, at offset 0x%08"PRIx64"\n", nat_seg_blk_offset);
if (dev_write(nat_blk, nat_seg_blk_offset, F2FS_BLKSIZE)) {
MSG(1, "\tError: While writing the nat_blk set0 to disk!\n");
return -1;
@@ -914,6 +882,7 @@ static int f2fs_add_default_dentry_root(void)
config.blks_per_seg;
data_blk_offset *= blk_size_bytes;
+ DBG(1, "\tWriting default dentry root, at offset 0x%08"PRIx64"\n", data_blk_offset);
if (dev_write(dent_blk, data_blk_offset, F2FS_BLKSIZE)) {
MSG(1, "\tError: While writing the dentry_blk to disk!!!\n");
return -1;
@@ -951,7 +920,7 @@ exit:
return err;
}
-static int f2fs_format_device(void)
+int f2fs_format_device(void)
{
int err = 0;
@@ -1000,32 +969,5 @@ exit:
if (err)
MSG(0, "\tError: Could not format the device!!!\n");
- f2fs_finalize_device();
-
return err;
}
-
-int make_f2fs_main(int argc, char *argv[])
-{
- MSG(0, "\n\tF2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n",
- F2FS_TOOLS_VERSION,
- F2FS_TOOLS_DATE);
- f2fs_init_configuration(&config);
-
- f2fs_parse_options(argc, argv);
-
- /*
- if (f2fs_dev_is_umounted(&config) < 0)
- return -1;
- */
-
- if (f2fs_get_device_info(&config) < 0)
- return -1;
-
- if (f2fs_format_device() < 0)
- return -1;
-
- MSG(0, "Info: format successful\n");
-
- return 0;
-}
diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c
new file mode 100644
index 0000000..fa92845
--- /dev/null
+++ b/mkfs/f2fs_format_main.c
@@ -0,0 +1,146 @@
+/**
+ * f2fs_format.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Dual licensed under the GPL or LGPL version 2 licenses.
+ */
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <time.h>
+//#include <linux/fs.h>
+#ifndef ANDROID
+#include <uuid/uuid.h>
+
+#include "f2fs_fs.h"
+#else
+#include "include/f2fs_fs.h"
+#endif
+#include "f2fs_format_utils.h"
+
+extern struct f2fs_configuration config;
+
+static void mkfs_usage()
+{
+ MSG(0, "\nUsage: mkfs.f2fs [options] device [sectors]\n");
+ MSG(0, "[options]:\n");
+ MSG(0, " -a heap-based allocation [default:1]\n");
+ MSG(0, " -d debug level [default:0]\n");
+ MSG(0, " -e [extension list] e.g. \"mp3,gif,mov\"\n");
+ MSG(0, " -l label\n");
+ MSG(0, " -o overprovision ratio [default:5]\n");
+ MSG(0, " -s # of segments per section [default:1]\n");
+ MSG(0, " -z # of sections per zone [default:1]\n");
+ MSG(0, " -t 0: nodiscard, 1: discard [default:1]\n");
+ MSG(0, "sectors: number of sectors. [default: determined by device size]\n");
+ exit(1);
+}
+
+static void f2fs_parse_options(int argc, char *argv[])
+{
+ static const char *option_string = "a:d:e:l:o:s:z:t:";
+ int32_t option=0;
+
+ while ((option = getopt(argc,argv,option_string)) != EOF) {
+ switch (option) {
+ case 'a':
+ config.heap = atoi(optarg);
+ if (config.heap == 0)
+ MSG(0, "Info: Disable heap-based policy\n");
+ break;
+ case 'd':
+ config.dbg_lv = atoi(optarg);
+ MSG(0, "Info: Debug level = %d\n", config.dbg_lv);
+ break;
+ case 'e':
+ config.extension_list = strdup(optarg);
+ MSG(0, "Info: Add new extension list\n");
+ break;
+ case 'l': /*v: volume label */
+ if (strlen(optarg) > 512) {
+ MSG(0, "Error: Volume Label should be less than\
+ 512 characters\n");
+ mkfs_usage();
+ }
+ config.vol_label = optarg;
+ MSG(0, "Info: Label = %s\n", config.vol_label);
+ break;
+ case 'o':
+ config.overprovision = atoi(optarg);
+ MSG(0, "Info: Overprovision ratio = %u%%\n",
+ atoi(optarg));
+ break;
+ case 's':
+ config.segs_per_sec = atoi(optarg);
+ MSG(0, "Info: Segments per section = %d\n",
+ atoi(optarg));
+ break;
+ case 'z':
+ config.secs_per_zone = atoi(optarg);
+ MSG(0, "Info: Sections per zone = %d\n", atoi(optarg));
+ break;
+ case 't':
+ config.trim = atoi(optarg);
+ MSG(0, "Info: Trim is %s\n", config.trim ? "enabled": "disabled");
+ break;
+ default:
+ mkfs_usage();
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ MSG(0, "\tError: Device not specified\n");
+ mkfs_usage();
+ }
+ config.device_name = argv[optind];
+
+ if ((optind + 1) < argc) {
+ /* We have a sector count. */
+ config.total_sectors = atoll(argv[optind+1]);
+ MSG(0, "\ttotal_sectors=%lu (%s bytes)\n", config.total_sectors, argv[optind+1]);
+ }
+
+ config.reserved_segments =
+ (2 * (100 / config.overprovision + 1) + 6)
+ * config.segs_per_sec;
+}
+
+#ifndef ANDROID
+int main(int argc, char *argv[])
+#else
+int make_f2fs_main(int argc, char *argv[])
+#endif
+{
+ MSG(0, "\n\tF2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n",
+ F2FS_TOOLS_VERSION,
+ F2FS_TOOLS_DATE);
+ f2fs_init_configuration(&config);
+
+ f2fs_parse_options(argc, argv);
+
+#ifndef ANDROID
+ if (f2fs_dev_is_umounted(&config) < 0)
+ return -1;
+#endif
+
+ if (f2fs_get_device_info(&config) < 0)
+ return -1;
+
+ if (f2fs_format_device() < 0)
+ return -1;
+
+ f2fs_finalize_device(&config);
+
+ MSG(0, "Info: format successful\n");
+
+ return 0;
+}
diff --git a/mkfs/f2fs_format_utils.c b/mkfs/f2fs_format_utils.c
index 5e466bc..6792ce0 100644
--- a/mkfs/f2fs_format_utils.c
+++ b/mkfs/f2fs_format_utils.c
@@ -4,9 +4,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * Dual licensed under the GPL or LGPL version 2 licenses.
*/
#define _LARGEFILE64_SOURCE
@@ -14,23 +12,16 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <linux/fs.h>
+#ifndef ANDROID
+#include "f2fs_fs.h"
+#else
#include "include/f2fs_fs.h"
+#endif
-void f2fs_finalize_device()
-{
- /*
- * We should call fsync() to flush out all the dirty pages
- * in the block device page cache.
- */
- if (fsync(config.fd) < 0)
- MSG(0, "\tError: Could not conduct fsync!!!\n");
-
- if (close(config.fd) < 0)
- MSG(0, "\tError: Failed to close device file!!!\n");
-
-}
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h>
+#endif
int f2fs_trim_device()
{
@@ -48,14 +39,20 @@ int f2fs_trim_device()
return -1;
}
+#if defined(WITH_BLKDISCARD) && defined(BLKDISCARD)
MSG(0, "Info: Discarding device\n");
if (S_ISREG(stat_buf.st_mode))
return 0;
else if (S_ISBLK(stat_buf.st_mode)) {
- if (ioctl(config.fd, BLKDISCARD, &range) < 0)
+ if (ioctl(config.fd, BLKDISCARD, &range) < 0) {
MSG(0, "Info: This device doesn't support TRIM\n");
+ } else {
+ MSG(0, "Info: Discarded %lu sectors\n",
+ config.total_sectors);
+ }
} else
return -1;
+#endif
return 0;
}
diff --git a/mkfs/f2fs_format_utils.h b/mkfs/f2fs_format_utils.h
index 3ba0fd6..9f531ee 100644
--- a/mkfs/f2fs_format_utils.h
+++ b/mkfs/f2fs_format_utils.h
@@ -4,16 +4,17 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * Dual licensed under the GPL or LGPL version 2 licenses.
*/
#define _LARGEFILE64_SOURCE
+#ifndef ANDROID
+#include "f2fs_fs.h"
+#else
#include "include/f2fs_fs.h"
-#include "include/f2fs_version.h"
+#endif
extern struct f2fs_configuration config;
-void f2fs_finalize_device();
-int f2fs_trim_device();
+int f2fs_trim_device(void);
+int f2fs_format_device(void);