Linux-f2fs-devel Archive on lore.kernel.org
 help / color / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim <jaegeuk@kernel.org>
Subject: [f2fs-dev] [PATCH 2/2] f2fs_io: add copy command
Date: Fri,  4 Oct 2019 15:43:17 -0700
Message-ID: <20191004224317.153566-3-ebiggers@kernel.org> (raw)
In-Reply-To: <20191004224317.153566-1-ebiggers@kernel.org>

From: Eric Biggers <ebiggers@google.com>

Add a copy command to f2fs_io, to allow testing direct I/O writes where
the source page is from a different file (mmap) or an internal kernel
page (sendfile).  It could be useful for other tests in the future too.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 tools/f2fs_io/f2fs_io.c | 108 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
index f5493ff..0d90835 100644
--- a/tools/f2fs_io/f2fs_io.c
+++ b/tools/f2fs_io/f2fs_io.c
@@ -21,7 +21,9 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <getopt.h>
 #include <inttypes.h>
+#include <limits.h>
 #include <signal.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -29,6 +31,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <sys/mman.h>
+#include <sys/sendfile.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <termios.h>
@@ -105,6 +109,27 @@ static int xopen(const char *pathname, int flags, mode_t mode)
 	return fd;
 }
 
+static ssize_t xread(int fd, void *buf, size_t count)
+{
+	ssize_t ret = read(fd, buf, count);
+
+	if (ret < 0)
+		die_errno("read failed");
+	return ret;
+}
+
+static void full_write(int fd, const void *buf, size_t count)
+{
+	while (count) {
+		ssize_t ret = write(fd, buf, count);
+
+		if (ret < 0)
+			die_errno("write failed");
+		buf = (char *)buf + ret;
+		count -= ret;
+	}
+}
+
 #define getflags_desc "getflags ioctl"
 #define getflags_help						\
 "f2fs_io getflags [file]\n\n"					\
@@ -563,6 +588,88 @@ static void do_defrag_file(int argc, char **argv, const struct cmd_desc *cmd)
 	exit(0);
 }
 
+#define copy_desc "copy a file"
+#define copy_help							\
+"f2fs_io copy [-d] [-m] [-s] src_path dst_path\n\n"			\
+"  src_path  : path to source file\n"					\
+"  dst_path  : path to destination file\n"				\
+"  -d        : use direct I/O\n"					\
+"  -m        : mmap the source file\n"					\
+"  -s        : use sendfile\n"						\
+
+static void do_copy(int argc, char **argv, const struct cmd_desc *cmd)
+{
+	int c;
+	int src_fd;
+	int dst_fd;
+	int open_flags = 0;
+	bool mmap_source_file = false;
+	bool use_sendfile = false;
+	ssize_t ret;
+
+	while ((c = getopt(argc, argv, "dms")) != -1) {
+		switch (c) {
+		case 'd':
+			open_flags |= O_DIRECT;
+			break;
+		case 'm':
+			mmap_source_file = true;
+			break;
+		case 's':
+			use_sendfile = true;
+			break;
+		default:
+			fputs(cmd->cmd_help, stderr);
+			exit(2);
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	if (argc != 2) {
+		fputs("Wrong number of arguments\n\n", stderr);
+		fputs(cmd->cmd_help, stderr);
+		exit(2);
+	}
+	if (mmap_source_file && use_sendfile)
+		die("-m and -s are mutually exclusive");
+
+	src_fd = xopen(argv[0], O_RDONLY | open_flags, 0);
+	dst_fd = xopen(argv[1], O_WRONLY | O_CREAT | O_TRUNC | open_flags, 0644);
+
+	if (mmap_source_file) {
+		struct stat stbuf;
+		void *src_addr;
+
+		if (fstat(src_fd, &stbuf) != 0)
+			die_errno("fstat of source file failed");
+
+		if ((size_t)stbuf.st_size != stbuf.st_size)
+			die("Source file is too large");
+
+		src_addr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_SHARED,
+				src_fd, 0);
+		if (src_addr == MAP_FAILED)
+			die("mmap of source file failed");
+
+		full_write(dst_fd, src_addr, stbuf.st_size);
+
+		munmap(src_addr, stbuf.st_size);
+	} else if (use_sendfile) {
+		while ((ret = sendfile(dst_fd, src_fd, NULL, INT_MAX)) > 0)
+			;
+		if (ret < 0)
+			die_errno("sendfile failed");
+	} else {
+		char *buf = aligned_xalloc(4096, 4096);
+
+		while ((ret = xread(src_fd, buf, 4096)) > 0)
+			full_write(dst_fd, buf, ret);
+		free(buf);
+	}
+	close(src_fd);
+	close(dst_fd);
+}
+
 
 #define CMD_HIDDEN 	0x0001
 #define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
@@ -581,6 +688,7 @@ const struct cmd_desc cmd_list[] = {
 	CMD(fiemap),
 	CMD(gc_urgent),
 	CMD(defrag_file),
+	CMD(copy),
 	{ NULL, NULL, NULL, NULL, 0 }
 };
 
-- 
2.23.0.581.g78d2f28ef7-goog



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

      parent reply index

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-04 22:43 [f2fs-dev] [PATCH 0/2] f2fs-tools: add 'copy' command to f2fs_io Eric Biggers
2019-10-04 22:43 ` [f2fs-dev] [PATCH 1/2] f2fs_io: add helper functions for handling errors Eric Biggers
2019-10-15  7:03   ` Chao Yu
2019-10-04 22:43 ` Eric Biggers [this message]

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191004224317.153566-3-ebiggers@kernel.org \
    --to=ebiggers@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-f2fs-devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-f2fs-devel/0 linux-f2fs-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-f2fs-devel linux-f2fs-devel/ https://lore.kernel.org/linux-f2fs-devel \
		linux-f2fs-devel@lists.sourceforge.net
	public-inbox-index linux-f2fs-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/net.sourceforge.lists.linux-f2fs-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git