All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/10 v13] merge request: No wait AIO
@ 2017-06-19 16:33 Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 01/10] fs: Separate out kiocb flags setup based on RWF_* flags Goldwyn Rodrigues
                   ` (10 more replies)
  0 siblings, 11 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block

Jens,

As Christoph suggested, I am sending the patches against the block
tree for merge since the block layer changes had the most conflicts.
My tree is at https://github.com/goldwynr/linux/tree/nowait-block

This series adds nonblocking feature to asynchronous I/O writes.
io_submit() can be delayed because of a number of reason:
 - Block allocation for files
 - Data writebacks for direct I/O
 - Sleeping because of waiting to acquire i_rwsem
 - Congested block device

The goal of the patch series is to return -EAGAIN/-EWOULDBLOCK if
any of these conditions are met. This way userspace can push most
of the write()s to the kernel to the best of its ability to complete
and if it returns -EAGAIN, can defer it to another thread.

In order to enable this, IOCB_RW_FLAG_NOWAIT is introduced in
uapi/linux/aio_abi.h. If set for aio_rw_flags, it translates to
IOCB_NOWAIT for struct iocb, REQ_NOWAIT for bio.bi_opf and IOMAP_NOWAIT for
iomap. aio_rw_flags is a new flag replacing aio_reserved1. We could
not use aio_flags because it is not currently checked for invalidity
in the kernel.

This feature is provided for direct I/O of asynchronous I/O only. I have
tested it against xfs, ext4, and btrfs while I intend to add more filesystems.
The nowait feature is for request based devices. In the future, I intend to
add support to stacked devices such as md.

Applications will have to check supportability by sending a async direct write
and any other error besides -EAGAIN would mean it is not supported.

First two patches are prep patches into nowait I/O.

Changes since v1:
 + changed name from _NONBLOCKING to *_NOWAIT
 + filemap_range_has_page call moved to closer to (just before) calling filemap_write_and_wait_range().
 + BIO_NOWAIT limited to get_request()
 + XFS fixes 
	- included reflink 
	- use of xfs_ilock_nowait() instead of a XFS_IOLOCK_NONBLOCKING flag
	- Translate the flag through IOMAP_NOWAIT (iomap) to check for
	  block allocation for the file.
 + ext4 coding style

Changes since v2:
 + Using aio_reserved1 as aio_rw_flags instead of aio_flags
 + blk-mq support
 + xfs uptodate with kernel and reflink changes

 Changes since v3:
  + Added FS_NOWAIT, which is set if the filesystem supports NOWAIT feature.
  + Checks in generic_make_request() to make sure BIO_NOWAIT comes in
    for async direct writes only.
  + Added QUEUE_FLAG_NOWAIT, which is set if the device supports BIO_NOWAIT.
    This is added (rather not set) to block devices such as dm/md currently.

 Changes since v4:
  + Ported AIO code to use RWF_* flags. Check for RWF_* flags in
    generic_file_write_iter().
  + Changed IOCB_RW_FLAGS_NOWAIT to RWF_NOWAIT.

 Changes since v5:
  + BIO_NOWAIT to REQ_NOWAIT
  + Common helper for RWF flags.

 Changes since v6:
  + REQ_NOWAIT will be ignored for request based devices since they
    cannot block. So, removed QUEUE_FLAG_NOWAIT since it is not
    required in the current implementation. It will be resurrected
    when we program for stacked devices.
  + changed kiocb_rw_flags() to kiocb_set_rw_flags() in order to accomodate
    for errors. Moved checks in the function.

 Changes since v7:
  + split patches into prep so the main patches are smaller and easier
    to understand
  + All patches are reviewed or acked!
 
 Changes since v8:
 + Err out AIO reads with -EINVAL flagged as RWF_NOWAIT

 Changes since v9:
 + Retract - Err out AIO reads with -EINVAL flagged as RWF_NOWAIT
 + XFS returns EAGAIN if extent list is not in memory
 + Man page updates to io_submit with iocb description and nowait features.

 Changes since v10:
 + Corrected comment and subject in "return on congested block device"

 Changes since v11:
 + FMODE_AIO_NOWAIT to show AIO NOWAIT support. This is to block
   non-supported filesystems instead of returning ENOTSUPP in each
   individual filesystem

 Changes since v12:
 + Updated with respect to linux-next. Primarily changes the patch in
   block patch, which changes bio.bi_error to bio.bi_status.
 + Fix FMODE_AIO_NOWAIT spellcheck 
 + Added RWF_SUPPORTED to encompass all flags
 + Added checks on the read side, namely generic_file_read_iter() and
   iomap_dio_rw()

-- 
Goldwyn

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 01/10] fs: Separate out kiocb flags setup based on RWF_* flags
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 02/10] fs: Introduce filemap_range_has_page() Goldwyn Rodrigues
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

Also added RWF_SUPPORTED to encompass all flags.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/read_write.c         | 12 +++---------
 include/linux/fs.h      | 14 ++++++++++++++
 include/uapi/linux/fs.h |  2 ++
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index 47c1d4484df9..53c816c61122 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -678,16 +678,10 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
 	struct kiocb kiocb;
 	ssize_t ret;
 
-	if (flags & ~(RWF_HIPRI | RWF_DSYNC | RWF_SYNC))
-		return -EOPNOTSUPP;
-
 	init_sync_kiocb(&kiocb, filp);
-	if (flags & RWF_HIPRI)
-		kiocb.ki_flags |= IOCB_HIPRI;
-	if (flags & RWF_DSYNC)
-		kiocb.ki_flags |= IOCB_DSYNC;
-	if (flags & RWF_SYNC)
-		kiocb.ki_flags |= (IOCB_DSYNC | IOCB_SYNC);
+	ret = kiocb_set_rw_flags(&kiocb, flags);
+	if (ret)
+		return ret;
 	kiocb.ki_pos = *ppos;
 
 	if (type == READ)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 023f0324762b..96a1a1fa54a9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3057,6 +3057,20 @@ static inline int iocb_flags(struct file *file)
 	return res;
 }
 
+static inline int kiocb_set_rw_flags(struct kiocb *ki, int flags)
+{
+	if (unlikely(flags & ~RWF_SUPPORTED))
+		return -EOPNOTSUPP;
+
+	if (flags & RWF_HIPRI)
+		ki->ki_flags |= IOCB_HIPRI;
+	if (flags & RWF_DSYNC)
+		ki->ki_flags |= IOCB_DSYNC;
+	if (flags & RWF_SYNC)
+		ki->ki_flags |= (IOCB_DSYNC | IOCB_SYNC);
+	return 0;
+}
+
 static inline ino_t parent_ino(struct dentry *dentry)
 {
 	ino_t res;
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 24e61a54feaa..937c3e39650a 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -361,4 +361,6 @@ struct fscrypt_key {
 #define RWF_DSYNC			0x00000002 /* per-IO O_DSYNC */
 #define RWF_SYNC			0x00000004 /* per-IO O_SYNC */
 
+#define RWF_SUPPORTED			(RWF_HIPRI | RWF_DSYNC | RWF_SYNC)
+
 #endif /* _UAPI_LINUX_FS_H */
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 02/10] fs: Introduce filemap_range_has_page()
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 01/10] fs: Separate out kiocb flags setup based on RWF_* flags Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 03/10] fs: Use RWF_* flags for AIO operations Goldwyn Rodrigues
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

filemap_range_has_page() return true if the file's mapping has
a page within the range mentioned. This function will be used
to check if a write() call will cause a writeback of previous
writes.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 include/linux/fs.h |  2 ++
 mm/filemap.c       | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 96a1a1fa54a9..0d34f5b5a6b0 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2518,6 +2518,8 @@ extern int filemap_fdatawait(struct address_space *);
 extern void filemap_fdatawait_keep_errors(struct address_space *);
 extern int filemap_fdatawait_range(struct address_space *, loff_t lstart,
 				   loff_t lend);
+extern bool filemap_range_has_page(struct address_space *, loff_t lstart,
+				  loff_t lend);
 extern int filemap_write_and_wait(struct address_space *mapping);
 extern int filemap_write_and_wait_range(struct address_space *mapping,
 				        loff_t lstart, loff_t lend);
diff --git a/mm/filemap.c b/mm/filemap.c
index 6f1be573a5e6..9b39a2390b9e 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -376,6 +376,38 @@ int filemap_flush(struct address_space *mapping)
 }
 EXPORT_SYMBOL(filemap_flush);
 
+/**
+ * filemap_range_has_page - check if a page exists in range.
+ * @mapping:           address space within which to check
+ * @start_byte:        offset in bytes where the range starts
+ * @end_byte:          offset in bytes where the range ends (inclusive)
+ *
+ * Find at least one page in the range supplied, usually used to check if
+ * direct writing in this range will trigger a writeback.
+ */
+bool filemap_range_has_page(struct address_space *mapping,
+			   loff_t start_byte, loff_t end_byte)
+{
+	pgoff_t index = start_byte >> PAGE_SHIFT;
+	pgoff_t end = end_byte >> PAGE_SHIFT;
+	struct pagevec pvec;
+	bool ret;
+
+	if (end_byte < start_byte)
+		return false;
+
+	if (mapping->nrpages == 0)
+		return false;
+
+	pagevec_init(&pvec, 0);
+	if (!pagevec_lookup(&pvec, mapping, index, 1))
+		return false;
+	ret = (pvec.pages[0]->index <= end);
+	pagevec_release(&pvec);
+	return ret;
+}
+EXPORT_SYMBOL(filemap_range_has_page);
+
 static int __filemap_fdatawait_range(struct address_space *mapping,
 				     loff_t start_byte, loff_t end_byte)
 {
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 03/10] fs: Use RWF_* flags for AIO operations
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 01/10] fs: Separate out kiocb flags setup based on RWF_* flags Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 02/10] fs: Introduce filemap_range_has_page() Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 04/10] fs: Introduce RWF_NOWAIT and FMODE_AIO_NOWAIT Goldwyn Rodrigues
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

aio_rw_flags is introduced in struct iocb (using aio_reserved1) which will
carry the RWF_* flags. We cannot use aio_flags because they are not
checked for validity which may break existing applications.

Note, the only place RWF_HIPRI comes in effect is dio_await_one().
All the rest of the locations, aio code return -EIOCBQUEUED before the
checks for RWF_HIPRI.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/aio.c                     | 8 +++++++-
 include/uapi/linux/aio_abi.h | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/fs/aio.c b/fs/aio.c
index f52d925ee259..020fa0045e3c 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1541,7 +1541,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 	ssize_t ret;
 
 	/* enforce forwards compatibility on users */
-	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2)) {
+	if (unlikely(iocb->aio_reserved2)) {
 		pr_debug("EINVAL: reserve field set\n");
 		return -EINVAL;
 	}
@@ -1586,6 +1586,12 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 		req->common.ki_flags |= IOCB_EVENTFD;
 	}
 
+	ret = kiocb_set_rw_flags(&req->common, iocb->aio_rw_flags);
+	if (unlikely(ret)) {
+		pr_debug("EINVAL: aio_rw_flags\n");
+		goto out_put_req;
+	}
+
 	ret = put_user(KIOCB_KEY, &user_iocb->aio_key);
 	if (unlikely(ret)) {
 		pr_debug("EFAULT: aio_key\n");
diff --git a/include/uapi/linux/aio_abi.h b/include/uapi/linux/aio_abi.h
index bb2554f7fbd1..a2d4a8ac94ca 100644
--- a/include/uapi/linux/aio_abi.h
+++ b/include/uapi/linux/aio_abi.h
@@ -79,7 +79,7 @@ struct io_event {
 struct iocb {
 	/* these are internal to the kernel/libc. */
 	__u64	aio_data;	/* data to be returned in event's data */
-	__u32	PADDED(aio_key, aio_reserved1);
+	__u32	PADDED(aio_key, aio_rw_flags);
 				/* the kernel sets aio_key to the req # */
 
 	/* common fields */
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 04/10] fs: Introduce RWF_NOWAIT and FMODE_AIO_NOWAIT
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
                   ` (2 preceding siblings ...)
  2017-06-19 16:33 ` [PATCH 03/10] fs: Use RWF_* flags for AIO operations Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 05/10] fs: return if direct I/O will trigger writeback Goldwyn Rodrigues
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

RWF_NOWAIT informs kernel to bail out if an AIO request will block
for reasons such as file allocations, or a writeback triggered,
or would block while allocating requests while performing
direct I/O.

RWF_NOWAIT is translated to IOCB_NOWAIT for iocb->ki_flags.

FMODE_AIO_NOWAIT is a flag which identifies the file opened is capable
of returning -EAGAIN if the AIO call will block. This must be set by
supporting filesystems in the ->open() call.

Filesystems xfs, btrfs and ext4 would be supported in the following patches.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/aio.c                | 6 ++++++
 include/linux/fs.h      | 9 +++++++++
 include/uapi/linux/fs.h | 4 +++-
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/fs/aio.c b/fs/aio.c
index 020fa0045e3c..34027b67e2f4 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1592,6 +1592,12 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 		goto out_put_req;
 	}
 
+	if ((req->common.ki_flags & IOCB_NOWAIT) &&
+			!(req->common.ki_flags & IOCB_DIRECT)) {
+		ret = -EOPNOTSUPP;
+		goto out_put_req;
+	}
+
 	ret = put_user(KIOCB_KEY, &user_iocb->aio_key);
 	if (unlikely(ret)) {
 		pr_debug("EFAULT: aio_key\n");
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0d34f5b5a6b0..4574121f4746 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -143,6 +143,9 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 /* File was opened by fanotify and shouldn't generate fanotify events */
 #define FMODE_NONOTIFY		((__force fmode_t)0x4000000)
 
+/* File is capable of returning -EAGAIN if AIO will block */
+#define FMODE_AIO_NOWAIT	((__force fmode_t)0x8000000)
+
 /*
  * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
  * that indicates that they should check the contents of the iovec are
@@ -269,6 +272,7 @@ struct writeback_control;
 #define IOCB_DSYNC		(1 << 4)
 #define IOCB_SYNC		(1 << 5)
 #define IOCB_WRITE		(1 << 6)
+#define IOCB_NOWAIT		(1 << 7)
 
 struct kiocb {
 	struct file		*ki_filp;
@@ -3064,6 +3068,11 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, int flags)
 	if (unlikely(flags & ~RWF_SUPPORTED))
 		return -EOPNOTSUPP;
 
+	if (flags & RWF_NOWAIT) {
+		if (!(ki->ki_filp->f_mode & FMODE_AIO_NOWAIT))
+			return -EOPNOTSUPP;
+		ki->ki_flags |= IOCB_NOWAIT;
+	}
 	if (flags & RWF_HIPRI)
 		ki->ki_flags |= IOCB_HIPRI;
 	if (flags & RWF_DSYNC)
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 937c3e39650a..27d8c36c04af 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -360,7 +360,9 @@ struct fscrypt_key {
 #define RWF_HIPRI			0x00000001 /* high priority request, poll if possible */
 #define RWF_DSYNC			0x00000002 /* per-IO O_DSYNC */
 #define RWF_SYNC			0x00000004 /* per-IO O_SYNC */
+#define RWF_NOWAIT			0x00000008 /* per-IO, return -EAGAIN if operation would block */
 
-#define RWF_SUPPORTED			(RWF_HIPRI | RWF_DSYNC | RWF_SYNC)
+#define RWF_SUPPORTED			(RWF_HIPRI | RWF_DSYNC | RWF_SYNC |\
+					 RWF_NOWAIT)
 
 #endif /* _UAPI_LINUX_FS_H */
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 05/10] fs: return if direct I/O will trigger writeback
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
                   ` (3 preceding siblings ...)
  2017-06-19 16:33 ` [PATCH 04/10] fs: Introduce RWF_NOWAIT and FMODE_AIO_NOWAIT Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:44   ` Al Viro
  2017-06-19 16:33 ` [PATCH 06/10] fs: Introduce IOMAP_NOWAIT Goldwyn Rodrigues
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

Find out if the I/O will trigger a wait due to writeback. If yes,
return -EAGAIN.

Return -EINVAL for buffered AIO: there are multiple causes of
delay such as page locks, dirty throttling logic, page loading
from disk etc. which cannot be taken care of.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 mm/filemap.c | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 9b39a2390b9e..742034e56100 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2070,10 +2070,17 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
 		loff_t size;
 
 		size = i_size_read(inode);
-		retval = filemap_write_and_wait_range(mapping, iocb->ki_pos,
-					iocb->ki_pos + count - 1);
-		if (retval < 0)
-			goto out;
+		if (iocb->ki_flags & IOCB_NOWAIT) {
+			if (filemap_range_has_page(mapping, iocb->ki_pos,
+						   iocb->ki_pos + count - 1))
+				return -EAGAIN;
+		} else {
+			retval = filemap_write_and_wait_range(mapping,
+						iocb->ki_pos,
+					        iocb->ki_pos + count - 1);
+			if (retval < 0)
+				goto out;
+		}
 
 		file_accessed(file);
 
@@ -2674,6 +2681,9 @@ inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
 
 	pos = iocb->ki_pos;
 
+	if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
+		return -EINVAL;
+
 	if (limit != RLIM_INFINITY) {
 		if (iocb->ki_pos >= limit) {
 			send_sig(SIGXFSZ, current, 0);
@@ -2742,9 +2752,17 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
 	write_len = iov_iter_count(from);
 	end = (pos + write_len - 1) >> PAGE_SHIFT;
 
-	written = filemap_write_and_wait_range(mapping, pos, pos + write_len - 1);
-	if (written)
-		goto out;
+	if (iocb->ki_flags & IOCB_NOWAIT) {
+		/* If there are pages to writeback, return */
+		if (filemap_range_has_page(inode->i_mapping, pos,
+					   pos + iov_iter_count(from)))
+			return -EAGAIN;
+	} else {
+		written = filemap_write_and_wait_range(mapping, pos,
+							pos + write_len - 1);
+		if (written)
+			goto out;
+	}
 
 	/*
 	 * After a write we want buffered reads to be sure to go to disk to get
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 06/10] fs: Introduce IOMAP_NOWAIT
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
                   ` (4 preceding siblings ...)
  2017-06-19 16:33 ` [PATCH 05/10] fs: return if direct I/O will trigger writeback Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 07/10] block: return on congested block device Goldwyn Rodrigues
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

IOCB_NOWAIT translates to IOMAP_NOWAIT for iomaps.
This is used by XFS in the XFS patch.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/iomap.c            | 8 ++++++++
 include/linux/iomap.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/fs/iomap.c b/fs/iomap.c
index 18f2f2b8ba2c..c71a64b97fba 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -881,6 +881,14 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 		flags |= IOMAP_WRITE;
 	}
 
+	if (iocb->ki_flags & IOCB_NOWAIT) {
+		if (filemap_range_has_page(mapping, start, end)) {
+			ret = -EAGAIN;
+			goto out_free_dio;
+		}
+		flags |= IOMAP_NOWAIT;
+	}
+
 	ret = filemap_write_and_wait_range(mapping, start, end);
 	if (ret)
 		goto out_free_dio;
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index f753e788da31..69f4e9470084 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -52,6 +52,7 @@ struct iomap {
 #define IOMAP_REPORT		(1 << 2) /* report extent status, e.g. FIEMAP */
 #define IOMAP_FAULT		(1 << 3) /* mapping for page fault */
 #define IOMAP_DIRECT		(1 << 4) /* direct I/O */
+#define IOMAP_NOWAIT		(1 << 5) /* Don't wait for writeback */
 
 struct iomap_ops {
 	/*
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 07/10] block: return on congested block device
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
                   ` (5 preceding siblings ...)
  2017-06-19 16:33 ` [PATCH 06/10] fs: Introduce IOMAP_NOWAIT Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 08/10] ext4: nowait aio support Goldwyn Rodrigues
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

A new bio operation flag REQ_NOWAIT is introduced to identify bio's
orignating from iocb with IOCB_NOWAIT. This flag indicates
to return immediately if a request cannot be made instead
of retrying.

Stacked devices such as md (the ones with make_request_fn hooks)
currently are not supported because it may block for housekeeping.
For example, an md can have a part of the device suspended.
For this reason, only request based devices are supported.
In the future, this feature will be expanded to stacked devices
by teaching them how to handle the REQ_NOWAIT flags.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 block/blk-core.c          | 22 ++++++++++++++++++++--
 block/blk-mq-sched.c      |  3 +++
 block/blk-mq.c            |  2 ++
 fs/direct-io.c            | 10 ++++++++--
 include/linux/bio.h       |  6 ++++++
 include/linux/blk_types.h |  4 ++++
 6 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 8592409db272..3999e6ac288d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -143,6 +143,7 @@ static const struct {
 	[BLK_STS_MEDIUM]	= { -ENODATA,	"critical medium" },
 	[BLK_STS_PROTECTION]	= { -EILSEQ,	"protection" },
 	[BLK_STS_RESOURCE]	= { -ENOMEM,	"kernel resource" },
+	[BLK_STS_AGAIN]		= { -EAGAIN,	"nonblocking retry" },
 
 	/* device mapper special case, should not leak out: */
 	[BLK_STS_DM_REQUEUE]	= { -EREMCHG, "dm internal retry" },
@@ -1314,6 +1315,11 @@ static struct request *get_request(struct request_queue *q, unsigned int op,
 	if (!IS_ERR(rq))
 		return rq;
 
+	if (op & REQ_NOWAIT) {
+		blk_put_rl(rl);
+		return ERR_PTR(-EAGAIN);
+	}
+
 	if (!gfpflags_allow_blocking(gfp_mask) || unlikely(blk_queue_dying(q))) {
 		blk_put_rl(rl);
 		return rq;
@@ -1961,6 +1967,14 @@ generic_make_request_checks(struct bio *bio)
 		goto end_io;
 	}
 
+	/*
+	 * For a REQ_NOWAIT based request, return -EOPNOTSUPP
+	 * if queue is not a request based queue.
+	 */
+
+	if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_rq_based(q))
+		goto not_supported;
+
 	part = bio->bi_bdev->bd_part;
 	if (should_fail_request(part, bio->bi_iter.bi_size) ||
 	    should_fail_request(&part_to_disk(part)->part0,
@@ -2118,7 +2132,7 @@ blk_qc_t generic_make_request(struct bio *bio)
 	do {
 		struct request_queue *q = bdev_get_queue(bio->bi_bdev);
 
-		if (likely(blk_queue_enter(q, false) == 0)) {
+		if (likely(blk_queue_enter(q, bio->bi_opf & REQ_NOWAIT) == 0)) {
 			struct bio_list lower, same;
 
 			/* Create a fresh bio_list for all subordinate requests */
@@ -2143,7 +2157,11 @@ blk_qc_t generic_make_request(struct bio *bio)
 			bio_list_merge(&bio_list_on_stack[0], &same);
 			bio_list_merge(&bio_list_on_stack[0], &bio_list_on_stack[1]);
 		} else {
-			bio_io_error(bio);
+			if (unlikely(!blk_queue_dying(q) &&
+					(bio->bi_opf & REQ_NOWAIT)))
+				bio_wouldblock_error(bio);
+			else
+				bio_io_error(bio);
 		}
 		bio = bio_list_pop(&bio_list_on_stack[0]);
 	} while (bio);
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
index c4e2afb9d12d..ab14295d8468 100644
--- a/block/blk-mq-sched.c
+++ b/block/blk-mq-sched.c
@@ -83,6 +83,9 @@ struct request *blk_mq_sched_get_request(struct request_queue *q,
 	if (likely(!data->hctx))
 		data->hctx = blk_mq_map_queue(q, data->ctx->cpu);
 
+	if (op & REQ_NOWAIT)
+		data->flags |= BLK_MQ_REQ_NOWAIT;
+
 	if (e) {
 		data->flags |= BLK_MQ_REQ_INTERNAL;
 
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 359d2dc0d414..387fc8e8a2ba 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1498,6 +1498,8 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 	rq = blk_mq_sched_get_request(q, bio, bio->bi_opf, &data);
 	if (unlikely(!rq)) {
 		__wbt_done(q->rq_wb, wb_acct);
+		if (bio->bi_opf & REQ_NOWAIT)
+			bio_wouldblock_error(bio);
 		return BLK_QC_T_NONE;
 	}
 
diff --git a/fs/direct-io.c b/fs/direct-io.c
index e8baaabebf13..c87077d1dc33 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -479,8 +479,12 @@ static blk_status_t dio_bio_complete(struct dio *dio, struct bio *bio)
 	unsigned i;
 	blk_status_t err = bio->bi_status;
 
-	if (err)
-		dio->io_error = -EIO;
+	if (err) {
+		if (err == BLK_STS_AGAIN && (bio->bi_opf & REQ_NOWAIT))
+			dio->io_error = -EAGAIN;
+		else
+			dio->io_error = -EIO;
+	}
 
 	if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty) {
 		bio_check_pages_dirty(bio);	/* transfers ownership */
@@ -1194,6 +1198,8 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
 	if (iov_iter_rw(iter) == WRITE) {
 		dio->op = REQ_OP_WRITE;
 		dio->op_flags = REQ_SYNC | REQ_IDLE;
+		if (iocb->ki_flags & IOCB_NOWAIT)
+			dio->op_flags |= REQ_NOWAIT;
 	} else {
 		dio->op = REQ_OP_READ;
 	}
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 9455aada1399..1eb47e8c6965 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -418,6 +418,12 @@ static inline void bio_io_error(struct bio *bio)
 	bio_endio(bio);
 }
 
+static inline void bio_wouldblock_error(struct bio *bio)
+{
+	bio->bi_status = BLK_STS_AGAIN;
+	bio_endio(bio);
+}
+
 struct request_queue;
 extern int bio_phys_segments(struct request_queue *, struct bio *);
 
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index dcd45b15a3a5..e210da6d14b8 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -36,6 +36,8 @@ typedef u8 __bitwise blk_status_t;
 /* hack for device mapper, don't use elsewhere: */
 #define BLK_STS_DM_REQUEUE    ((__force blk_status_t)11)
 
+#define BLK_STS_AGAIN		((__force blk_status_t)12)
+
 struct blk_issue_stat {
 	u64 stat;
 };
@@ -224,6 +226,7 @@ enum req_flag_bits {
 	/* command specific flags for REQ_OP_WRITE_ZEROES: */
 	__REQ_NOUNMAP,		/* do not free blocks when zeroing */
 
+	__REQ_NOWAIT,           /* Don't wait if request will block */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -242,6 +245,7 @@ enum req_flag_bits {
 #define REQ_BACKGROUND		(1ULL << __REQ_BACKGROUND)
 
 #define REQ_NOUNMAP		(1ULL << __REQ_NOUNMAP)
+#define REQ_NOWAIT		(1ULL << __REQ_NOWAIT)
 
 #define REQ_FAILFAST_MASK \
 	(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 08/10] ext4: nowait aio support
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
                   ` (6 preceding siblings ...)
  2017-06-19 16:33 ` [PATCH 07/10] block: return on congested block device Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 09/10] xfs: " Goldwyn Rodrigues
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

Return EAGAIN if any of the following checks fail for direct I/O:
  + i_rwsem is lockable
  + Writing beyond end of file (will trigger allocation)
  + Blocks are not allocated at the write location

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Reviewed-by: Jan Kara <jack@suse.cz>
---
 fs/ext4/file.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 02ce7e7bbdf5..25cd42baadea 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -216,7 +216,13 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 		return ext4_dax_write_iter(iocb, from);
 #endif
 
-	inode_lock(inode);
+	if (iocb->ki_flags & IOCB_NOWAIT) {
+		if (!inode_trylock(inode))
+			return -EAGAIN;
+	} else {
+		inode_lock(inode);
+	}
+
 	ret = ext4_write_checks(iocb, from);
 	if (ret <= 0)
 		goto out;
@@ -235,9 +241,15 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 
 	iocb->private = &overwrite;
 	/* Check whether we do a DIO overwrite or not */
-	if (o_direct && ext4_should_dioread_nolock(inode) && !unaligned_aio &&
-	    ext4_overwrite_io(inode, iocb->ki_pos, iov_iter_count(from)))
-		overwrite = 1;
+	if (o_direct && !unaligned_aio) {
+		if (ext4_overwrite_io(inode, iocb->ki_pos, iov_iter_count(from))) {
+			if (ext4_should_dioread_nolock(inode))
+				overwrite = 1;
+		} else if (iocb->ki_flags & IOCB_NOWAIT) {
+			ret = -EAGAIN;
+			goto out;
+		}
+	}
 
 	ret = __generic_file_write_iter(iocb, from);
 	inode_unlock(inode);
@@ -435,6 +447,10 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
 		if (ret < 0)
 			return ret;
 	}
+
+	/* Set the flags to support nowait AIO */
+	filp->f_mode |= FMODE_AIO_NOWAIT;
+
 	return dquot_file_open(inode, filp);
 }
 
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 09/10] xfs: nowait aio support
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
                   ` (7 preceding siblings ...)
  2017-06-19 16:33 ` [PATCH 08/10] ext4: nowait aio support Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 16:33 ` [PATCH 10/10] btrfs: " Goldwyn Rodrigues
  2017-06-19 23:15 ` [PATCH 0/10 v13] merge request: No wait AIO Jens Axboe
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

If IOCB_NOWAIT is set, bail if the i_rwsem is not lockable
immediately.

IF IOMAP_NOWAIT is set, return EAGAIN in xfs_file_iomap_begin
if it needs allocation either due to file extension, writing to a hole,
or COW or waiting for other DIOs to finish.

Return -EAGAIN if we don't have extent list in memory.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/xfs_file.c  | 20 +++++++++++++++-----
 fs/xfs/xfs_iomap.c | 22 ++++++++++++++++++++++
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 5fb5a0958a14..e159eb381d9f 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -541,8 +541,11 @@ xfs_file_dio_aio_write(
 		iolock = XFS_IOLOCK_SHARED;
 	}
 
-	xfs_ilock(ip, iolock);
-
+	if (!xfs_ilock_nowait(ip, iolock)) {
+		if (iocb->ki_flags & IOCB_NOWAIT)
+			return -EAGAIN;
+		xfs_ilock(ip, iolock);
+	}
 	ret = xfs_file_aio_write_checks(iocb, from, &iolock);
 	if (ret)
 		goto out;
@@ -553,9 +556,15 @@ xfs_file_dio_aio_write(
 	 * otherwise demote the lock if we had to take the exclusive lock
 	 * for other reasons in xfs_file_aio_write_checks.
 	 */
-	if (unaligned_io)
-		inode_dio_wait(inode);
-	else if (iolock == XFS_IOLOCK_EXCL) {
+	if (unaligned_io) {
+		/* If we are going to wait for other DIO to finish, bail */
+		if (iocb->ki_flags & IOCB_NOWAIT) {
+			if (atomic_read(&inode->i_dio_count))
+				return -EAGAIN;
+		} else {
+			inode_dio_wait(inode);
+		}
+	} else if (iolock == XFS_IOLOCK_EXCL) {
 		xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
 		iolock = XFS_IOLOCK_SHARED;
 	}
@@ -892,6 +901,7 @@ xfs_file_open(
 		return -EFBIG;
 	if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb)))
 		return -EIO;
+	file->f_mode |= FMODE_AIO_NOWAIT;
 	return 0;
 }
 
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 94e5bdf7304c..05dc87e8c1f5 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -995,6 +995,11 @@ xfs_file_iomap_begin(
 		lockmode = xfs_ilock_data_map_shared(ip);
 	}
 
+	if ((flags & IOMAP_NOWAIT) && !(ip->i_df.if_flags & XFS_IFEXTENTS)) {
+		error = -EAGAIN;
+		goto out_unlock;
+	}
+
 	ASSERT(offset <= mp->m_super->s_maxbytes);
 	if ((xfs_fsize_t)offset + length > mp->m_super->s_maxbytes)
 		length = mp->m_super->s_maxbytes - offset;
@@ -1016,6 +1021,15 @@ xfs_file_iomap_begin(
 
 	if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
 		if (flags & IOMAP_DIRECT) {
+			/*
+			 * A reflinked inode will result in CoW alloc.
+			 * FIXME: It could still overwrite on unshared extents
+			 * and not need allocation.
+			 */
+			if (flags & IOMAP_NOWAIT) {
+				error = -EAGAIN;
+				goto out_unlock;
+			}
 			/* may drop and re-acquire the ilock */
 			error = xfs_reflink_allocate_cow(ip, &imap, &shared,
 					&lockmode);
@@ -1033,6 +1047,14 @@ xfs_file_iomap_begin(
 
 	if ((flags & IOMAP_WRITE) && imap_needs_alloc(inode, &imap, nimaps)) {
 		/*
+		 * If nowait is set bail since we are going to make
+		 * allocations.
+		 */
+		if (flags & IOMAP_NOWAIT) {
+			error = -EAGAIN;
+			goto out_unlock;
+		}
+		/*
 		 * We cap the maximum length we map here to MAX_WRITEBACK_PAGES
 		 * pages to keep the chunks of work done where somewhat symmetric
 		 * with the work writeback does. This is a completely arbitrary
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 10/10] btrfs: nowait aio support
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
                   ` (8 preceding siblings ...)
  2017-06-19 16:33 ` [PATCH 09/10] xfs: " Goldwyn Rodrigues
@ 2017-06-19 16:33 ` Goldwyn Rodrigues
  2017-06-19 23:15 ` [PATCH 0/10 v13] merge request: No wait AIO Jens Axboe
  10 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 16:33 UTC (permalink / raw)
  To: axboe; +Cc: viro, hch, jack, akpm, linux-block, Goldwyn Rodrigues

From: Goldwyn Rodrigues <rgoldwyn@suse.com>

Return EAGAIN if any of the following checks fail
 + i_rwsem is not lockable
 + NODATACOW or PREALLOC is not set
 + Cannot nocow at the desired location
 + Writing beyond end of file which is not allocated

Acked-by: David Sterba <dsterba@suse.com>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/btrfs/file.c  | 33 +++++++++++++++++++++++++++------
 fs/btrfs/inode.c |  3 +++
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index da1096eb1a40..59e2dccdf75b 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1875,12 +1875,29 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
 	ssize_t num_written = 0;
 	bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host);
 	ssize_t err;
-	loff_t pos;
-	size_t count;
+	loff_t pos = iocb->ki_pos;
+	size_t count = iov_iter_count(from);
 	loff_t oldsize;
 	int clean_page = 0;
 
-	inode_lock(inode);
+	if ((iocb->ki_flags & IOCB_NOWAIT) &&
+			(iocb->ki_flags & IOCB_DIRECT)) {
+		/* Don't sleep on inode rwsem */
+		if (!inode_trylock(inode))
+			return -EAGAIN;
+		/*
+		 * We will allocate space in case nodatacow is not set,
+		 * so bail
+		 */
+		if (!(BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
+					      BTRFS_INODE_PREALLOC)) ||
+		    check_can_nocow(BTRFS_I(inode), pos, &count) <= 0) {
+			inode_unlock(inode);
+			return -EAGAIN;
+		}
+	} else
+		inode_lock(inode);
+
 	err = generic_write_checks(iocb, from);
 	if (err <= 0) {
 		inode_unlock(inode);
@@ -1914,8 +1931,6 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
 	 */
 	update_time_for_write(inode);
 
-	pos = iocb->ki_pos;
-	count = iov_iter_count(from);
 	start_pos = round_down(pos, fs_info->sectorsize);
 	oldsize = i_size_read(inode);
 	if (start_pos > oldsize) {
@@ -3071,13 +3086,19 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence)
 	return offset;
 }
 
+static int btrfs_file_open(struct inode *inode, struct file *filp)
+{
+	filp->f_mode |= FMODE_AIO_NOWAIT;
+	return generic_file_open(inode, filp);
+}
+
 const struct file_operations btrfs_file_operations = {
 	.llseek		= btrfs_file_llseek,
 	.read_iter      = generic_file_read_iter,
 	.splice_read	= generic_file_splice_read,
 	.write_iter	= btrfs_file_write_iter,
 	.mmap		= btrfs_file_mmap,
-	.open		= generic_file_open,
+	.open		= btrfs_file_open,
 	.release	= btrfs_release_file,
 	.fsync		= btrfs_sync_file,
 	.fallocate	= btrfs_fallocate,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index f942293dd7e7..556c93060606 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8754,6 +8754,9 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 			dio_data.overwrite = 1;
 			inode_unlock(inode);
 			relock = true;
+		} else if (iocb->ki_flags & IOCB_NOWAIT) {
+			ret = -EAGAIN;
+			goto out;
 		}
 		ret = btrfs_delalloc_reserve_space(inode, offset, count);
 		if (ret)
-- 
2.12.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 05/10] fs: return if direct I/O will trigger writeback
  2017-06-19 16:33 ` [PATCH 05/10] fs: return if direct I/O will trigger writeback Goldwyn Rodrigues
@ 2017-06-19 16:44   ` Al Viro
  0 siblings, 0 replies; 19+ messages in thread
From: Al Viro @ 2017-06-19 16:44 UTC (permalink / raw)
  To: Goldwyn Rodrigues; +Cc: axboe, hch, jack, akpm, linux-block, Goldwyn Rodrigues

On Mon, Jun 19, 2017 at 11:33:43AM -0500, Goldwyn Rodrigues wrote:
> From: Goldwyn Rodrigues <rgoldwyn@suse.com>
> 
> Find out if the I/O will trigger a wait due to writeback. If yes,
> return -EAGAIN.
> 
> Return -EINVAL for buffered AIO: there are multiple causes of
> delay such as page locks, dirty throttling logic, page loading
> from disk etc. which cannot be taken care of.
> 

I don't believe that generic_file_read_iter() is sufficient.  Consider
ext4_file_read_iter() -> ext4_dax_read_iter():
static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
        struct inode *inode = file_inode(iocb->ki_filp);
        ssize_t ret;

        inode_lock_shared(inode);

IOW, your ext4 patch is missing a chunk.  I hadn't checked xfs one...

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/10 v13] merge request: No wait AIO
  2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
                   ` (9 preceding siblings ...)
  2017-06-19 16:33 ` [PATCH 10/10] btrfs: " Goldwyn Rodrigues
@ 2017-06-19 23:15 ` Jens Axboe
  2017-06-19 23:20   ` Goldwyn Rodrigues
  2017-06-19 23:34   ` Al Viro
  10 siblings, 2 replies; 19+ messages in thread
