Commit 8151b4c8 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Linus Torvalds

mm: add readahead address space operation

This replaces ->readpages with a saner interface:
 - Return void instead of an ignored error code.
 - Page cache is already populated with locked pages when ->readahead
   is called.
 - New arguments can be passed to the implementation without changing
   all the filesystems that use a common helper function like
   mpage_readahead().
Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Reviewed-by: default avatarJohn Hubbard <jhubbard@nvidia.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarWilliam Kucharski <william.kucharski@oracle.com>
Cc: Chao Yu <yuchao0@huawei.com>
Cc: Cong Wang <xiyou.wangcong@gmail.com>
Cc: Darrick J. Wong <darrick.wong@oracle.com>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: Eric Biggers <ebiggers@google.com>
Cc: Gao Xiang <gaoxiang25@huawei.com>
Cc: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: Joseph Qi <joseph.qi@linux.alibaba.com>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Cc: Miklos Szeredi <mszeredi@redhat.com>
Link: http://lkml.kernel.org/r/20200414150233.24495-12-willy@infradead.orgSigned-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c1f6925e
...@@ -239,6 +239,7 @@ prototypes:: ...@@ -239,6 +239,7 @@ prototypes::
int (*readpage)(struct file *, struct page *); int (*readpage)(struct file *, struct page *);
int (*writepages)(struct address_space *, struct writeback_control *); int (*writepages)(struct address_space *, struct writeback_control *);
int (*set_page_dirty)(struct page *page); int (*set_page_dirty)(struct page *page);
void (*readahead)(struct readahead_control *);
int (*readpages)(struct file *filp, struct address_space *mapping, int (*readpages)(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages); struct list_head *pages, unsigned nr_pages);
int (*write_begin)(struct file *, struct address_space *mapping, int (*write_begin)(struct file *, struct address_space *mapping,
...@@ -271,7 +272,8 @@ writepage: yes, unlocks (see below) ...@@ -271,7 +272,8 @@ writepage: yes, unlocks (see below)
readpage: yes, unlocks readpage: yes, unlocks
writepages: writepages:
set_page_dirty no set_page_dirty no
readpages: readahead: yes, unlocks
readpages: no
write_begin: locks the page exclusive write_begin: locks the page exclusive
write_end: yes, unlocks exclusive write_end: yes, unlocks exclusive
bmap: bmap:
...@@ -295,6 +297,8 @@ the request handler (/dev/loop). ...@@ -295,6 +297,8 @@ the request handler (/dev/loop).
->readpage() unlocks the page, either synchronously or via I/O ->readpage() unlocks the page, either synchronously or via I/O
completion. completion.
->readahead() unlocks the pages that I/O is attempted on like ->readpage().
->readpages() populates the pagecache with the passed pages and starts ->readpages() populates the pagecache with the passed pages and starts
I/O against them. They come unlocked upon I/O completion. I/O against them. They come unlocked upon I/O completion.
......
...@@ -706,6 +706,7 @@ cache in your filesystem. The following members are defined: ...@@ -706,6 +706,7 @@ cache in your filesystem. The following members are defined:
int (*readpage)(struct file *, struct page *); int (*readpage)(struct file *, struct page *);
int (*writepages)(struct address_space *, struct writeback_control *); int (*writepages)(struct address_space *, struct writeback_control *);
int (*set_page_dirty)(struct page *page); int (*set_page_dirty)(struct page *page);
void (*readahead)(struct readahead_control *);
int (*readpages)(struct file *filp, struct address_space *mapping, int (*readpages)(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages); struct list_head *pages, unsigned nr_pages);
int (*write_begin)(struct file *, struct address_space *mapping, int (*write_begin)(struct file *, struct address_space *mapping,
...@@ -781,12 +782,26 @@ cache in your filesystem. The following members are defined: ...@@ -781,12 +782,26 @@ cache in your filesystem. The following members are defined:
If defined, it should set the PageDirty flag, and the If defined, it should set the PageDirty flag, and the
PAGECACHE_TAG_DIRTY tag in the radix tree. PAGECACHE_TAG_DIRTY tag in the radix tree.
``readahead``
Called by the VM to read pages associated with the address_space
object. The pages are consecutive in the page cache and are
locked. The implementation should decrement the page refcount
after starting I/O on each page. Usually the page will be
unlocked by the I/O completion handler. If the filesystem decides
to stop attempting I/O before reaching the end of the readahead
window, it can simply return. The caller will decrement the page
refcount and unlock the remaining pages for you. Set PageUptodate
if the I/O completes successfully. Setting PageError on any page
will be ignored; simply unlock the page if an I/O error occurs.
``readpages`` ``readpages``
called by the VM to read pages associated with the address_space called by the VM to read pages associated with the address_space
object. This is essentially just a vector version of readpage. object. This is essentially just a vector version of readpage.
Instead of just one page, several pages are requested. Instead of just one page, several pages are requested.
readpages is only used for read-ahead, so read errors are readpages is only used for read-ahead, so read errors are
ignored. If anything goes wrong, feel free to give up. ignored. If anything goes wrong, feel free to give up.
This interface is deprecated and will be removed by the end of
2020; implement readahead instead.
``write_begin`` ``write_begin``
Called by the generic buffered write code to ask the filesystem Called by the generic buffered write code to ask the filesystem
......
...@@ -292,6 +292,7 @@ enum positive_aop_returns { ...@@ -292,6 +292,7 @@ enum positive_aop_returns {
struct page; struct page;
struct address_space; struct address_space;
struct writeback_control; struct writeback_control;
struct readahead_control;
/* /*
* Write life time hint values. * Write life time hint values.
...@@ -375,6 +376,7 @@ struct address_space_operations { ...@@ -375,6 +376,7 @@ struct address_space_operations {
*/ */
int (*readpages)(struct file *filp, struct address_space *mapping, int (*readpages)(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages); struct list_head *pages, unsigned nr_pages);
void (*readahead)(struct readahead_control *);
int (*write_begin)(struct file *, struct address_space *mapping, int (*write_begin)(struct file *, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags, loff_t pos, unsigned len, unsigned flags,
......
...@@ -125,7 +125,14 @@ static void read_pages(struct readahead_control *rac, struct list_head *pages, ...@@ -125,7 +125,14 @@ static void read_pages(struct readahead_control *rac, struct list_head *pages,
blk_start_plug(&plug); blk_start_plug(&plug);
if (aops->readpages) { if (aops->readahead) {
aops->readahead(rac);
/* Clean up the remaining pages */
while ((page = readahead_page(rac))) {
unlock_page(page);
put_page(page);
}
} else if (aops->readpages) {
aops->readpages(rac->file, rac->mapping, pages, aops->readpages(rac->file, rac->mapping, pages,
readahead_count(rac)); readahead_count(rac));
/* Clean up the remaining pages */ /* Clean up the remaining pages */
...@@ -233,7 +240,8 @@ void force_page_cache_readahead(struct address_space *mapping, ...@@ -233,7 +240,8 @@ void force_page_cache_readahead(struct address_space *mapping,
struct file_ra_state *ra = &filp->f_ra; struct file_ra_state *ra = &filp->f_ra;
unsigned long max_pages; unsigned long max_pages;
if (unlikely(!mapping->a_ops->readpage && !mapping->a_ops->readpages)) if (unlikely(!mapping->a_ops->readpage && !mapping->a_ops->readpages &&
!mapping->a_ops->readahead))
return; return;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment