Readahead support for IOCB_NOWAIT was introduced in commit 2e85abf053b9 ("mm: allow read-ahead with IOCB_NOWAIT set"). However, this behavior was altered in commit efa8480a8316 ("fs: RWF_NOWAIT should imply IOCB_NOIO") to prevent potential blocking during memory reclamation. To address the blocking issue during memory reclamation, we can use memalloc_nowait_{save,restore} to ensure non-blocking behavior. With this change, we can restore the original functionality, allowing preadv2(IOCB_NOWAIT) to read data directly from the disk if it's not already in the page cache. Link: https://lore.gnuweeb.org/io-uring/20200624164127.GP21350@xxxxxxxxxxxxxxxxxxxx/ Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> Cc: Jens Axboe <axboe@xxxxxxxxx> Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> Cc: Dave Chinner <david@xxxxxxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Cc: Christian Brauner <brauner@xxxxxxxxxx> --- include/linux/fs.h | 1 - mm/filemap.c | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index fd34b5755c0b..ced74b1b350d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3455,7 +3455,6 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags, if (flags & RWF_NOWAIT) { if (!(ki->ki_filp->f_mode & FMODE_NOWAIT)) return -EOPNOTSUPP; - kiocb_flags |= IOCB_NOIO; } if (flags & RWF_ATOMIC) { if (rw_type != WRITE) diff --git a/mm/filemap.c b/mm/filemap.c index 657bcd887fdb..93c690e1d1fd 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -46,6 +46,7 @@ #include <linux/pipe_fs_i.h> #include <linux/splice.h> #include <linux/rcupdate_wait.h> +#include <linux/sched/mm.h> #include <asm/pgalloc.h> #include <asm/tlbflush.h> #include "internal.h" @@ -2514,6 +2515,7 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, pgoff_t index = iocb->ki_pos >> PAGE_SHIFT; pgoff_t last_index; struct folio *folio; + unsigned int flags; int err = 0; /* "last_index" is the index of the page beyond the end of the read */ @@ -2526,8 +2528,12 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, if (!folio_batch_count(fbatch)) { if (iocb->ki_flags & IOCB_NOIO) return -EAGAIN; + if (iocb->ki_flags & IOCB_NOWAIT) + flags = memalloc_nowait_save(); page_cache_sync_readahead(mapping, ra, filp, index, last_index - index); + if (iocb->ki_flags & IOCB_NOWAIT) + memalloc_nowait_restore(flags); filemap_get_read_batch(mapping, index, last_index - 1, fbatch); } if (!folio_batch_count(fbatch)) { -- 2.43.5