From: Jens Axboe @ 2017-06-19 23:15 UTC (permalink / raw)
  To: Goldwyn Rodrigues; +Cc: viro, hch, jack, akpm, linux-block

On 06/19/2017 10:33 AM, Goldwyn Rodrigues wrote:
> Jens,
> 
> As Christoph suggested, I am sending the patches against the block
> tree for merge since the block layer changes had the most conflicts.
> My tree is at https://github.com/goldwynr/linux/tree/nowait-block

I can merge it for 4.13, but I need Al to be happy with it first.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/10 v13] merge request: No wait AIO
  2017-06-19 23:15 ` [PATCH 0/10 v13] merge request: No wait AIO Jens Axboe
@ 2017-06-19 23:20   ` Goldwyn Rodrigues
  2017-06-19 23:34   ` Al Viro
  1 sibling, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-19 23:20 UTC (permalink / raw)
  To: Jens Axboe; +Cc: viro, hch, jack, akpm, linux-block



On 06/19/2017 06:15 PM, Jens Axboe wrote:
> On 06/19/2017 10:33 AM, Goldwyn Rodrigues wrote:
>> Jens,
>>
>> As Christoph suggested, I am sending the patches against the block
>> tree for merge since the block layer changes had the most conflicts.
>> My tree is at https://github.com/goldwynr/linux/tree/nowait-block
> 
> I can merge it for 4.13, but I need Al to be happy with it first.
> 

I understand. I am working on another version to include support for dax
files. I will post the updated patches shortly.

-- 
Goldwyn

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/10 v13] merge request: No wait AIO
  2017-06-19 23:15 ` [PATCH 0/10 v13] merge request: No wait AIO Jens Axboe
  2017-06-19 23:20   ` Goldwyn Rodrigues
@ 2017-06-19 23:34   ` Al Viro
  2017-06-19 23:36     ` Jens Axboe
  1 sibling, 1 reply; 19+ messages in thread
From: Al Viro @ 2017-06-19 23:34 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Goldwyn Rodrigues, hch, jack, akpm, linux-block

On Mon, Jun 19, 2017 at 05:15:16PM -0600, Jens Axboe wrote:
> On 06/19/2017 10:33 AM, Goldwyn Rodrigues wrote:
> > Jens,
> > 
> > As Christoph suggested, I am sending the patches against the block
> > tree for merge since the block layer changes had the most conflicts.
> > My tree is at https://github.com/goldwynr/linux/tree/nowait-block
> 
> I can merge it for 4.13, but I need Al to be happy with it first.

FWIW, it's really a matter of who gets more conflicts - I'm OK with the
general shape of that code and it could go through either tree (or both,
for that matter, if an immutable branch is promised).

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/10 v13] merge request: No wait AIO
  2017-06-19 23:34   ` Al Viro
