15e5c12b0Sopenharmony_ci/*
25e5c12b0Sopenharmony_ci * f2fs_io.c - f2fs ioctl utility
35e5c12b0Sopenharmony_ci *
45e5c12b0Sopenharmony_ci * Author: Jaegeuk Kim <jaegeuk@kernel.org>
55e5c12b0Sopenharmony_ci *
65e5c12b0Sopenharmony_ci * Copied portion of the code from ../f2fscrypt.c
75e5c12b0Sopenharmony_ci */
85e5c12b0Sopenharmony_ci
95e5c12b0Sopenharmony_ci#ifndef _GNU_SOURCE
105e5c12b0Sopenharmony_ci#define _GNU_SOURCE
115e5c12b0Sopenharmony_ci#endif
125e5c12b0Sopenharmony_ci#ifndef _LARGEFILE_SOURCE
135e5c12b0Sopenharmony_ci#define _LARGEFILE_SOURCE
145e5c12b0Sopenharmony_ci#endif
155e5c12b0Sopenharmony_ci#ifndef _LARGEFILE64_SOURCE
165e5c12b0Sopenharmony_ci#define _LARGEFILE64_SOURCE
175e5c12b0Sopenharmony_ci#endif
185e5c12b0Sopenharmony_ci#ifndef O_LARGEFILE
195e5c12b0Sopenharmony_ci#define O_LARGEFILE 0
205e5c12b0Sopenharmony_ci#endif
215e5c12b0Sopenharmony_ci#ifndef __SANE_USERSPACE_TYPES__
225e5c12b0Sopenharmony_ci#define __SANE_USERSPACE_TYPES__       /* For PPC64, to get LL64 types */
235e5c12b0Sopenharmony_ci#endif
245e5c12b0Sopenharmony_ci
255e5c12b0Sopenharmony_ci#include <errno.h>
265e5c12b0Sopenharmony_ci#include <fcntl.h>
275e5c12b0Sopenharmony_ci#include <getopt.h>
285e5c12b0Sopenharmony_ci#include <inttypes.h>
295e5c12b0Sopenharmony_ci#include <limits.h>
305e5c12b0Sopenharmony_ci#include <linux/fs.h>
315e5c12b0Sopenharmony_ci#include <signal.h>
325e5c12b0Sopenharmony_ci#include <stdarg.h>
335e5c12b0Sopenharmony_ci#include <stdbool.h>
345e5c12b0Sopenharmony_ci#include <stdio.h>
355e5c12b0Sopenharmony_ci#include <stdlib.h>
365e5c12b0Sopenharmony_ci#include <string.h>
375e5c12b0Sopenharmony_ci#include <sys/mman.h>
385e5c12b0Sopenharmony_ci#include <sys/sendfile.h>
395e5c12b0Sopenharmony_ci#include <sys/stat.h>
405e5c12b0Sopenharmony_ci#include <sys/types.h>
415e5c12b0Sopenharmony_ci#include <termios.h>
425e5c12b0Sopenharmony_ci#include <time.h>
435e5c12b0Sopenharmony_ci#include <unistd.h>
445e5c12b0Sopenharmony_ci
455e5c12b0Sopenharmony_ci#ifdef HAVE_CONFIG_H
465e5c12b0Sopenharmony_ci#include <config.h>
475e5c12b0Sopenharmony_ci#endif
485e5c12b0Sopenharmony_ci#include <android_config.h>
495e5c12b0Sopenharmony_ci
505e5c12b0Sopenharmony_ci#include "f2fs_io.h"
515e5c12b0Sopenharmony_ci
525e5c12b0Sopenharmony_cistruct cmd_desc {
535e5c12b0Sopenharmony_ci	const char *cmd_name;
545e5c12b0Sopenharmony_ci	void (*cmd_func)(int, char **, const struct cmd_desc *);
555e5c12b0Sopenharmony_ci	const char *cmd_desc;
565e5c12b0Sopenharmony_ci	const char *cmd_help;
575e5c12b0Sopenharmony_ci	int cmd_flags;
585e5c12b0Sopenharmony_ci};
595e5c12b0Sopenharmony_ci
605e5c12b0Sopenharmony_cistatic void __attribute__((noreturn))
615e5c12b0Sopenharmony_cido_die(const char *format, va_list va, int err)
625e5c12b0Sopenharmony_ci{
635e5c12b0Sopenharmony_ci	vfprintf(stderr, format, va);
645e5c12b0Sopenharmony_ci	if (err)
655e5c12b0Sopenharmony_ci		fprintf(stderr, ": %s", strerror(err));
665e5c12b0Sopenharmony_ci	putc('\n', stderr);
675e5c12b0Sopenharmony_ci	exit(1);
685e5c12b0Sopenharmony_ci}
695e5c12b0Sopenharmony_ci
705e5c12b0Sopenharmony_cistatic void __attribute__((noreturn, format(printf, 1, 2)))
715e5c12b0Sopenharmony_cidie_errno(const char *format, ...)
725e5c12b0Sopenharmony_ci{
735e5c12b0Sopenharmony_ci	va_list va;
745e5c12b0Sopenharmony_ci
755e5c12b0Sopenharmony_ci	va_start(va, format);
765e5c12b0Sopenharmony_ci	do_die(format, va, errno);
775e5c12b0Sopenharmony_ci	va_end(va);
785e5c12b0Sopenharmony_ci}
795e5c12b0Sopenharmony_ci
805e5c12b0Sopenharmony_cistatic void __attribute__((noreturn, format(printf, 1, 2)))
815e5c12b0Sopenharmony_cidie(const char *format, ...)
825e5c12b0Sopenharmony_ci{
835e5c12b0Sopenharmony_ci	va_list va;
845e5c12b0Sopenharmony_ci
855e5c12b0Sopenharmony_ci	va_start(va, format);
865e5c12b0Sopenharmony_ci	do_die(format, va, 0);
875e5c12b0Sopenharmony_ci	va_end(va);
885e5c12b0Sopenharmony_ci}
895e5c12b0Sopenharmony_ci
905e5c12b0Sopenharmony_cistatic void *xmalloc(size_t size)
915e5c12b0Sopenharmony_ci{
925e5c12b0Sopenharmony_ci	void *p = malloc(size);
935e5c12b0Sopenharmony_ci
945e5c12b0Sopenharmony_ci	if (!p)
955e5c12b0Sopenharmony_ci		die("Memory alloc failed (requested %zu bytes)", size);
965e5c12b0Sopenharmony_ci	return p;
975e5c12b0Sopenharmony_ci}
985e5c12b0Sopenharmony_ci
995e5c12b0Sopenharmony_cistatic void *aligned_xalloc(size_t alignment, size_t size)
1005e5c12b0Sopenharmony_ci{
1015e5c12b0Sopenharmony_ci	void *p = aligned_alloc(alignment, size);
1025e5c12b0Sopenharmony_ci
1035e5c12b0Sopenharmony_ci	if (!p)
1045e5c12b0Sopenharmony_ci		die("Memory alloc failed (requested %zu bytes)", size);
1055e5c12b0Sopenharmony_ci	return p;
1065e5c12b0Sopenharmony_ci}
1075e5c12b0Sopenharmony_ci
1085e5c12b0Sopenharmony_cistatic int xopen(const char *pathname, int flags, mode_t mode)
1095e5c12b0Sopenharmony_ci{
1105e5c12b0Sopenharmony_ci	int fd = open(pathname, flags, mode);
1115e5c12b0Sopenharmony_ci
1125e5c12b0Sopenharmony_ci	if (fd < 0)
1135e5c12b0Sopenharmony_ci		die_errno("Failed to open %s", pathname);
1145e5c12b0Sopenharmony_ci	return fd;
1155e5c12b0Sopenharmony_ci}
1165e5c12b0Sopenharmony_ci
1175e5c12b0Sopenharmony_cistatic ssize_t xread(int fd, void *buf, size_t count)
1185e5c12b0Sopenharmony_ci{
1195e5c12b0Sopenharmony_ci	ssize_t ret = read(fd, buf, count);
1205e5c12b0Sopenharmony_ci
1215e5c12b0Sopenharmony_ci	if (ret < 0)
1225e5c12b0Sopenharmony_ci		die_errno("read failed");
1235e5c12b0Sopenharmony_ci	return ret;
1245e5c12b0Sopenharmony_ci}
1255e5c12b0Sopenharmony_ci
1265e5c12b0Sopenharmony_cistatic void full_write(int fd, const void *buf, size_t count)
1275e5c12b0Sopenharmony_ci{
1285e5c12b0Sopenharmony_ci	while (count) {
1295e5c12b0Sopenharmony_ci		ssize_t ret = write(fd, buf, count);
1305e5c12b0Sopenharmony_ci
1315e5c12b0Sopenharmony_ci		if (ret < 0)
1325e5c12b0Sopenharmony_ci			die_errno("write failed");
1335e5c12b0Sopenharmony_ci		buf = (char *)buf + ret;
1345e5c12b0Sopenharmony_ci		count -= ret;
1355e5c12b0Sopenharmony_ci	}
1365e5c12b0Sopenharmony_ci}
1375e5c12b0Sopenharmony_ci
1385e5c12b0Sopenharmony_ci#ifdef HAVE_MACH_TIME_H
1395e5c12b0Sopenharmony_cistatic u64 get_current_us()
1405e5c12b0Sopenharmony_ci{
1415e5c12b0Sopenharmony_ci	return mach_absolute_time() / 1000;
1425e5c12b0Sopenharmony_ci}
1435e5c12b0Sopenharmony_ci#elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_BOOTTIME)
1445e5c12b0Sopenharmony_cistatic u64 get_current_us()
1455e5c12b0Sopenharmony_ci{
1465e5c12b0Sopenharmony_ci	struct timespec t;
1475e5c12b0Sopenharmony_ci	t.tv_sec = t.tv_nsec = 0;
1485e5c12b0Sopenharmony_ci	clock_gettime(CLOCK_BOOTTIME, &t);
1495e5c12b0Sopenharmony_ci	return (u64)t.tv_sec * 1000000LL + t.tv_nsec / 1000;
1505e5c12b0Sopenharmony_ci}
1515e5c12b0Sopenharmony_ci#else
1525e5c12b0Sopenharmony_cistatic u64 get_current_us()
1535e5c12b0Sopenharmony_ci{
1545e5c12b0Sopenharmony_ci	return 0;
1555e5c12b0Sopenharmony_ci}
1565e5c12b0Sopenharmony_ci#endif
1575e5c12b0Sopenharmony_ci
1585e5c12b0Sopenharmony_ci#define fsync_desc "fsync"
1595e5c12b0Sopenharmony_ci#define fsync_help						\
1605e5c12b0Sopenharmony_ci"f2fs_io fsync [file]\n\n"					\
1615e5c12b0Sopenharmony_ci"fsync given the file\n"					\
1625e5c12b0Sopenharmony_ci
1635e5c12b0Sopenharmony_cistatic void do_fsync(int argc, char **argv, const struct cmd_desc *cmd)
1645e5c12b0Sopenharmony_ci{
1655e5c12b0Sopenharmony_ci	int fd;
1665e5c12b0Sopenharmony_ci
1675e5c12b0Sopenharmony_ci	if (argc != 2) {
1685e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
1695e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
1705e5c12b0Sopenharmony_ci		exit(1);
1715e5c12b0Sopenharmony_ci	}
1725e5c12b0Sopenharmony_ci
1735e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_WRONLY, 0);
1745e5c12b0Sopenharmony_ci
1755e5c12b0Sopenharmony_ci	if (fsync(fd) != 0)
1765e5c12b0Sopenharmony_ci		die_errno("fsync failed");
1775e5c12b0Sopenharmony_ci
1785e5c12b0Sopenharmony_ci	printf("fsync a file\n");
1795e5c12b0Sopenharmony_ci	exit(0);
1805e5c12b0Sopenharmony_ci}
1815e5c12b0Sopenharmony_ci
1825e5c12b0Sopenharmony_ci#define set_verity_desc "Set fs-verity"
1835e5c12b0Sopenharmony_ci#define set_verity_help					\
1845e5c12b0Sopenharmony_ci"f2fs_io set_verity [file]\n\n"				\
1855e5c12b0Sopenharmony_ci"Set fsverity bit given a file\n"			\
1865e5c12b0Sopenharmony_ci
1875e5c12b0Sopenharmony_cistatic void do_set_verity(int argc, char **argv, const struct cmd_desc *cmd)
1885e5c12b0Sopenharmony_ci{
1895e5c12b0Sopenharmony_ci	int ret, fd;
1905e5c12b0Sopenharmony_ci
1915e5c12b0Sopenharmony_ci	if (argc != 2) {
1925e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
1935e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
1945e5c12b0Sopenharmony_ci		exit(1);
1955e5c12b0Sopenharmony_ci	}
1965e5c12b0Sopenharmony_ci
1975e5c12b0Sopenharmony_ci	fd = open(argv[1], O_RDWR);
1985e5c12b0Sopenharmony_ci
1995e5c12b0Sopenharmony_ci	ret = ioctl(fd, FS_IOC_ENABLE_VERITY);
2005e5c12b0Sopenharmony_ci	if (ret < 0) {
2015e5c12b0Sopenharmony_ci		perror("FS_IOC_ENABLE_VERITY");
2025e5c12b0Sopenharmony_ci		exit(1);
2035e5c12b0Sopenharmony_ci	}
2045e5c12b0Sopenharmony_ci
2055e5c12b0Sopenharmony_ci	printf("Set fsverity bit to %s\n", argv[1]);
2065e5c12b0Sopenharmony_ci	exit(0);
2075e5c12b0Sopenharmony_ci}
2085e5c12b0Sopenharmony_ci
2095e5c12b0Sopenharmony_ci#define getflags_desc "getflags ioctl"
2105e5c12b0Sopenharmony_ci#define getflags_help						\
2115e5c12b0Sopenharmony_ci"f2fs_io getflags [file]\n\n"					\
2125e5c12b0Sopenharmony_ci"get a flag given the file\n"					\
2135e5c12b0Sopenharmony_ci"flag can show \n"						\
2145e5c12b0Sopenharmony_ci"  encryption\n"						\
2155e5c12b0Sopenharmony_ci"  nocow(pinned)\n"						\
2165e5c12b0Sopenharmony_ci"  inline_data\n"						\
2175e5c12b0Sopenharmony_ci"  verity\n"							\
2185e5c12b0Sopenharmony_ci"  casefold\n"							\
2195e5c12b0Sopenharmony_ci"  compression\n"						\
2205e5c12b0Sopenharmony_ci"  nocompression\n"						\
2215e5c12b0Sopenharmony_ci"  immutable\n"
2225e5c12b0Sopenharmony_ci
2235e5c12b0Sopenharmony_cistatic void do_getflags(int argc, char **argv, const struct cmd_desc *cmd)
2245e5c12b0Sopenharmony_ci{
2255e5c12b0Sopenharmony_ci	long flag = 0;
2265e5c12b0Sopenharmony_ci	int ret, fd;
2275e5c12b0Sopenharmony_ci	int exist = 0;
2285e5c12b0Sopenharmony_ci
2295e5c12b0Sopenharmony_ci	if (argc != 2) {
2305e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
2315e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
2325e5c12b0Sopenharmony_ci		exit(1);
2335e5c12b0Sopenharmony_ci	}
2345e5c12b0Sopenharmony_ci
2355e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_RDONLY, 0);
2365e5c12b0Sopenharmony_ci
2375e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_GETFLAGS, &flag);
2385e5c12b0Sopenharmony_ci	printf("get a flag on %s ret=%d, flags=", argv[1], ret);
2395e5c12b0Sopenharmony_ci	if (flag & FS_CASEFOLD_FL) {
2405e5c12b0Sopenharmony_ci		printf("casefold");
2415e5c12b0Sopenharmony_ci		exist = 1;
2425e5c12b0Sopenharmony_ci	}
2435e5c12b0Sopenharmony_ci	if (flag & FS_COMPR_FL) {
2445e5c12b0Sopenharmony_ci		if (exist)
2455e5c12b0Sopenharmony_ci			printf(",");
2465e5c12b0Sopenharmony_ci		printf("compression");
2475e5c12b0Sopenharmony_ci		exist = 1;
2485e5c12b0Sopenharmony_ci	}
2495e5c12b0Sopenharmony_ci	if (flag & FS_NOCOMP_FL) {
2505e5c12b0Sopenharmony_ci		if (exist)
2515e5c12b0Sopenharmony_ci			printf(",");
2525e5c12b0Sopenharmony_ci		printf("nocompression");
2535e5c12b0Sopenharmony_ci		exist = 1;
2545e5c12b0Sopenharmony_ci	}
2555e5c12b0Sopenharmony_ci	if (flag & FS_ENCRYPT_FL) {
2565e5c12b0Sopenharmony_ci		if (exist)
2575e5c12b0Sopenharmony_ci			printf(",");
2585e5c12b0Sopenharmony_ci		printf("encrypt");
2595e5c12b0Sopenharmony_ci		exist = 1;
2605e5c12b0Sopenharmony_ci	}
2615e5c12b0Sopenharmony_ci	if (flag & FS_VERITY_FL) {
2625e5c12b0Sopenharmony_ci		if (exist)
2635e5c12b0Sopenharmony_ci			printf(",");
2645e5c12b0Sopenharmony_ci		printf("verity");
2655e5c12b0Sopenharmony_ci		exist = 1;
2665e5c12b0Sopenharmony_ci	}
2675e5c12b0Sopenharmony_ci	if (flag & FS_INLINE_DATA_FL) {
2685e5c12b0Sopenharmony_ci		if (exist)
2695e5c12b0Sopenharmony_ci			printf(",");
2705e5c12b0Sopenharmony_ci		printf("inline_data");
2715e5c12b0Sopenharmony_ci		exist = 1;
2725e5c12b0Sopenharmony_ci	}
2735e5c12b0Sopenharmony_ci	if (flag & FS_NOCOW_FL) {
2745e5c12b0Sopenharmony_ci		if (exist)
2755e5c12b0Sopenharmony_ci			printf(",");
2765e5c12b0Sopenharmony_ci		printf("nocow(pinned)");
2775e5c12b0Sopenharmony_ci		exist = 1;
2785e5c12b0Sopenharmony_ci	}
2795e5c12b0Sopenharmony_ci	if (flag & FS_IMMUTABLE_FL) {
2805e5c12b0Sopenharmony_ci		if (exist)
2815e5c12b0Sopenharmony_ci			printf(",");
2825e5c12b0Sopenharmony_ci		printf("immutable");
2835e5c12b0Sopenharmony_ci		exist = 1;
2845e5c12b0Sopenharmony_ci	}
2855e5c12b0Sopenharmony_ci	if (!exist)
2865e5c12b0Sopenharmony_ci		printf("none");
2875e5c12b0Sopenharmony_ci	printf("\n");
2885e5c12b0Sopenharmony_ci	exit(0);
2895e5c12b0Sopenharmony_ci}
2905e5c12b0Sopenharmony_ci
2915e5c12b0Sopenharmony_ci#define setflags_desc "setflags ioctl"
2925e5c12b0Sopenharmony_ci#define setflags_help						\
2935e5c12b0Sopenharmony_ci"f2fs_io setflags [flag] [file]\n\n"				\
2945e5c12b0Sopenharmony_ci"set a flag given the file\n"					\
2955e5c12b0Sopenharmony_ci"flag can be\n"							\
2965e5c12b0Sopenharmony_ci"  casefold\n"							\
2975e5c12b0Sopenharmony_ci"  compression\n"						\
2985e5c12b0Sopenharmony_ci"  nocompression\n"						\
2995e5c12b0Sopenharmony_ci"  noimmutable\n"
3005e5c12b0Sopenharmony_ci
3015e5c12b0Sopenharmony_cistatic void do_setflags(int argc, char **argv, const struct cmd_desc *cmd)
3025e5c12b0Sopenharmony_ci{
3035e5c12b0Sopenharmony_ci	long flag = 0;
3045e5c12b0Sopenharmony_ci	int ret, fd;
3055e5c12b0Sopenharmony_ci
3065e5c12b0Sopenharmony_ci	if (argc != 3) {
3075e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
3085e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
3095e5c12b0Sopenharmony_ci		exit(1);
3105e5c12b0Sopenharmony_ci	}
3115e5c12b0Sopenharmony_ci
3125e5c12b0Sopenharmony_ci	fd = xopen(argv[2], O_RDONLY, 0);
3135e5c12b0Sopenharmony_ci
3145e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_GETFLAGS, &flag);
3155e5c12b0Sopenharmony_ci	printf("get a flag on %s ret=%d, flags=%lx\n", argv[1], ret, flag);
3165e5c12b0Sopenharmony_ci	if (ret)
3175e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_GETFLAGS failed");
3185e5c12b0Sopenharmony_ci
3195e5c12b0Sopenharmony_ci	if (!strcmp(argv[1], "casefold"))
3205e5c12b0Sopenharmony_ci		flag |= FS_CASEFOLD_FL;
3215e5c12b0Sopenharmony_ci	else if (!strcmp(argv[1], "compression"))
3225e5c12b0Sopenharmony_ci		flag |= FS_COMPR_FL;
3235e5c12b0Sopenharmony_ci	else if (!strcmp(argv[1], "nocompression"))
3245e5c12b0Sopenharmony_ci		flag |= FS_NOCOMP_FL;
3255e5c12b0Sopenharmony_ci	else if (!strcmp(argv[1], "noimmutable"))
3265e5c12b0Sopenharmony_ci		flag &= ~FS_IMMUTABLE_FL;
3275e5c12b0Sopenharmony_ci
3285e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_SETFLAGS, &flag);
3295e5c12b0Sopenharmony_ci	printf("set a flag on %s ret=%d, flags=%s\n", argv[2], ret, argv[1]);
3305e5c12b0Sopenharmony_ci	exit(0);
3315e5c12b0Sopenharmony_ci}
3325e5c12b0Sopenharmony_ci
3335e5c12b0Sopenharmony_ci#define shutdown_desc "shutdown filesystem"
3345e5c12b0Sopenharmony_ci#define shutdown_help					\
3355e5c12b0Sopenharmony_ci"f2fs_io shutdown [level] [dir]\n\n"			\
3365e5c12b0Sopenharmony_ci"Freeze and stop all IOs given mount point\n"		\
3375e5c12b0Sopenharmony_ci"level can be\n"					\
3385e5c12b0Sopenharmony_ci"  0 : going down with full sync\n"			\
3395e5c12b0Sopenharmony_ci"  1 : going down with checkpoint only\n"		\
3405e5c12b0Sopenharmony_ci"  2 : going down with no sync\n"			\
3415e5c12b0Sopenharmony_ci"  3 : going down with metadata flush\n"		\
3425e5c12b0Sopenharmony_ci"  4 : going down with fsck mark\n"
3435e5c12b0Sopenharmony_ci
3445e5c12b0Sopenharmony_cistatic void do_shutdown(int argc, char **argv, const struct cmd_desc *cmd)
3455e5c12b0Sopenharmony_ci{
3465e5c12b0Sopenharmony_ci	u32 flag;
3475e5c12b0Sopenharmony_ci	int ret, fd;
3485e5c12b0Sopenharmony_ci
3495e5c12b0Sopenharmony_ci	if (argc != 3) {
3505e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
3515e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
3525e5c12b0Sopenharmony_ci		exit(1);
3535e5c12b0Sopenharmony_ci	}
3545e5c12b0Sopenharmony_ci
3555e5c12b0Sopenharmony_ci	flag = atoi(argv[1]);
3565e5c12b0Sopenharmony_ci	if (flag >= F2FS_GOING_DOWN_MAX) {
3575e5c12b0Sopenharmony_ci		fputs("Wrong level\n\n", stderr);
3585e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
3595e5c12b0Sopenharmony_ci		exit(1);
3605e5c12b0Sopenharmony_ci	}
3615e5c12b0Sopenharmony_ci	fd = xopen(argv[2], O_RDONLY, 0);
3625e5c12b0Sopenharmony_ci
3635e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_SHUTDOWN, &flag);
3645e5c12b0Sopenharmony_ci	if (ret < 0)
3655e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_SHUTDOWN failed");
3665e5c12b0Sopenharmony_ci
3675e5c12b0Sopenharmony_ci	printf("Shutdown %s with level=%d\n", argv[2], flag);
3685e5c12b0Sopenharmony_ci	exit(0);
3695e5c12b0Sopenharmony_ci}
3705e5c12b0Sopenharmony_ci
3715e5c12b0Sopenharmony_ci#define pinfile_desc "pin file control"
3725e5c12b0Sopenharmony_ci#define pinfile_help						\
3735e5c12b0Sopenharmony_ci"f2fs_io pinfile [get|set] [file]\n\n"			\
3745e5c12b0Sopenharmony_ci"get/set pinning given the file\n"				\
3755e5c12b0Sopenharmony_ci
3765e5c12b0Sopenharmony_cistatic void do_pinfile(int argc, char **argv, const struct cmd_desc *cmd)
3775e5c12b0Sopenharmony_ci{
3785e5c12b0Sopenharmony_ci	u32 pin;
3795e5c12b0Sopenharmony_ci	int ret, fd;
3805e5c12b0Sopenharmony_ci
3815e5c12b0Sopenharmony_ci	if (argc != 3) {
3825e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
3835e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
3845e5c12b0Sopenharmony_ci		exit(1);
3855e5c12b0Sopenharmony_ci	}
3865e5c12b0Sopenharmony_ci
3875e5c12b0Sopenharmony_ci	fd = xopen(argv[2], O_RDONLY, 0);
3885e5c12b0Sopenharmony_ci
3895e5c12b0Sopenharmony_ci	ret = -1;
3905e5c12b0Sopenharmony_ci	if (!strcmp(argv[1], "set")) {
3915e5c12b0Sopenharmony_ci		pin = 1;
3925e5c12b0Sopenharmony_ci		ret = ioctl(fd, F2FS_IOC_SET_PIN_FILE, &pin);
3935e5c12b0Sopenharmony_ci		if (ret != 0)
3945e5c12b0Sopenharmony_ci			die_errno("F2FS_IOC_SET_PIN_FILE failed");
3955e5c12b0Sopenharmony_ci		printf("set_pin_file: %u blocks moved in %s\n", ret, argv[2]);
3965e5c12b0Sopenharmony_ci	} else if (!strcmp(argv[1], "get")) {
3975e5c12b0Sopenharmony_ci		unsigned int flags;
3985e5c12b0Sopenharmony_ci
3995e5c12b0Sopenharmony_ci		ret = ioctl(fd, F2FS_IOC_GET_PIN_FILE, &pin);
4005e5c12b0Sopenharmony_ci		if (ret < 0)
4015e5c12b0Sopenharmony_ci			die_errno("F2FS_IOC_GET_PIN_FILE failed");
4025e5c12b0Sopenharmony_ci
4035e5c12b0Sopenharmony_ci		ret = ioctl(fd, F2FS_IOC_GETFLAGS, &flags);
4045e5c12b0Sopenharmony_ci		if (ret < 0)
4055e5c12b0Sopenharmony_ci			die_errno("F2FS_IOC_GETFLAGS failed");
4065e5c12b0Sopenharmony_ci
4075e5c12b0Sopenharmony_ci		printf("get_pin_file: %s with %u blocks moved in %s\n",
4085e5c12b0Sopenharmony_ci				(flags & F2FS_NOCOW_FL) ? "pinned" : "un-pinned",
4095e5c12b0Sopenharmony_ci				pin, argv[2]);
4105e5c12b0Sopenharmony_ci	}
4115e5c12b0Sopenharmony_ci	exit(0);
4125e5c12b0Sopenharmony_ci}
4135e5c12b0Sopenharmony_ci
4145e5c12b0Sopenharmony_ci#define fallocate_desc "fallocate"
4155e5c12b0Sopenharmony_ci#define fallocate_help						\
4165e5c12b0Sopenharmony_ci"f2fs_io fallocate [keep_size] [offset] [length] [file]\n\n"	\
4175e5c12b0Sopenharmony_ci"fallocate given the file\n"					\
4185e5c12b0Sopenharmony_ci" [keep_size] : 1 or 0\n"					\
4195e5c12b0Sopenharmony_ci
4205e5c12b0Sopenharmony_cistatic void do_fallocate(int argc, char **argv, const struct cmd_desc *cmd)
4215e5c12b0Sopenharmony_ci{
4225e5c12b0Sopenharmony_ci	int fd;
4235e5c12b0Sopenharmony_ci	off_t offset, length;
4245e5c12b0Sopenharmony_ci	struct stat sb;
4255e5c12b0Sopenharmony_ci	int mode = 0;
4265e5c12b0Sopenharmony_ci
4275e5c12b0Sopenharmony_ci	if (argc != 5) {
4285e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
4295e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
4305e5c12b0Sopenharmony_ci		exit(1);
4315e5c12b0Sopenharmony_ci	}
4325e5c12b0Sopenharmony_ci
4335e5c12b0Sopenharmony_ci	if (!strcmp(argv[1], "1"))
4345e5c12b0Sopenharmony_ci		mode |= FALLOC_FL_KEEP_SIZE;
4355e5c12b0Sopenharmony_ci
4365e5c12b0Sopenharmony_ci	offset = atoi(argv[2]);
4375e5c12b0Sopenharmony_ci	length = atoll(argv[3]);
4385e5c12b0Sopenharmony_ci
4395e5c12b0Sopenharmony_ci	fd = xopen(argv[4], O_RDWR, 0);
4405e5c12b0Sopenharmony_ci
4415e5c12b0Sopenharmony_ci	if (fallocate(fd, mode, offset, length) != 0)
4425e5c12b0Sopenharmony_ci		die_errno("fallocate failed");
4435e5c12b0Sopenharmony_ci
4445e5c12b0Sopenharmony_ci	if (fstat(fd, &sb) != 0)
4455e5c12b0Sopenharmony_ci		die_errno("fstat failed");
4465e5c12b0Sopenharmony_ci
4475e5c12b0Sopenharmony_ci	printf("fallocated a file: i_size=%"PRIu64", i_blocks=%"PRIu64"\n", sb.st_size, sb.st_blocks);
4485e5c12b0Sopenharmony_ci	exit(0);
4495e5c12b0Sopenharmony_ci}
4505e5c12b0Sopenharmony_ci
4515e5c12b0Sopenharmony_ci#define erase_desc "erase a block device"
4525e5c12b0Sopenharmony_ci#define erase_help				\
4535e5c12b0Sopenharmony_ci"f2fs_io erase [block_device_path]\n\n"		\
4545e5c12b0Sopenharmony_ci"Send DISCARD | BLKSECDISCARD comamnd to"	\
4555e5c12b0Sopenharmony_ci"block device in block_device_path\n"		\
4565e5c12b0Sopenharmony_ci
4575e5c12b0Sopenharmony_cistatic void do_erase(int argc, char **argv, const struct cmd_desc *cmd)
4585e5c12b0Sopenharmony_ci{
4595e5c12b0Sopenharmony_ci	int fd, ret;
4605e5c12b0Sopenharmony_ci	struct stat st;
4615e5c12b0Sopenharmony_ci	u64 range[2];
4625e5c12b0Sopenharmony_ci
4635e5c12b0Sopenharmony_ci	if (argc != 2) {
4645e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
4655e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
4665e5c12b0Sopenharmony_ci		exit(1);
4675e5c12b0Sopenharmony_ci	}
4685e5c12b0Sopenharmony_ci
4695e5c12b0Sopenharmony_ci	if (stat(argv[1], &st) != 0) {
4705e5c12b0Sopenharmony_ci		fputs("stat error\n", stderr);
4715e5c12b0Sopenharmony_ci		exit(1);
4725e5c12b0Sopenharmony_ci	}
4735e5c12b0Sopenharmony_ci
4745e5c12b0Sopenharmony_ci	if (!S_ISBLK(st.st_mode)) {
4755e5c12b0Sopenharmony_ci		fputs(argv[1], stderr);
4765e5c12b0Sopenharmony_ci		fputs(" is not a block device\n", stderr);
4775e5c12b0Sopenharmony_ci		exit(1);
4785e5c12b0Sopenharmony_ci	}
4795e5c12b0Sopenharmony_ci
4805e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_WRONLY, 0);
4815e5c12b0Sopenharmony_ci
4825e5c12b0Sopenharmony_ci	range[0] = 0;
4835e5c12b0Sopenharmony_ci	ret = ioctl(fd, BLKGETSIZE64, &range[1]);
4845e5c12b0Sopenharmony_ci	if (ret < 0) {
4855e5c12b0Sopenharmony_ci		fputs("get size failed\n", stderr);
4865e5c12b0Sopenharmony_ci		exit(1);
4875e5c12b0Sopenharmony_ci	}
4885e5c12b0Sopenharmony_ci
4895e5c12b0Sopenharmony_ci	ret = ioctl(fd, BLKSECDISCARD, &range);
4905e5c12b0Sopenharmony_ci	if (ret < 0) {
4915e5c12b0Sopenharmony_ci		ret = ioctl(fd, BLKDISCARD, &range);
4925e5c12b0Sopenharmony_ci		if (ret < 0) {
4935e5c12b0Sopenharmony_ci			fputs("Discard failed\n", stderr);
4945e5c12b0Sopenharmony_ci			exit(1);
4955e5c12b0Sopenharmony_ci		}
4965e5c12b0Sopenharmony_ci	}
4975e5c12b0Sopenharmony_ci
4985e5c12b0Sopenharmony_ci	exit(0);
4995e5c12b0Sopenharmony_ci}
5005e5c12b0Sopenharmony_ci
5015e5c12b0Sopenharmony_ci#define write_desc "write data into file"
5025e5c12b0Sopenharmony_ci#define write_help					\
5035e5c12b0Sopenharmony_ci"f2fs_io write [chunk_size in 4kb] [offset in chunk_size] [count] [pattern] [IO] [file_path] {delay}\n\n"	\
5045e5c12b0Sopenharmony_ci"Write given patten data in file_path\n"		\
5055e5c12b0Sopenharmony_ci"pattern can be\n"					\
5065e5c12b0Sopenharmony_ci"  zero          : zeros\n"				\
5075e5c12b0Sopenharmony_ci"  inc_num       : incrementing numbers\n"		\
5085e5c12b0Sopenharmony_ci"  rand          : random numbers\n"			\
5095e5c12b0Sopenharmony_ci"IO can be\n"						\
5105e5c12b0Sopenharmony_ci"  buffered      : buffered IO\n"			\
5115e5c12b0Sopenharmony_ci"  dio           : O_DIRECT\n"				\
5125e5c12b0Sopenharmony_ci"  dsync         : O_DIRECT | O_DSYNC\n"		\
5135e5c12b0Sopenharmony_ci"  osync         : O_SYNC\n"				\
5145e5c12b0Sopenharmony_ci"  atomic_commit : atomic write & commit\n"		\
5155e5c12b0Sopenharmony_ci"  atomic_abort  : atomic write & abort\n"		\
5165e5c12b0Sopenharmony_ci"  atomic_rcommit: atomic replace & commit\n"	\
5175e5c12b0Sopenharmony_ci"  atomic_rabort : atomic replace & abort\n"	\
5185e5c12b0Sopenharmony_ci"{delay} is in ms unit and optional only for atomic operations\n"
5195e5c12b0Sopenharmony_ci
5205e5c12b0Sopenharmony_cistatic void do_write(int argc, char **argv, const struct cmd_desc *cmd)
5215e5c12b0Sopenharmony_ci{
5225e5c12b0Sopenharmony_ci	u64 buf_size = 0, inc_num = 0, written = 0;
5235e5c12b0Sopenharmony_ci	u64 offset;
5245e5c12b0Sopenharmony_ci	char *buf = NULL;
5255e5c12b0Sopenharmony_ci	unsigned bs, count, i;
5265e5c12b0Sopenharmony_ci	int flags = 0;
5275e5c12b0Sopenharmony_ci	int fd;
5285e5c12b0Sopenharmony_ci	u64 total_time = 0, max_time = 0, max_time_t = 0;
5295e5c12b0Sopenharmony_ci	bool atomic_commit = false, atomic_abort = false, replace = false;
5305e5c12b0Sopenharmony_ci	int useconds = 0;
5315e5c12b0Sopenharmony_ci
5325e5c12b0Sopenharmony_ci	srand(time(0));
5335e5c12b0Sopenharmony_ci
5345e5c12b0Sopenharmony_ci	if (argc < 7 || argc > 8) {
5355e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
5365e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
5375e5c12b0Sopenharmony_ci		exit(1);
5385e5c12b0Sopenharmony_ci	}
5395e5c12b0Sopenharmony_ci
5405e5c12b0Sopenharmony_ci	bs = atoi(argv[1]);
5415e5c12b0Sopenharmony_ci	if (bs > 1024)
5425e5c12b0Sopenharmony_ci		die("Too big chunk size - limit: 4MB");
5435e5c12b0Sopenharmony_ci
5445e5c12b0Sopenharmony_ci	buf_size = bs * 4096;
5455e5c12b0Sopenharmony_ci
5465e5c12b0Sopenharmony_ci	offset = atoi(argv[2]) * buf_size;
5475e5c12b0Sopenharmony_ci
5485e5c12b0Sopenharmony_ci	buf = aligned_xalloc(4096, buf_size);
5495e5c12b0Sopenharmony_ci	count = atoi(argv[3]);
5505e5c12b0Sopenharmony_ci
5515e5c12b0Sopenharmony_ci	if (!strcmp(argv[4], "zero"))
5525e5c12b0Sopenharmony_ci		memset(buf, 0, buf_size);
5535e5c12b0Sopenharmony_ci	else if (strcmp(argv[4], "inc_num") && strcmp(argv[4], "rand"))
5545e5c12b0Sopenharmony_ci		die("Wrong pattern type");
5555e5c12b0Sopenharmony_ci
5565e5c12b0Sopenharmony_ci	if (!strcmp(argv[5], "dio")) {
5575e5c12b0Sopenharmony_ci		flags |= O_DIRECT;
5585e5c12b0Sopenharmony_ci	} else if (!strcmp(argv[5], "dsync")) {
5595e5c12b0Sopenharmony_ci		flags |= O_DIRECT | O_DSYNC;
5605e5c12b0Sopenharmony_ci	} else if (!strcmp(argv[5], "osync")) {
5615e5c12b0Sopenharmony_ci		flags |= O_SYNC;
5625e5c12b0Sopenharmony_ci	} else if (!strcmp(argv[5], "atomic_commit")) {
5635e5c12b0Sopenharmony_ci		atomic_commit = true;
5645e5c12b0Sopenharmony_ci	} else if (!strcmp(argv[5], "atomic_abort")) {
5655e5c12b0Sopenharmony_ci		atomic_abort = true;
5665e5c12b0Sopenharmony_ci	} else if (!strcmp(argv[5], "atomic_rcommit")) {
5675e5c12b0Sopenharmony_ci		atomic_commit = true;
5685e5c12b0Sopenharmony_ci		replace = true;
5695e5c12b0Sopenharmony_ci	} else if (!strcmp(argv[5], "atomic_rabort")) {
5705e5c12b0Sopenharmony_ci		atomic_abort = true;
5715e5c12b0Sopenharmony_ci		replace = true;
5725e5c12b0Sopenharmony_ci	} else if (strcmp(argv[5], "buffered")) {
5735e5c12b0Sopenharmony_ci		die("Wrong IO type");
5745e5c12b0Sopenharmony_ci	}
5755e5c12b0Sopenharmony_ci
5765e5c12b0Sopenharmony_ci	fd = xopen(argv[6], O_CREAT | O_WRONLY | flags, 0755);
5775e5c12b0Sopenharmony_ci
5785e5c12b0Sopenharmony_ci	if (atomic_commit || atomic_abort) {
5795e5c12b0Sopenharmony_ci		int ret;
5805e5c12b0Sopenharmony_ci
5815e5c12b0Sopenharmony_ci		if (argc == 8)
5825e5c12b0Sopenharmony_ci			useconds = atoi(argv[7]) * 1000;
5835e5c12b0Sopenharmony_ci
5845e5c12b0Sopenharmony_ci		if (replace)
5855e5c12b0Sopenharmony_ci			ret = ioctl(fd, F2FS_IOC_START_ATOMIC_REPLACE);
5865e5c12b0Sopenharmony_ci		else
5875e5c12b0Sopenharmony_ci			ret = ioctl(fd, F2FS_IOC_START_ATOMIC_WRITE);
5885e5c12b0Sopenharmony_ci
5895e5c12b0Sopenharmony_ci		if (ret < 0) {
5905e5c12b0Sopenharmony_ci			fputs("setting atomic file mode failed\n", stderr);
5915e5c12b0Sopenharmony_ci			exit(1);
5925e5c12b0Sopenharmony_ci		}
5935e5c12b0Sopenharmony_ci	}
5945e5c12b0Sopenharmony_ci
5955e5c12b0Sopenharmony_ci	total_time = get_current_us();
5965e5c12b0Sopenharmony_ci	for (i = 0; i < count; i++) {
5975e5c12b0Sopenharmony_ci		uint64_t ret;
5985e5c12b0Sopenharmony_ci
5995e5c12b0Sopenharmony_ci		if (!strcmp(argv[4], "inc_num"))
6005e5c12b0Sopenharmony_ci			*(int *)buf = inc_num++;
6015e5c12b0Sopenharmony_ci		else if (!strcmp(argv[4], "rand"))
6025e5c12b0Sopenharmony_ci			*(int *)buf = rand();
6035e5c12b0Sopenharmony_ci
6045e5c12b0Sopenharmony_ci		/* write data */
6055e5c12b0Sopenharmony_ci		max_time_t = get_current_us();
6065e5c12b0Sopenharmony_ci		ret = pwrite(fd, buf, buf_size, offset + buf_size * i);
6075e5c12b0Sopenharmony_ci		max_time_t = get_current_us() - max_time_t;
6085e5c12b0Sopenharmony_ci		if (max_time < max_time_t)
6095e5c12b0Sopenharmony_ci			max_time = max_time_t;
6105e5c12b0Sopenharmony_ci		if (ret != buf_size)
6115e5c12b0Sopenharmony_ci			break;
6125e5c12b0Sopenharmony_ci		written += ret;
6135e5c12b0Sopenharmony_ci	}
6145e5c12b0Sopenharmony_ci
6155e5c12b0Sopenharmony_ci	if (useconds)
6165e5c12b0Sopenharmony_ci		usleep(useconds);
6175e5c12b0Sopenharmony_ci
6185e5c12b0Sopenharmony_ci	if (atomic_commit) {
6195e5c12b0Sopenharmony_ci		int ret;
6205e5c12b0Sopenharmony_ci
6215e5c12b0Sopenharmony_ci		ret = ioctl(fd, F2FS_IOC_COMMIT_ATOMIC_WRITE);
6225e5c12b0Sopenharmony_ci		if (ret < 0) {
6235e5c12b0Sopenharmony_ci			fputs("committing atomic write failed\n", stderr);
6245e5c12b0Sopenharmony_ci			exit(1);
6255e5c12b0Sopenharmony_ci		}
6265e5c12b0Sopenharmony_ci	} else if (atomic_abort) {
6275e5c12b0Sopenharmony_ci		int ret;
6285e5c12b0Sopenharmony_ci
6295e5c12b0Sopenharmony_ci		ret = ioctl(fd, F2FS_IOC_ABORT_VOLATILE_WRITE);
6305e5c12b0Sopenharmony_ci		if (ret < 0) {
6315e5c12b0Sopenharmony_ci			fputs("aborting atomic write failed\n", stderr);
6325e5c12b0Sopenharmony_ci			exit(1);
6335e5c12b0Sopenharmony_ci		}
6345e5c12b0Sopenharmony_ci	}
6355e5c12b0Sopenharmony_ci
6365e5c12b0Sopenharmony_ci	printf("Written %"PRIu64" bytes with pattern=%s, total_time=%"PRIu64" us, max_latency=%"PRIu64" us\n",
6375e5c12b0Sopenharmony_ci				written, argv[4],
6385e5c12b0Sopenharmony_ci				get_current_us() - total_time,
6395e5c12b0Sopenharmony_ci				max_time);
6405e5c12b0Sopenharmony_ci	exit(0);
6415e5c12b0Sopenharmony_ci}
6425e5c12b0Sopenharmony_ci
6435e5c12b0Sopenharmony_ci#define read_desc "read data from file"
6445e5c12b0Sopenharmony_ci#define read_help					\
6455e5c12b0Sopenharmony_ci"f2fs_io read [chunk_size in 4kb] [offset in chunk_size] [count] [IO] [print_nbytes] [file_path]\n\n"	\
6465e5c12b0Sopenharmony_ci"Read data in file_path and print nbytes\n"		\
6475e5c12b0Sopenharmony_ci"IO can be\n"						\
6485e5c12b0Sopenharmony_ci"  buffered : buffered IO\n"				\
6495e5c12b0Sopenharmony_ci"  dio      : direct IO\n"				\
6505e5c12b0Sopenharmony_ci"  mmap     : mmap IO\n"				\
6515e5c12b0Sopenharmony_ci
6525e5c12b0Sopenharmony_cistatic void do_read(int argc, char **argv, const struct cmd_desc *cmd)
6535e5c12b0Sopenharmony_ci{
6545e5c12b0Sopenharmony_ci	u64 buf_size = 0, ret = 0, read_cnt = 0;
6555e5c12b0Sopenharmony_ci	u64 offset;
6565e5c12b0Sopenharmony_ci	char *buf = NULL;
6575e5c12b0Sopenharmony_ci	char *data;
6585e5c12b0Sopenharmony_ci	char *print_buf = NULL;
6595e5c12b0Sopenharmony_ci	unsigned bs, count, i, print_bytes;
6605e5c12b0Sopenharmony_ci	int flags = 0;
6615e5c12b0Sopenharmony_ci	int do_mmap = 0;
6625e5c12b0Sopenharmony_ci	int fd;
6635e5c12b0Sopenharmony_ci
6645e5c12b0Sopenharmony_ci	if (argc != 7) {
6655e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
6665e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
6675e5c12b0Sopenharmony_ci		exit(1);
6685e5c12b0Sopenharmony_ci	}
6695e5c12b0Sopenharmony_ci
6705e5c12b0Sopenharmony_ci	bs = atoi(argv[1]);
6715e5c12b0Sopenharmony_ci	if (bs > 1024)
6725e5c12b0Sopenharmony_ci		die("Too big chunk size - limit: 4MB");
6735e5c12b0Sopenharmony_ci	buf_size = bs * 4096;
6745e5c12b0Sopenharmony_ci
6755e5c12b0Sopenharmony_ci	offset = atoi(argv[2]) * buf_size;
6765e5c12b0Sopenharmony_ci
6775e5c12b0Sopenharmony_ci	buf = aligned_xalloc(4096, buf_size);
6785e5c12b0Sopenharmony_ci
6795e5c12b0Sopenharmony_ci	count = atoi(argv[3]);
6805e5c12b0Sopenharmony_ci	if (!strcmp(argv[4], "dio"))
6815e5c12b0Sopenharmony_ci		flags |= O_DIRECT;
6825e5c12b0Sopenharmony_ci	else if (!strcmp(argv[4], "mmap"))
6835e5c12b0Sopenharmony_ci		do_mmap = 1;
6845e5c12b0Sopenharmony_ci	else if (strcmp(argv[4], "buffered"))
6855e5c12b0Sopenharmony_ci		die("Wrong IO type");
6865e5c12b0Sopenharmony_ci
6875e5c12b0Sopenharmony_ci	print_bytes = atoi(argv[5]);
6885e5c12b0Sopenharmony_ci	if (print_bytes > buf_size)
6895e5c12b0Sopenharmony_ci		die("Print_nbytes should be less then chunk_size in kb");
6905e5c12b0Sopenharmony_ci
6915e5c12b0Sopenharmony_ci	print_buf = xmalloc(print_bytes);
6925e5c12b0Sopenharmony_ci
6935e5c12b0Sopenharmony_ci	fd = xopen(argv[6], O_RDONLY | flags, 0);
6945e5c12b0Sopenharmony_ci
6955e5c12b0Sopenharmony_ci	if (do_mmap) {
6965e5c12b0Sopenharmony_ci		data = mmap(NULL, count * buf_size, PROT_READ,
6975e5c12b0Sopenharmony_ci						MAP_SHARED, fd, offset);
6985e5c12b0Sopenharmony_ci		if (data == MAP_FAILED)
6995e5c12b0Sopenharmony_ci			die("Mmap failed");
7005e5c12b0Sopenharmony_ci	}
7015e5c12b0Sopenharmony_ci
7025e5c12b0Sopenharmony_ci	for (i = 0; i < count; i++) {
7035e5c12b0Sopenharmony_ci		if (do_mmap) {
7045e5c12b0Sopenharmony_ci			memcpy(buf, data + offset + buf_size * i, buf_size);
7055e5c12b0Sopenharmony_ci			ret = buf_size;
7065e5c12b0Sopenharmony_ci		} else {
7075e5c12b0Sopenharmony_ci			ret = pread(fd, buf, buf_size, offset + buf_size * i);
7085e5c12b0Sopenharmony_ci		}
7095e5c12b0Sopenharmony_ci		if (ret != buf_size)
7105e5c12b0Sopenharmony_ci			break;
7115e5c12b0Sopenharmony_ci
7125e5c12b0Sopenharmony_ci		read_cnt += ret;
7135e5c12b0Sopenharmony_ci		if (i == 0)
7145e5c12b0Sopenharmony_ci			memcpy(print_buf, buf, print_bytes);
7155e5c12b0Sopenharmony_ci	}
7165e5c12b0Sopenharmony_ci	printf("Read %"PRIu64" bytes and print %u bytes:\n", read_cnt, print_bytes);
7175e5c12b0Sopenharmony_ci	printf("%08"PRIx64" : ", offset);
7185e5c12b0Sopenharmony_ci	for (i = 1; i <= print_bytes; i++) {
7195e5c12b0Sopenharmony_ci		printf("%02x", print_buf[i - 1]);
7205e5c12b0Sopenharmony_ci		if (i % 16 == 0)
7215e5c12b0Sopenharmony_ci			printf("\n%08"PRIx64" : ", offset + 16 * i);
7225e5c12b0Sopenharmony_ci		else if (i % 2 == 0)
7235e5c12b0Sopenharmony_ci			printf(" ");
7245e5c12b0Sopenharmony_ci	}
7255e5c12b0Sopenharmony_ci	printf("\n");
7265e5c12b0Sopenharmony_ci	exit(0);
7275e5c12b0Sopenharmony_ci}
7285e5c12b0Sopenharmony_ci
7295e5c12b0Sopenharmony_ci#define randread_desc "random read data from file"
7305e5c12b0Sopenharmony_ci#define randread_help					\
7315e5c12b0Sopenharmony_ci"f2fs_io randread [chunk_size in 4kb] [count] [IO] [file_path]\n\n"	\
7325e5c12b0Sopenharmony_ci"Do random read data in file_path\n"		\
7335e5c12b0Sopenharmony_ci"IO can be\n"						\
7345e5c12b0Sopenharmony_ci"  buffered : buffered IO\n"				\
7355e5c12b0Sopenharmony_ci"  dio      : direct IO\n"				\
7365e5c12b0Sopenharmony_ci
7375e5c12b0Sopenharmony_cistatic void do_randread(int argc, char **argv, const struct cmd_desc *cmd)
7385e5c12b0Sopenharmony_ci{
7395e5c12b0Sopenharmony_ci	u64 buf_size = 0, ret = 0, read_cnt = 0;
7405e5c12b0Sopenharmony_ci	u64 idx, end_idx, aligned_size;
7415e5c12b0Sopenharmony_ci	char *buf = NULL;
7425e5c12b0Sopenharmony_ci	unsigned bs, count, i;
7435e5c12b0Sopenharmony_ci	int flags = 0;
7445e5c12b0Sopenharmony_ci	int fd;
7455e5c12b0Sopenharmony_ci	time_t t;
7465e5c12b0Sopenharmony_ci	struct stat stbuf;
7475e5c12b0Sopenharmony_ci
7485e5c12b0Sopenharmony_ci	if (argc != 5) {
7495e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
7505e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
7515e5c12b0Sopenharmony_ci		exit(1);
7525e5c12b0Sopenharmony_ci	}
7535e5c12b0Sopenharmony_ci
7545e5c12b0Sopenharmony_ci	bs = atoi(argv[1]);
7555e5c12b0Sopenharmony_ci	if (bs > 1024)
7565e5c12b0Sopenharmony_ci		die("Too big chunk size - limit: 4MB");
7575e5c12b0Sopenharmony_ci	buf_size = bs * 4096;
7585e5c12b0Sopenharmony_ci
7595e5c12b0Sopenharmony_ci	buf = aligned_xalloc(4096, buf_size);
7605e5c12b0Sopenharmony_ci
7615e5c12b0Sopenharmony_ci	count = atoi(argv[2]);
7625e5c12b0Sopenharmony_ci	if (!strcmp(argv[3], "dio"))
7635e5c12b0Sopenharmony_ci		flags |= O_DIRECT;
7645e5c12b0Sopenharmony_ci	else if (strcmp(argv[3], "buffered"))
7655e5c12b0Sopenharmony_ci		die("Wrong IO type");
7665e5c12b0Sopenharmony_ci
7675e5c12b0Sopenharmony_ci	fd = xopen(argv[4], O_RDONLY | flags, 0);
7685e5c12b0Sopenharmony_ci
7695e5c12b0Sopenharmony_ci	if (fstat(fd, &stbuf) != 0)
7705e5c12b0Sopenharmony_ci		die_errno("fstat of source file failed");
7715e5c12b0Sopenharmony_ci
7725e5c12b0Sopenharmony_ci	aligned_size = (u64)stbuf.st_size & ~((u64)(4096 - 1));
7735e5c12b0Sopenharmony_ci	if (aligned_size < buf_size)
7745e5c12b0Sopenharmony_ci		die("File is too small to random read");
7755e5c12b0Sopenharmony_ci	end_idx = (u64)(aligned_size - buf_size) / (u64)4096 + 1;
7765e5c12b0Sopenharmony_ci
7775e5c12b0Sopenharmony_ci	srand((unsigned) time(&t));
7785e5c12b0Sopenharmony_ci
7795e5c12b0Sopenharmony_ci	for (i = 0; i < count; i++) {
7805e5c12b0Sopenharmony_ci		idx = rand() % end_idx;
7815e5c12b0Sopenharmony_ci
7825e5c12b0Sopenharmony_ci		ret = pread(fd, buf, buf_size, 4096 * idx);
7835e5c12b0Sopenharmony_ci		if (ret != buf_size)
7845e5c12b0Sopenharmony_ci			break;
7855e5c12b0Sopenharmony_ci
7865e5c12b0Sopenharmony_ci		read_cnt += ret;
7875e5c12b0Sopenharmony_ci	}
7885e5c12b0Sopenharmony_ci	printf("Read %"PRIu64" bytes\n", read_cnt);
7895e5c12b0Sopenharmony_ci	exit(0);
7905e5c12b0Sopenharmony_ci}
7915e5c12b0Sopenharmony_ci
7925e5c12b0Sopenharmony_ci#define fiemap_desc "get block address in file"
7935e5c12b0Sopenharmony_ci#define fiemap_help					\
7945e5c12b0Sopenharmony_ci"f2fs_io fiemap [offset in 4kb] [count] [file_path]\n\n"\
7955e5c12b0Sopenharmony_ci
7965e5c12b0Sopenharmony_ci#if defined(HAVE_LINUX_FIEMAP_H) && defined(HAVE_LINUX_FS_H)
7975e5c12b0Sopenharmony_cistatic void do_fiemap(int argc, char **argv, const struct cmd_desc *cmd)
7985e5c12b0Sopenharmony_ci{
7995e5c12b0Sopenharmony_ci	unsigned int i;
8005e5c12b0Sopenharmony_ci	int fd, extents_mem_size;
8015e5c12b0Sopenharmony_ci	u64 start, length;
8025e5c12b0Sopenharmony_ci	u32 mapped_extents;
8035e5c12b0Sopenharmony_ci	struct fiemap *fm = xmalloc(sizeof(struct fiemap));
8045e5c12b0Sopenharmony_ci
8055e5c12b0Sopenharmony_ci	if (argc != 4) {
8065e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
8075e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
8085e5c12b0Sopenharmony_ci		exit(1);
8095e5c12b0Sopenharmony_ci	}
8105e5c12b0Sopenharmony_ci
8115e5c12b0Sopenharmony_ci	memset(fm, 0, sizeof(struct fiemap));
8125e5c12b0Sopenharmony_ci	start = atoi(argv[1]) * F2FS_BLKSIZE;
8135e5c12b0Sopenharmony_ci	length = atoi(argv[2]) * F2FS_BLKSIZE;
8145e5c12b0Sopenharmony_ci	fm->fm_start = start;
8155e5c12b0Sopenharmony_ci	fm->fm_length = length;
8165e5c12b0Sopenharmony_ci
8175e5c12b0Sopenharmony_ci	fd = xopen(argv[3], O_RDONLY | O_LARGEFILE, 0);
8185e5c12b0Sopenharmony_ci
8195e5c12b0Sopenharmony_ci	printf("Fiemap: offset = %"PRIu64" len = %"PRIu64"\n",
8205e5c12b0Sopenharmony_ci				start / F2FS_BLKSIZE, length / F2FS_BLKSIZE);
8215e5c12b0Sopenharmony_ci	if (ioctl(fd, FS_IOC_FIEMAP, fm) < 0)
8225e5c12b0Sopenharmony_ci		die_errno("FIEMAP failed");
8235e5c12b0Sopenharmony_ci
8245e5c12b0Sopenharmony_ci	mapped_extents = fm->fm_mapped_extents;
8255e5c12b0Sopenharmony_ci	extents_mem_size = sizeof(struct fiemap_extent) * mapped_extents;
8265e5c12b0Sopenharmony_ci	free(fm);
8275e5c12b0Sopenharmony_ci	fm = xmalloc(sizeof(struct fiemap) + extents_mem_size);
8285e5c12b0Sopenharmony_ci
8295e5c12b0Sopenharmony_ci	memset(fm, 0, sizeof(struct fiemap) + extents_mem_size);
8305e5c12b0Sopenharmony_ci	fm->fm_start = start;
8315e5c12b0Sopenharmony_ci	fm->fm_length = length;
8325e5c12b0Sopenharmony_ci	fm->fm_extent_count = mapped_extents;
8335e5c12b0Sopenharmony_ci
8345e5c12b0Sopenharmony_ci	if (ioctl(fd, FS_IOC_FIEMAP, fm) < 0)
8355e5c12b0Sopenharmony_ci		die_errno("FIEMAP failed");
8365e5c12b0Sopenharmony_ci
8375e5c12b0Sopenharmony_ci	printf("\t%-17s%-17s%-17s%s\n", "logical addr.", "physical addr.", "length", "flags");
8385e5c12b0Sopenharmony_ci	for (i = 0; i < fm->fm_mapped_extents; i++) {
8395e5c12b0Sopenharmony_ci		printf("%d\t%.16llx %.16llx %.16llx %.8x\n", i,
8405e5c12b0Sopenharmony_ci		    fm->fm_extents[i].fe_logical, fm->fm_extents[i].fe_physical,
8415e5c12b0Sopenharmony_ci		    fm->fm_extents[i].fe_length, fm->fm_extents[i].fe_flags);
8425e5c12b0Sopenharmony_ci
8435e5c12b0Sopenharmony_ci		if (fm->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST)
8445e5c12b0Sopenharmony_ci			break;
8455e5c12b0Sopenharmony_ci	}
8465e5c12b0Sopenharmony_ci	printf("\n");
8475e5c12b0Sopenharmony_ci	free(fm);
8485e5c12b0Sopenharmony_ci	exit(0);
8495e5c12b0Sopenharmony_ci}
8505e5c12b0Sopenharmony_ci#else
8515e5c12b0Sopenharmony_cistatic void do_fiemap(int UNUSED(argc), char **UNUSED(argv),
8525e5c12b0Sopenharmony_ci			const struct cmd_desc *UNUSED(cmd))
8535e5c12b0Sopenharmony_ci{
8545e5c12b0Sopenharmony_ci	die("Not support for this platform");
8555e5c12b0Sopenharmony_ci}
8565e5c12b0Sopenharmony_ci#endif
8575e5c12b0Sopenharmony_ci
8585e5c12b0Sopenharmony_ci#define gc_urgent_desc "start/end/run gc_urgent for given time period"
8595e5c12b0Sopenharmony_ci#define gc_urgent_help					\
8605e5c12b0Sopenharmony_ci"f2fs_io gc_urgent $dev [start/end/run] [time in sec]\n\n"\
8615e5c12b0Sopenharmony_ci" - f2fs_io gc_urgent sda21 start\n"		\
8625e5c12b0Sopenharmony_ci" - f2fs_io gc_urgent sda21 end\n"		\
8635e5c12b0Sopenharmony_ci" - f2fs_io gc_urgent sda21 run 10\n"		\
8645e5c12b0Sopenharmony_ci
8655e5c12b0Sopenharmony_cistatic void do_gc_urgent(int argc, char **argv, const struct cmd_desc *cmd)
8665e5c12b0Sopenharmony_ci{
8675e5c12b0Sopenharmony_ci	char command[255];
8685e5c12b0Sopenharmony_ci
8695e5c12b0Sopenharmony_ci	if (argc == 3 && !strcmp(argv[2], "start")) {
8705e5c12b0Sopenharmony_ci		printf("gc_urgent: start on %s\n", argv[1]);
8715e5c12b0Sopenharmony_ci		sprintf(command, "echo %d > %s/%s/gc_urgent", 1, "/sys/fs/f2fs/", argv[1]);
8725e5c12b0Sopenharmony_ci		if (system(command))
8735e5c12b0Sopenharmony_ci			exit(1);
8745e5c12b0Sopenharmony_ci	} else if (argc == 3 && !strcmp(argv[2], "end")) {
8755e5c12b0Sopenharmony_ci		printf("gc_urgent: end on %s\n", argv[1]);
8765e5c12b0Sopenharmony_ci		sprintf(command, "echo %d > %s/%s/gc_urgent", 0, "/sys/fs/f2fs/", argv[1]);
8775e5c12b0Sopenharmony_ci		if (system(command))
8785e5c12b0Sopenharmony_ci			exit(1);
8795e5c12b0Sopenharmony_ci	} else if (argc == 4 && !strcmp(argv[2], "run")) {
8805e5c12b0Sopenharmony_ci		printf("gc_urgent: start on %s for %d secs\n", argv[1], atoi(argv[3]));
8815e5c12b0Sopenharmony_ci		sprintf(command, "echo %d > %s/%s/gc_urgent", 1, "/sys/fs/f2fs/", argv[1]);
8825e5c12b0Sopenharmony_ci		if (system(command))
8835e5c12b0Sopenharmony_ci			exit(1);
8845e5c12b0Sopenharmony_ci		sleep(atoi(argv[3]));
8855e5c12b0Sopenharmony_ci		printf("gc_urgent: end on %s for %d secs\n", argv[1], atoi(argv[3]));
8865e5c12b0Sopenharmony_ci		sprintf(command, "echo %d > %s/%s/gc_urgent", 0, "/sys/fs/f2fs/", argv[1]);
8875e5c12b0Sopenharmony_ci		if (system(command))
8885e5c12b0Sopenharmony_ci			exit(1);
8895e5c12b0Sopenharmony_ci	} else {
8905e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
8915e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
8925e5c12b0Sopenharmony_ci		exit(1);
8935e5c12b0Sopenharmony_ci	}
8945e5c12b0Sopenharmony_ci}
8955e5c12b0Sopenharmony_ci
8965e5c12b0Sopenharmony_ci#define defrag_file_desc "do defragment on file"
8975e5c12b0Sopenharmony_ci#define defrag_file_help						\
8985e5c12b0Sopenharmony_ci"f2fs_io defrag_file [start] [length] [file_path]\n\n"		\
8995e5c12b0Sopenharmony_ci"  start     : start offset of defragment region, unit: bytes\n"	\
9005e5c12b0Sopenharmony_ci"  length    : bytes number of defragment region\n"			\
9015e5c12b0Sopenharmony_ci
9025e5c12b0Sopenharmony_cistatic void do_defrag_file(int argc, char **argv, const struct cmd_desc *cmd)
9035e5c12b0Sopenharmony_ci{
9045e5c12b0Sopenharmony_ci	struct f2fs_defragment df;
9055e5c12b0Sopenharmony_ci	u64 len;
9065e5c12b0Sopenharmony_ci	int ret, fd;
9075e5c12b0Sopenharmony_ci
9085e5c12b0Sopenharmony_ci	if (argc != 4) {
9095e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
9105e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
9115e5c12b0Sopenharmony_ci		exit(1);
9125e5c12b0Sopenharmony_ci	}
9135e5c12b0Sopenharmony_ci
9145e5c12b0Sopenharmony_ci	df.start = atoll(argv[1]);
9155e5c12b0Sopenharmony_ci	df.len = len = atoll(argv[2]);
9165e5c12b0Sopenharmony_ci
9175e5c12b0Sopenharmony_ci	fd = xopen(argv[3], O_RDWR, 0);
9185e5c12b0Sopenharmony_ci
9195e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_DEFRAGMENT, &df);
9205e5c12b0Sopenharmony_ci	if (ret < 0)
9215e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_DEFRAGMENT failed");
9225e5c12b0Sopenharmony_ci
9235e5c12b0Sopenharmony_ci	printf("defrag %s in region[%"PRIu64", %"PRIu64"]\n",
9245e5c12b0Sopenharmony_ci			argv[3], df.start, df.start + len);
9255e5c12b0Sopenharmony_ci	exit(0);
9265e5c12b0Sopenharmony_ci}
9275e5c12b0Sopenharmony_ci
9285e5c12b0Sopenharmony_ci#define copy_desc "copy a file"
9295e5c12b0Sopenharmony_ci#define copy_help							\
9305e5c12b0Sopenharmony_ci"f2fs_io copy [-d] [-m] [-s] src_path dst_path\n\n"			\
9315e5c12b0Sopenharmony_ci"  src_path  : path to source file\n"					\
9325e5c12b0Sopenharmony_ci"  dst_path  : path to destination file\n"				\
9335e5c12b0Sopenharmony_ci"  -d        : use direct I/O\n"					\
9345e5c12b0Sopenharmony_ci"  -m        : mmap the source file\n"					\
9355e5c12b0Sopenharmony_ci"  -s        : use sendfile\n"						\
9365e5c12b0Sopenharmony_ci
9375e5c12b0Sopenharmony_cistatic void do_copy(int argc, char **argv, const struct cmd_desc *cmd)
9385e5c12b0Sopenharmony_ci{
9395e5c12b0Sopenharmony_ci	int c;
9405e5c12b0Sopenharmony_ci	int src_fd;
9415e5c12b0Sopenharmony_ci	int dst_fd;
9425e5c12b0Sopenharmony_ci	int open_flags = 0;
9435e5c12b0Sopenharmony_ci	bool mmap_source_file = false;
9445e5c12b0Sopenharmony_ci	bool use_sendfile = false;
9455e5c12b0Sopenharmony_ci	ssize_t ret;
9465e5c12b0Sopenharmony_ci
9475e5c12b0Sopenharmony_ci	while ((c = getopt(argc, argv, "dms")) != -1) {
9485e5c12b0Sopenharmony_ci		switch (c) {
9495e5c12b0Sopenharmony_ci		case 'd':
9505e5c12b0Sopenharmony_ci			open_flags |= O_DIRECT;
9515e5c12b0Sopenharmony_ci			break;
9525e5c12b0Sopenharmony_ci		case 'm':
9535e5c12b0Sopenharmony_ci			mmap_source_file = true;
9545e5c12b0Sopenharmony_ci			break;
9555e5c12b0Sopenharmony_ci		case 's':
9565e5c12b0Sopenharmony_ci			use_sendfile = true;
9575e5c12b0Sopenharmony_ci			break;
9585e5c12b0Sopenharmony_ci		default:
9595e5c12b0Sopenharmony_ci			fputs(cmd->cmd_help, stderr);
9605e5c12b0Sopenharmony_ci			exit(2);
9615e5c12b0Sopenharmony_ci		}
9625e5c12b0Sopenharmony_ci	}
9635e5c12b0Sopenharmony_ci	argc -= optind;
9645e5c12b0Sopenharmony_ci	argv += optind;
9655e5c12b0Sopenharmony_ci	if (argc != 2) {
9665e5c12b0Sopenharmony_ci		fputs("Wrong number of arguments\n\n", stderr);
9675e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
9685e5c12b0Sopenharmony_ci		exit(2);
9695e5c12b0Sopenharmony_ci	}
9705e5c12b0Sopenharmony_ci	if (mmap_source_file && use_sendfile)
9715e5c12b0Sopenharmony_ci		die("-m and -s are mutually exclusive");
9725e5c12b0Sopenharmony_ci
9735e5c12b0Sopenharmony_ci	src_fd = xopen(argv[0], O_RDONLY | open_flags, 0);
9745e5c12b0Sopenharmony_ci	dst_fd = xopen(argv[1], O_WRONLY | O_CREAT | O_TRUNC | open_flags, 0644);
9755e5c12b0Sopenharmony_ci
9765e5c12b0Sopenharmony_ci	if (mmap_source_file) {
9775e5c12b0Sopenharmony_ci		struct stat stbuf;
9785e5c12b0Sopenharmony_ci		void *src_addr;
9795e5c12b0Sopenharmony_ci
9805e5c12b0Sopenharmony_ci		if (fstat(src_fd, &stbuf) != 0)
9815e5c12b0Sopenharmony_ci			die_errno("fstat of source file failed");
9825e5c12b0Sopenharmony_ci
9835e5c12b0Sopenharmony_ci		if ((size_t)stbuf.st_size != stbuf.st_size)
9845e5c12b0Sopenharmony_ci			die("Source file is too large");
9855e5c12b0Sopenharmony_ci
9865e5c12b0Sopenharmony_ci		src_addr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_SHARED,
9875e5c12b0Sopenharmony_ci				src_fd, 0);
9885e5c12b0Sopenharmony_ci		if (src_addr == MAP_FAILED)
9895e5c12b0Sopenharmony_ci			die("mmap of source file failed");
9905e5c12b0Sopenharmony_ci
9915e5c12b0Sopenharmony_ci		full_write(dst_fd, src_addr, stbuf.st_size);
9925e5c12b0Sopenharmony_ci
9935e5c12b0Sopenharmony_ci		munmap(src_addr, stbuf.st_size);
9945e5c12b0Sopenharmony_ci	} else if (use_sendfile) {
9955e5c12b0Sopenharmony_ci		while ((ret = sendfile(dst_fd, src_fd, NULL, INT_MAX)) > 0)
9965e5c12b0Sopenharmony_ci			;
9975e5c12b0Sopenharmony_ci		if (ret < 0)
9985e5c12b0Sopenharmony_ci			die_errno("sendfile failed");
9995e5c12b0Sopenharmony_ci	} else {
10005e5c12b0Sopenharmony_ci		char *buf = aligned_xalloc(4096, 4096);
10015e5c12b0Sopenharmony_ci
10025e5c12b0Sopenharmony_ci		while ((ret = xread(src_fd, buf, 4096)) > 0)
10035e5c12b0Sopenharmony_ci			full_write(dst_fd, buf, ret);
10045e5c12b0Sopenharmony_ci		free(buf);
10055e5c12b0Sopenharmony_ci	}
10065e5c12b0Sopenharmony_ci	close(src_fd);
10075e5c12b0Sopenharmony_ci	close(dst_fd);
10085e5c12b0Sopenharmony_ci}
10095e5c12b0Sopenharmony_ci
10105e5c12b0Sopenharmony_ci#define get_cblocks_desc "get number of reserved blocks on compress inode"
10115e5c12b0Sopenharmony_ci#define get_cblocks_help "f2fs_io get_cblocks [file]\n\n"
10125e5c12b0Sopenharmony_ci
10135e5c12b0Sopenharmony_cistatic void do_get_cblocks(int argc, char **argv, const struct cmd_desc *cmd)
10145e5c12b0Sopenharmony_ci{
10155e5c12b0Sopenharmony_ci	unsigned long long blkcnt;
10165e5c12b0Sopenharmony_ci	int ret, fd;
10175e5c12b0Sopenharmony_ci
10185e5c12b0Sopenharmony_ci	if (argc != 2) {
10195e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
10205e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
10215e5c12b0Sopenharmony_ci		exit(1);
10225e5c12b0Sopenharmony_ci	}
10235e5c12b0Sopenharmony_ci
10245e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_RDONLY, 0);
10255e5c12b0Sopenharmony_ci
10265e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_GET_COMPRESS_BLOCKS, &blkcnt);
10275e5c12b0Sopenharmony_ci	if (ret < 0)
10285e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_GET_COMPRESS_BLOCKS failed");
10295e5c12b0Sopenharmony_ci
10305e5c12b0Sopenharmony_ci	printf("%llu\n", blkcnt);
10315e5c12b0Sopenharmony_ci
10325e5c12b0Sopenharmony_ci	exit(0);
10335e5c12b0Sopenharmony_ci}
10345e5c12b0Sopenharmony_ci
10355e5c12b0Sopenharmony_ci#define release_cblocks_desc "release reserved blocks on compress inode"
10365e5c12b0Sopenharmony_ci#define release_cblocks_help "f2fs_io release_cblocks [file]\n\n"
10375e5c12b0Sopenharmony_ci
10385e5c12b0Sopenharmony_cistatic void do_release_cblocks(int argc, char **argv, const struct cmd_desc *cmd)
10395e5c12b0Sopenharmony_ci{
10405e5c12b0Sopenharmony_ci	unsigned long long blkcnt;
10415e5c12b0Sopenharmony_ci	int ret, fd;
10425e5c12b0Sopenharmony_ci
10435e5c12b0Sopenharmony_ci	if (argc != 2) {
10445e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
10455e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
10465e5c12b0Sopenharmony_ci		exit(1);
10475e5c12b0Sopenharmony_ci	}
10485e5c12b0Sopenharmony_ci
10495e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_RDONLY, 0);
10505e5c12b0Sopenharmony_ci
10515e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_RELEASE_COMPRESS_BLOCKS, &blkcnt);
10525e5c12b0Sopenharmony_ci	if (ret < 0)
10535e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_RELEASE_COMPRESS_BLOCKS failed");
10545e5c12b0Sopenharmony_ci
10555e5c12b0Sopenharmony_ci	printf("%llu\n", blkcnt);
10565e5c12b0Sopenharmony_ci
10575e5c12b0Sopenharmony_ci	exit(0);
10585e5c12b0Sopenharmony_ci}
10595e5c12b0Sopenharmony_ci
10605e5c12b0Sopenharmony_ci#define reserve_cblocks_desc "reserve blocks on compress inode"
10615e5c12b0Sopenharmony_ci#define reserve_cblocks_help "f2fs_io reserve_cblocks [file]\n\n"
10625e5c12b0Sopenharmony_ci
10635e5c12b0Sopenharmony_cistatic void do_reserve_cblocks(int argc, char **argv, const struct cmd_desc *cmd)
10645e5c12b0Sopenharmony_ci{
10655e5c12b0Sopenharmony_ci	unsigned long long blkcnt;
10665e5c12b0Sopenharmony_ci	int ret, fd;
10675e5c12b0Sopenharmony_ci
10685e5c12b0Sopenharmony_ci	if (argc != 2) {
10695e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
10705e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
10715e5c12b0Sopenharmony_ci		exit(1);
10725e5c12b0Sopenharmony_ci	}
10735e5c12b0Sopenharmony_ci
10745e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_RDONLY, 0);
10755e5c12b0Sopenharmony_ci
10765e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_RESERVE_COMPRESS_BLOCKS, &blkcnt);
10775e5c12b0Sopenharmony_ci	if (ret < 0)
10785e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_RESERVE_COMPRESS_BLOCKS failed");
10795e5c12b0Sopenharmony_ci
10805e5c12b0Sopenharmony_ci	printf("%llu\n", blkcnt);
10815e5c12b0Sopenharmony_ci
10825e5c12b0Sopenharmony_ci	exit(0);
10835e5c12b0Sopenharmony_ci}
10845e5c12b0Sopenharmony_ci
10855e5c12b0Sopenharmony_ci#define get_coption_desc "get compression option of a compressed file"
10865e5c12b0Sopenharmony_ci#define get_coption_help						\
10875e5c12b0Sopenharmony_ci"f2fs_io get_coption [file]\n\n"	\
10885e5c12b0Sopenharmony_ci"  algorithm        : compression algorithm (0:lzo, 1: lz4, 2:zstd, 3:lzorle)\n"	\
10895e5c12b0Sopenharmony_ci"  log_cluster_size : compression cluster log size (2 <= log_size <= 8)\n"
10905e5c12b0Sopenharmony_ci
10915e5c12b0Sopenharmony_cistatic void do_get_coption(int argc, char **argv, const struct cmd_desc *cmd)
10925e5c12b0Sopenharmony_ci{
10935e5c12b0Sopenharmony_ci	struct f2fs_comp_option option;
10945e5c12b0Sopenharmony_ci	int ret, fd;
10955e5c12b0Sopenharmony_ci
10965e5c12b0Sopenharmony_ci	if (argc != 2) {
10975e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
10985e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
10995e5c12b0Sopenharmony_ci		exit(1);
11005e5c12b0Sopenharmony_ci	}
11015e5c12b0Sopenharmony_ci
11025e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_RDONLY, 0);
11035e5c12b0Sopenharmony_ci
11045e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_GET_COMPRESS_OPTION, &option);
11055e5c12b0Sopenharmony_ci	if (ret < 0)
11065e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_GET_COMPRESS_OPTION failed");
11075e5c12b0Sopenharmony_ci
11085e5c12b0Sopenharmony_ci	printf("compression algorithm:%u\n", option.algorithm);
11095e5c12b0Sopenharmony_ci	printf("compression cluster log size:%u\n", option.log_cluster_size);
11105e5c12b0Sopenharmony_ci
11115e5c12b0Sopenharmony_ci	exit(0);
11125e5c12b0Sopenharmony_ci}
11135e5c12b0Sopenharmony_ci
11145e5c12b0Sopenharmony_ci#define set_coption_desc "set compression option of a compressed file"
11155e5c12b0Sopenharmony_ci#define set_coption_help						\
11165e5c12b0Sopenharmony_ci"f2fs_io set_coption [algorithm] [log_cluster_size] [file_path]\n\n"	\
11175e5c12b0Sopenharmony_ci"  algorithm        : compression algorithm (0:lzo, 1: lz4, 2:zstd, 3:lzorle)\n"	\
11185e5c12b0Sopenharmony_ci"  log_cluster_size : compression cluster log size (2 <= log_size <= 8)\n"
11195e5c12b0Sopenharmony_ci
11205e5c12b0Sopenharmony_cistatic void do_set_coption(int argc, char **argv, const struct cmd_desc *cmd)
11215e5c12b0Sopenharmony_ci{
11225e5c12b0Sopenharmony_ci	struct f2fs_comp_option option;
11235e5c12b0Sopenharmony_ci	int fd, ret;
11245e5c12b0Sopenharmony_ci
11255e5c12b0Sopenharmony_ci	if (argc != 4) {
11265e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
11275e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
11285e5c12b0Sopenharmony_ci		exit(1);
11295e5c12b0Sopenharmony_ci	}
11305e5c12b0Sopenharmony_ci
11315e5c12b0Sopenharmony_ci	option.algorithm = atoi(argv[1]);
11325e5c12b0Sopenharmony_ci	option.log_cluster_size = atoi(argv[2]);
11335e5c12b0Sopenharmony_ci
11345e5c12b0Sopenharmony_ci	fd = xopen(argv[3], O_WRONLY, 0);
11355e5c12b0Sopenharmony_ci
11365e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_SET_COMPRESS_OPTION, &option);
11375e5c12b0Sopenharmony_ci	if (ret < 0)
11385e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_SET_COMPRESS_OPTION failed");
11395e5c12b0Sopenharmony_ci
11405e5c12b0Sopenharmony_ci	printf("set compression option: algorithm=%u, log_cluster_size=%u\n",
11415e5c12b0Sopenharmony_ci			option.algorithm, option.log_cluster_size);
11425e5c12b0Sopenharmony_ci	exit(0);
11435e5c12b0Sopenharmony_ci}
11445e5c12b0Sopenharmony_ci
11455e5c12b0Sopenharmony_ci#define decompress_desc "decompress an already compressed file"
11465e5c12b0Sopenharmony_ci#define decompress_help "f2fs_io decompress [file_path]\n\n"
11475e5c12b0Sopenharmony_ci
11485e5c12b0Sopenharmony_cistatic void do_decompress(int argc, char **argv, const struct cmd_desc *cmd)
11495e5c12b0Sopenharmony_ci{
11505e5c12b0Sopenharmony_ci	int fd, ret;
11515e5c12b0Sopenharmony_ci
11525e5c12b0Sopenharmony_ci	if (argc != 2) {
11535e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
11545e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
11555e5c12b0Sopenharmony_ci		exit(1);
11565e5c12b0Sopenharmony_ci	}
11575e5c12b0Sopenharmony_ci
11585e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_WRONLY, 0);
11595e5c12b0Sopenharmony_ci
11605e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_DECOMPRESS_FILE);
11615e5c12b0Sopenharmony_ci	if (ret < 0)
11625e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_DECOMPRESS_FILE failed");
11635e5c12b0Sopenharmony_ci
11645e5c12b0Sopenharmony_ci	exit(0);
11655e5c12b0Sopenharmony_ci}
11665e5c12b0Sopenharmony_ci
11675e5c12b0Sopenharmony_ci#define compress_desc "compress a compression enabled file"
11685e5c12b0Sopenharmony_ci#define compress_help "f2fs_io compress [file_path]\n\n"
11695e5c12b0Sopenharmony_ci
11705e5c12b0Sopenharmony_cistatic void do_compress(int argc, char **argv, const struct cmd_desc *cmd)
11715e5c12b0Sopenharmony_ci{
11725e5c12b0Sopenharmony_ci	int fd, ret;
11735e5c12b0Sopenharmony_ci
11745e5c12b0Sopenharmony_ci	if (argc != 2) {
11755e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
11765e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
11775e5c12b0Sopenharmony_ci		exit(1);
11785e5c12b0Sopenharmony_ci	}
11795e5c12b0Sopenharmony_ci
11805e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_WRONLY, 0);
11815e5c12b0Sopenharmony_ci
11825e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_COMPRESS_FILE);
11835e5c12b0Sopenharmony_ci	if (ret < 0)
11845e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_COMPRESS_FILE failed");
11855e5c12b0Sopenharmony_ci
11865e5c12b0Sopenharmony_ci	exit(0);
11875e5c12b0Sopenharmony_ci}
11885e5c12b0Sopenharmony_ci
11895e5c12b0Sopenharmony_ci#define get_filename_encrypt_mode_desc "get file name encrypt mode"
11905e5c12b0Sopenharmony_ci#define get_filename_encrypt_mode_help					\
11915e5c12b0Sopenharmony_ci"f2fs_io filename_encrypt_mode [file or directory path]\n\n"		\
11925e5c12b0Sopenharmony_ci"Get the file name encription mode of the given file/directory.\n"	\
11935e5c12b0Sopenharmony_ci
11945e5c12b0Sopenharmony_cistatic void do_get_filename_encrypt_mode (int argc, char **argv,
11955e5c12b0Sopenharmony_ci						const struct cmd_desc *cmd)
11965e5c12b0Sopenharmony_ci{
11975e5c12b0Sopenharmony_ci	static const char *enc_name[] = {
11985e5c12b0Sopenharmony_ci		"invalid", /* FSCRYPT_MODE_INVALID (0) */
11995e5c12b0Sopenharmony_ci		"aes-256-xts", /* FSCRYPT_MODE_AES_256_XTS (1) */
12005e5c12b0Sopenharmony_ci		"aes-256-gcm", /* FSCRYPT_MODE_AES_256_GCM (2) */
12015e5c12b0Sopenharmony_ci		"aes-256-cbc", /* FSCRYPT_MODE_AES_256_CBC (3) */
12025e5c12b0Sopenharmony_ci		"aes-256-cts", /* FSCRYPT_MODE_AES_256_CTS (4) */
12035e5c12b0Sopenharmony_ci		"aes-128-cbc", /* FSCRYPT_MODE_AES_128_CBC (5) */
12045e5c12b0Sopenharmony_ci		"aes-128-cts", /* FSCRYPT_MODE_AES_128_CTS (6) */
12055e5c12b0Sopenharmony_ci		"speck128-256-xts", /* FSCRYPT_MODE_SPECK128_256_XTS (7) */
12065e5c12b0Sopenharmony_ci		"speck128-256-cts", /* FSCRYPT_MODE_SPECK128_256_CTS (8) */
12075e5c12b0Sopenharmony_ci		"adiantum", /* FSCRYPT_MODE_ADIANTUM (9) */
12085e5c12b0Sopenharmony_ci		"aes-256-hctr2", /* FSCRYPT_MODE_AES_256_HCTR2 (10) */
12095e5c12b0Sopenharmony_ci	};
12105e5c12b0Sopenharmony_ci	int fd, mode, ret;
12115e5c12b0Sopenharmony_ci	struct fscrypt_get_policy_ex_arg arg;
12125e5c12b0Sopenharmony_ci
12135e5c12b0Sopenharmony_ci	if (argc != 2) {
12145e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
12155e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
12165e5c12b0Sopenharmony_ci		exit(1);
12175e5c12b0Sopenharmony_ci	}
12185e5c12b0Sopenharmony_ci
12195e5c12b0Sopenharmony_ci	fd = xopen(argv[1], O_RDONLY, 0);
12205e5c12b0Sopenharmony_ci	arg.policy_size = sizeof(arg.policy);
12215e5c12b0Sopenharmony_ci	ret = ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY_EX, &arg);
12225e5c12b0Sopenharmony_ci	if (ret != 0 && errno == ENOTTY)
12235e5c12b0Sopenharmony_ci		ret = ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, arg.policy.v1);
12245e5c12b0Sopenharmony_ci	close(fd);
12255e5c12b0Sopenharmony_ci
12265e5c12b0Sopenharmony_ci	if (ret) {
12275e5c12b0Sopenharmony_ci		perror("FS_IOC_GET_ENCRYPTION_POLICY|_EX");
12285e5c12b0Sopenharmony_ci		exit(1);
12295e5c12b0Sopenharmony_ci	}
12305e5c12b0Sopenharmony_ci
12315e5c12b0Sopenharmony_ci	switch (arg.policy.version) {
12325e5c12b0Sopenharmony_ci	case FSCRYPT_POLICY_V1:
12335e5c12b0Sopenharmony_ci		mode = arg.policy.v1.filenames_encryption_mode;
12345e5c12b0Sopenharmony_ci		break;
12355e5c12b0Sopenharmony_ci	case FSCRYPT_POLICY_V2:
12365e5c12b0Sopenharmony_ci		mode = arg.policy.v2.filenames_encryption_mode;
12375e5c12b0Sopenharmony_ci		break;
12385e5c12b0Sopenharmony_ci	default:
12395e5c12b0Sopenharmony_ci		printf("Do not support policy version: %d\n",
12405e5c12b0Sopenharmony_ci							arg.policy.version);
12415e5c12b0Sopenharmony_ci		exit(1);
12425e5c12b0Sopenharmony_ci	}
12435e5c12b0Sopenharmony_ci
12445e5c12b0Sopenharmony_ci	if (mode >= sizeof(enc_name)/sizeof(enc_name[0])) {
12455e5c12b0Sopenharmony_ci		printf("Do not support algorithm: %d\n", mode);
12465e5c12b0Sopenharmony_ci		exit(1);
12475e5c12b0Sopenharmony_ci	}
12485e5c12b0Sopenharmony_ci	printf ("%s\n", enc_name[mode]);
12495e5c12b0Sopenharmony_ci	exit(0);
12505e5c12b0Sopenharmony_ci}
12515e5c12b0Sopenharmony_ci
12525e5c12b0Sopenharmony_ci#define rename_desc "rename source to target file with fsync option"
12535e5c12b0Sopenharmony_ci#define rename_help							\
12545e5c12b0Sopenharmony_ci"f2fs_io rename [src_path] [target_path] [fsync_after_rename]\n\n"	\
12555e5c12b0Sopenharmony_ci"e.g., f2fs_io rename source dest 1\n"					\
12565e5c12b0Sopenharmony_ci"      1. open(source)\n"						\
12575e5c12b0Sopenharmony_ci"      2. rename(source, dest)\n"					\
12585e5c12b0Sopenharmony_ci"      3. fsync(source)\n"						\
12595e5c12b0Sopenharmony_ci"      4. close(source)\n"
12605e5c12b0Sopenharmony_ci
12615e5c12b0Sopenharmony_cistatic void do_rename(int argc, char **argv, const struct cmd_desc *cmd)
12625e5c12b0Sopenharmony_ci{
12635e5c12b0Sopenharmony_ci	int fd = -1;
12645e5c12b0Sopenharmony_ci	int ret;
12655e5c12b0Sopenharmony_ci
12665e5c12b0Sopenharmony_ci	if (argc != 4) {
12675e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
12685e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
12695e5c12b0Sopenharmony_ci		exit(1);
12705e5c12b0Sopenharmony_ci	}
12715e5c12b0Sopenharmony_ci
12725e5c12b0Sopenharmony_ci	if (atoi(argv[3]))
12735e5c12b0Sopenharmony_ci		fd = xopen(argv[1], O_WRONLY, 0);
12745e5c12b0Sopenharmony_ci
12755e5c12b0Sopenharmony_ci	ret = rename(argv[1], argv[2]);
12765e5c12b0Sopenharmony_ci	if (ret < 0)
12775e5c12b0Sopenharmony_ci		die_errno("rename failed");
12785e5c12b0Sopenharmony_ci
12795e5c12b0Sopenharmony_ci	if (fd >= 0) {
12805e5c12b0Sopenharmony_ci		if (fsync(fd) != 0)
12815e5c12b0Sopenharmony_ci			die_errno("fsync failed: %s", argv[1]);
12825e5c12b0Sopenharmony_ci		close(fd);
12835e5c12b0Sopenharmony_ci	}
12845e5c12b0Sopenharmony_ci	exit(0);
12855e5c12b0Sopenharmony_ci}
12865e5c12b0Sopenharmony_ci
12875e5c12b0Sopenharmony_ci#define gc_desc "trigger filesystem GC"
12885e5c12b0Sopenharmony_ci#define gc_help "f2fs_io gc sync_mode [file_path]\n\n"
12895e5c12b0Sopenharmony_ci
12905e5c12b0Sopenharmony_cistatic void do_gc(int argc, char **argv, const struct cmd_desc *cmd)
12915e5c12b0Sopenharmony_ci{
12925e5c12b0Sopenharmony_ci	u32 sync;
12935e5c12b0Sopenharmony_ci	int ret, fd;
12945e5c12b0Sopenharmony_ci
12955e5c12b0Sopenharmony_ci	if (argc != 3) {
12965e5c12b0Sopenharmony_ci		fputs("Excess arguments\n\n", stderr);
12975e5c12b0Sopenharmony_ci		fputs(cmd->cmd_help, stderr);
12985e5c12b0Sopenharmony_ci		exit(1);
12995e5c12b0Sopenharmony_ci	}
13005e5c12b0Sopenharmony_ci
13015e5c12b0Sopenharmony_ci	sync = atoi(argv[1]);
13025e5c12b0Sopenharmony_ci
13035e5c12b0Sopenharmony_ci	fd = xopen(argv[2], O_RDONLY, 0);
13045e5c12b0Sopenharmony_ci
13055e5c12b0Sopenharmony_ci	ret = ioctl(fd, F2FS_IOC_GARBAGE_COLLECT, &sync);
13065e5c12b0Sopenharmony_ci	if (ret < 0)
13075e5c12b0Sopenharmony_ci		die_errno("F2FS_IOC_GARBAGE_COLLECT failed");
13085e5c12b0Sopenharmony_ci
13095e5c12b0Sopenharmony_ci	printf("trigger %s gc ret=%d\n",
13105e5c12b0Sopenharmony_ci		sync ? "synchronous" : "asynchronous", ret);
13115e5c12b0Sopenharmony_ci	exit(0);
13125e5c12b0Sopenharmony_ci}
13135e5c12b0Sopenharmony_ci
13145e5c12b0Sopenharmony_ci#define CMD_HIDDEN 	0x0001
13155e5c12b0Sopenharmony_ci#define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
13165e5c12b0Sopenharmony_ci#define _CMD(name) { #name, do_##name, NULL, NULL, CMD_HIDDEN }
13175e5c12b0Sopenharmony_ci
13185e5c12b0Sopenharmony_cistatic void do_help(int argc, char **argv, const struct cmd_desc *cmd);
13195e5c12b0Sopenharmony_ciconst struct cmd_desc cmd_list[] = {
13205e5c12b0Sopenharmony_ci	_CMD(help),
13215e5c12b0Sopenharmony_ci	CMD(fsync),
13225e5c12b0Sopenharmony_ci	CMD(set_verity),
13235e5c12b0Sopenharmony_ci	CMD(getflags),
13245e5c12b0Sopenharmony_ci	CMD(setflags),
13255e5c12b0Sopenharmony_ci	CMD(shutdown),
13265e5c12b0Sopenharmony_ci	CMD(pinfile),
13275e5c12b0Sopenharmony_ci	CMD(fallocate),
13285e5c12b0Sopenharmony_ci	CMD(erase),
13295e5c12b0Sopenharmony_ci	CMD(write),
13305e5c12b0Sopenharmony_ci	CMD(read),
13315e5c12b0Sopenharmony_ci	CMD(randread),
13325e5c12b0Sopenharmony_ci	CMD(fiemap),
13335e5c12b0Sopenharmony_ci	CMD(gc_urgent),
13345e5c12b0Sopenharmony_ci	CMD(defrag_file),
13355e5c12b0Sopenharmony_ci	CMD(copy),
13365e5c12b0Sopenharmony_ci	CMD(get_cblocks),
13375e5c12b0Sopenharmony_ci	CMD(release_cblocks),
13385e5c12b0Sopenharmony_ci	CMD(reserve_cblocks),
13395e5c12b0Sopenharmony_ci	CMD(get_coption),
13405e5c12b0Sopenharmony_ci	CMD(set_coption),
13415e5c12b0Sopenharmony_ci	CMD(decompress),
13425e5c12b0Sopenharmony_ci	CMD(compress),
13435e5c12b0Sopenharmony_ci	CMD(get_filename_encrypt_mode),
13445e5c12b0Sopenharmony_ci	CMD(rename),
13455e5c12b0Sopenharmony_ci	CMD(gc),
13465e5c12b0Sopenharmony_ci	{ NULL, NULL, NULL, NULL, 0 }
13475e5c12b0Sopenharmony_ci};
13485e5c12b0Sopenharmony_ci
13495e5c12b0Sopenharmony_cistatic void do_help(int argc, char **argv, const struct cmd_desc *UNUSED(cmd))
13505e5c12b0Sopenharmony_ci{
13515e5c12b0Sopenharmony_ci	const struct cmd_desc *p;
13525e5c12b0Sopenharmony_ci
13535e5c12b0Sopenharmony_ci	if (argc > 1) {
13545e5c12b0Sopenharmony_ci		for (p = cmd_list; p->cmd_name; p++) {
13555e5c12b0Sopenharmony_ci			if (p->cmd_flags & CMD_HIDDEN)
13565e5c12b0Sopenharmony_ci				continue;
13575e5c12b0Sopenharmony_ci			if (strcmp(p->cmd_name, argv[1]) == 0) {
13585e5c12b0Sopenharmony_ci				putc('\n', stdout);
13595e5c12b0Sopenharmony_ci				fputs("USAGE:\n  ", stdout);
13605e5c12b0Sopenharmony_ci				fputs(p->cmd_help, stdout);
13615e5c12b0Sopenharmony_ci				exit(0);
13625e5c12b0Sopenharmony_ci			}
13635e5c12b0Sopenharmony_ci		}
13645e5c12b0Sopenharmony_ci		printf("Unknown command: %s\n\n", argv[1]);
13655e5c12b0Sopenharmony_ci	}
13665e5c12b0Sopenharmony_ci
13675e5c12b0Sopenharmony_ci	fputs("Available commands:\n", stdout);
13685e5c12b0Sopenharmony_ci	for (p = cmd_list; p->cmd_name; p++) {
13695e5c12b0Sopenharmony_ci		if (p->cmd_flags & CMD_HIDDEN)
13705e5c12b0Sopenharmony_ci			continue;
13715e5c12b0Sopenharmony_ci		printf("  %-20s %s\n", p->cmd_name, p->cmd_desc);
13725e5c12b0Sopenharmony_ci	}
13735e5c12b0Sopenharmony_ci	printf("\nTo get more information on a command, "
13745e5c12b0Sopenharmony_ci	       "type 'f2fs_io help cmd'\n");
13755e5c12b0Sopenharmony_ci	exit(0);
13765e5c12b0Sopenharmony_ci}
13775e5c12b0Sopenharmony_ci
13785e5c12b0Sopenharmony_cistatic void die_signal_handler(int UNUSED(signum), siginfo_t *UNUSED(siginfo),
13795e5c12b0Sopenharmony_ci				void *UNUSED(context))
13805e5c12b0Sopenharmony_ci{
13815e5c12b0Sopenharmony_ci	exit(-1);
13825e5c12b0Sopenharmony_ci}
13835e5c12b0Sopenharmony_ci
13845e5c12b0Sopenharmony_cistatic void sigcatcher_setup(void)
13855e5c12b0Sopenharmony_ci{
13865e5c12b0Sopenharmony_ci	struct sigaction	sa;
13875e5c12b0Sopenharmony_ci
13885e5c12b0Sopenharmony_ci	memset(&sa, 0, sizeof(struct sigaction));
13895e5c12b0Sopenharmony_ci	sa.sa_sigaction = die_signal_handler;
13905e5c12b0Sopenharmony_ci	sa.sa_flags = SA_SIGINFO;
13915e5c12b0Sopenharmony_ci
13925e5c12b0Sopenharmony_ci	sigaction(SIGHUP, &sa, 0);
13935e5c12b0Sopenharmony_ci	sigaction(SIGINT, &sa, 0);
13945e5c12b0Sopenharmony_ci	sigaction(SIGQUIT, &sa, 0);
13955e5c12b0Sopenharmony_ci	sigaction(SIGFPE, &sa, 0);
13965e5c12b0Sopenharmony_ci	sigaction(SIGILL, &sa, 0);
13975e5c12b0Sopenharmony_ci	sigaction(SIGBUS, &sa, 0);
13985e5c12b0Sopenharmony_ci	sigaction(SIGSEGV, &sa, 0);
13995e5c12b0Sopenharmony_ci	sigaction(SIGABRT, &sa, 0);
14005e5c12b0Sopenharmony_ci	sigaction(SIGPIPE, &sa, 0);
14015e5c12b0Sopenharmony_ci	sigaction(SIGALRM, &sa, 0);
14025e5c12b0Sopenharmony_ci	sigaction(SIGTERM, &sa, 0);
14035e5c12b0Sopenharmony_ci	sigaction(SIGUSR1, &sa, 0);
14045e5c12b0Sopenharmony_ci	sigaction(SIGUSR2, &sa, 0);
14055e5c12b0Sopenharmony_ci	sigaction(SIGPOLL, &sa, 0);
14065e5c12b0Sopenharmony_ci	sigaction(SIGPROF, &sa, 0);
14075e5c12b0Sopenharmony_ci	sigaction(SIGSYS, &sa, 0);
14085e5c12b0Sopenharmony_ci	sigaction(SIGTRAP, &sa, 0);
14095e5c12b0Sopenharmony_ci	sigaction(SIGVTALRM, &sa, 0);
14105e5c12b0Sopenharmony_ci	sigaction(SIGXCPU, &sa, 0);
14115e5c12b0Sopenharmony_ci	sigaction(SIGXFSZ, &sa, 0);
14125e5c12b0Sopenharmony_ci}
14135e5c12b0Sopenharmony_ci
14145e5c12b0Sopenharmony_ciint main(int argc, char **argv)
14155e5c12b0Sopenharmony_ci{
14165e5c12b0Sopenharmony_ci	const struct cmd_desc *cmd;
14175e5c12b0Sopenharmony_ci
14185e5c12b0Sopenharmony_ci	if (argc < 2)
14195e5c12b0Sopenharmony_ci		do_help(argc, argv, cmd_list);
14205e5c12b0Sopenharmony_ci
14215e5c12b0Sopenharmony_ci	sigcatcher_setup();
14225e5c12b0Sopenharmony_ci	for (cmd = cmd_list; cmd->cmd_name; cmd++) {
14235e5c12b0Sopenharmony_ci		if (strcmp(cmd->cmd_name, argv[1]) == 0) {
14245e5c12b0Sopenharmony_ci			cmd->cmd_func(argc - 1, argv + 1, cmd);
14255e5c12b0Sopenharmony_ci			exit(0);
14265e5c12b0Sopenharmony_ci		}
14275e5c12b0Sopenharmony_ci	}
14285e5c12b0Sopenharmony_ci	printf("Unknown command: %s\n\n", argv[1]);
14295e5c12b0Sopenharmony_ci	do_help(1, argv, cmd_list);
14305e5c12b0Sopenharmony_ci	return 0;
14315e5c12b0Sopenharmony_ci}
1432