btrfs: don't redirty locked_page in run_delalloc_zoned
authorChristoph Hellwig <hch@lst.de>
Wed, 28 Jun 2023 15:31:42 +0000 (17:31 +0200)
committerDavid Sterba <dsterba@suse.com>
Mon, 21 Aug 2023 12:52:16 +0000 (14:52 +0200)
extent_write_locked_range currently expects that either all or no
pages are dirty when it is called.  Bur run_delalloc_zoned is called
directly in the writepages path, and has the dirty bit cleared only
for locked_page and which the extent_write_cache_pages currently
operates.  It currently works around this by redirtying locked_page,
but that is a bit inefficient and cumbersome.  Pass a locked_page
argument to run_delalloc_zoned so that clearing the dirty bit can
be skipped on just that page.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/inode.c

index bcf8244..90a58a3 100644 (file)
@@ -2161,8 +2161,9 @@ retry:
  * already been ran (aka, ordered extent inserted) and all pages are still
  * locked.
  */
-void extent_write_locked_range(struct inode *inode, u64 start, u64 end,
-                              struct writeback_control *wbc, bool pages_dirty)
+void extent_write_locked_range(struct inode *inode, struct page *locked_page,
+                              u64 start, u64 end, struct writeback_control *wbc,
+                              bool pages_dirty)
 {
        bool found_error = false;
        int ret = 0;
@@ -2189,7 +2190,7 @@ void extent_write_locked_range(struct inode *inode, u64 start, u64 end,
 
                page = find_get_page(mapping, cur >> PAGE_SHIFT);
                ASSERT(PageLocked(page));
-               if (pages_dirty) {
+               if (pages_dirty && page != locked_page) {
                        ASSERT(PageDirty(page));
                        clear_page_dirty_for_io(page);
                }
index 2678906..c01f9c5 100644 (file)
@@ -177,8 +177,9 @@ int try_release_extent_mapping(struct page *page, gfp_t mask);
 int try_release_extent_buffer(struct page *page);
 
 int btrfs_read_folio(struct file *file, struct folio *folio);
-void extent_write_locked_range(struct inode *inode, u64 start, u64 end,
-                              struct writeback_control *wbc, bool pages_dirty);
+void extent_write_locked_range(struct inode *inode, struct page *locked_page,
+                              u64 start, u64 end, struct writeback_control *wbc,
+                              bool pages_dirty);
 int extent_writepages(struct address_space *mapping,
                      struct writeback_control *wbc);
 int btree_write_cache_pages(struct address_space *mapping,
index 0617e47..29a137d 100644 (file)
@@ -1105,7 +1105,8 @@ static void submit_uncompressed_range(struct btrfs_inode *inode,
 
        /* All pages will be unlocked, including @locked_page */
        wbc_attach_fdatawrite_inode(&wbc, &inode->vfs_inode);
-       extent_write_locked_range(&inode->vfs_inode, start, end, &wbc, false);
+       extent_write_locked_range(&inode->vfs_inode, NULL, start, end, &wbc,
+                                 false);
        wbc_detach_inode(&wbc);
 }
 
@@ -1719,7 +1720,6 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
 {
        u64 done_offset = end;
        int ret;
-       bool locked_page_done = false;
 
        while (start <= end) {
                ret = cow_file_range(inode, locked_page, start, end, &done_offset,
@@ -1727,13 +1727,8 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
                if (ret)
                        return ret;
 
-               if (!locked_page_done) {
-                       __set_page_dirty_nobuffers(locked_page);
-                       account_page_redirty(locked_page);
-               }
-               locked_page_done = true;
-               extent_write_locked_range(&inode->vfs_inode, start, done_offset,
-                                         wbc, true);
+               extent_write_locked_range(&inode->vfs_inode, locked_page, start,
+                                         done_offset, wbc, true);
                start = done_offset + 1;
        }