Commit 128d1f82 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle)
Browse files

fs: Add invalidate_folio() aops method



This is used in preference to invalidatepage, if defined.

Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Tested-by: default avatarDamien Le Moal <damien.lemoal@opensource.wdc.com>
Acked-by: default avatarDamien Le Moal <damien.lemoal@opensource.wdc.com>
Tested-by: Mike Marshall <hubcap@omnibond.com> # orangefs
Tested-by: David Howells <dhowells@redhat.com> # afs
parent 020df9ba
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ prototypes::
				loff_t pos, unsigned len, unsigned copied,
				struct page *page, void *fsdata);
	sector_t (*bmap)(struct address_space *, sector_t);
	void (*invalidate_folio) (struct folio *, size_t start, size_t len);
	void (*invalidatepage) (struct page *, unsigned int, unsigned int);
	int (*releasepage) (struct page *, int);
	void (*freepage)(struct page *);
@@ -278,6 +279,7 @@ readpages: no shared
write_begin:		locks the page		 exclusive
write_end:		yes, unlocks		 exclusive
bmap:
invalidate_folio:	yes					exclusive
invalidatepage:		yes					exclusive
releasepage:		yes
freepage:		yes
@@ -370,13 +372,12 @@ not locked.
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
+6 −5
Original line number Diff line number Diff line
@@ -735,6 +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 (*invalidate_folio) (struct folio *, size_t start, size_t len);
		void (*invalidatepage) (struct page *, unsigned int, unsigned int);
		int (*releasepage) (struct page *, int);
		void (*freepage)(struct page *);
@@ -868,15 +869,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.
+1 −0
Original line number Diff line number Diff line
@@ -387,6 +387,7 @@ struct address_space_operations {

	/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
	sector_t (*bmap)(struct address_space *, sector_t);
	void (*invalidate_folio) (struct folio *, size_t offset, size_t len);
	void (*invalidatepage) (struct page *, unsigned int, unsigned int);
	int (*releasepage) (struct page *, gfp_t);
	void (*freepage)(struct page *);
+7 −1
Original line number Diff line number Diff line
@@ -154,9 +154,15 @@ static int invalidate_exceptional_entry2(struct address_space *mapping,
 */
void folio_invalidate(struct folio *folio, size_t offset, size_t length)
{
	const struct address_space_operations *aops = folio->mapping->a_ops;
	void (*invalidatepage)(struct page *, unsigned int, unsigned int);

	invalidatepage = folio->mapping->a_ops->invalidatepage;
	if (aops->invalidate_folio) {
		aops->invalidate_folio(folio, offset, length);
		return;
	}

	invalidatepage = aops->invalidatepage;
#ifdef CONFIG_BLOCK
	if (!invalidatepage)
		invalidatepage = block_invalidatepage;