Snap for 6596975 from a0823d077cf56d79a98da23059fce6eeabd92062 to rvc-release

Change-Id: I416ae77e67cb212a8c3168bf01e35e336125005d
diff --git a/fsck/dump.c b/fsck/dump.c
index 8481a58..001b7cb 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -309,6 +309,8 @@
 	int ret;
 
 	xattr = read_all_xattrs(sbi, node_blk);
+	if (!xattr)
+		return;
 
 	list_for_each_xattr(ent, xattr) {
 		char *name = strndup(ent->e_name, ent->e_name_len);
@@ -486,10 +488,15 @@
 	DBG(1, "nat_entry.version     [0x%x]\n", ni.version);
 	DBG(1, "nat_entry.ino         [0x%x]\n", ni.ino);
 
+	if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) {
+		MSG(force, "Invalid node blkaddr: %u\n\n", ni.blk_addr);
+		goto out;
+	}
+
 	if (ni.blk_addr == 0x0)
 		MSG(force, "Invalid nat entry\n\n");
 	else if (!is_sit_bitmap_set(sbi, ni.blk_addr))
-		MSG(force, "Invalid node blk addr\n\n");
+		MSG(force, "Invalid sit bitmap, %u\n\n", ni.blk_addr);
 
 	DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino));
 	DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid));
@@ -504,7 +511,7 @@
 		print_node_info(sbi, node_blk, force);
 		MSG(force, "Invalid (i)node block\n\n");
 	}
-
+out:
 	free(node_blk);
 }
 
diff --git a/fsck/fsck.c b/fsck/fsck.c
index a08a8cb..c249dfa 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -487,6 +487,14 @@
 	return 0;
 }
 
+int fsck_sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
+			struct f2fs_node *node_blk,
+			enum FILE_TYPE ftype, enum NODE_TYPE ntype,
+			struct node_info *ni)
+{
+	return sanity_check_nid(sbi, nid, node_blk, ftype, ntype, ni);
+}
+
 static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino,
 					u32 x_nid, u32 *blk_cnt)
 {
@@ -1340,11 +1348,10 @@
 	return i;
 }
 
-static int f2fs_check_dirent_position(int encoding, int casefolded,
-						u8 *name, u16 name_len, u32 pgofs,
-						u8 dir_level, u32 pino)
+static int f2fs_check_dirent_position(const struct f2fs_dir_entry *dentry,
+				      const char *printable_name,
+				      u32 pgofs, u8 dir_level, u32 pino)
 {
-	f2fs_hash_t namehash = f2fs_dentry_hash(encoding, casefolded, name, name_len);
 	unsigned int nbucket, nblock;
 	unsigned int bidx, end_block;
 	int level;
@@ -1355,7 +1362,7 @@
 	nblock = bucket_blocks(level);
 
 	bidx = dir_block_index(level, dir_level,
-					le32_to_cpu(namehash) % nbucket);
+			       le32_to_cpu(dentry->hash_code) % nbucket);
 	end_block = bidx + nblock;
 
 	if (pgofs >= bidx && pgofs < end_block)
@@ -1363,7 +1370,8 @@
 
 	ASSERT_MSG("Wrong position of dirent pino:%u, name:%s, level:%d, "
 		"dir_level:%d, pgofs:%u, correct range:[%u, %u]\n",
-		pino, name, level, dir_level, pgofs, bidx, end_block - 1);
+		pino, printable_name, level, dir_level, pgofs, bidx,
+		end_block - 1);
 	return 1;
 }
 
@@ -1544,10 +1552,12 @@
 		if (f2fs_check_hash_code(get_encoding(sbi), casefolded, dentry + i, name, name_len, enc_name))
 			fixed = 1;
 
