linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: linux-f2fs-devel@lists.sourceforge.net,
	Jaegeuk Kim <jaegeuk@kernel.org>, Chao Yu <chao@kernel.org>
Cc: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org,
	Satya Tangirala <satyaprateek2357@gmail.com>,
	Changheun Lee <nanich.lee@samsung.com>,
	Matthew Bobrowski <mbobrowski@mbobrowski.org>
Subject: [PATCH 7/9] f2fs: use iomap for direct I/O reads
Date: Fri, 16 Jul 2021 09:39:17 -0500	[thread overview]
Message-ID: <20210716143919.44373-8-ebiggers@kernel.org> (raw)
In-Reply-To: <20210716143919.44373-1-ebiggers@kernel.org>

From: Eric Biggers <ebiggers@google.com>

Convert f2fs_file_read_iter() to use iomap_dio_rw() for direct I/O
rather than using f2fs_direct_IO() via generic_file_read_iter().

Besides the new direct I/O implementation being more efficient
(especially with regards to the block mapping), this change retains the
existing f2fs behavior such as the conditions for falling back to
buffered I/O, the locking of i_gc_rwsem[READ], the iostat gathering, and
the f2fs_direct_IO_{enter,exit} tracepoints.  An exception is that we no
longer fall back to a buffered I/O read if a direct I/O read returns a
short read (previously this was done by generic_file_read_iter()), as
this doesn't appear to be a useful thing to do on f2fs.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 fs/f2fs/f2fs.h |  7 ++---
 fs/f2fs/file.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 82 insertions(+), 9 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d2b1ef6976c4..f869c4a2f79f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3243,10 +3243,9 @@ static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
 			sbi->rw_iostat[APP_WRITE_IO] -
 			sbi->rw_iostat[APP_DIRECT_IO];
 
-	if (type == APP_READ_IO || type == APP_DIRECT_READ_IO)
-		sbi->rw_iostat[APP_BUFFERED_READ_IO] =
-			sbi->rw_iostat[APP_READ_IO] -
-			sbi->rw_iostat[APP_DIRECT_READ_IO];
+	if (type == APP_BUFFERED_READ_IO || type == APP_DIRECT_READ_IO)
+		sbi->rw_iostat[APP_READ_IO] += io_bytes;
+
 	spin_unlock(&sbi->iostat_lock);
 
 	f2fs_record_iostat(sbi);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 279252c7f7bc..52de655ef833 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -23,6 +23,7 @@
 #include <linux/nls.h>
 #include <linux/sched/signal.h>
 #include <linux/fileattr.h>
+#include <linux/iomap.h>
 
 #include "f2fs.h"
 #include "node.h"
@@ -4201,20 +4202,93 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	return __f2fs_ioctl(filp, cmd, arg);
 }
 
-static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+/*
+ * Return %true if the given read or write request should use direct I/O, or
+ * %false if it should use buffered I/O.
+ */
+static bool f2fs_should_use_dio(struct inode *inode, struct kiocb *iocb,
+				struct iov_iter *iter)
+{
+	unsigned int align;
+
+	if (!(iocb->ki_flags & IOCB_DIRECT))
+		return false;
+
+	if (f2fs_force_buffered_io(inode, iocb, iter))
+		return false;
+
+	/*
+	 * Direct I/O not aligned to the disk's logical_block_size will be
+	 * attempted, but will fail with -EINVAL.
+	 *
+	 * f2fs additionally requires that direct I/O be aligned to the
+	 * filesystem block size, which is often a stricter requirement.
+	 * However, f2fs traditionally falls back to buffered I/O on requests
+	 * that are logical_block_size-aligned but not fs-block aligned.
+	 *
+	 * The below logic implements this behavior.
+	 */
+	align = iocb->ki_pos | iov_iter_alignment(iter);
+	if (!IS_ALIGNED(align, i_blocksize(inode)) &&
+	    IS_ALIGNED(align, bdev_logical_block_size(inode->i_sb->s_bdev)))
+		return false;
+
+	return true;
+}
+
+static ssize_t f2fs_dio_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = file_inode(file);
-	int ret;
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	const loff_t pos = iocb->ki_pos;
+	const size_t count = iov_iter_count(to);
+	ssize_t ret;
+
+	if (count == 0)
+		return 0; /* skip atime update */
+
+	trace_f2fs_direct_IO_enter(inode, pos, count, READ);
+
+	if (iocb->ki_flags & IOCB_NOWAIT) {
+		if (!down_read_trylock(&fi->i_gc_rwsem[READ])) {
+			ret = -EAGAIN;
+			goto out;
+		}
+	} else {
+		down_read(&fi->i_gc_rwsem[READ]);
+	}
+
+	ret = iomap_dio_rw(iocb, to, &f2fs_iomap_ops, &f2fs_iomap_dio_ops, 0);
+
+	up_read(&fi->i_gc_rwsem[READ]);
+
+	file_accessed(file);
+
+	if (ret > 0)
+		f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_READ_IO, ret);
+	else if (ret == -EIOCBQUEUED)
+		f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_READ_IO,
+				   count - iov_iter_count(to));
+out:
+	trace_f2fs_direct_IO_exit(inode, pos, count, READ, ret);
+	return ret;
+}
+
+static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+	struct inode *inode = file_inode(iocb->ki_filp);
+	ssize_t ret;
 
 	if (!f2fs_is_compress_backend_ready(inode))
 		return -EOPNOTSUPP;
 
-	ret = generic_file_read_iter(iocb, iter);
+	if (f2fs_should_use_dio(inode, iocb, to))
+		return f2fs_dio_read_iter(iocb, to);
 
+	ret = filemap_read(iocb, to, 0);
 	if (ret > 0)
-		f2fs_update_iostat(F2FS_I_SB(inode), APP_READ_IO, ret);
-
+		f2fs_update_iostat(F2FS_I_SB(inode), APP_BUFFERED_READ_IO, ret);
 	return ret;
 }
 
-- 
2.32.0


  parent reply	other threads:[~2021-07-16 14:40 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-16 14:39 [PATCH 0/9] f2fs: use iomap for direct I/O Eric Biggers
2021-07-16 14:39 ` [PATCH 1/9] f2fs: make f2fs_write_failed() take struct inode Eric Biggers
2021-07-25 10:00   ` Chao Yu
2021-07-16 14:39 ` [PATCH 2/9] f2fs: remove allow_outplace_dio() Eric Biggers
2021-07-19  8:41   ` Christoph Hellwig
2021-07-16 14:39 ` [PATCH 3/9] f2fs: rework write preallocations Eric Biggers
2021-07-25 10:50   ` Chao Yu
2021-07-25 17:57     ` Eric Biggers
2021-07-27  2:00       ` Jaegeuk Kim
2021-07-27  3:23         ` Chao Yu
2021-07-27  7:38           ` Eric Biggers
2021-07-27  8:30             ` Chao Yu
2021-07-27 15:33               ` Darrick J. Wong
2021-07-29  0:26                 ` Chao Yu
2021-07-28  2:29         ` Jaegeuk Kim
2021-07-25 15:35   ` Jaegeuk Kim
2021-07-25 15:47     ` Jaegeuk Kim
2021-07-25 18:01       ` Eric Biggers
2021-07-26 19:04         ` Jaegeuk Kim
2021-07-16 14:39 ` [PATCH 4/9] f2fs: reduce indentation in f2fs_file_write_iter() Eric Biggers
2021-07-16 14:39 ` [PATCH 5/9] f2fs: fix the f2fs_file_write_iter tracepoint Eric Biggers
2021-07-16 14:39 ` [PATCH 6/9] f2fs: implement iomap operations Eric Biggers
2021-07-19  8:59   ` Christoph Hellwig
2021-07-22 20:47     ` Jaegeuk Kim
2021-07-22 20:49       ` Jaegeuk Kim
2021-07-22 20:54       ` Eric Biggers
2021-07-22 21:57         ` Jaegeuk Kim
2021-07-23  1:52     ` Eric Biggers
2021-07-23  5:00       ` Christoph Hellwig
2021-07-23  8:05         ` Eric Biggers
2021-07-16 14:39 ` Eric Biggers [this message]
2021-07-16 14:39 ` [PATCH 8/9] f2fs: use iomap for direct I/O writes Eric Biggers
2021-07-16 14:39 ` [PATCH 9/9] f2fs: remove f2fs_direct_IO() Eric Biggers

Reply instructions:

You may reply publicly 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=20210716143919.44373-8-ebiggers@kernel.org \
    --to=ebiggers@kernel.org \
    --cc=chao@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=mbobrowski@mbobrowski.org \
    --cc=nanich.lee@samsung.com \
    --cc=satyaprateek2357@gmail.com \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).