Re: [PATCHSET v5 0/12] Add support for async buffered reads

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 6/1/20 7:35 AM, Sedat Dilek wrote:
> Hi Jens,
> 
> with Linux v5.7 final I switched to linux-block.git/for-next and reverted...
> 
> "block: read-ahead submission should imply no-wait as well"
> 
> ...and see no boot-slowdowns.

Can you try with these patches applied instead? Or pull my async-readahead
branch from the same location.

-- 
Jens Axboe

>From 297f4d794780f7f55180fb0de6692bd1a1d81c58 Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@xxxxxxxxx>
Date: Sun, 31 May 2020 21:31:08 -0600
Subject: [PATCH 6/6] Revert "block: read-ahead submission should imply no-wait
 as well"

This reverts commit 381000ebbf4fed96c206571a04511c0667e38e18.
---
 include/linux/blk_types.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index c296463c15eb..ccb895f911b1 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -374,8 +374,7 @@ enum req_flag_bits {
 #define REQ_INTEGRITY		(1ULL << __REQ_INTEGRITY)
 #define REQ_FUA			(1ULL << __REQ_FUA)
 #define REQ_PREFLUSH		(1ULL << __REQ_PREFLUSH)
-#define REQ_RAHEAD		\
-	((1ULL << __REQ_RAHEAD) | (1ULL << __REQ_NOWAIT))
+#define REQ_RAHEAD		(1ULL << __REQ_RAHEAD)
 #define REQ_BACKGROUND		(1ULL << __REQ_BACKGROUND)
 #define REQ_NOWAIT		(1ULL << __REQ_NOWAIT)
 #define REQ_CGROUP_PUNT		(1ULL << __REQ_CGROUP_PUNT)
-- 
2.26.2

>From ffbf3c623a4835c388296d52d82ee7abe75535cf Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@xxxxxxxxx>
Date: Sun, 31 May 2020 20:53:26 -0600
Subject: [PATCH 5/6] fs: make mpage_readpages() take a struct kiocb argument

The callers already have it, so just pass it in. Have mpage_readpages()
set REQ_NOWAIT, if IOCB_NOWAIT is set in the iocb.

Signed-off-by: Jens Axboe <axboe@xxxxxxxxx>
---
 fs/block_dev.c        |  2 +-
 fs/exfat/inode.c      |  2 +-
 fs/ext2/inode.c       |  2 +-
 fs/fat/inode.c        |  2 +-
 fs/gfs2/aops.c        |  2 +-
 fs/hpfs/file.c        |  2 +-
 fs/isofs/inode.c      |  2 +-
 fs/jfs/inode.c        |  2 +-
 fs/mpage.c            | 17 +++++++++++++----
 fs/nilfs2/inode.c     |  2 +-
 fs/ocfs2/aops.c       |  2 +-
 fs/omfs/file.c        |  2 +-
 fs/qnx6/inode.c       |  2 +-
 fs/reiserfs/inode.c   |  2 +-
 fs/udf/inode.c        |  2 +-
 include/linux/mpage.h |  5 +++--
 16 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 87a540b42fa7..bbc1bd8078d6 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -617,7 +617,7 @@ static int blkdev_readpage(struct file * file, struct page * page)
 static int blkdev_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, blkdev_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, blkdev_get_block);
 }
 
 static int blkdev_write_begin(struct file *file, struct address_space *mapping,
diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
index 9905307dfba2..a7757edf5534 100644
--- a/fs/exfat/inode.c
+++ b/fs/exfat/inode.c
@@ -375,7 +375,7 @@ static int exfat_readpage(struct file *file, struct page *page)
 static int exfat_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned int nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, exfat_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, exfat_get_block);
 }
 
 static int exfat_writepage(struct page *page, struct writeback_control *wbc)
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 3843900d6251..706fc2628a3a 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -881,7 +881,7 @@ static int
 ext2_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, ext2_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, ext2_get_block);
 }
 
 static int
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index ab9dfcbf1bd3..3c47485d7f83 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -213,7 +213,7 @@ static int fat_readpage(struct file *file, struct page *page)
 static int fat_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			 struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, fat_get_block);
 }
 
 static void fat_write_failed(struct address_space *mapping, loff_t to)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 37d18f82e5a1..3e26ca463ca3 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -608,7 +608,7 @@ static int gfs2_readpages(struct kiocb *kiocb, struct address_space *mapping,
 	if (unlikely(ret))
 		goto out_uninit;
 	if (!gfs2_is_stuffed(ip))
-		ret = mpage_readpages(mapping, pages, nr_pages, gfs2_block_map);
+		ret = mpage_readpages(mapping, kiocb, pages, nr_pages, gfs2_block_map);
 	gfs2_glock_dq(&gh);
 out_uninit:
 	gfs2_holder_uninit(&gh);
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 5b9c537d011c..21df02964219 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -128,7 +128,7 @@ static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
 static int hpfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			  struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, hpfs_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, hpfs_get_block);
 }
 
 static int hpfs_writepages(struct address_space *mapping,
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 071da59b7266..060e8dfbe1a2 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -1186,7 +1186,7 @@ static int isofs_readpage(struct file *file, struct page *page)
 static int isofs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, isofs_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, isofs_get_block);
 }
 
 static sector_t _isofs_bmap(struct address_space *mapping, sector_t block)
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 503e2e5cb79d..569e4f4123dd 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -299,7 +299,7 @@ static int jfs_readpage(struct file *file, struct page *page)
 static int jfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, jfs_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, jfs_get_block);
 }
 
 static void jfs_write_failed(struct address_space *mapping, loff_t to)
diff --git a/fs/mpage.c b/fs/mpage.c
index ccba3c4c4479..9148d1eae8ff 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -138,6 +138,7 @@ struct mpage_readpage_args {
 	struct page *page;
 	unsigned int nr_pages;
 	bool is_readahead;
+	bool nowait;
 	sector_t last_block_in_bio;
 	struct buffer_head map_bh;
 	unsigned long first_logical_block;
@@ -182,6 +183,8 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
 		op_flags = 0;
 		gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL);
 	}