+		pretty_print_filename(name, name_len, en, enc_name);
+
 		if (max == NR_DENTRY_IN_BLOCK) {
-			ret = f2fs_check_dirent_position(get_encoding(sbi), casefolded,
-					name, name_len,	child->pgofs,
-					child->dir_level, child->p_ino);
+			ret = f2fs_check_dirent_position(dentry + i, en,
+					child->pgofs, child->dir_level,
+					child->p_ino);
 			if (ret) {
 				if (c.fix_on) {
 					FIX_MSG("Clear bad dentry 0x%x", i);
@@ -1560,7 +1570,6 @@
 			}
 		}
 
-		pretty_print_filename(name, name_len, en, enc_name);
 		DBG(1, "[%3u]-[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n",
 				fsck->dentry_depth, i, en, name_len,
 				le32_to_cpu(dentry[i].ino),
diff --git a/fsck/fsck.h b/fsck/fsck.h
index c4432e8..2de6f62 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -144,6 +144,9 @@
 extern int fsck_chk_orphan_node(struct f2fs_sb_info *);
 extern int fsck_chk_quota_node(struct f2fs_sb_info *);
 extern int fsck_chk_quota_files(struct f2fs_sb_info *);
+extern int fsck_sanity_check_nid(struct f2fs_sb_info *, u32,
+			struct f2fs_node *, enum FILE_TYPE, enum NODE_TYPE,
+			struct node_info *);
 extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32,
 		enum FILE_TYPE, enum NODE_TYPE, u32 *,
 		struct child_info *);
diff --git a/fsck/mount.c b/fsck/mount.c
index 6700ddb..fb45941 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -171,7 +171,7 @@
 	unsigned int i = 0;
 	u32 namelen = le32_to_cpu(inode->i_namelen);
 	int enc_name = file_enc_name(inode);
-	int ofs = __get_extra_isize(inode);
+	int ofs = get_extra_isize(node);
 
 	pretty_print_filename(inode->i_name, namelen, en, enc_name);
 	if (name && en[0]) {
@@ -236,17 +236,22 @@
 		}
 	}
 
