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
...@@ -250,6 +250,7 @@ prototypes:: ...@@ -250,6 +250,7 @@ prototypes::
loff_t pos, unsigned len, unsigned copied, loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata); struct page *page, void *fsdata);
sector_t (*bmap)(struct address_space *, sector_t); 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); void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, int); int (*releasepage) (struct page *, int);
void (*freepage)(struct page *); void (*freepage)(struct page *);
...@@ -278,6 +279,7 @@ readpages: no shared ...@@ -278,6 +279,7 @@ readpages: no shared
write_begin: locks the page exclusive write_begin: locks the page exclusive
write_end: yes, unlocks exclusive write_end: yes, unlocks exclusive
bmap: bmap:
invalidate_folio: yes exclusive
invalidatepage: yes exclusive invalidatepage: yes exclusive
releasepage: yes releasepage: yes
freepage: yes freepage: yes
...@@ -370,13 +372,12 @@ not locked. ...@@ -370,13 +372,12 @@ not locked.
filesystems and by the swapper. The latter will eventually go away. Please, filesystems and by the swapper. The latter will eventually go away. Please,
keep it that way and don't breed new callers. 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 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 returns zero on success. The filesystem must exclusively acquire
block_invalidatepage() instead. The filesystem must exclusively acquire invalidate_lock before invalidating page cache in truncate / hole punch
invalidate_lock before invalidating page cache in truncate / hole punch path path (and thus calling into ->invalidate_folio) to block races between page
(and thus calling into ->invalidatepage) to block races between page cache cache invalidation and page cache filling functions (fault, read, ...).
invalidation and page cache filling functions (fault, read, ...).
->releasepage() is called when the kernel is about to try to drop the ->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 buffers from the page in preparation for freeing it. It returns zero to
......
...@@ -735,6 +735,7 @@ cache in your filesystem. The following members are defined: ...@@ -735,6 +735,7 @@ cache in your filesystem. The following members are defined:
loff_t pos, unsigned len, unsigned copied, loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata); struct page *page, void *fsdata);
sector_t (*bmap)(struct address_space *, sector_t); 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); void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, int); int (*releasepage) (struct page *, int);
void (*freepage)(struct page *); void (*freepage)(struct page *);
...@@ -868,15 +869,15 @@ cache in your filesystem. The following members are defined: ...@@ -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 to find out where the blocks in the file are and uses those
addresses directly. addresses directly.
``invalidatepage`` ``invalidate_folio``
If a page has PagePrivate set, then invalidatepage will be If a folio has private data, then invalidate_folio will be
called when part or all of the page is to be removed from the called when part or all of the folio is to be removed from the
address space. This generally corresponds to either a address space. This generally corresponds to either a
truncation, punch hole or a complete invalidation of the address truncation, punch hole or a complete invalidation of the address
space (in the latter case 'offset' will always be 0 and 'length' 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 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 released, because the page must be able to be completely
discarded. This may be done by calling the ->releasepage discarded. This may be done by calling the ->releasepage
function, but in this case the release MUST succeed. function, but in this case the release MUST succeed.
......
...@@ -387,6 +387,7 @@ struct address_space_operations { ...@@ -387,6 +387,7 @@ struct address_space_operations {
/* Unfortunately this kludge is needed for FIBMAP. Don't use it */ /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
sector_t (*bmap)(struct address_space *, sector_t); 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); void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, gfp_t); int (*releasepage) (struct page *, gfp_t);
void (*freepage)(struct page *); void (*freepage)(struct page *);
......
...@@ -154,9 +154,15 @@ static int invalidate_exceptional_entry2(struct address_space *mapping, ...@@ -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) 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); 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 #ifdef CONFIG_BLOCK
if (!invalidatepage) if (!invalidatepage)
invalidatepage = block_invalidatepage; invalidatepage = block_invalidatepage;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment