From: Christoph Hellwig <hch@lst.de>
To: Chris Mason <clm@fb.com>, Josef Bacik <josef@toxicpanda.com>,
David Sterba <dsterba@suse.com>
Cc: linux-btrfs@vger.kernel.org
Subject: [PATCH 16/16] btrfs: split page locking out of __process_pages_contig
Date: Tue, 23 May 2023 10:13:22 +0200 [thread overview]
Message-ID: <20230523081322.331337-17-hch@lst.de> (raw)
In-Reply-To: <20230523081322.331337-1-hch@lst.de>
There is a lot of complexity in __process_pages_contig to deal with the
PAGE_LOCK case that can return an error unlike all the other actions.
Open code the page iteration for page locking in lock_delalloc_pages and
remove all the now unused code from __process_pages_contig.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/btrfs/extent_io.c | 149 +++++++++++++++++--------------------------
fs/btrfs/extent_io.h | 1 -
2 files changed, 59 insertions(+), 91 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 77f0e405280736..15021d25155f97 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -197,18 +197,9 @@ void extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end)
}
}
-/*
- * Process one page for __process_pages_contig().
- *
- * Return >0 if we hit @page == @locked_page.
- * Return 0 if we updated the page status.
- * Return -EGAIN if the we need to try again.
- * (For PAGE_LOCK case but got dirty page or page not belong to mapping)
- */
-static int process_one_page(struct btrfs_fs_info *fs_info,
- struct address_space *mapping,
- struct page *page, struct page *locked_page,
- unsigned long page_ops, u64 start, u64 end)
+static void process_one_page(struct btrfs_fs_info *fs_info,
+ struct page *page, struct page *locked_page,
+ unsigned long page_ops, u64 start, u64 end)
{
u32 len;
@@ -224,29 +215,13 @@ static int process_one_page(struct btrfs_fs_info *fs_info,
if (page_ops & PAGE_END_WRITEBACK)
btrfs_page_clamp_clear_writeback(fs_info, page, start, len);
- if (page == locked_page)
- return 1;
-
- if (page_ops & PAGE_LOCK) {
- int ret;
-
- ret = btrfs_page_start_writer_lock(fs_info, page, start, len);
- if (ret)
- return ret;
- if (!PageDirty(page) || page->mapping != mapping) {
- btrfs_page_end_writer_lock(fs_info, page, start, len);
- return -EAGAIN;
- }
- }
- if (page_ops & PAGE_UNLOCK)
+ if (page != locked_page && (page_ops & PAGE_UNLOCK))
btrfs_page_end_writer_lock(fs_info, page, start, len);
- return 0;
}
-static int __process_pages_contig(struct address_space *mapping,
- struct page *locked_page,
- u64 start, u64 end, unsigned long page_ops,
- u64 *processed_end)
+static void __process_pages_contig(struct address_space *mapping,
+ struct page *locked_page, u64 start, u64 end,
+ unsigned long page_ops)
{
struct btrfs_fs_info *fs_info = btrfs_sb(mapping->host->i_sb);
pgoff_t start_index = start >> PAGE_SHIFT;
@@ -254,64 +229,24 @@ static int __process_pages_contig(struct address_space *mapping,
pgoff_t index = start_index;
unsigned long pages_processed = 0;
struct folio_batch fbatch;
- int err = 0;
int i;
- if (page_ops & PAGE_LOCK) {
- ASSERT(page_ops == PAGE_LOCK);
- ASSERT(processed_end && *processed_end == start);
- }
-
folio_batch_init(&fbatch);
while (index <= end_index) {
int found_folios;
found_folios = filemap_get_folios_contig(mapping, &index,
end_index, &fbatch);
-
- if (found_folios == 0) {
- /*
- * Only if we're going to lock these pages, we can find
- * nothing at @index.
- */
- ASSERT(page_ops & PAGE_LOCK);
- err = -EAGAIN;
- goto out;
- }
-
for (i = 0; i < found_folios; i++) {
- int process_ret;
struct folio *folio = fbatch.folios[i];
- process_ret = process_one_page(fs_info, mapping,
- &folio->page, locked_page, page_ops,
- start, end);
- if (process_ret < 0) {
- err = -EAGAIN;
- folio_batch_release(&fbatch);
- goto out;
- }
+
+ process_one_page(fs_info, &folio->page, locked_page,
+ page_ops, start, end);
pages_processed += folio_nr_pages(folio);
}
folio_batch_release(&fbatch);
cond_resched();
}
-out:
- if (err && processed_end) {
- /*
- * Update @processed_end. I know this is awful since it has
- * two different return value patterns (inclusive vs exclusive).
- *
- * But the exclusive pattern is necessary if @start is 0, or we
- * underflow and check against processed_end won't work as
- * expected.
- */
- if (pages_processed)
- *processed_end = min(end,
- ((u64)(start_index + pages_processed) << PAGE_SHIFT) - 1);
- else
- *processed_end = start;
- }
- return err;
}
static noinline void __unlock_for_delalloc(struct inode *inode,
@@ -326,29 +261,63 @@ static noinline void __unlock_for_delalloc(struct inode *inode,
return;
__process_pages_contig(inode->i_mapping, locked_page, start, end,
- PAGE_UNLOCK, NULL);
+ PAGE_UNLOCK);
}
static noinline int lock_delalloc_pages(struct inode *inode,
struct page *locked_page,
- u64 delalloc_start,
- u64 delalloc_end)
+ u64 start,
+ u64 end)
{
- unsigned long index = delalloc_start >> PAGE_SHIFT;
- unsigned long end_index = delalloc_end >> PAGE_SHIFT;
- u64 processed_end = delalloc_start;
- int ret;
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+ struct address_space *mapping = inode->i_mapping;
+ pgoff_t start_index = start >> PAGE_SHIFT;
+ pgoff_t end_index = end >> PAGE_SHIFT;
+ pgoff_t index = start_index;
+ u64 processed_end = start;
+ struct folio_batch fbatch;
- ASSERT(locked_page);
if (index == locked_page->index && index == end_index)
return 0;
- ret = __process_pages_contig(inode->i_mapping, locked_page, delalloc_start,
- delalloc_end, PAGE_LOCK, &processed_end);
- if (ret == -EAGAIN && processed_end > delalloc_start)
- __unlock_for_delalloc(inode, locked_page, delalloc_start,
- processed_end);
- return ret;
+ folio_batch_init(&fbatch);
+ while (index <= end_index) {
+ unsigned int found_folios, i;
+
+ found_folios = filemap_get_folios_contig(mapping, &index,
+ end_index, &fbatch);
+ if (found_folios == 0)
+ goto out;
+
+ for (i = 0; i < found_folios; i++) {
+ struct page *page = &fbatch.folios[i]->page;
+ u32 len = end + 1 - start;
+
+ if (page == locked_page)
+ continue;
+
+ if (btrfs_page_start_writer_lock(fs_info, page, start,
+ len))
+ goto out;
+
+ if (!PageDirty(page) || page->mapping != mapping) {
+ btrfs_page_end_writer_lock(fs_info, page, start,
+ len);
+ goto out;
+ }
+
+ processed_end = page_offset(page) + PAGE_SIZE - 1;
+ }
+ folio_batch_release(&fbatch);
+ cond_resched();
+ }
+
+ return 0;
+out:
+ folio_batch_release(&fbatch);
+ if (processed_end > start)
+ __unlock_for_delalloc(inode, locked_page, start, processed_end);
+ return -EAGAIN;
}
/*
@@ -467,7 +436,7 @@ void extent_clear_unlock_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
clear_extent_bit(&inode->io_tree, start, end, clear_bits, NULL);
__process_pages_contig(inode->vfs_inode.i_mapping, locked_page,
- start, end, page_ops, NULL);
+ start, end, page_ops);
}
static int btrfs_verify_page(struct page *page, u64 start)
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index daef9374c2095f..423853be57ed87 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -39,7 +39,6 @@ enum {
ENUM_BIT(PAGE_START_WRITEBACK),
ENUM_BIT(PAGE_END_WRITEBACK),
ENUM_BIT(PAGE_SET_ORDERED),
- ENUM_BIT(PAGE_LOCK),
};
/*
--
2.39.2
next prev parent reply other threads:[~2023-05-23 8:16 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-23 8:13 writeback fixlets and tidyups Christoph Hellwig
2023-05-23 8:13 ` [PATCH 01/16] btrfs: fix range_end calculation in extent_write_locked_range Christoph Hellwig
2023-05-29 17:13 ` David Sterba
2023-05-30 13:13 ` David Sterba
2023-05-30 14:23 ` Christoph Hellwig
2023-05-23 8:13 ` [PATCH 02/16] btrfs: factor out a btrfs_verify_page helper Christoph Hellwig
2023-05-23 9:23 ` Qu Wenruo
2023-05-23 11:38 ` Christoph Hellwig
2023-05-23 10:16 ` Anand Jain
2023-05-23 11:39 ` Christoph Hellwig
2023-05-23 11:47 ` Anand Jain
2023-05-23 11:54 ` Christoph Hellwig
2023-05-29 17:34 ` David Sterba
2023-05-23 8:13 ` [PATCH 03/16] btrfs: unify fsverify vs other read error handling in end_page_read Christoph Hellwig
2023-05-29 17:39 ` David Sterba
2023-05-23 8:13 ` [PATCH 04/16] btrfs: don't check PageError in btrfs_verify_page Christoph Hellwig
2023-05-23 8:13 ` [PATCH 05/16] btrfs: don't fail writeback when allocating the compression context fails Christoph Hellwig
2023-05-23 8:13 ` [PATCH 06/16] btrfs: rename cow_file_range_async to run_delalloc_compressed Christoph Hellwig
2023-05-23 10:23 ` Anand Jain
2023-05-23 8:13 ` [PATCH 07/16] btrfs: don't check PageError in __extent_writepage Christoph Hellwig
2023-05-23 8:13 ` [PATCH 08/16] btrfs: stop setting PageError in the data I/O path Christoph Hellwig
2023-05-29 17:52 ` David Sterba
2023-05-30 5:45 ` Christoph Hellwig
2023-05-30 6:08 ` Matthew Wilcox
2023-05-30 13:34 ` David Sterba
2023-05-30 14:26 ` Christoph Hellwig
2023-05-30 13:23 ` David Sterba
2023-05-30 14:24 ` Christoph Hellwig
2023-05-23 8:13 ` [PATCH 09/16] btrfs: remove PAGE_SET_ERROR Christoph Hellwig
2023-05-23 8:13 ` [PATCH 10/16] btrfs: remove non-standard extent handling in __extent_writepage_io Christoph Hellwig
2023-05-23 8:13 ` [PATCH 11/16] btrfs: move nr_to_write to __extent_writepage Christoph Hellwig
2023-05-23 10:30 ` Anand Jain
2023-05-23 8:13 ` [PATCH 12/16] btrfs: only call __extent_writepage_io from extent_write_locked_range Christoph Hellwig
2023-05-23 8:13 ` [PATCH 13/16] btrfs: don't treat zoned writeback as being from an async helper thread Christoph Hellwig
2023-05-23 8:13 ` [PATCH 14/16] btrfs: don't redirty the locked page for extent_write_locked_range Christoph Hellwig
2023-05-23 8:13 ` [PATCH 15/16] btrfs: refactor the zoned device handling in cow_file_range Christoph Hellwig
2023-05-23 8:13 ` Christoph Hellwig [this message]
2023-05-23 23:27 ` [PATCH 16/16] btrfs: split page locking out of __process_pages_contig kernel test robot
-- strict thread matches above, loose matches on Subject: below --
2023-05-31 6:04 writeback fixlets and tidyups v2 Christoph Hellwig
2023-05-31 6:05 ` [PATCH 16/16] btrfs: split page locking out of __process_pages_contig Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230523081322.331337-17-hch@lst.de \
--to=hch@lst.de \
--cc=clm@fb.com \
--cc=dsterba@suse.com \
--cc=josef@toxicpanda.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).