Commit 6b1f86f8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull filesystem folio updates from Matthew Wilcox:
 "Primarily this series converts some of the address_space operations to
  take a folio instead of a page.

  Notably:

   - a_ops->is_partially_uptodate() takes a folio instead of a page and
     changes the type of the 'from' and 'count' arguments to make it
     obvious they're bytes.

   - a_ops->invalidatepage() becomes ->invalidate_folio() and has a
     similar type change.

   - a_ops->launder_page() becomes ->launder_folio()

   - a_ops->set_page_dirty() becomes ->dirty_folio() and adds the
     address_space as an argument.

  There are a couple of other misc changes up front that weren't worth
  separating into their own pull request"

* tag 'folio-5.18b' of git://git.infradead.org/users/willy/pagecache: (53 commits)
  fs: Remove aops ->set_page_dirty
  fb_defio: Use noop_dirty_folio()
  fs: Convert __set_page_dirty_no_writeback to noop_dirty_folio
  fs: Convert __set_page_dirty_buffers to block_dirty_folio
  nilfs: Convert nilfs_set_page_dirty() to nilfs_dirty_folio()
  mm: Convert swap_set_page_dirty() to swap_dirty_folio()
  ubifs: Convert ubifs_set_page_dirty to ubifs_dirty_folio
  f2fs: Convert f2fs_set_node_page_dirty to f2fs_dirty_node_folio
  f2fs: Convert f2fs_set_data_page_dirty to f2fs_dirty_data_folio
  f2fs: Convert f2fs_set_meta_page_dirty to f2fs_dirty_meta_folio
  afs: Convert afs_dir_set_page_dirty() to afs_dir_dirty_folio()
  btrfs: Convert extent_range_redirty_for_io() to use folios
  fs: Convert trivial uses of __set_page_dirty_nobuffers to filemap_dirty_folio
  btrfs: Convert from set_page_dirty to dirty_folio
  fscache: Convert fscache_set_page_dirty() to fscache_dirty_folio()
  fs: Add aops->dirty_folio
  fs: Remove aops->launder_page
  orangefs: Convert launder_page to launder_folio
  nfs: Convert from launder_page to launder_folio
  fuse: Convert from launder_page to launder_folio
  ...
parents 9030fb0b 3a3bae50
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -345,7 +345,8 @@ The following facilities are provided to manage this:

To support this, the following functions are provided::

	int fscache_set_page_dirty(struct page *page,
	bool fscache_dirty_folio(struct address_space *mapping,
				 struct folio *folio,
				 struct fscache_cookie *cookie);
	void fscache_unpin_writeback(struct writeback_control *wbc,
				     struct fscache_cookie *cookie);
@@ -354,7 +355,7 @@ To support this, the following functions are provided::
					   const void *aux);

The *set* function is intended to be called from the filesystem's
``set_page_dirty`` address space operation.  If ``I_PINNING_FSCACHE_WB`` is not
``dirty_folio`` address space operation.  If ``I_PINNING_FSCACHE_WB`` is not
set, it sets that flag and increments the use count on the cookie (the caller
must already have called ``fscache_use_cookie()``).

+21 −21
Original line number Diff line number Diff line
@@ -239,7 +239,7 @@ prototypes::
	int (*writepage)(struct page *page, struct writeback_control *wbc);
	int (*readpage)(struct file *, struct page *);
	int (*writepages)(struct address_space *, struct writeback_control *);
	int (*set_page_dirty)(struct page *page);
	bool (*dirty_folio)(struct address_space *, struct folio *folio);
	void (*readahead)(struct readahead_control *);
	int (*readpages)(struct file *filp, struct address_space *mapping,
			struct list_head *pages, unsigned nr_pages);
@@ -250,21 +250,21 @@ prototypes::
				loff_t pos, unsigned len, unsigned copied,
				struct page *page, void *fsdata);
	sector_t (*bmap)(struct address_space *, sector_t);
	void (*invalidatepage) (struct page *, unsigned int, unsigned int);
	void (*invalidate_folio) (struct folio *, size_t start, size_t len);
	int (*releasepage) (struct page *, int);
	void (*freepage)(struct page *);
	int (*direct_IO)(struct kiocb *, struct iov_iter *iter);
	bool (*isolate_page) (struct page *, isolate_mode_t);
	int (*migratepage)(struct address_space *, struct page *, struct page *);
	void (*putback_page) (struct page *);
	int (*launder_page)(struct page *);
	int (*is_partially_uptodate)(struct page *, unsigned long, unsigned long);
	int (*launder_folio)(struct folio *);
	bool (*is_partially_uptodate)(struct folio *, size_t from, size_t count);
	int (*error_remove_page)(struct address_space *, struct page *);
	int (*swap_activate)(struct file *);
	int (*swap_deactivate)(struct file *);