@ 2017-06-19 23:36     ` Jens Axboe
  2017-06-20  0:24       ` Al Viro
  0 siblings, 1 reply; 19+ messages in thread
From: Jens Axboe @ 2017-06-19 23:36 UTC (permalink / raw)
  To: Al Viro; +Cc: Goldwyn Rodrigues, hch, jack, akpm, linux-block

On 06/19/2017 05:34 PM, Al Viro wrote:
> On Mon, Jun 19, 2017 at 05:15:16PM -0600, Jens Axboe wrote:
>> On 06/19/2017 10:33 AM, Goldwyn Rodrigues wrote:
>>> Jens,
>>>
>>> As Christoph suggested, I am sending the patches against the block
>>> tree for merge since the block layer changes had the most conflicts.
>>> My tree is at https://github.com/goldwynr/linux/tree/nowait-block
>>
>> I can merge it for 4.13, but I need Al to be happy with it first.
> 
> FWIW, it's really a matter of who gets more conflicts - I'm OK with the
> general shape of that code and it could go through either tree (or both,
> for that matter, if an immutable branch is promised).

I'm still hopeful that the write hint patchset will make it as well,
which will definitely conflict with this. So if you don't mind, I'd
like to queue it through the block tree. The block for-4.x/ branches
are not rebased.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/10 v13] merge request: No wait AIO
  2017-06-19 23:36     ` Jens Axboe
@ 2017-06-20  0:24       ` Al Viro
  2017-06-20  7:20         ` Christoph Hellwig
  0 siblings, 1 reply; 19+ messages in thread
From: Al Viro @ 2017-06-20  0:24 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Goldwyn Rodrigues, hch, jack, akpm, linux-block

On Mon, Jun 19, 2017 at 05:36:05PM -0600, Jens Axboe wrote:
> On 06/19/2017 05:34 PM, Al Viro wrote:
> > On Mon, Jun 19, 2017 at 05:15:16PM -0600, Jens Axboe wrote:
> >> On 06/19/2017 10:33 AM, Goldwyn Rodrigues wrote:
> >>> Jens,
> >>>
> >>> As Christoph suggested, I am sending the patches against the block
> >>> tree for merge since the block layer changes had the most conflicts.
> >>> My tree is at https://github.com/goldwynr/linux/tree/nowait-block
> >>
> >> I can merge it for 4.13, but I need Al to be happy with it first.
> > 
> > FWIW, it's really a matter of who gets more conflicts - I'm OK with the
> > general shape of that code and it could go through either tree (or both,
> > for that matter, if an immutable branch is promised).
> 
> I'm still hopeful that the write hint patchset will make it as well,
> which will definitely conflict with this. So if you don't mind, I'd
> like to queue it through the block tree. The block for-4.x/ branches
> are not rebased.

Fine by me; the only problem I see there at the moment is with ext4 and
xfs ->read_iter() not buggering off on nowait (xfs one has
        xfs_ilock(ip, XFS_IOLOCK_SHARED);
done before it gets to generic_file_read_iter()).

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/10 v13] merge request: No wait AIO
  2017-06-20  0:24       ` Al Viro
