Skip to content

Commit

Permalink
Merge tag 'folio-5.18b' of git://git.infradead.org/users/willy/pagecache
Browse files Browse the repository at this point in the history
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
  ...
  • Loading branch information
torvalds committed Mar 23, 2022
2 parents 9030fb0 + 3a3bae5 commit 6b1f86f
Show file tree
Hide file tree
Showing 94 changed files with 849 additions and 875 deletions.
7 changes: 4 additions & 3 deletions Documentation/filesystems/caching/netfs-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -345,16 +345,17 @@ The following facilities are provided to manage this:

To support this, the following functions are provided::

int fscache_set_page_dirty(struct page *page,
struct fscache_cookie *cookie);
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);
void fscache_clear_inode_writeback(struct fscache_cookie *cookie,
struct inode *inode,
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()``).

Expand Down
42 changes: 21 additions & 21 deletions Documentation/filesystems/locking.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -250,42 +250,42 @@ 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
====================== ======================== ========= ===============
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
Expand Down Expand Up @@ -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
Expand All @@ -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.

Expand Down
46 changes: 23 additions & 23 deletions Documentation/filesystems/vfs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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 *);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion block/fops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 1 addition & 2 deletions drivers/dax/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 1 addition & 8 deletions drivers/video/fbdev/core/fb_defio.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,8 @@ static const struct vm_operations_struct fb_deferred_io_vm_ops = {
.page_mkwrite = fb_deferred_io_mkwrite,
};

static int fb_deferred_io_set_page_dirty(struct page *page)
{
if (!PageDirty(page))
SetPageDirty(page);
return 0;
}

static const struct address_space_operations fb_deferred_io_aops = {
.set_page_dirty = fb_deferred_io_set_page_dirty,
.dirty_folio = noop_dirty_folio,
};

int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
Expand Down
37 changes: 10 additions & 27 deletions fs/9p/vfs_addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,18 +158,9 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
return 1;
}

/**
* v9fs_invalidate_page - Invalidate a page completely or partially
* @page: The page to be invalidated
* @offset: offset of the invalidated region
* @length: length of the invalidated region
*/

static void v9fs_invalidate_page(struct page *page, unsigned int offset,
unsigned int length)
static void v9fs_invalidate_folio(struct folio *folio, size_t offset,
size_t length)
{
struct folio *folio = page_folio(page);

folio_wait_fscache(folio);
}

Expand Down Expand Up @@ -249,16 +240,8 @@ static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc)
return retval;
}

/**
* v9fs_launder_page - Writeback a dirty page
* @page: The page to be cleaned up
*
* Returns 0 on success.
*/

static int v9fs_launder_page(struct page *page)
static int v9fs_launder_folio(struct folio *folio)
{
struct folio *folio = page_folio(page);
int retval;

if (folio_clear_dirty_for_io(folio)) {
Expand Down Expand Up @@ -376,25 +359,25 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping,
* Mark a page as having been made dirty and thus needing writeback. We also
* need to pin the cache object to write back to.
*/
static int v9fs_set_page_dirty(struct page *page)
static bool v9fs_dirty_folio(struct address_space *mapping, struct folio *folio)
{
struct v9fs_inode *v9inode = V9FS_I(page->mapping->host);
struct v9fs_inode *v9inode = V9FS_I(mapping->host);

return fscache_set_page_dirty(page, v9fs_inode_cookie(v9inode));
return fscache_dirty_folio(mapping, folio, v9fs_inode_cookie(v9inode));
}
#else
#define v9fs_set_page_dirty __set_page_dirty_nobuffers
#define v9fs_dirty_folio filemap_dirty_folio
#endif

const struct address_space_operations v9fs_addr_operations = {
.readpage = v9fs_vfs_readpage,
.readahead = v9fs_vfs_readahead,
.set_page_dirty = v9fs_set_page_dirty,
.dirty_folio = v9fs_dirty_folio,
.writepage = v9fs_vfs_writepage,
.write_begin = v9fs_write_begin,
.write_end = v9fs_write_end,
.releasepage = v9fs_release_page,
.invalidatepage = v9fs_invalidate_page,
.launder_page = v9fs_launder_page,
.invalidate_folio = v9fs_invalidate_folio,
.launder_folio = v9fs_launder_folio,
.direct_IO = v9fs_direct_IO,
};
3 changes: 2 additions & 1 deletion fs/adfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ static sector_t _adfs_bmap(struct address_space *mapping, sector_t block)
}

static const struct address_space_operations adfs_aops = {
.set_page_dirty = __set_page_dirty_buffers,
.dirty_folio = block_dirty_folio,
.invalidate_folio = block_invalidate_folio,
.readpage = adfs_readpage,
.writepage = adfs_writepage,
.write_begin = adfs_write_begin,
Expand Down
6 changes: 4 additions & 2 deletions fs/affs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,8 @@ static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
}

const struct address_space_operations affs_aops = {
.set_page_dirty = __set_page_dirty_buffers,
.dirty_folio = block_dirty_folio,
.invalidate_folio = block_invalidate_folio,
.readpage = affs_readpage,
.writepage = affs_writepage,
.write_begin = affs_write_begin,
Expand Down Expand Up @@ -834,7 +835,8 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
}

const struct address_space_operations affs_aops_ofs = {
.set_page_dirty = __set_page_dirty_buffers,
.dirty_folio = block_dirty_folio,
.invalidate_folio = block_invalidate_folio,
.readpage = affs_readpage_ofs,
//.writepage = affs_writepage_ofs,
.write_begin = affs_write_begin_ofs,
Expand Down
Loading

0 comments on commit 6b1f86f

Please sign in to comment.