-	for (i = ofs; i < ADDRS_PER_INODE(inode); i++) {
-		block_t blkaddr = le32_to_cpu(inode->i_addr[i]);
+	for (i = 0; i < ADDRS_PER_INODE(inode); i++) {
+		block_t blkaddr;
 		char *flag = "";
 
+		if (i + ofs >= DEF_ADDRS_PER_INODE)
+			break;
+
+		blkaddr = le32_to_cpu(inode->i_addr[i + ofs]);
+
 		if (blkaddr == 0x0)
 			continue;
 		if (blkaddr == COMPRESS_ADDR)
 			flag = "cluster flag";
 		else if (blkaddr == NEW_ADDR)
 			flag = "reserved flag";
-		printf("i_addr[0x%x] %-16s\t\t[0x%8x : %u]\n", i, flag,
+		printf("i_addr[0x%x] %-16s\t\t[0x%8x : %u]\n", i + ofs, flag,
 				blkaddr, blkaddr);
 	}
 
@@ -257,10 +262,12 @@
 	DISP_u32(inode, i_nid[4]);	/* double indirect */
 
 	xattr_addr = read_all_xattrs(sbi, node);
-	list_for_each_xattr(ent, xattr_addr) {
-		print_xattr_entry(ent);
+	if (xattr_addr) {
+		list_for_each_xattr(ent, xattr_addr) {
+			print_xattr_entry(ent);
+		}
+		free(xattr_addr);
 	}
-	free(xattr_addr);
 
 	printf("\n");
 }
diff --git a/fsck/xattr.c b/fsck/xattr.c
index d5350e3..e9dcb52 100644
--- a/fsck/xattr.c
+++ b/fsck/xattr.c
@@ -22,6 +22,22 @@
 	struct f2fs_xattr_header *header;
 	void *txattr_addr;
 	u64 inline_size = inline_xattr_size(&inode->i);
+	nid_t xnid = le32_to_cpu(inode->i.i_xattr_nid);
+
+	if (xnid) {
+		struct f2fs_node *node_blk = NULL;
+		struct node_info ni;
+		int ret;
+
+		node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
+		ASSERT(node_blk != NULL);
+
+		ret = fsck_sanity_check_nid(sbi, xnid, node_blk,
+					F2FS_FT_XATTR, TYPE_XATTR, &ni);
+		free(node_blk);
+		if (ret)
+			return NULL;
+	}
 
 	txattr_addr = calloc(inline_size + BLOCK_SZ, 1);
 	ASSERT(txattr_addr);
@@ -30,11 +46,11 @@
 		memcpy(txattr_addr, inline_xattr_addr(&inode->i), inline_size);
 
 	/* Read from xattr node block. */
-	if (inode->i.i_xattr_nid) {
+	if (xnid) {
 		struct node_info ni;
 		int ret;
 
-		get_node_info(sbi, le32_to_cpu(inode->i.i_xattr_nid), &ni);
+		get_node_info(sbi, xnid, &ni);
 		ret = dev_read_block(txattr_addr + inline_size, ni.blk_addr);
 		ASSERT(ret >= 0);
 	}
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 265f50c..709bfd8 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -1178,6 +1178,10 @@
 	F2FS_FT_LAST_FILE_TYPE = F2FS_FT_XATTR,
 };
 
+#define LINUX_S_IFMT  00170000
+#define LINUX_S_IFREG  0100000
+#define LINUX_S_ISREG(m)	(((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
+
 /* from f2fs/segment.h */
 enum {
 	LFS = 0,
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 5c064c8..55d3a5c 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -504,14 +504,16 @@
 {
 	unsigned int addrs = CUR_ADDRS_PER_INODE(i) - get_inline_xattr_addrs(i);
 
-	if (!(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
+	if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
+			!(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
 		return addrs;
 	return ALIGN_DOWN(addrs, 1 << i->i_log_cluster_size);
 }
 
 unsigned int addrs_per_block(struct f2fs_inode *i)
 {
-	if (!(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
+	if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
+			!(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
 		return DEF_ADDRS_PER_BLOCK;
 	return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, 1 << i->i_log_cluster_size);
 }
diff --git a/man/Makefile.am b/man/Makefile.am
index 7856586..1d16c6f 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,3 +1,3 @@
 ## Makefile.am
 
-dist_man_MANS = mkfs.f2fs.8 fsck.f2fs.8 dump.f2fs.8 defrag.f2fs.8 resize.f2fs.8 sload.f2fs.8
+dist_man_MANS = mkfs.f2fs.8 fsck.f2fs.8 dump.f2fs.8 defrag.f2fs.8 resize.f2fs.8 sload.f2fs.8 f2fs_io.8
diff --git a/man/f2fs_io.8 b/man/f2fs_io.8
new file mode 100644
index 0000000..8a2c374
--- /dev/null
+++ b/man/f2fs_io.8
@@ -0,0 +1,138 @@
+.\" Generated by help2man 1.47.12.
+.TH f2fs_io "8" "March 2020" "f2fs-tools" "System Administration Utilities"
+.SH NAME
+f2fs_io \- f2fs ioctl utility
+.SH DESCRIPTION
+.B f2fs_io
+is used to send various commands to the f2fs file system for
+administrative purposes.
+.SH "AVAILABLE COMMANDS"
+.TP
+\fBset_verity\fR \fI[file]\fR
+Set the verity flags associated with the specified file.
+.TP
+\fBgetflags\fR \fI[file]\fR
+Get the flags associated with the specified file.
+.TP
+\fBsetflags\fR \fI[flag] [file]\fR
+Set an f2fs file on specified file.  The flag can be casefold,
+compression, and nocompression.
+.TP
+\fBshutdown\fR \fIshutdown filesystem\fR
+Freeze and stop all IOs for the file system mounted on
+.IR dir.
+The level parameter can be:
+.RS 1.2i
+.TP
+0
+going down with full sync
+.TP
+1
+going down with checkpoint only
+.TP
+2
+going down with no sync
+.TP
+3
+going down with metadata flush
+.TP
+4
+going down with fsck mark
+.RE
+.TP
+\fBpinfile\fR \fI[get|set] [file]\fR
+Get or set the pinning status on a file.
+.TP
+\fBfallocate\fR \fI[keep_size] [offset] [length] [file]\fR
+Request that space be allocated on a file.  The
+.I keep_size
+parameter can be either 1 or 0.
+.TP
+\fBwrite\fR \fI[chunk_size in 4kb] [offset in chunk_size] [count] [pattern] [IO] [file_path]\fR
+Write a given pattern to
+.IR file_path .
+The
+.I pattern
+parameter can be:
+.RS 1.2in
+.TP
+.B zero
+zeros
+.TP
+.B inc_num
+incrementing numbers
+.TP
+.B rand
+random numbers
+.RE
+.IP
+The
+.I IO
+parameter can be:
+.RS 1.2in
+.TP
+.B buffered
+buffered I/O
+.TP
+.B dio
+direct I/O
+.RE
+.TP
+\fBread\fR \fI[chunk_size in 4kb] [offset in chunk_size] [count] [IO] [print_nbytes] [file_path]\fR
+Read data in
+.I file_path
+and print
+.IR print_nbytes .
+The
+.I IO
+options can be:
+.RS 1.2in
+.TP
+.B buffered
+buffered I/O
+.TP
+.B dio
+direct I/O
+.RE
+.TP
+\fBfiemap\fR \fI[offset in 4kb] [count] [file_path]\fR
+get block address in file
+.TP
+\fBgc_urgent\fR \fIdev [start|end|run] [time in sec]\fR
+Start, end, or run gc_urgent for a given time period
+.TP
+\fBdefrag_file\fR \fI[start] [length] [file_path]\fR
+Defragment a file.
+.TP
+\fBcopy\fR \fI[-d] [-m] [-s] [src_path] [dst_path]\fR
+Copy file from src_path to dst_path.
+The
+.I pattern
+parameter can be:
+.RS 1.2in
+.TP
+.B -d
+use direct I/O
+.TP
+.B -m
+use mmap for source file
+.TP
+.B -s
+use sendfile to transfer data
+.RE
+.TP
+\fBget_cblocks\fR \fI[file]\fR
+Get the number of compressed blocks.
+.TP
+\fBrelease_cblocks\fR \fI[file]\fR
+Release compressed blocks to get free space.
+.TP
+\fBreserve_cblocks\fR \fI[file]\fR
+Reserve free blocks to prepare decompressing blocks in the file.
+.SH AUTHOR
+This version of
+.B f2fs_io
+has been written by Jaegeuk Kim <jaegeuk@kernel.org>.
+.SH AVAILABILITY
+.B f2fs_io
+is available from git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git.
diff --git a/man/mkfs.f2fs.8 b/man/mkfs.f2fs.8
index f9484eb..022941f 100644
--- a/man/mkfs.f2fs.8
+++ b/man/mkfs.f2fs.8
@@ -13,20 +13,30 @@
 ]
 [
 .B \-c
-.I device
+.I device-list
 ]
 [
 .B \-d
-.I debugging-level
+.I debug-level
 ]
 [
 .B \-e
 .I extension-list
 ]
 [
+.B \-E
+.I extension-list
+]
+[
 .B \-f
 ]
 [
+.B \-g
+]
+[
+.B \-i
+]
+[
 .B \-l
 .I volume-label
 ]
@@ -42,6 +52,10 @@
 .I feature-list
 ]
 [
+.B \-C
+.I encoding:flags
+]
+[
 .B \-q
 ]
 [
@@ -53,17 +67,23 @@
 .I #-of-segments-per-section
 ]
 [
+.B \-S
+]
+[
 .B \-t
 .I nodiscard/discard
 ]
 [
 .B \-w
-.I specific sector_size for target sectors
+.I wanted-sector-size
 ]
 [
 .B \-z
 .I #-of-sections-per-zone
 ]
+[
+.B \-V
+]
 .I device
 .I [sectors]
 .SH DESCRIPTION
@@ -84,45 +104,113 @@
 assigned separately according to the whole volume size.
 The default value is 1.
 .TP
-.BI \-c " device"
-Build f2fs with this device additionally, so that user can see all
-the devices as one big volume.
+.BI \-c " device-list"
+Build f2fs with these additional comma separated devices, so that the user can
+see all the devices as one big volume.
+Supports up to 7 devices except meta device.
 .TP
 .BI \-d " debug-level"
 Specify the level of debugging options.
 The default number is 0, which shows basic debugging messages.
 .TP
 .BI \-e " extension-list"
-Specify a file extension list in order f2fs to treat them as cold files.
-The data of files having those extensions will be stored to the cold log.
-The default list includes most of multimedia file extensions such as jpg, gif,
-mpeg, mkv, and so on.
+Specify a list of file extensions that f2fs will treat as cold files.
+The data of files with those extensions will be stored in the cold log.
+The default list includes most of the multimedia file extensions such as
+jpg, gif, mpeg, mkv, and so on.
+.TP
+.BI \-E " extension-list"
+Specify a list of file extensions that f2fs will treat as hot files.
+The data of files with those extensions will be stored in the hot log.
+The default list includes database file extensions, such as db.
 .TP
 .BI \-f
 Force overwrite when an existing filesystem is detected on the device.
 By default, mkfs.f2fs will not write to the device if it suspects that
 there is a filesystem or partition table on the device already.
 .TP
+.BI \-g
+Add default Android options.
+.TP
+.BI \-i
+Enable extended node bitmap.
 .BI \-l " volume-label"
 Specify the volume label to the partition mounted as F2FS.
 .TP
 .BI \-m
 Specify f2fs filesystem to supports the block zoned feature.
-Without it, the filesystem isn't supports the feature.
+Without it, the filesystem doesn't support the feature.
 .TP
 .BI \-o " overprovision-ratio-percentage"
-Specify the percentage over the volume size for overprovision area. This area
-is hidden to users, and utilized by F2FS cleaner. If not specified, the best
-number will be assigned automatically accoring to the partition size.
+Specify the percentage of the volume that will be used as overprovision area.
+This area is hidden to users, and utilized by F2FS cleaner. If not specified, the
+best number will be assigned automatically according to the partition size.
 .TP
 .BI \-O " feature-list"
-Specify a feature list like feature1[feature2,feature3,...] in order f2fs
-filesystem will supports.
-e.g "encrypt" and so on.
+Set additional features for the filesystem. Features are comma separated, and
+the flag can be repeated. The following features are supported:
+.RS 1.2i
+.TP 1.2i
+.B encrypt
+Enable support for filesystem level encryption.
+.TP
+.B extra_attr
+Enable extra attr feature, required for some of the other features.
+.TP
+.B project_quota
+Enable project ID tracking. This is used for projet quota accounting. Requires extra attr.
+.TP
+.B inode_checksum
+Enable inode checksum. Requires extra attr.
+.TP
+.B flexible_inline_xattr
+Enable flexible inline xattr. Requires extra attr.
+.TP
+.B quota
+Enable quotas.
+.TP
+.B inode_crtime
+Enable inode creation time feature. Requires extra attr.
+.TP
+.B lost_found
+Enable lost+found feature.
+.TP
+.B verity
+Reserved feature.
+.TP
+.B sb_checksum
+Enable superblock checksum.
+.TP
+.B casefold
+Enable casefolding support in the filesystem. Optional flags can be passed with
+.B \-C
+.TP
+.B compression
+Enable support for filesystem level compression. Requires extra attr.
+.RE
+.TP
+.BI \-C " encoding:flags"
+Support casefolding with a specific encoding, with optional comma separated flags.
+.RS 1.2i
+.TP 1.2i
+.I encoding:
+.RS 1.2i
+.TP 1.2i
+.B utf8
+Use UTF-8 for casefolding.
+.RE
+.I flags:
+.RS 1.2i
+.TP 1.2i
+.B strict
+This flag specifies that invalid strings should be rejected by the filesystem.
+Default is disabled.
+.RE
+.RE
 .TP
 .BI \-q
 Quiet mode.
-With it, mkfs.f2fs does not show any messages include the basic messages.
+With it, mkfs.f2fs does not show any messages, including the basic messages.
 .TP
 .BI \-R
 Give root_owner option for initial uid/gid assignment.
@@ -133,13 +221,15 @@
 multiple consecutive segments, and is the unit of garbage collection.
 The default number is 1, which means one segment is assigned to a section.
 .TP
-.BI \-t " nodiscard/discard"
-Specify 1 or 0 to enable/disable discard policy.
-If the value is equal to 1, discard policy is enabled, otherwise is disable.
+.BI \-S
+Enable sparse mode.
+.TP
+.BI \-t " 1/0"
+Specify 1 or 0 to enable or disable discard policy, respectively.
 The default value is 1.
 .TP
-.BI \-w "sector-size"
-Specify the sector size in bytes along with given target sectors.
+.BI \-w " wanted-sector-size"
+Specify the sector size in bytes.
 Without it, the sectors will be calculated by device sector size.
 .TP
 .BI \-z " #-of-sections-per-zone"
@@ -147,6 +237,11 @@
 F2FS allocates segments for active logs with separated zones as much as possible.
 The default number is 1, which means a zone consists of one section.
 .TP
+.BI sectors
+Number of sectors. Default is determined by device size.
+.TP
+.BI \-V
+Print the version number and exit.
 .SH AUTHOR
 This version of
 .B mkfs.f2fs
diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c
index d68fc65..204a410 100644
--- a/mkfs/f2fs_format_main.c
+++ b/mkfs/f2fs_format_main.c
@@ -44,17 +44,18 @@
 	MSG(0, "\nUsage: mkfs.f2fs [options] device [sectors]\n");
 	MSG(0, "[options]:\n");
 	MSG(0, "  -a heap-based allocation [default:0]\n");
-	MSG(0, "  -c [device path] up to 7 devices excepts meta device\n");
+	MSG(0, "  -c device1[,device2,...] up to 7 additional devices, except meta device\n");
 	MSG(0, "  -d debug level [default:0]\n");
 	MSG(0, "  -e [cold file ext list] e.g. \"mp3,gif,mov\"\n");
 	MSG(0, "  -E [hot file ext list] e.g. \"db\"\n");
-	MSG(0, "  -f force overwrite the exist filesystem\n");
+	MSG(0, "  -f force overwrite of the existing filesystem\n");
 	MSG(0, "  -g add default options\n");
 	MSG(0, "  -i extended node bitmap, node ratio is 20%% by default\n");
 	MSG(0, "  -l label\n");
 	MSG(0, "  -m support zoned block device [default:0]\n");
-	MSG(0, "  -o overprovision ratio [default:5]\n");
-	MSG(0, "  -O feature1[feature2,feature3,...] e.g. \"encrypt\"\n");
+	MSG(0, "  -o overprovision percentage [default:auto]\n");
+	MSG(0, "  -O feature1[,feature2,...] e.g. \"encrypt\"\n");
+	MSG(0, "  -C [encoding[:flag1,...]] Support casefolding with optional flags\n");
 	MSG(0, "  -q quiet mode\n");
 	MSG(0, "  -R root_owner [default: 0:0]\n");
 	MSG(0, "  -s # of segments per section [default:1]\n");
@@ -63,8 +64,7 @@
 	MSG(0, "  -w wanted sector size\n");
 	MSG(0, "  -z # of sections per zone [default:1]\n");
 	MSG(0, "  -V print the version number and exit\n");
-	MSG(0, "sectors: number of sectors. [default: determined by device size]\n");
-	MSG(0, "  -C [encoding:flag1,flag2] Support casefolding with optional flags\n");
+	MSG(0, "sectors: number of sectors [default: determined by device size]\n");
 	exit(1);
 }
 
diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
index c1edef1..30544c1 100644
--- a/tools/f2fs_io/f2fs_io.c
+++ b/tools/f2fs_io/f2fs_io.c
@@ -130,6 +130,30 @@
 	}
 }
 
+#define fsync_desc "fsync"
+#define fsync_help						\
+"f2fs_io fsync [file]\n\n"					\
+"fsync given the file\n"					\
+
+static void do_fsync(int argc, char **argv, const struct cmd_desc *cmd)
+{
+	int fd;
+
+	if (argc != 2) {
+		fputs("Excess arguments\n\n", stderr);
+		fputs(cmd->cmd_help, stderr);
+		exit(1);
+	}
+
+	fd = xopen(argv[1], O_WRONLY, 0);
+
+	if (fsync(fd) != 0)
+		die_errno("fsync failed");
+
+	printf("fsync a file\n");
+	exit(0);
+}
+
 #define set_verity_desc "Set fs-verity"
 #define set_verity_help					\
 "f2fs_io set_verity [file]\n\n"				\
@@ -162,13 +186,17 @@
 "f2fs_io getflags [file]\n\n"					\
 "get a flag given the file\n"					\
 "flag can show \n"						\
+"  encryption\n"						\
+"  nocow(pinned)\n"						\
+"  inline_data\n"						\
+"  verity\n"							\
 "  casefold\n"							\
 "  compression\n"						\
 "  nocompression\n"
 
 static void do_getflags(int argc, char **argv, const struct cmd_desc *cmd)
 {
-	long flag;
+	long flag = 0;
 	int ret, fd;
 	int exist = 0;
 
@@ -198,6 +226,30 @@
 		printf("nocompression");
 		exist = 1;
 	}
+	if (flag & FS_ENCRYPT_FL) {
+		if (exist)
+			printf(",");
+		printf("encrypt");
+		exist = 1;
+	}
+	if (flag & FS_VERITY_FL) {
+		if (exist)
+			printf(",");
+		printf("verity");
+		exist = 1;
+	}
+	if (flag & FS_INLINE_DATA_FL) {
+		if (exist)
+			printf(",");
+		printf("inline_data");
+		exist = 1;
+	}
+	if (flag & FS_NOCOW_FL) {
+		if (exist)
+			printf(",");
+		printf("nocow(pinned)");
+		exist = 1;
+	}
 	if (!exist)
 		printf("none");
 	printf("\n");
@@ -215,7 +267,7 @@
 
 static void do_setflags(int argc, char **argv, const struct cmd_desc *cmd)
 {
-	long flag;
+	long flag = 0;
 	int ret, fd;
 
 	if (argc != 3) {
@@ -499,6 +551,69 @@
 	exit(0);
 }
 
+#define randread_desc "random read data from file"
+#define randread_help					\
+"f2fs_io randread [chunk_size in 4kb] [count] [IO] [file_path]\n\n"	\
+"Do random read data in file_path\n"		\
+"IO can be\n"						\
+"  buffered : buffered IO\n"				\
+"  dio      : direct IO\n"				\
+
+static void do_randread(int argc, char **argv, const struct cmd_desc *cmd)
+{
+	u64 buf_size = 0, ret = 0, read_cnt = 0;
+	u64 idx, end_idx, aligned_size;
+	char *buf = NULL;
+	unsigned bs, count, i;
+	int flags = 0;
+	int fd;
+	time_t t;
+	struct stat stbuf;
+
+	if (argc != 5) {
+		fputs("Excess arguments\n\n", stderr);
+		fputs(cmd->cmd_help, stderr);
+		exit(1);
+	}
+
+	bs = atoi(argv[1]);
+	if (bs > 1024)
+		die("Too big chunk size - limit: 4MB");
+	buf_size = bs * 4096;
+
+	buf = aligned_xalloc(4096, buf_size);
+
+	count = atoi(argv[2]);
+	if (!strcmp(argv[3], "dio"))
+		flags |= O_DIRECT;
+	else if (strcmp(argv[3], "buffered"))
+		die("Wrong IO type");
+
+	fd = xopen(argv[4], O_RDONLY | flags, 0);
+
+	if (fstat(fd, &stbuf) != 0)
+		die_errno("fstat of source file failed");
+
+	aligned_size = (u64)stbuf.st_size & ~((u64)(4096 - 1));
+	if (aligned_size < buf_size)
+		die("File is too small to random read");
+	end_idx = (u64)(aligned_size - buf_size) / (u64)4096 + 1;
+
+	srand((unsigned) time(&t));
+
+	for (i = 0; i < count; i++) {
+		idx = rand() % end_idx;
+
+		ret = pread(fd, buf, buf_size, 4096 * idx);
+		if (ret != buf_size)
+			break;
+
+		read_cnt += ret;
+	}
+	printf("Read %"PRIu64" bytes\n", read_cnt);
+	exit(0);
+}
+
 struct file_ext {
 	__u32 f_pos;
 	__u32 start_blk;
@@ -780,6 +895,7 @@
 static void do_help(int argc, char **argv, const struct cmd_desc *cmd);
 const struct cmd_desc cmd_list[] = {
 	_CMD(help),
+	CMD(fsync),
 	CMD(set_verity),
 	CMD(getflags),
 	CMD(setflags),
@@ -788,6 +904,7 @@
 	CMD(fallocate),
 	CMD(write),
 	CMD(read),
+	CMD(randread),
 	CMD(fiemap),
 	CMD(gc_urgent),
 	CMD(defrag_file),
diff --git a/tools/f2fs_io/f2fs_io.h b/tools/f2fs_io/f2fs_io.h
index c6ea7ff..bd19ff9 100644
--- a/tools/f2fs_io/f2fs_io.h
+++ b/tools/f2fs_io/f2fs_io.h
@@ -110,6 +110,18 @@
 #define F2FS_IOC_FSGETXATTR		FS_IOC_FSGETXATTR
 #define F2FS_IOC_FSSETXATTR		FS_IOC_FSSETXATTR
 
+#ifndef FS_ENCRYPT_FL
+#define FS_ENCRYPT_FL			0x00000800 /* Encrypted file */
+#endif
+#ifndef FS_VERITY_FL
+#define FS_VERITY_FL			0x00100000 /* Verity protected inode */
+#endif
+#ifndef FS_INLINE_DATA_FL
+#define FS_INLINE_DATA_FL		0x10000000 /* Inline data for regular/symlink files */
+#endif
+#ifndef FS_NOCOW_FL
+#define FS_NOCOW_FL			0x00800000 /* Do not cow file */
+#endif
 #ifndef FS_NOCOMP_FL
 #define FS_NOCOMP_FL			0x00000400 /* Don't compress */
 #endif