@@ -315,6 +315,7 @@ enum rw_hint {
#define IOCB_SYNC (1 << 5)
#define IOCB_WRITE (1 << 6)
#define IOCB_NOWAIT (1 << 7)
+#define IOCB_CACHED (1 << 8)
struct kiocb {
struct file *ki_filp;
@@ -2028,7 +2028,7 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
page = find_get_page(mapping, index);
if (!page) {
- if (iocb->ki_flags & IOCB_NOWAIT)
+ if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_CACHED))
goto would_block;
page_cache_sync_readahead(mapping,
ra, filp,
@@ -2038,12 +2038,17 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
goto no_cached_page;
}
if (PageReadahead(page)) {
+ if (iocb->ki_flags & IOCB_CACHED) {
+ put_page(page);
+ error = -ECANCELED;
+ goto out;
+ }
page_cache_async_readahead(mapping,
ra, filp, page,
index, last_index - index);
}
if (!PageUptodate(page)) {
- if (iocb->ki_flags & IOCB_NOWAIT) {
+ if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_CACHED)) {
put_page(page);
goto would_block;
}
@@ -2249,6 +2254,13 @@ EXPORT_SYMBOL_GPL(generic_file_buffered_read);
*
* This is the "read_iter()" routine for all filesystems
* that can use the page cache directly.
+ *
+ * In the IOCB_NOWAIT flag in iocb->ki_flags indicates that -EAGAIN should be
+ * returned if completing the request would require I/O; this does not prevent
+ * readahead. The IOCB_CACHED flag indicates that -EAGAIN should be returned
+ * as under the IOCB_NOWAIT flag, and that -ECANCELED should be returned when
+ * readhead would be triggered.
+ *
* Return:
* * number of bytes copied, even for partial reads
* * negative error code if nothing was read
Add an IOCB_CACHED flag which indicates to generic_file_read_iter that it should only regard the page cache, without triggering any filesystem I/O for the actual request or for readahead. With this flag, -EAGAIN is returned when regular I/O would be triggered similar to the IOCB_NOWAIT flag, and -ECANCELED is returned when readahead would be triggered. This allows the caller to perform a tentative read out of the page cache, and to retry the read if the requested pages are not cached. Please see the next commit for what this is used for. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> --- include/linux/fs.h | 1 + mm/filemap.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-)