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: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: John Hubbard <jhubbard@nvidia.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: William 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.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
c1f6925e10
commit
8151b4c8be
|
@ -239,6 +239,7 @@ prototypes::
|
|||
int (*readpage)(struct file *, struct page *);
|
||||
int (*writepages)(struct address_space *, struct writeback_control *);
|
||||
int (*set_page_dirty)(struct page *page);
|
||||
void (*readahead)(struct readahead_control *);
|
||||
int (*readpages)(struct file *filp, struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages);
|
||||
int (*write_begin)(struct file *, struct address_space *mapping,
|
||||
|
@ -271,7 +272,8 @@ writepage: yes, unlocks (see below)
|
|||
readpage: yes, unlocks
|
||||
writepages:
|
||||
set_page_dirty no
|
||||
readpages:
|
||||
readahead: yes, unlocks
|
||||
readpages: no
|
||||
write_begin: locks the page exclusive
|
||||
write_end: yes, unlocks exclusive
|
||||
bmap:
|
||||
|
@ -295,6 +297,8 @@ the request handler (/dev/loop).
|
|||
->readpage() unlocks the page, either synchronously or via I/O
|
||||
completion.
|
||||
|
||||
->readahead() unlocks the pages that I/O is attempted on like ->readpage().
|
||||
|
||||
->readpages() populates the pagecache with the passed pages and starts
|
||||
I/O against them. They come unlocked upon I/O completion.
|
||||
|
||||
|
|
|
@ -706,6 +706,7 @@ cache in your filesystem. The following members are defined:
|
|||
int (*readpage)(struct file *, struct page *);
|
||||
int (*writepages)(struct address_space *, struct writeback_control *);
|
||||
int (*set_page_dirty)(struct page *page);
|
||||
void (*readahead)(struct readahead_control *);
|
||||
int (*readpages)(struct file *filp, struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages);
|
||||
int (*write_begin)(struct file *, struct address_space *mapping,
|
||||
|
@ -781,12 +782,26 @@ cache in your filesystem. The following members are defined:
|
|||
If defined, it should set the PageDirty flag, and the
|
||||
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``
|
||||
called by the VM to read pages associated with the address_space
|
||||
object. This is essentially just a vector version of readpage.
|
||||
Instead of just one page, several pages are requested.
|
||||
readpages is only used for read-ahead, so read errors are
|
||||
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``
|
||||
Called by the generic buffered write code to ask the filesystem
|
||||
|
|
|
@ -292,6 +292,7 @@ enum positive_aop_returns {
|
|||
struct page;
|
||||
struct address_space;
|
||||
struct writeback_control;
|
||||
struct readahead_control;
|
||||
|
||||
/*
|
||||
* Write life time hint values.
|
||||
|
@ -375,6 +376,7 @@ struct address_space_operations {
|
|||
*/
|
||||
int (*readpages)(struct file *filp, struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages);
|
||||
void (*readahead)(struct readahead_control *);
|
||||
|
||||
int (*write_begin)(struct file *, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
|
|
|
@ -125,7 +125,14 @@ static void read_pages(struct readahead_control *rac, struct list_head *pages,
|
|||
|
||||
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,
|
||||
readahead_count(rac));
|
||||
/* Clean up the remaining pages */
|
||||
|
@ -233,7 +240,8 @@ void force_page_cache_readahead(struct address_space *mapping,
|
|||
struct file_ra_state *ra = &filp->f_ra;
|
||||
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;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue