mm/filemap: Add FGP_STABLE
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 24 Dec 2020 17:55:56 +0000 (12:55 -0500)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Mon, 18 Oct 2021 11:49:41 +0000 (07:49 -0400)
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>
include/linux/pagemap.h
mm/filemap.c
mm/folio-compat.c

index 401a903..b68b053 100644 (file)
@@ -301,6 +301,7 @@ pgoff_t page_cache_prev_miss(struct address_space *mapping,
 #define FGP_FOR_MMAP           0x00000040
 #define FGP_HEAD               0x00000080
 #define FGP_ENTRY              0x00000100
+#define FGP_STABLE             0x00000200
 
 struct folio *__filemap_get_folio(struct address_space *mapping, pgoff_t index,
                int fgp_flags, gfp_t gfp);
index de4cc1b..3e9feb5 100644 (file)
@@ -1872,6 +1872,7 @@ out:
  * * %FGP_WRITE - The page will be written to by the caller.
  * * %FGP_NOFS - __GFP_FS will get cleared in gfp.
  * * %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 the %GFP flags specified for %FGP_CREAT are atomic.
@@ -1922,6 +1923,8 @@ repeat:
                        folio_clear_idle(folio);
        }
 
+       if (fgp_flags & FGP_STABLE)
+               folio_wait_stable(folio);
 no_page:
        if (!folio && (fgp_flags & FGP_CREAT)) {
                int err;
@@ -3704,28 +3707,6 @@ out:
 }
 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,
                                struct iov_iter *i, loff_t pos)
 {
index e833e68..5b6ae1d 100644 (file)
@@ -116,6 +116,7 @@ int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
 }
 EXPORT_SYMBOL(add_to_page_cache_lru);
 
+noinline
 struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
                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);
 }
 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);