+	if (args->nowait)
+		op_flags |= REQ_NOWAIT;
 
 	if (page_has_buffers(page))
 		goto confused;
@@ -382,12 +385,14 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args)
  * This all causes the disk requests to be issued in the correct order.
  */
 int
-mpage_readpages(struct address_space *mapping, struct list_head *pages,
-				unsigned nr_pages, get_block_t get_block)
+mpage_readpages(struct address_space *mapping, struct kiocb *kiocb,
+		struct list_head *pages, unsigned nr_pages,
+		get_block_t get_block)
 {
 	struct mpage_readpage_args args = {
 		.get_block = get_block,
 		.is_readahead = true,
+		.nowait = kiocb->ki_flags & IOCB_NOWAIT,
 	};
 	unsigned page_idx;
 
@@ -406,8 +411,12 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
 		put_page(page);
 	}
 	BUG_ON(!list_empty(pages));
-	if (args.bio)
-		mpage_bio_submit(REQ_OP_READ, REQ_RAHEAD, args.bio);
+	if (args.bio) {
+		int op = REQ_RAHEAD;
+		if (args.nowait)
+			op |= REQ_NOWAIT;
+		mpage_bio_submit(REQ_OP_READ, op, args.bio);
+	}
 	return 0;
 }
 EXPORT_SYMBOL(mpage_readpages);
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index a981c9404fbc..3cbc8b7284a4 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -156,7 +156,7 @@ static int nilfs_readpage(struct file *file, struct page *page)
 static int nilfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			   struct list_head *pages, unsigned int nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, nilfs_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, nilfs_get_block);
 }
 
 static int nilfs_writepages(struct address_space *mapping,
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index aa54b0d0d4a1..50ed84f53b20 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -388,7 +388,7 @@ static int ocfs2_readpages(struct kiocb *kiocb, struct address_space *mapping,
 	if (start >= i_size_read(inode))
 		goto out_unlock;
 
-	err = mpage_readpages(mapping, pages, nr_pages, ocfs2_get_block);
+	err = mpage_readpages(mapping, kiocb, pages, nr_pages, ocfs2_get_block);
 
 out_unlock:
 	up_read(&oi->ip_alloc_sem);
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
index 195bb390ba24..384e8c99fc4f 100644
--- a/fs/omfs/file.c
+++ b/fs/omfs/file.c
@@ -292,7 +292,7 @@ static int omfs_readpage(struct file *file, struct page *page)
 static int omfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, omfs_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, omfs_get_block);
 }
 
 static int omfs_writepage(struct page *page, struct writeback_control *wbc)
diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c
index c964fd63d4a5..ef603636ca2d 100644
--- a/fs/qnx6/inode.c
+++ b/fs/qnx6/inode.c
@@ -102,7 +102,7 @@ static int qnx6_readpage(struct file *file, struct page *page)
 static int qnx6_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		   struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, qnx6_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, qnx6_get_block);
 }
 
 /*
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 01d5ccdaa5b4..50c93c526557 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1164,7 +1164,7 @@ static int
 reiserfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		   struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, reiserfs_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, reiserfs_get_block);
 }
 
 /*
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index c541ca95f851..c45d4da5e707 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -198,7 +198,7 @@ static int udf_readpage(struct file *file, struct page *page)
 static int udf_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, udf_get_block);
+	return mpage_readpages(mapping, kiocb, pages, nr_pages, udf_get_block);
 }
 
 static int udf_write_begin(struct file *file, struct address_space *mapping,
diff --git a/include/linux/mpage.h b/include/linux/mpage.h
index 001f1fcf9836..f708c7a442ae 100644
--- a/include/linux/mpage.h
+++ b/include/linux/mpage.h
@@ -14,8 +14,9 @@
 
 struct writeback_control;
 
-int mpage_readpages(struct address_space *mapping, struct list_head *pages,
-				unsigned nr_pages, get_block_t get_block);
+int mpage_readpages(struct address_space *mapping, struct kiocb *kiocb,
+			struct list_head *pages, unsigned nr_pages,
+			get_block_t get_block);
 int mpage_readpage(struct page *page, get_block_t get_block);
 int mpage_writepages(struct address_space *mapping,
 		struct writeback_control *wbc, get_block_t get_block);
-- 
2.26.2

>From d17311d78f5d5ffa73cbdd5cbf925d0a4188807d Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@xxxxxxxxx>
Date: Sun, 31 May 2020 20:44:18 -0600
Subject: [PATCH 4/6] iomap: set REQ_NOWAIT on bio if IOCB_NOWAIT is set in
 kiocb

Signed-off-by: Jens Axboe <axboe@xxxxxxxxx>
---
 fs/iomap/buffered-io.c | 9 +++++++--
 fs/xfs/xfs_aops.c      | 3 ++-
 fs/zonefs/super.c      | 5 +++--
 include/linux/iomap.h  | 5 +++--
 4 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 89e21961d1ad..4558b455182f 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -215,6 +215,7 @@ struct iomap_readpage_ctx {
 	struct page		*cur_page;
 	bool			cur_page_in_bio;
 	bool			is_readahead;
+	bool			nowait;
 	struct bio		*bio;
 	struct list_head	*pages;
 };
@@ -321,6 +322,8 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 		ctx->bio->bi_opf = REQ_OP_READ;
 		if (ctx->is_readahead)
 			ctx->bio->bi_opf |= REQ_RAHEAD;
+		if (ctx->nowait)
+			ctx->bio->bi_opf |= REQ_NOWAIT;
 		ctx->bio->bi_iter.bi_sector = sector;
 		bio_set_dev(ctx->bio, iomap->bdev);
 		ctx->bio->bi_end_io = iomap_read_end_io;
@@ -432,12 +435,14 @@ iomap_readpages_actor(struct inode *inode, loff_t pos, loff_t length,
 }
 
 int
-iomap_readpages(struct address_space *mapping, struct list_head *pages,
-		unsigned nr_pages, const struct iomap_ops *ops)
+iomap_readpages(struct address_space *mapping, struct kiocb *kiocb,
+		struct list_head *pages, unsigned nr_pages,
+		const struct iomap_ops *ops)
 {
 	struct iomap_readpage_ctx ctx = {
 		.pages		= pages,
 		.is_readahead	= true,
+		.nowait		= kiocb->ki_flags & IOCB_NOWAIT,
 	};
 	loff_t pos = page_offset(list_entry(pages->prev, struct page, lru));
 	loff_t last = page_offset(list_entry(pages->next, struct page, lru));
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index bff9a2374ece..bc8ea7cd1441 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -628,7 +628,8 @@ xfs_vm_readpages(
 	struct list_head	*pages,
 	unsigned		nr_pages)
 {
-	return iomap_readpages(mapping, pages, nr_pages, &xfs_read_iomap_ops);
+	return iomap_readpages(mapping, kiocb, pages, nr_pages,
+				&xfs_read_iomap_ops);
 }
 
 static int
diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c
index 11812841a5fa..06b4f621a14a 100644
--- a/fs/zonefs/super.c
+++ b/fs/zonefs/super.c
@@ -79,10 +79,11 @@ static int zonefs_readpage(struct file *unused, struct page *page)
 	return iomap_readpage(page, &zonefs_iomap_ops);
 }
 
-static int zonefs_readpages(struct kiocb *unused, struct address_space *mapping,
+static int zonefs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			    struct list_head *pages, unsigned int nr_pages)
 {
-	return iomap_readpages(mapping, pages, nr_pages, &zonefs_iomap_ops);
+	return iomap_readpages(mapping, kiocb, pages, nr_pages,
+				&zonefs_iomap_ops);
 }
 
 /*
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 8b09463dae0d..6b5d802d7227 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -155,8 +155,9 @@ loff_t iomap_apply(struct inode *inode, loff_t pos, loff_t length,
 ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from,
 		const struct iomap_ops *ops);
 int iomap_readpage(struct page *page, const struct iomap_ops *ops);
-int iomap_readpages(struct address_space *mapping, struct list_head *pages,
-		unsigned nr_pages, const struct iomap_ops *ops);
+int iomap_readpages(struct address_space *mapping, struct kiocb *kiocb,
+		struct list_head *pages, unsigned nr_pages,
+		const struct iomap_ops *ops);
 int iomap_set_page_dirty(struct page *page);
 int iomap_is_partially_uptodate(struct page *page, unsigned long from,
 		unsigned long count);
-- 
2.26.2

>From 3a7284cf4ef7c762ac21ffb9644c04346f0f4a59 Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@xxxxxxxxx>
Date: Sun, 31 May 2020 20:26:34 -0600
Subject: [PATCH 3/6] mm: make generic_file_buffered_read() use iocb read-ahead
 helpers

Signed-off-by: Jens Axboe <axboe@xxxxxxxxx>
---
 mm/filemap.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index abdd3f32c932..eea40b5894fb 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2053,17 +2053,16 @@ static ssize_t generic_file_buffered_read(struct kiocb *iocb,
 
 		page = find_get_page(mapping, index);
 		if (!page) {
-			page_cache_sync_readahead(mapping,
-					ra, filp,
-					index, last_index - index);
+			__page_cache_sync_readahead(mapping, ra, iocb, index,
+							last_index - index);
 			page = find_get_page(mapping, index);
 			if (unlikely(page == NULL))
 				goto no_cached_page;
 		}
 		if (PageReadahead(page)) {
-			page_cache_async_readahead(mapping,
-					ra, filp, page,
-					index, last_index - index);
+			__page_cache_async_readahead(mapping, ra, iocb, page,
+							index,
+							last_index - index);
 		}
 		if (!PageUptodate(page)) {
 			/*
-- 
2.26.2

>From 72dfe63dd44979d182be741d2446d364546c5df5 Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@xxxxxxxxx>
Date: Sun, 31 May 2020 20:25:04 -0600
Subject: [PATCH 2/6] mm: provide read-ahead helpers that take a struct kiocb

Signed-off-by: Jens Axboe <axboe@xxxxxxxxx>
---
 mm/internal.h  | 10 +++++++
 mm/readahead.c | 79 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 59 insertions(+), 30 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index 1d051cbadf1a..c486d675af41 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -63,6 +63,16 @@ static inline unsigned long ra_submit(struct file_ra_state *ra,
 					ra->start, ra->size, ra->async_size);
 }
 
+void __page_cache_sync_readahead(struct address_space *mapping,
+				 struct file_ra_state *ra,
+				 struct kiocb *kiocb,  pgoff_t offset,
+				 unsigned long req_size);
+
+void __page_cache_async_readahead(struct address_space *mapping,
+				  struct file_ra_state *ra, struct kiocb *kiocb,
+				  struct page *page, pgoff_t offset,
+				  unsigned long req_size);
+
 /**
  * page_evictable - test whether a page is evictable
  * @page: the page to test
diff --git a/mm/readahead.c b/mm/readahead.c
index 657206f6318d..54a41dae4fea 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -493,6 +493,29 @@ ondemand_readahead(struct address_space *mapping,
 	return ra_submit(ra, mapping, kiocb);
 }
 
+void __page_cache_sync_readahead(struct address_space *mapping,
+				 struct file_ra_state *ra, struct kiocb *kiocb,
+				 pgoff_t offset, unsigned long req_size)
+{
+	struct file *filp = kiocb->ki_filp;
+
+	/* no read-ahead */
+	if (!ra->ra_pages)
+		return;
+
+	if (blk_cgroup_congested())
+		return;
+
+	/* be dumb */
+	if (filp && (filp->f_mode & FMODE_RANDOM)) {
+		force_page_cache_readahead(mapping, kiocb, offset, req_size);
+		return;
+	}
+
+	/* do read-ahead */
+	ondemand_readahead(mapping, ra, kiocb, false, offset, req_size);
+}
+
 /**
  * page_cache_sync_readahead - generic file readahead
  * @mapping: address_space which holds the pagecache and I/O vectors
@@ -513,23 +536,40 @@ void page_cache_sync_readahead(struct address_space *mapping,
 {
 	struct kiocb kiocb = { .ki_filp = filp, };
 
+	__page_cache_sync_readahead(mapping, ra, &kiocb, offset, req_size);
+}
+EXPORT_SYMBOL_GPL(page_cache_sync_readahead);
+
+void
+__page_cache_async_readahead(struct address_space *mapping,
+			     struct file_ra_state *ra, struct kiocb *kiocb,
+			     struct page *page, pgoff_t offset,
+			     unsigned long req_size)
+{
 	/* no read-ahead */
 	if (!ra->ra_pages)
 		return;
 
-	if (blk_cgroup_congested())
+	/*
+	 * Same bit is used for PG_readahead and PG_reclaim.
+	 */
+	if (PageWriteback(page))
 		return;
 
-	/* be dumb */
-	if (filp && (filp->f_mode & FMODE_RANDOM)) {
-		force_page_cache_readahead(mapping, &kiocb, offset, req_size);
+	ClearPageReadahead(page);
+
+	/*
+	 * Defer asynchronous read-ahead on IO congestion.
+	 */
+	if (inode_read_congested(mapping->host))
+		return;
+
+	if (blk_cgroup_congested())
 		return;
-	}
 
 	/* do read-ahead */
-	ondemand_readahead(mapping, ra, &kiocb, false, offset, req_size);
+	ondemand_readahead(mapping, ra, kiocb, true, offset, req_size);
 }
-EXPORT_SYMBOL_GPL(page_cache_sync_readahead);
 
 /**
  * page_cache_async_readahead - file readahead for marked pages
@@ -554,29 +594,8 @@ page_cache_async_readahead(struct address_space *mapping,
 {
 	struct kiocb kiocb = { .ki_filp = filp, };
 
-	/* no read-ahead */
-	if (!ra->ra_pages)
-		return;
-
-	/*
-	 * Same bit is used for PG_readahead and PG_reclaim.
-	 */
-	if (PageWriteback(page))
-		return;
-
-	ClearPageReadahead(page);
-
-	/*
-	 * Defer asynchronous read-ahead on IO congestion.
-	 */
-	if (inode_read_congested(mapping->host))
-		return;
-
-	if (blk_cgroup_congested())
-		return;
-
-	/* do read-ahead */
-	ondemand_readahead(mapping, ra, &kiocb, true, offset, req_size);
+	__page_cache_async_readahead(mapping, ra, &kiocb, page, offset,
+					req_size);
 }
 EXPORT_SYMBOL_GPL(page_cache_async_readahead);
 
-- 
2.26.2

>From 707258c22fea35a5915ff0373231fb07a8a1c9eb Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@xxxxxxxxx>
Date: Sun, 31 May 2020 19:35:33 -0600
Subject: [PATCH 1/6] fs: make aops->readpages() take kiocb argument

Instead of passing in a file, pass in the kiocb instead. This still
provides access to the file through kiocb->ki_filp, but also provides
access to more information related to the IO. We'll be using that to
ensure that ->readpages() understands IOCB_NOWAIT.

Signed-off-by: Jens Axboe <axboe@xxxxxxxxx>
---
 fs/9p/vfs_addr.c       |  3 ++-
 fs/afs/file.c          |  8 ++++----
 fs/block_dev.c         |  2 +-
 fs/btrfs/inode.c       |  2 +-
 fs/ceph/addr.c         |  3 ++-
 fs/cifs/file.c         |  3 ++-
 fs/erofs/data.c        |  2 +-
 fs/erofs/zdata.c       |  2 +-
 fs/exfat/inode.c       |  2 +-
 fs/ext2/inode.c        |  2 +-
 fs/ext4/inode.c        |  2 +-
 fs/f2fs/data.c         |  2 +-
 fs/fat/inode.c         |  2 +-
 fs/fuse/file.c         |  6 +++---
 fs/gfs2/aops.c         |  2 +-
 fs/hpfs/file.c         |  2 +-
 fs/isofs/inode.c       |  2 +-
 fs/jfs/inode.c         |  2 +-
 fs/nfs/read.c          |  3 ++-
 fs/nilfs2/inode.c      |  2 +-
 fs/ocfs2/aops.c        |  2 +-
 fs/omfs/file.c         |  2 +-
 fs/qnx6/inode.c        |  2 +-
 fs/reiserfs/inode.c    |  2 +-
 fs/udf/inode.c         |  2 +-
 fs/xfs/xfs_aops.c      |  2 +-
 fs/zonefs/super.c      |  2 +-
 include/linux/fs.h     |  2 +-
 include/linux/mm.h     |  6 +++---
 include/linux/nfs_fs.h |  2 +-
 mm/fadvise.c           |  7 +++++--
 mm/filemap.c           |  3 ++-
 mm/internal.h          |  6 +++---
 mm/readahead.c         | 39 ++++++++++++++++++++++-----------------
 34 files changed, 73 insertions(+), 60 deletions(-)

diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index cce9ace651a2..f2980829bb9f 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -95,9 +95,10 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
  *
  */
 
