Skip to content

Commit 1a0a785

Browse files
committed
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: Johannes Weiner <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent dd3e6d5 commit 1a0a785

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

mm/filemap.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,14 @@ static int __wait_on_page_locked_async(struct page *page,
12101210
return ret;
12111211
}
12121212

1213+
static int wait_on_page_locked_async(struct page *page,
1214+
struct wait_page_queue *wait)
1215+
{
1216+
if (!PageLocked(page))
1217+
return 0;
1218+
return __wait_on_page_locked_async(compound_head(page), wait, false);
1219+
}
1220+
12131221
/**
12141222
* put_and_wait_on_page_locked - Drop a reference and wait for it to be unlocked
12151223
* @page: The page to wait for.
@@ -2049,17 +2057,25 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
20492057
index, last_index - index);
20502058
}
20512059
if (!PageUptodate(page)) {
2052-
if (iocb->ki_flags & IOCB_NOWAIT) {
2053-
put_page(page);
2054-
goto would_block;
2055-
}
2056-
20572060
/*
20582061
* See comment in do_read_cache_page on why
20592062
* wait_on_page_locked is used to avoid unnecessarily
20602063
* serialisations and why it's safe.
20612064
*/
2062-
error = wait_on_page_locked_killable(page);
2065+
if (iocb->ki_flags & IOCB_WAITQ) {
2066+
if (written) {
2067+
put_page(page);
2068+
goto out;
2069+
}
2070+
error = wait_on_page_locked_async(page,
2071+
iocb->ki_waitq);
2072+
} else {
2073+
if (iocb->ki_flags & IOCB_NOWAIT) {
2074+
put_page(page);
2075+
goto would_block;
2076+
}
2077+
error = wait_on_page_locked_killable(page);
2078+
}
20632079
if (unlikely(error))
20642080
goto readpage_error;
20652081
if (PageUptodate(page))
@@ -2147,7 +2163,10 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
21472163

21482164
page_not_up_to_date:
21492165
/* Get exclusive access to the page ... */
2150-
error = lock_page_killable(page);
2166+
if (iocb->ki_flags & IOCB_WAITQ)
2167+
error = lock_page_async(page, iocb->ki_waitq);
2168+
else
2169+
error = lock_page_killable(page);
21512170
if (unlikely(error))
21522171
goto readpage_error;
21532172

@@ -2190,10 +2209,7 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
21902209
}
21912210

21922211
if (!PageUptodate(page)) {
2193-
if (iocb->ki_flags & IOCB_WAITQ)
2194-
error = lock_page_async(page, iocb->ki_waitq);
2195-
else
2196-
error = lock_page_killable(page);
2212+
error = lock_page_killable(page);
21972213
if (unlikely(error))
21982214
goto readpage_error;
21992215
if (!PageUptodate(page)) {

0 commit comments

Comments
 (0)