Skip to content

Commit 6f31a5a

Browse files
author
Matthew Wilcox (Oracle)
committed
fs: Add aops->dirty_folio
This replaces ->set_page_dirty(). It returns a bool instead of an int and takes the address_space as a parameter instead of expecting the implementations to retrieve the address_space from the page. This is particularly important for filesystems which use FS_OPS for swap. Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Tested-by: Damien Le Moal <[email protected]> Acked-by: Damien Le Moal <[email protected]> Tested-by: Mike Marshall <[email protected]> # orangefs Tested-by: David Howells <[email protected]> # afs
1 parent 072acba commit 6f31a5a

File tree

5 files changed

+31
-23
lines changed

5 files changed

+31
-23
lines changed

Documentation/filesystems/locking.rst

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ prototypes::
239239
int (*writepage)(struct page *page, struct writeback_control *wbc);
240240
int (*readpage)(struct file *, struct page *);
241241
int (*writepages)(struct address_space *, struct writeback_control *);
242-
int (*set_page_dirty)(struct page *page);
242+
bool (*dirty_folio)(struct address_space *, struct folio *folio);
243243
void (*readahead)(struct readahead_control *);
244244
int (*readpages)(struct file *filp, struct address_space *mapping,
245245
struct list_head *pages, unsigned nr_pages);
@@ -264,15 +264,15 @@ prototypes::
264264
int (*swap_deactivate)(struct file *);
265265

266266
locking rules:
267-
All except set_page_dirty and freepage may block
267+
All except dirty_folio and freepage may block
268268

269269
====================== ======================== ========= ===============
270270
ops PageLocked(page) i_rwsem invalidate_lock
271271
====================== ======================== ========= ===============
272272
writepage: yes, unlocks (see below)
273273
readpage: yes, unlocks shared
274274
writepages:
275-
set_page_dirty no
275+
dirty_folio maybe
276276
readahead: yes, unlocks shared
277277
readpages: no shared
278278
write_begin: locks the page exclusive
@@ -361,10 +361,11 @@ If nr_to_write is NULL, all dirty pages must be written.
361361
writepages should _only_ write pages which are present on
362362
mapping->io_pages.
363363

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

369370
->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some
370371
filesystems and by the swapper. The latter will eventually go away. Please,

Documentation/filesystems/vfs.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ pages, however the address_space has finer control of write sizes.
658658

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

664664
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:
724724
int (*writepage)(struct page *page, struct writeback_control *wbc);
725725
int (*readpage)(struct file *, struct page *);
726726
int (*writepages)(struct address_space *, struct writeback_control *);
727-
int (*set_page_dirty)(struct page *page);
727+
bool (*dirty_folio)(struct address_space *, struct folio *);
728728
void (*readahead)(struct readahead_control *);
729729
int (*readpages)(struct file *filp, struct address_space *mapping,
730730
struct list_head *pages, unsigned nr_pages);
@@ -793,13 +793,13 @@ cache in your filesystem. The following members are defined:
793793
This will choose pages from the address space that are tagged as
794794
DIRTY and will pass them to ->writepage.
795795

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

804804
``readahead``
805805
Called by the VM to read pages associated with the address_space

include/linux/fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ struct address_space_operations {
369369

370370
/* Set a page dirty. Return true if this dirtied it */
371371
int (*set_page_dirty)(struct page *page);
372+
bool (*dirty_folio)(struct address_space *, struct folio *);
372373

373374
/*
374375
* Reads in the requested pages. Unlike ->readpage(), this is

mm/page-writeback.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2616,7 +2616,7 @@ EXPORT_SYMBOL(folio_redirty_for_writepage);
26162616
* folio_mark_dirty - Mark a folio as being modified.
26172617
* @folio: The folio.
26182618
*
2619-
* For folios with a mapping this should be done under the page lock
2619+
* For folios with a mapping this should be done with the folio lock held
26202620
* for the benefit of asynchronous memory errors who prefer a consistent
26212621
* dirty state. This rule can be broken in some special cases,
26222622
* but should be better not to.
@@ -2630,16 +2630,19 @@ bool folio_mark_dirty(struct folio *folio)
26302630
if (likely(mapping)) {
26312631
/*
26322632
* readahead/lru_deactivate_page could remain
2633-
* PG_readahead/PG_reclaim due to race with end_page_writeback
2634-
* About readahead, if the page is written, the flags would be
2633+
* PG_readahead/PG_reclaim due to race with folio_end_writeback
2634+
* About readahead, if the folio is written, the flags would be
26352635
* reset. So no problem.
2636-
* About lru_deactivate_page, if the page is redirty, the flag
2637-
* will be reset. So no problem. but if the page is used by readahead
2638-
* it will confuse readahead and make it restart the size rampup
2639-
* process. But it's a trivial problem.
2636+
* About lru_deactivate_page, if the folio is redirtied,
2637+
* the flag will be reset. So no problem. but if the
2638+
* folio is used by readahead it will confuse readahead
2639+
* and make it restart the size rampup process. But it's
2640+
* a trivial problem.
26402641
*/
26412642
if (folio_test_reclaim(folio))
26422643
folio_clear_reclaim(folio);
2644+
if (mapping->a_ops->dirty_folio)
2645+
return mapping->a_ops->dirty_folio(mapping, folio);
26432646
return mapping->a_ops->set_page_dirty(&folio->page);
26442647
}
26452648
if (!folio_test_dirty(folio)) {

mm/page_io.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,9 +444,12 @@ int swap_set_page_dirty(struct page *page)
444444

445445
if (data_race(sis->flags & SWP_FS_OPS)) {
446446
struct address_space *mapping = sis->swap_file->f_mapping;
447+
const struct address_space_operations *aops = mapping->a_ops;
447448

448449
VM_BUG_ON_PAGE(!PageSwapCache(page), page);
449-
return mapping->a_ops->set_page_dirty(page);
450+
if (aops->dirty_folio)
451+
return aops->dirty_folio(mapping, page_folio(page));
452+
return aops->set_page_dirty(page);
450453
} else {
451454
return __set_page_dirty_no_writeback(page);
452455
}

0 commit comments

Comments
 (0)