mm/filemap: Add FGP_STABLE
Allow filemap_get_folio() to wait for writeback to complete (if the filesystem wants that behaviour). This is the folio equivalent of grab_cache_page_write_begin(), which is moved into the folio-compat file as a reminder to migrate all the code using it. This paves the way for getting rid of AOP_FLAG_NOFS once grab_cache_page_write_begin() is removed. Kernel grows by 11 bytes. filemap_get_folio() grows by 33 bytes but grab_cache_page_write_begin() shrinks by 22 bytes to make up for it. Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: David Howells <dhowells@redhat.com> Acked-by: Vlastimil Babka <vbabka@suse.cz>
This commit is contained in:
Родитель
3f0c6a07fe
Коммит
b27652d935
|
@ -301,6 +301,7 @@ pgoff_t page_cache_prev_miss(struct address_space *mapping,
|
||||||
#define FGP_FOR_MMAP 0x00000040
|
#define FGP_FOR_MMAP 0x00000040
|
||||||
#define FGP_HEAD 0x00000080
|
#define FGP_HEAD 0x00000080
|
||||||
#define FGP_ENTRY 0x00000100
|
#define FGP_ENTRY 0x00000100
|
||||||
|
#define FGP_STABLE 0x00000200
|
||||||
|
|
||||||
struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
|
struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
|
||||||
int fgp_flags, gfp_t gfp);
|
int fgp_flags, gfp_t gfp);
|
||||||
|
|
25
mm/filemap.c
25
mm/filemap.c
|
@ -1872,6 +1872,7 @@ out:
|
||||||
* * %FGP_WRITE - The page will be written to by the caller.
|
* * %FGP_WRITE - The page will be written to by the caller.
|
||||||
* * %FGP_NOFS - __GFP_FS will get cleared in gfp.
|
* * %FGP_NOFS - __GFP_FS will get cleared in gfp.
|
||||||
* * %FGP_NOWAIT - Don't get blocked by page lock.
|
* * %FGP_NOWAIT - Don't get blocked by page lock.
|
||||||
|
* * %FGP_STABLE - Wait for the folio to be stable (finished writeback)
|
||||||
*
|
*
|
||||||
* If %FGP_LOCK or %FGP_CREAT are specified then the function may sleep even
|
* If %FGP_LOCK or %FGP_CREAT are specified then the function may sleep even
|
||||||
* if the %GFP flags specified for %FGP_CREAT are atomic.
|
* if the %GFP flags specified for %FGP_CREAT are atomic.
|
||||||
|
@ -1922,6 +1923,8 @@ repeat:
|
||||||
folio_clear_idle(folio);
|
folio_clear_idle(folio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fgp_flags & FGP_STABLE)
|
||||||
|
folio_wait_stable(folio);
|
||||||
no_page:
|
no_page:
|
||||||
if (!folio && (fgp_flags & FGP_CREAT)) {
|
if (!folio && (fgp_flags & FGP_CREAT)) {
|
||||||
int err;
|
int err;
|
||||||
|
@ -3704,28 +3707,6 @@ out:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(generic_file_direct_write);
|
EXPORT_SYMBOL(generic_file_direct_write);
|
||||||
|
|
||||||
/*
|
|
||||||
* Find or create a page at the given pagecache position. Return the locked
|
|
||||||
* page. This function is specifically for buffered writes.
|
|
||||||
*/
|
|
||||||
struct page *grab_cache_page_write_begin(struct address_space *mapping,
|
|
||||||
pgoff_t index, unsigned flags)
|
|
||||||
{
|
|
||||||
struct page *page;
|
|
||||||
int fgp_flags = FGP_LOCK|FGP_WRITE|FGP_CREAT;
|
|
||||||
|
|
||||||
if (flags & AOP_FLAG_NOFS)
|
|
||||||
fgp_flags |= FGP_NOFS;
|
|
||||||
|
|
||||||
page = pagecache_get_page(mapping, index, fgp_flags,
|
|
||||||
mapping_gfp_mask(mapping));
|
|
||||||
if (page)
|
|
||||||
wait_for_stable_page(page);
|
|
||||||
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(grab_cache_page_write_begin);
|
|
||||||
|
|
||||||
ssize_t generic_perform_write(struct file *file,
|
ssize_t generic_perform_write(struct file *file,
|
||||||
struct iov_iter *i, loff_t pos)
|
struct iov_iter *i, loff_t pos)
|
||||||
{
|
{
|
||||||
|
|
|
@ -116,6 +116,7 @@ int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(add_to_page_cache_lru);
|
EXPORT_SYMBOL(add_to_page_cache_lru);
|
||||||
|
|
||||||
|
noinline
|
||||||
struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
|
struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
|
||||||
int fgp_flags, gfp_t gfp)
|
int fgp_flags, gfp_t gfp)
|
||||||
{
|
{
|
||||||
|
@ -127,3 +128,15 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
|
||||||
return folio_file_page(folio, index);
|
return folio_file_page(folio, index);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pagecache_get_page);
|
EXPORT_SYMBOL(pagecache_get_page);
|
||||||
|
|
||||||
|
struct page *grab_cache_page_write_begin(struct address_space *mapping,
|
||||||
|
pgoff_t index, unsigned flags)
|
||||||
|
{
|
||||||
|
unsigned fgp_flags = FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE;
|
||||||
|
|
||||||
|
if (flags & AOP_FLAG_NOFS)
|
||||||
|
fgp_flags |= FGP_NOFS;
|
||||||
|
return pagecache_get_page(mapping, index, fgp_flags,
|
||||||
|
mapping_gfp_mask(mapping));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(grab_cache_page_write_begin);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче