linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Goldwyn Rodrigues <rgoldwyn@suse.de>
To: darrick.wong@oracle.com
Cc: linux-btrfs@vger.kernel.org, fdmanana@gmail.com,
	linux-fsdevel@vger.kernel.org, hch@lst.de,
	Goldwyn Rodrigues <rgoldwyn@suse.com>
Subject: [PATCH 3/3] xfs: fallback to buffered I/O if direct I/O is short
Date: Fri,  5 Jun 2020 15:48:38 -0500	[thread overview]
Message-ID: <20200605204838.10765-4-rgoldwyn@suse.de> (raw)
In-Reply-To: <20200605204838.10765-1-rgoldwyn@suse.de>

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

Most filesystems such as ext4 and btrfs fallback to buffered I/O in case
direct write's fail. In case direct I/O is short, fallback to buffered
write to complete the I/O. Make sure the data is on disk by performing a
filemap_write_and_wait_range() and invalidating the pages in the range.

For reads, call xfs_file_buffered_aio_read() in case of short I/O.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/xfs/xfs_file.c | 41 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 4b8bdecc3863..786391228dea 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -31,6 +31,10 @@
 #include <linux/fadvise.h>
 
 static const struct vm_operations_struct xfs_file_vm_ops;
+STATIC ssize_t xfs_file_buffered_aio_write(struct kiocb *iocb,
+		struct iov_iter	*from);
+STATIC ssize_t xfs_file_buffered_aio_read(struct kiocb *iocb,
+		struct iov_iter	*to);
 
 int
 xfs_update_prealloc_flags(
@@ -169,6 +173,7 @@ xfs_file_dio_aio_read(
 	struct xfs_inode	*ip = XFS_I(file_inode(iocb->ki_filp));
 	size_t			count = iov_iter_count(to);
 	ssize_t			ret;
+	ssize_t			buffered_read = 0;
 
 	trace_xfs_file_direct_read(ip, count, iocb->ki_pos);
 
@@ -187,7 +192,13 @@ xfs_file_dio_aio_read(
 			is_sync_kiocb(iocb));
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
-	return ret;
+	if (ret < 0 || ret == count)
+		return ret;
+
+	iocb->ki_flags &= ~IOCB_DIRECT;
+	buffered_read = xfs_file_buffered_aio_read(iocb, to);
+
+	return ret + buffered_read;
 }
 
 static noinline ssize_t
@@ -483,6 +494,9 @@ xfs_file_dio_aio_write(
 	int			iolock;
 	size_t			count = iov_iter_count(from);
 	struct xfs_buftarg      *target = xfs_inode_buftarg(ip);
+	loff_t			offset, end;
+	ssize_t			buffered_write = 0;
+	int			err;
 
 	/* DIO must be aligned to device logical sector size */
 	if ((iocb->ki_pos | count) & target->bt_logical_sectormask)
@@ -552,12 +566,25 @@ xfs_file_dio_aio_write(
 out:
 	xfs_iunlock(ip, iolock);
 
-	/*
-	 * No fallback to buffered IO on errors for XFS, direct IO will either
-	 * complete fully or fail.
-	 */
-	ASSERT(ret < 0 || ret == count);
-	return ret;
+	if (ret < 0 || ret == count)
+		return ret;
+
+	/* Fallback to buffered write */
+
+	offset = iocb->ki_pos;
+
+	buffered_write = xfs_file_buffered_aio_write(iocb, from);
+	if (buffered_write < 0)
+		return ret;
+
+	end = offset + buffered_write - 1;
+
+	err = filemap_write_and_wait_range(mapping, offset, end);
+	if (!err)
+		invalidate_mapping_pages(mapping, offset >> PAGE_SHIFT,
+				end >> PAGE_SHIFT);
+
+	return ret + buffered_write;
 }
 
 static noinline ssize_t
-- 
2.25.0


  parent reply	other threads:[~2020-06-05 20:48 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-05 20:48 [PATCH 0/3] Transient errors in Direct I/O Goldwyn Rodrigues
2020-06-05 20:48 ` [PATCH 1/3] iomap: dio Return zero in case of unsuccessful pagecache invalidation Goldwyn Rodrigues
2020-06-06  3:13   ` Matthew Wilcox
2020-06-05 20:48 ` [PATCH 2/3] btrfs: Wait for extent bits to release page Goldwyn Rodrigues
2020-06-08 10:20   ` Filipe Manana
2020-06-08 12:13     ` Goldwyn Rodrigues
2020-06-05 20:48 ` Goldwyn Rodrigues [this message]
2020-06-10  2:59 ` [PATCH 0/3] Transient errors in Direct I/O Dave Chinner
2020-06-10  5:05   ` Dave Chinner
2020-06-11 14:13     ` Goldwyn Rodrigues
2020-06-10  5:31 ` Qu Wenruo
2020-06-11 14:11   ` Goldwyn Rodrigues
2020-06-12 12:56     ` Qu Wenruo

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=20200605204838.10765-4-rgoldwyn@suse.de \
    --to=rgoldwyn@suse.de \
    --cc=darrick.wong@oracle.com \
    --cc=fdmanana@gmail.com \
    --cc=hch@lst.de \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=rgoldwyn@suse.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).