-static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping,
+static int v9fs_vfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			     struct list_head *pages, unsigned nr_pages)
 {
+	struct file *filp = kiocb->ki_filp;
 	int ret = 0;
 	struct inode *inode;
 
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 8415733f7bc1..447b6524c2e9 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -22,7 +22,7 @@ static void afs_invalidatepage(struct page *page, unsigned int offset,
 			       unsigned int length);
 static int afs_releasepage(struct page *page, gfp_t gfp_flags);
 
-static int afs_readpages(struct file *filp, struct address_space *mapping,
+static int afs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			 struct list_head *pages, unsigned nr_pages);
 
 const struct file_operations afs_file_operations = {
@@ -538,10 +538,10 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping,
 /*
  * read a set of pages
  */
-static int afs_readpages(struct file *file, struct address_space *mapping,
+static int afs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			 struct list_head *pages, unsigned nr_pages)
 {
-	struct key *key = afs_file_key(file);
+	struct key *key = afs_file_key(kiocb->ki_filp);
 	struct afs_vnode *vnode;
 	int ret = 0;
 
@@ -589,7 +589,7 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
 	}
 
 	while (!list_empty(pages)) {
-		ret = afs_readpages_one(file, mapping, pages);
+		ret = afs_readpages_one(kiocb->ki_filp, mapping, pages);
 		if (ret < 0)
 			break;
 	}
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 980cfce01c9a..87a540b42fa7 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -614,7 +614,7 @@ static int blkdev_readpage(struct file * file, struct page * page)
 	return block_read_full_page(page, blkdev_get_block);
 }
 
-static int blkdev_readpages(struct file *file, struct address_space *mapping,
+static int blkdev_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, blkdev_get_block);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 320d1062068d..1569d29fdfc4 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8294,7 +8294,7 @@ static int btrfs_writepages(struct address_space *mapping,
 }
 
 static int
-btrfs_readpages(struct file *file, struct address_space *mapping,
+btrfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
 	return extent_readpages(mapping, pages, nr_pages);
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 6f4678d98df7..687714a29e89 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -477,9 +477,10 @@ static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx,
  * Read multiple pages.  Leave pages we don't read + unlock in page_list;
  * the caller (VM) cleans them up.
  */
-static int ceph_readpages(struct file *file, struct address_space *mapping,
+static int ceph_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			  struct list_head *page_list, unsigned nr_pages)
 {
+	struct file *file = kiocb->ki_filp;
 	struct inode *inode = file_inode(file);
 	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
 	struct ceph_file_info *fi = file->private_data;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 75ddce8ef456..5eec4f40811c 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -4344,11 +4344,12 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list,
 	return rc;
 }
 
-static int cifs_readpages(struct file *file, struct address_space *mapping,
+static int cifs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 	struct list_head *page_list, unsigned num_pages)
 {
 	int rc;
 	struct list_head tmplist;
+	struct file *file = kiocb->ki_filp;
 	struct cifsFileInfo *open_file = file->private_data;
 	struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
 	struct TCP_Server_Info *server;
diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index fc3a8d8064f8..853b905a15c4 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -280,7 +280,7 @@ static int erofs_raw_access_readpage(struct file *file, struct page *page)
 	return 0;
 }
 
-static int erofs_raw_access_readpages(struct file *filp,
+static int erofs_raw_access_readpages(struct kiocb *kiocb,
 				      struct address_space *mapping,
 				      struct list_head *pages,
 				      unsigned int nr_pages)
diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
index c4b6c9aa87ec..bc8c02b088ce 100644
--- a/fs/erofs/zdata.c
+++ b/fs/erofs/zdata.c
@@ -1305,7 +1305,7 @@ static bool should_decompress_synchronously(struct erofs_sb_info *sbi,
 	return nr <= sbi->max_sync_decompress_pages;
 }
 
-static int z_erofs_readpages(struct file *filp, struct address_space *mapping,
+static int z_erofs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			     struct list_head *pages, unsigned int nr_pages)
 {
 	struct inode *const inode = mapping->host;
diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
index 06887492f54b..9905307dfba2 100644
--- a/fs/exfat/inode.c
+++ b/fs/exfat/inode.c
@@ -372,7 +372,7 @@ static int exfat_readpage(struct file *file, struct page *page)
 	return mpage_readpage(page, exfat_get_block);
 }
 
-static int exfat_readpages(struct file *file, struct address_space *mapping,
+static int exfat_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned int nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, exfat_get_block);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index c885cf7d724b..3843900d6251 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -878,7 +878,7 @@ static int ext2_readpage(struct file *file, struct page *page)
 }
 
 static int
-ext2_readpages(struct file *file, struct address_space *mapping,
+ext2_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, ext2_get_block);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 2a4aae6acdcb..6297804d1ac2 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3231,7 +3231,7 @@ static int ext4_readpage(struct file *file, struct page *page)
 }
 
 static int
-ext4_readpages(struct file *file, struct address_space *mapping,
+ext4_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
 	struct inode *inode = mapping->host;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index cdf2f626bea7..7330aa1e2e39 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2304,7 +2304,7 @@ static int f2fs_read_data_page(struct file *file, struct page *page)
 	return ret;
 }
 
-static int f2fs_read_data_pages(struct file *file,
+static int f2fs_read_data_pages(struct kiocb *kiocb,
 			struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages)
 {
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 71946da84388..ab9dfcbf1bd3 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -210,7 +210,7 @@ static int fat_readpage(struct file *file, struct page *page)
 	return mpage_readpage(page, fat_get_block);
 }
 
-static int fat_readpages(struct file *file, struct address_space *mapping,
+static int fat_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			 struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 9d67b830fb7a..ebd40681ee94 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -962,7 +962,7 @@ static int fuse_readpages_fill(void *_data, struct page *page)
 	return 0;
 }
 
-static int fuse_readpages(struct file *file, struct address_space *mapping,
+static int fuse_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			  struct list_head *pages, unsigned nr_pages)
 {
 	struct inode *inode = mapping->host;
@@ -974,7 +974,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
 	if (is_bad_inode(inode))
 		goto out;
 
-	data.file = file;
+	data.file = kiocb->ki_filp;
 	data.inode = inode;
 	data.nr_pages = nr_pages;
 	data.max_pages = min_t(unsigned int, nr_pages, fc->max_pages);
@@ -987,7 +987,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
 	err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
 	if (!err) {
 		if (data.ia->ap.num_pages)
-			fuse_send_readpages(data.ia, file);
+			fuse_send_readpages(data.ia, kiocb->ki_filp);
 		else
 			fuse_io_free(data.ia);
 	}
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 786c1ce8f030..37d18f82e5a1 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -594,7 +594,7 @@ int gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos,
  * 4. gfs2_block_map() is relied upon to set BH_Boundary in the right places.
  */
 
-static int gfs2_readpages(struct file *file, struct address_space *mapping,
+static int gfs2_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			  struct list_head *pages, unsigned nr_pages)
 {
 	struct inode *inode = mapping->host;
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index b36abf9cb345..5b9c537d011c 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -125,7 +125,7 @@ static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
 	return block_write_full_page(page, hpfs_get_block, wbc);
 }
 
-static int hpfs_readpages(struct file *file, struct address_space *mapping,
+static int hpfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			  struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, hpfs_get_block);
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 276107cdaaf1..071da59b7266 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -1183,7 +1183,7 @@ static int isofs_readpage(struct file *file, struct page *page)
 	return mpage_readpage(page, isofs_get_block);
 }
 
-static int isofs_readpages(struct file *file, struct address_space *mapping,
+static int isofs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, isofs_get_block);
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 9486afcdac76..503e2e5cb79d 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -296,7 +296,7 @@ static int jfs_readpage(struct file *file, struct page *page)
 	return mpage_readpage(page, jfs_get_block);
 }
 
-static int jfs_readpages(struct file *file, struct address_space *mapping,
+static int jfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, jfs_get_block);
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 13b22e898116..4719f6b67b5c 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -402,9 +402,10 @@ readpage_async_filler(void *data, struct page *page)
 	return error;
 }
 
-int nfs_readpages(struct file *filp, struct address_space *mapping,
+int nfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
+	struct file *filp = kiocb->ki_filp;
 	struct nfs_pageio_descriptor pgio;
 	struct nfs_pgio_mirror *pgm;
 	struct nfs_readdesc desc = {
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 671085512e0f..a981c9404fbc 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -153,7 +153,7 @@ static int nilfs_readpage(struct file *file, struct page *page)
  * @pages - the pages to be read
  * @nr_pages - number of pages to be read
  */
-static int nilfs_readpages(struct file *file, struct address_space *mapping,
+static int nilfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			   struct list_head *pages, unsigned int nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, nilfs_get_block);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 3a67a6518ddf..aa54b0d0d4a1 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -350,7 +350,7 @@ static int ocfs2_readpage(struct file *file, struct page *page)
  * grow out to a tree. If need be, detecting boundary extents could
  * trivially be added in a future version of ocfs2_get_block().
  */
-static int ocfs2_readpages(struct file *filp, struct address_space *mapping,
+static int ocfs2_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			   struct list_head *pages, unsigned nr_pages)
 {
 	int ret, err = -EIO;
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
index d640b9388238..195bb390ba24 100644
--- a/fs/omfs/file.c
+++ b/fs/omfs/file.c
@@ -289,7 +289,7 @@ static int omfs_readpage(struct file *file, struct page *page)
 	return block_read_full_page(page, omfs_get_block);
 }
 
-static int omfs_readpages(struct file *file, struct address_space *mapping,
+static int omfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, omfs_get_block);
diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c
index 345db56c98fd..c964fd63d4a5 100644
--- a/fs/qnx6/inode.c
+++ b/fs/qnx6/inode.c
@@ -99,7 +99,7 @@ static int qnx6_readpage(struct file *file, struct page *page)
 	return mpage_readpage(page, qnx6_get_block);
 }
 
-static int qnx6_readpages(struct file *file, struct address_space *mapping,
+static int qnx6_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		   struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, qnx6_get_block);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 6419e6dacc39..01d5ccdaa5b4 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1161,7 +1161,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
 }
 
 static int
-reiserfs_readpages(struct file *file, struct address_space *mapping,
+reiserfs_readpages(struct kiocb *kiocb, struct address_space *mapping,
 		   struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, reiserfs_get_block);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index e875bc5668ee..c541ca95f851 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -195,7 +195,7 @@ static int udf_readpage(struct file *file, struct page *page)
 	return mpage_readpage(page, udf_get_block);
 }
 
