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