@ 2017-06-20  7:20         ` Christoph Hellwig
  2017-06-20 11:53           ` Goldwyn Rodrigues
  0 siblings, 1 reply; 19+ messages in thread
From: Christoph Hellwig @ 2017-06-20  7:20 UTC (permalink / raw)
  To: Al Viro; +Cc: Jens Axboe, Goldwyn Rodrigues, hch, jack, akpm, linux-block

On Tue, Jun 20, 2017 at 01:24:28AM +0100, Al Viro wrote:
> On Mon, Jun 19, 2017 at 05:36:05PM -0600, Jens Axboe wrote:
> > On 06/19/2017 05:34 PM, Al Viro wrote:
> > > On Mon, Jun 19, 2017 at 05:15:16PM -0600, Jens Axboe wrote:
> > >> On 06/19/2017 10:33 AM, Goldwyn Rodrigues wrote:
> > >>> Jens,
> > >>>
> > >>> As Christoph suggested, I am sending the patches against the block
> > >>> tree for merge since the block layer changes had the most conflicts.
> > >>> My tree is at https://github.com/goldwynr/linux/tree/nowait-block
> > >>
> > >> I can merge it for 4.13, but I need Al to be happy with it first.
> > > 
> > > FWIW, it's really a matter of who gets more conflicts - I'm OK with the
> > > general shape of that code and it could go through either tree (or both,
> > > for that matter, if an immutable branch is promised).
> > 
> > I'm still hopeful that the write hint patchset will make it as well,
> > which will definitely conflict with this. So if you don't mind, I'd
> > like to queue it through the block tree. The block for-4.x/ branches
> > are not rebased.
> 
> Fine by me; the only problem I see there at the moment is with ext4 and
> xfs ->read_iter() not buggering off on nowait (xfs one has
>         xfs_ilock(ip, XFS_IOLOCK_SHARED);
> done before it gets to generic_file_read_iter()).

Something like the patch below should take care of the XFS, free feel
to fold.


diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index e159eb381d9f..c74847f71b3d 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -216,7 +216,11 @@ xfs_file_dio_aio_read(
 
 	file_accessed(iocb->ki_filp);
 
-	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
+		if (iocb->ki_flags & IOCB_NOWAIT)
+			return -EAGAIN;
+		xfs_ilock(ip, XFS_IOLOCK_SHARED);
+	}
 	ret = iomap_dio_rw(iocb, to, &xfs_iomap_ops, NULL);
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
@@ -237,7 +241,11 @@ xfs_file_dax_read(
 	if (!count)
 		return 0; /* skip atime */
 
-	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
+		if (iocb->ki_flags & IOCB_NOWAIT)
+			return -EAGAIN;
+		xfs_ilock(ip, XFS_IOLOCK_SHARED);
+	}
 	ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops);
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/10 v13] merge request: No wait AIO
  2017-06-20  7:20         ` Christoph Hellwig
@ 2017-06-20 11:53           ` Goldwyn Rodrigues
  0 siblings, 0 replies; 19+ messages in thread
From: Goldwyn Rodrigues @ 2017-06-20 11:53 UTC (permalink / raw)
  To: Christoph Hellwig, Al Viro; +Cc: Jens Axboe, jack, akpm, linux-block



On 06/20/2017 02:20 AM, Christoph Hellwig wrote:
> On Tue, Jun 20, 2017 at 01:24:28AM +0100, Al Viro wrote:
>> On Mon, Jun 19, 2017 at 05:36:05PM -0600, Jens Axboe wrote:
>>> On 06/19/2017 05:34 PM, Al Viro wrote:
>>>> On Mon, Jun 19, 2017 at 05:15:16PM -0600, Jens Axboe wrote:
>>>>> On 06/19/2017 10:33 AM, Goldwyn Rodrigues wrote:
>>>>>> Jens,
>>>>>>
>>>>>> As Christoph suggested, I am sending the patches against the block
>>>>>> tree for merge since the block layer changes had the most conflicts.
>>>>>> My tree is at https://github.com/goldwynr/linux/tree/nowait-block
>>>>>
>>>>> I can merge it for 4.13, but I need Al to be happy with it first.
>>>>
>>>> FWIW, it's really a matter of who gets more conflicts - I'm OK with the
>>>> general shape of that code and it could go through either tree (or both,
>>>> for that matter, if an immutable branch is promised).
>>>
>>> I'm still hopeful that the write hint patchset will make it as well,
>>> which will definitely conflict with this. So if you don't mind, I'd
>>> like to queue it through the block tree. The block for-4.x/ branches
>>> are not rebased.
>>
>> Fine by me; the only problem I see there at the moment is with ext4 and
>> xfs ->read_iter() not buggering off on nowait (xfs one has
>>         xfs_ilock(ip, XFS_IOLOCK_SHARED);
>> done before it gets to generic_file_read_iter()).
> 
> Something like the patch below should take care of the XFS, free feel
> to fold.
> 

I had missed on the dax support completely so I added a chunk for
xfs_file_dax_write() as well (and also ext4). Patches coming shortly,
after their usual round of testing. They are pushed onto
https://github.com/goldwynr/linux/tree/nowait-block

> 
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index e159eb381d9f..c74847f71b3d 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -216,7 +216,11 @@ xfs_file_dio_aio_read(
>  
>  	file_accessed(iocb->ki_filp);
>  
> -	xfs_ilock(ip, XFS_IOLOCK_SHARED);
> +	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
> +		if (iocb->ki_flags & IOCB_NOWAIT)
> +			return -EAGAIN;
> +		xfs_ilock(ip, XFS_IOLOCK_SHARED);
> +	}
>  	ret = iomap_dio_rw(iocb, to, &xfs_iomap_ops, NULL);
>  	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
>  
> @@ -237,7 +241,11 @@ xfs_file_dax_read(
>  	if (!count)
>  		return 0; /* skip atime */
>  
> -	xfs_ilock(ip, XFS_IOLOCK_SHARED);
> +	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
> +		if (iocb->ki_flags & IOCB_NOWAIT)
> +			return -EAGAIN;
> +		xfs_ilock(ip, XFS_IOLOCK_SHARED);
> +	}
>  	ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops);
>  	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
>  
> 

-- 
Goldwyn

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2017-06-20 11:53 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-19 16:33 [PATCH 0/10 v13] merge request: No wait AIO Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 01/10] fs: Separate out kiocb flags setup based on RWF_* flags Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 02/10] fs: Introduce filemap_range_has_page() Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 03/10] fs: Use RWF_* flags for AIO operations Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 04/10] fs: Introduce RWF_NOWAIT and FMODE_AIO_NOWAIT Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 05/10] fs: return if direct I/O will trigger writeback Goldwyn Rodrigues
2017-06-19 16:44   ` Al Viro
2017-06-19 16:33 ` [PATCH 06/10] fs: Introduce IOMAP_NOWAIT Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 07/10] block: return on congested block device Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 08/10] ext4: nowait aio support Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 09/10] xfs: " Goldwyn Rodrigues
2017-06-19 16:33 ` [PATCH 10/10] btrfs: " Goldwyn Rodrigues
2017-06-19 23:15 ` [PATCH 0/10 v13] merge request: No wait AIO Jens Axboe
2017-06-19 23:20   ` Goldwyn Rodrigues
2017-06-19 23:34   ` Al Viro
2017-06-19 23:36     ` Jens Axboe
2017-06-20  0:24       ` Al Viro
2017-06-20  7:20         ` Christoph Hellwig
2017-06-20 11:53           ` Goldwyn Rodrigues

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.