locking rules:
	All except set_page_dirty and freepage may block
	All except dirty_folio and freepage may block

======================	======================== =========	===============
ops			PageLocked(page)	 i_rwsem	invalidate_lock
@@ -272,20 +272,20 @@ ops PageLocked(page) i_rwsem invalidate_lock
writepage:		yes, unlocks (see below)
readpage:		yes, unlocks				shared
writepages:
set_page_dirty		no
dirty_folio		maybe
readahead:		yes, unlocks				shared
readpages:		no					shared
write_begin:		locks the page		 exclusive
write_end:		yes, unlocks		 exclusive
bmap:
invalidatepage:		yes					exclusive
invalidate_folio:	yes					exclusive
releasepage:		yes
freepage:		yes
direct_IO:
isolate_page:		yes
migratepage:		yes (both)
putback_page:		yes
launder_page:		yes
launder_folio:		yes
is_partially_uptodate:	yes
error_remove_page:	yes
swap_activate:		no
@@ -361,22 +361,22 @@ If nr_to_write is NULL, all dirty pages must be written.
writepages should _only_ write pages which are present on
mapping->io_pages.

->set_page_dirty() is called from various places in the kernel
when the target page is marked as needing writeback.  It may be called
under spinlock (it cannot block) and is sometimes called with the page
not locked.
->dirty_folio() is called from various places in the kernel when
the target folio is marked as needing writeback.  The folio cannot be
truncated because either the caller holds the folio lock, or the caller
has found the folio while holding the page table lock which will block
truncation.

->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some
filesystems and by the swapper. The latter will eventually go away.  Please,
keep it that way and don't breed new callers.

->invalidatepage() is called when the filesystem must attempt to drop
->invalidate_folio() is called when the filesystem must attempt to drop
some or all of the buffers from the page when it is being truncated. It
returns zero on success. If ->invalidatepage is zero, the kernel uses
block_invalidatepage() instead. The filesystem must exclusively acquire
invalidate_lock before invalidating page cache in truncate / hole punch path
(and thus calling into ->invalidatepage) to block races between page cache
invalidation and page cache filling functions (fault, read, ...).
returns zero on success.  The filesystem must exclusively acquire
invalidate_lock before invalidating page cache in truncate / hole punch
path (and thus calling into ->invalidate_folio) to block races between page
cache invalidation and page cache filling functions (fault, read, ...).

->releasepage() is called when the kernel is about to try to drop the
buffers from the page in preparation for freeing it.  It returns zero to
@@ -386,9 +386,9 @@ the kernel assumes that the fs has no private interest in the buffers.
->freepage() is called when the kernel is done dropping the page
from the page cache.

->launder_page() may be called prior to releasing a page if
it is still found to be dirty. It returns zero if the page was successfully
cleaned, or an error value if not. Note that in order to prevent the page
->launder_folio() may be called prior to releasing a folio if
it is still found to be dirty. It returns zero if the folio was successfully
cleaned, or an error value if not. Note that in order to prevent the folio
getting mapped back in and redirtied, it needs to be kept locked
across the entire operation.

+23 −23
Original line number Diff line number Diff line
@@ -658,7 +658,7 @@ pages, however the address_space has finer control of write sizes.

The read process essentially only requires 'readpage'.  The write
process is more complicated and uses write_begin/write_end or
set_page_dirty to write data into the address_space, and writepage and
dirty_folio to write data into the address_space, and writepage and
writepages to writeback data to storage.

Adding and removing pages to/from an address_space is protected by the
@@ -724,7 +724,7 @@ cache in your filesystem. The following members are defined:
		int (*writepage)(struct page *page, struct writeback_control *wbc);
		int (*readpage)(struct file *, struct page *);
		int (*writepages)(struct address_space *, struct writeback_control *);
		int (*set_page_dirty)(struct page *page);
		bool (*dirty_folio)(struct address_space *, struct folio *);
		void (*readahead)(struct readahead_control *);
		int (*readpages)(struct file *filp, struct address_space *mapping,
				 struct list_head *pages, unsigned nr_pages);
@@ -735,7 +735,7 @@ cache in your filesystem. The following members are defined:
				 loff_t pos, unsigned len, unsigned copied,
				 struct page *page, void *fsdata);
		sector_t (*bmap)(struct address_space *, sector_t);
		void (*invalidatepage) (struct page *, unsigned int, unsigned int);
		void (*invalidate_folio) (struct folio *, size_t start, size_t len);
		int (*releasepage) (struct page *, int);
		void (*freepage)(struct page *);
		ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
@@ -745,10 +745,10 @@ cache in your filesystem. The following members are defined:
		int (*migratepage) (struct page *, struct page *);
		/* put migration-failed page back to right list */
		void (*putback_page) (struct page *);
		int (*launder_page) (struct page *);
		int (*launder_folio) (struct folio *);

		int (*is_partially_uptodate) (struct page *, unsigned long,
					      unsigned long);
		bool (*is_partially_uptodate) (struct folio *, size_t from,
					       size_t count);
		void (*is_dirty_writeback) (struct page *, bool *, bool *);
		int (*error_remove_page) (struct mapping *mapping, struct page *page);
		int (*swap_activate)(struct file *);
@@ -793,13 +793,13 @@ cache in your filesystem. The following members are defined:
	This will choose pages from the address space that are tagged as
	DIRTY and will pass them to ->writepage.

``set_page_dirty``
	called by the VM to set a page dirty.  This is particularly
	needed if an address space attaches private data to a page, and
	that data needs to be updated when a page is dirtied.  This is
``dirty_folio``
	called by the VM to mark a folio as dirty.  This is particularly
	needed if an address space attaches private data to a folio, and
	that data needs to be updated when a folio is dirtied.  This is
	called, for example, when a memory mapped page gets modified.
	If defined, it should set the PageDirty flag, and the
	PAGECACHE_TAG_DIRTY tag in the radix tree.
	If defined, it should set the folio dirty flag, and the
	PAGECACHE_TAG_DIRTY search mark in i_pages.

``readahead``
	Called by the VM to read pages associated with the address_space
@@ -872,15 +872,15 @@ cache in your filesystem. The following members are defined:
	to find out where the blocks in the file are and uses those
	addresses directly.

``invalidatepage``
	If a page has PagePrivate set, then invalidatepage will be
	called when part or all of the page is to be removed from the
``invalidate_folio``
	If a folio has private data, then invalidate_folio will be
	called when part or all of the folio is to be removed from the
	address space.  This generally corresponds to either a
	truncation, punch hole or a complete invalidation of the address
	space (in the latter case 'offset' will always be 0 and 'length'
	will be PAGE_SIZE).  Any private data associated with the page
	will be folio_size()).  Any private data associated with the page
	should be updated to reflect this truncation.  If offset is 0
	and length is PAGE_SIZE, then the private data should be
	and length is folio_size(), then the private data should be
	released, because the page must be able to be completely
	discarded.  This may be done by calling the ->releasepage
	function, but in this case the release MUST succeed.
@@ -934,16 +934,16 @@ cache in your filesystem. The following members are defined:
``putback_page``
	Called by the VM when isolated page's migration fails.

``launder_page``
	Called before freeing a page - it writes back the dirty page.
	To prevent redirtying the page, it is kept locked during the
``launder_folio``
	Called before freeing a folio - it writes back the dirty folio.
	To prevent redirtying the folio, it is kept locked during the
	whole operation.

``is_partially_uptodate``
	Called by the VM when reading a file through the pagecache when
	the underlying blocksize != pagesize.  If the required block is
	up to date then the read can complete without needing the IO to
	bring the whole page up to date.
	the underlying blocksize is smaller than the size of the folio.
	If the required block is up to date then the read can complete
	without needing I/O to bring the whole page up to date.

``is_dirty_writeback``
	Called by the VM when attempting to reclaim a page.  The VM uses
+2 −1
Original line number Diff line number Diff line
@@ -428,7 +428,8 @@ static int blkdev_writepages(struct address_space *mapping,
}

const struct address_space_operations def_blk_aops = {
	.set_page_dirty	= __set_page_dirty_buffers,
	.dirty_folio	= block_dirty_folio,
	.invalidate_folio = block_invalidate_folio,
	.readpage	= blkdev_readpage,
	.readahead	= blkdev_readahead,
	.writepage	= blkdev_writepage,
+1 −2
Original line number Diff line number Diff line
@@ -346,8 +346,7 @@ static unsigned long dax_get_unmapped_area(struct file *filp,
}

static const struct address_space_operations dev_dax_aops = {
	.set_page_dirty		= __set_page_dirty_no_writeback,
	.invalidatepage		= noop_invalidatepage,
	.dirty_folio	= noop_dirty_folio,
};

static int dax_open(struct inode *inode, struct file *filp)
Loading