-static int udf_readpages(struct file *file, struct address_space *mapping,
+static int udf_readpages(struct kiocb *kiocb, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages)
 {
 	return mpage_readpages(mapping, pages, nr_pages, udf_get_block);
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 9d9cebf18726..bff9a2374ece 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -623,7 +623,7 @@ xfs_vm_readpage(
 
 STATIC int
 xfs_vm_readpages(
-	struct file		*unused,
+	struct kiocb		*kiocb,
 	struct address_space	*mapping,
 	struct list_head	*pages,
 	unsigned		nr_pages)
diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c
index 25afcf55aa41..11812841a5fa 100644
--- a/fs/zonefs/super.c
+++ b/fs/zonefs/super.c
@@ -79,7 +79,7 @@ static int zonefs_readpage(struct file *unused, struct page *page)
 	return iomap_readpage(page, &zonefs_iomap_ops);
 }
 
-static int zonefs_readpages(struct file *unused, struct address_space *mapping,
+static int zonefs_readpages(struct kiocb *unused, struct address_space *mapping,
 			    struct list_head *pages, unsigned int nr_pages)
 {
 	return iomap_readpages(mapping, pages, nr_pages, &zonefs_iomap_ops);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5ffc6d236b01..cb5adf72041b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -381,7 +381,7 @@ struct address_space_operations {
 	 * Reads in the requested pages. Unlike ->readpage(), this is
 	 * PURELY used for read-ahead!.
 	 */
-	int (*readpages)(struct file *filp, struct address_space *mapping,
+	int (*readpages)(struct kiocb *kiocb, struct address_space *mapping,
 			struct list_head *pages, unsigned nr_pages);
 
 	int (*write_begin)(struct file *, struct address_space *mapping,
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5a323422d783..7c805a32fdc7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2604,18 +2604,18 @@ void task_dirty_inc(struct task_struct *tsk);
 /* readahead.c */
 #define VM_READAHEAD_PAGES	(SZ_128K / PAGE_SIZE)
 
-int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
+int force_page_cache_readahead(struct address_space *mapping, struct kiocb *kiocb,
 			pgoff_t offset, unsigned long nr_to_read);
 
 void page_cache_sync_readahead(struct address_space *mapping,
 			       struct file_ra_state *ra,
-			       struct file *filp,
+			       struct file *file,
 			       pgoff_t offset,
 			       unsigned long size);
 
 void page_cache_async_readahead(struct address_space *mapping,
 				struct file_ra_state *ra,
-				struct file *filp,
+				struct file *file,
 				struct page *pg,
 				pgoff_t offset,
 				unsigned long size);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 73eda45f1cfd..27c62a08f499 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -550,7 +550,7 @@ nfs_have_writebacks(struct inode *inode)
  * linux/fs/nfs/read.c
  */
 extern int  nfs_readpage(struct file *, struct page *);
-extern int  nfs_readpages(struct file *, struct address_space *,
+extern int  nfs_readpages(struct kiocb *, struct address_space *,
 		struct list_head *, unsigned);
 extern int  nfs_readpage_async(struct nfs_open_context *, struct inode *,
 			       struct page *);
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 4f17c83db575..58654fd13486 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -92,7 +92,9 @@ int generic_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
 		file->f_mode &= ~FMODE_RANDOM;
 		spin_unlock(&file->f_lock);
 		break;
-	case POSIX_FADV_WILLNEED:
+	case POSIX_FADV_WILLNEED: {
+		struct kiocb kiocb = { .ki_filp = file, };
+
 		/* First and last PARTIAL page! */
 		start_index = offset >> PAGE_SHIFT;
 		end_index = endbyte >> PAGE_SHIFT;
@@ -106,8 +108,9 @@ int generic_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
 		 * Ignore return value because fadvise() shall return
 		 * success even if filesystem can't retrieve a hint,
 		 */
-		force_page_cache_readahead(mapping, file, start_index, nrpages);
+		force_page_cache_readahead(mapping, &kiocb, start_index, nrpages);
 		break;
+		}
 	case POSIX_FADV_NOREUSE:
 		break;
 	case POSIX_FADV_DONTNEED:
diff --git a/mm/filemap.c b/mm/filemap.c
index 18022de7dc33..abdd3f32c932 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2403,6 +2403,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf)
 	struct address_space *mapping = file->f_mapping;
 	struct file *fpin = NULL;
 	pgoff_t offset = vmf->pgoff;
+	struct kiocb kiocb = { .ki_filp = file, };
 
 	/* If we don't want any read-ahead, don't bother */
 	if (vmf->vma->vm_flags & VM_RAND_READ)
@@ -2435,7 +2436,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf)
 	ra->start = max_t(long, 0, offset - ra->ra_pages / 2);
 	ra->size = ra->ra_pages;
 	ra->async_size = ra->ra_pages / 4;
-	ra_submit(ra, mapping, file);
+	ra_submit(ra, mapping, &kiocb);
 	return fpin;
 }
 
diff --git a/mm/internal.h b/mm/internal.h
index b5634e78f01d..1d051cbadf1a 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -50,16 +50,16 @@ void unmap_page_range(struct mmu_gather *tlb,
 			     struct zap_details *details);
 
 extern unsigned int __do_page_cache_readahead(struct address_space *mapping,
-		struct file *filp, pgoff_t offset, unsigned long nr_to_read,
+		struct kiocb *kiocb, pgoff_t offset, unsigned long nr_to_read,
 		unsigned long lookahead_size);
 
 /*
  * Submit IO for the read-ahead request in file_ra_state.
  */
 static inline unsigned long ra_submit(struct file_ra_state *ra,
-		struct address_space *mapping, struct file *filp)
+		struct address_space *mapping, struct kiocb *kiocb)
 {
-	return __do_page_cache_readahead(mapping, filp,
+	return __do_page_cache_readahead(mapping, kiocb,
 					ra->start, ra->size, ra->async_size);
 }
 
diff --git a/mm/readahead.c b/mm/readahead.c
index 2fe72cd29b47..657206f6318d 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -113,7 +113,7 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,
 
 EXPORT_SYMBOL(read_cache_pages);
 
-static int read_pages(struct address_space *mapping, struct file *filp,
+static int read_pages(struct address_space *mapping, struct kiocb *kiocb,
 		struct list_head *pages, unsigned int nr_pages, gfp_t gfp)
 {
 	struct blk_plug plug;
@@ -123,7 +123,7 @@ static int read_pages(struct address_space *mapping, struct file *filp,
 	blk_start_plug(&plug);
 
 	if (mapping->a_ops->readpages) {
-		ret = mapping->a_ops->readpages(filp, mapping, pages, nr_pages);
+		ret = mapping->a_ops->readpages(kiocb, mapping, pages, nr_pages);
 		/* Clean up the remaining pages */
 		put_pages_list(pages);
 		goto out;
@@ -133,7 +133,7 @@ static int read_pages(struct address_space *mapping, struct file *filp,
 		struct page *page = lru_to_page(pages);
 		list_del(&page->lru);
 		if (!add_to_page_cache_lru(page, mapping, page->index, gfp))
-			mapping->a_ops->readpage(filp, page);
+			mapping->a_ops->readpage(kiocb->ki_filp, page);
 		put_page(page);
 	}
 	ret = 0;
@@ -153,7 +153,7 @@ static int read_pages(struct address_space *mapping, struct file *filp,
  * Returns the number of pages requested, or the maximum amount of I/O allowed.
  */
 unsigned int __do_page_cache_readahead(struct address_space *mapping,
-		struct file *filp, pgoff_t offset, unsigned long nr_to_read,
+		struct kiocb *kiocb, pgoff_t offset, unsigned long nr_to_read,
 		unsigned long lookahead_size)
 {
 	struct inode *inode = mapping->host;
@@ -187,7 +187,7 @@ unsigned int __do_page_cache_readahead(struct address_space *mapping,
 			 * batch.
 			 */
 			if (nr_pages)
-				read_pages(mapping, filp, &page_pool, nr_pages,
+				read_pages(mapping, kiocb, &page_pool, nr_pages,
 						gfp_mask);
 			nr_pages = 0;
 			continue;
@@ -209,7 +209,7 @@ unsigned int __do_page_cache_readahead(struct address_space *mapping,
 	 * will then handle the error.
 	 */
 	if (nr_pages)
-		read_pages(mapping, filp, &page_pool, nr_pages, gfp_mask);
+		read_pages(mapping, kiocb, &page_pool, nr_pages, gfp_mask);
 	BUG_ON(!list_empty(&page_pool));
 out:
 	return nr_pages;
@@ -219,11 +219,12 @@ unsigned int __do_page_cache_readahead(struct address_space *mapping,
  * Chunk the readahead into 2 megabyte units, so that we don't pin too much
  * memory at once.
  */
-int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
-			       pgoff_t offset, unsigned long nr_to_read)
+int force_page_cache_readahead(struct address_space *mapping,
+			       struct kiocb *kiocb, pgoff_t offset,
+			       unsigned long nr_to_read)
 {
 	struct backing_dev_info *bdi = inode_to_bdi(mapping->host);
-	struct file_ra_state *ra = &filp->f_ra;
+	struct file_ra_state *ra = &kiocb->ki_filp->f_ra;
 	unsigned long max_pages;
 
 	if (unlikely(!mapping->a_ops->readpage && !mapping->a_ops->readpages))
@@ -240,7 +241,7 @@ int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
 
 		if (this_chunk > nr_to_read)
 			this_chunk = nr_to_read;
-		__do_page_cache_readahead(mapping, filp, offset, this_chunk, 0);
+		__do_page_cache_readahead(mapping, kiocb, offset, this_chunk, 0);
 
 		offset += this_chunk;
 		nr_to_read -= this_chunk;
@@ -380,7 +381,7 @@ static int try_context_readahead(struct address_space *mapping,
  */
 static unsigned long
 ondemand_readahead(struct address_space *mapping,
-		   struct file_ra_state *ra, struct file *filp,
+		   struct file_ra_state *ra, struct kiocb *kiocb,
 		   bool hit_readahead_marker, pgoff_t offset,
 		   unsigned long req_size)
 {
@@ -464,7 +465,7 @@ ondemand_readahead(struct address_space *mapping,
 	 * standalone, small random read
 	 * Read as is, and do not pollute the readahead state.
 	 */
-	return __do_page_cache_readahead(mapping, filp, offset, req_size, 0);
+	return __do_page_cache_readahead(mapping, kiocb, offset, req_size, 0);
 
 initial_readahead:
 	ra->start = offset;
@@ -489,14 +490,14 @@ ondemand_readahead(struct address_space *mapping,
 		}
 	}
 
-	return ra_submit(ra, mapping, filp);
+	return ra_submit(ra, mapping, kiocb);
 }
 
 /**
  * page_cache_sync_readahead - generic file readahead
  * @mapping: address_space which holds the pagecache and I/O vectors
  * @ra: file_ra_state which holds the readahead state
- * @filp: passed on to ->readpage() and ->readpages()
+ * @kiocb: passed on to ->readpage() and ->readpages()
  * @offset: start offset into @mapping, in pagecache page-sized units
  * @req_size: hint: total size of the read which the caller is performing in
  *            pagecache pages
@@ -510,6 +511,8 @@ void page_cache_sync_readahead(struct address_space *mapping,
 			       struct file_ra_state *ra, struct file *filp,
 			       pgoff_t offset, unsigned long req_size)
 {
+	struct kiocb kiocb = { .ki_filp = filp, };
+
 	/* no read-ahead */
 	if (!ra->ra_pages)
 		return;
@@ -519,12 +522,12 @@ void page_cache_sync_readahead(struct address_space *mapping,
 
 	/* be dumb */
 	if (filp && (filp->f_mode & FMODE_RANDOM)) {
-		force_page_cache_readahead(mapping, filp, offset, req_size);
+		force_page_cache_readahead(mapping, &kiocb, offset, req_size);
 		return;
 	}
 
 	/* do read-ahead */
-	ondemand_readahead(mapping, ra, filp, false, offset, req_size);
+	ondemand_readahead(mapping, ra, &kiocb, false, offset, req_size);
 }
 EXPORT_SYMBOL_GPL(page_cache_sync_readahead);
 
@@ -549,6 +552,8 @@ page_cache_async_readahead(struct address_space *mapping,
 			   struct page *page, pgoff_t offset,
 			   unsigned long req_size)
 {
+	struct kiocb kiocb = { .ki_filp = filp, };
+
 	/* no read-ahead */
 	if (!ra->ra_pages)
 		return;
@@ -571,7 +576,7 @@ page_cache_async_readahead(struct address_space *mapping,
 		return;
 
 	/* do read-ahead */
-	ondemand_readahead(mapping, ra, filp, true, offset, req_size);
+	ondemand_readahead(mapping, ra, &kiocb, true, offset, req_size);
 }
 EXPORT_SYMBOL_GPL(page_cache_async_readahead);
 
-- 
2.26.2


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux