Add filemap_dirty_folio_pages() which takes in the number of pages to dirty. Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> --- fs/buffer.c | 4 ++-- include/linux/pagemap.h | 2 +- include/linux/writeback.h | 2 ++ mm/page-writeback.c | 25 +++++++++++++++++++++---- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 327bae3f724d..7c05f6205d39 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -752,7 +752,7 @@ bool block_dirty_folio(struct address_space *mapping, struct folio *folio) if (newly_dirty) __folio_mark_dirty(folio, mapping, 1, - folio_nr_pages(folio)); + folio_nr_pages(folio), true); if (newly_dirty) __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); @@ -1211,7 +1211,7 @@ void mark_buffer_dirty(struct buffer_head *bh) mapping = folio->mapping; if (mapping) __folio_mark_dirty(folio, mapping, 0, - folio_nr_pages(folio)); + folio_nr_pages(folio), true); } if (mapping) __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 0ae2c1e93ca5..64f17aec9141 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -1205,7 +1205,7 @@ void folio_end_writeback(struct folio *folio); void folio_end_writeback_pages(struct folio *folio, long nr_pages); void folio_wait_stable(struct folio *folio); void __folio_mark_dirty(struct folio *folio, struct address_space *, int warn, - long nr_pages); + long nr_pages, bool newly_dirty); void folio_account_cleaned(struct folio *folio, struct bdi_writeback *wb); void __folio_cancel_dirty(struct folio *folio); static inline void folio_cancel_dirty(struct folio *folio) diff --git a/include/linux/writeback.h b/include/linux/writeback.h index eda4b62511f7..34afa6912a1c 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -383,6 +383,8 @@ void tag_pages_for_writeback(struct address_space *mapping, pgoff_t start, pgoff_t end); bool filemap_dirty_folio(struct address_space *mapping, struct folio *folio); +bool filemap_dirty_folio_pages(struct address_space *mapping, + struct folio *folio, long nr_pages); bool folio_redirty_for_writepage(struct writeback_control *, struct folio *); bool redirty_page_for_writepage(struct writeback_control *, struct page *); diff --git a/mm/page-writeback.c b/mm/page-writeback.c index b0ae10a6687d..a3805988f3ad 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -2732,7 +2732,7 @@ void folio_account_cleaned(struct folio *folio, struct bdi_writeback *wb) * try_to_free_buffers() to fail. */ void __folio_mark_dirty(struct folio *folio, struct address_space *mapping, - int warn, long nr_pages) + int warn, long nr_pages, bool newly_dirty) { unsigned long flags; @@ -2740,12 +2740,29 @@ void __folio_mark_dirty(struct folio *folio, struct address_space *mapping, if (folio->mapping) { /* Race with truncate? */ WARN_ON_ONCE(warn && !folio_test_uptodate(folio)); folio_account_dirtied(folio, mapping, nr_pages); - __xa_set_mark(&mapping->i_pages, folio_index(folio), - PAGECACHE_TAG_DIRTY); + if (newly_dirty) + __xa_set_mark(&mapping->i_pages, folio_index(folio), + PAGECACHE_TAG_DIRTY); } xa_unlock_irqrestore(&mapping->i_pages, flags); } +bool filemap_dirty_folio_pages(struct address_space *mapping, struct folio *folio, + long nr_pages) +{ + bool newly_dirty = !folio_test_set_dirty(folio); + + __folio_mark_dirty(folio, mapping, !folio_test_private(folio), + nr_pages, newly_dirty); + + if (newly_dirty && mapping->host) { + /* !PageAnon && !swapper_space */ + __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); + } + + return newly_dirty; +} + /** * filemap_dirty_folio - Mark a folio dirty for filesystems which do not use buffer_heads. * @mapping: Address space this folio belongs to. @@ -2771,7 +2788,7 @@ bool filemap_dirty_folio(struct address_space *mapping, struct folio *folio) return false; __folio_mark_dirty(folio, mapping, !folio_test_private(folio), - folio_nr_pages(folio)); + folio_nr_pages(folio), true); if (mapping->host) { /* !PageAnon && !swapper_space */ -- 2.47.3