Commit 1a0a7853 authored by Jens Axboe's avatar Jens Axboe
Browse files

mm: support async buffered reads in generic_file_buffered_read()



Use the async page locking infrastructure, if IOCB_WAITQ is set in the
passed in iocb. The caller must expect an -EIOCBQUEUED return value,
which means that IO is started but not done yet. This is similar to how
O_DIRECT signals the same operation. Once the callback is received by
the caller for IO completion, the caller must retry the operation.

Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent dd3e6d50
Loading
Loading
Loading
Loading
+27 −11
Original line number Diff line number Diff line
@@ -1210,6 +1210,14 @@ static int __wait_on_page_locked_async(struct page *page,
	return ret;
}

static int wait_on_page_locked_async(struct page *page,
				     struct wait_page_queue *wait)
{
	if (!PageLocked(page))
		return 0;
	return __wait_on_page_locked_async(compound_head(page), wait, false);
}

/**
 * put_and_wait_on_page_locked - Drop a reference and wait for it to be unlocked
 * @page: The page to wait for.
@@ -2049,17 +2057,25 @@ find_page:
					index, last_index - index);
		}
		if (!PageUptodate(page)) {
			if (iocb->ki_flags & IOCB_NOWAIT) {
				put_page(page);
				goto would_block;
			}

			/*
			 * See comment in do_read_cache_page on why
			 * wait_on_page_locked is used to avoid unnecessarily
			 * serialisations and why it's safe.
			 */
			if (iocb->ki_flags & IOCB_WAITQ) {
				if (written) {
					put_page(page);
					goto out;
				}
				error = wait_on_page_locked_async(page,
								iocb->ki_waitq);
			} else {
				if (iocb->ki_flags & IOCB_NOWAIT) {
					put_page(page);
					goto would_block;
				}
				error = wait_on_page_locked_killable(page);
			}
			if (unlikely(error))
				goto readpage_error;
			if (PageUptodate(page))
@@ -2147,6 +2163,9 @@ page_ok:

page_not_up_to_date:
		/* Get exclusive access to the page ... */
		if (iocb->ki_flags & IOCB_WAITQ)
			error = lock_page_async(page, iocb->ki_waitq);
		else
			error = lock_page_killable(page);
		if (unlikely(error))
			goto readpage_error;
@@ -2190,9 +2209,6 @@ readpage:
		}

		if (!PageUptodate(page)) {
			if (iocb->ki_flags & IOCB_WAITQ)
				error = lock_page_async(page, iocb->ki_waitq);
			else
			error = lock_page_killable(page);
			if (unlikely(error))
				goto readpage_error;