[PATCH 12/21] btrfs: lock extents before pages - defrag

Goldwyn Rodrigues
2023-03-02T22:25:36Z

lock and flush the range before performing defrag.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/btrfs/defrag.c | 48 ++++++++++-------------------------------------
1 file changed, 10 insertions(+), 38 deletions(-)

diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c
index 8065341d831a..dff53458bf52 100644
--- a/fs/btrfs/defrag.c
+++ b/fs/btrfs/defrag.c
@@ -721,9 +721,6 @@ static struct page *defrag_prepare_one_page(struct btrfs_inode *inode, pgoff_t i
{
struct address_space *mapping = inode->vfs_inode.i_mapping;
gfp_t mask = btrfs_alloc_write_mask(mapping);
- u64 page_start = (u64)index << PAGE_SHIFT;
- u64 page_end = page_start + PAGE_SIZE - 1;
- struct extent_state *cached_state = NULL;
struct page *page;
int ret;

@@ -753,32 +750,6 @@ static struct page *defrag_prepare_one_page(struct btrfs_inode *inode, pgoff_t i
return ERR_PTR(ret);
}

- /* Wait for any existing ordered extent in the range */
- while (1) {
- struct btrfs_ordered_extent *ordered;
-
- lock_extent(&inode->io_tree, page_start, page_end, &cached_state);
- ordered = btrfs_lookup_ordered_range(inode, page_start, PAGE_SIZE);
- unlock_extent(&inode->io_tree, page_start, page_end,
- &cached_state);
- if (!ordered)
- break;
-
- unlock_page(page);
- btrfs_start_ordered_extent(ordered);
- btrfs_put_ordered_extent(ordered);
- lock_page(page);
- /*
- * We unlocked the page above, so we need check if it was
- * released or not.
- */
- if (page->mapping != mapping || !PagePrivate(page)) {
- unlock_page(page);
- put_page(page);
- goto again;
- }
- }
-
/*
* Now the page range has no ordered extent any more. Read the page to
* make it uptodate.
@@ -1076,6 +1047,11 @@ static int defrag_one_range(struct btrfs_inode *inode, u64 start, u32 len,
if (!pages)
return -ENOMEM;

+ /* Lock the pages range */
+ btrfs_lock_and_flush_ordered_range(inode, start_index << PAGE_SHIFT,
+ (last_index << PAGE_SHIFT) + PAGE_SIZE - 1,
+ &cached_state);
+
/* Prepare all pages */
for (i = 0; i < nr_pages; i++) {
pages[i] = defrag_prepare_one_page(inode, start_index + i);
@@ -1088,10 +1064,6 @@ static int defrag_one_range(struct btrfs_inode *inode, u64 start, u32 len,
for (i = 0; i < nr_pages; i++)
wait_on_page_writeback(pages[i]);

- /* Lock the pages range */
- lock_extent(&inode->io_tree, start_index << PAGE_SHIFT,
- (last_index << PAGE_SHIFT) + PAGE_SIZE - 1,
- &cached_state);
/*
* Now we have a consistent view about the extent map, re-check
* which range really needs to be defragged.
@@ -1103,7 +1075,7 @@ static int defrag_one_range(struct btrfs_inode *inode, u64 start, u32 len,
newer_than, do_compress, true,
&target_list, last_scanned_ret);
if (ret < 0)
- goto unlock_extent;
+ goto free_pages;

list_for_each_entry(entry, &target_list, list) {
ret = defrag_one_locked_target(inode, entry, pages, nr_pages,
@@ -1116,10 +1088,6 @@ static int defrag_one_range(struct btrfs_inode *inode, u64 start, u32 len,
list_del_init(&entry->list);
kfree(entry);
}
-unlock_extent:
- unlock_extent(&inode->io_tree, start_index << PAGE_SHIFT,
- (last_index << PAGE_SHIFT) + PAGE_SIZE - 1,
- &cached_state);
free_pages:
for (i = 0; i < nr_pages; i++) {
if (pages[i]) {
@@ -1128,6 +1096,10 @@ static int defrag_one_range(struct btrfs_inode *inode, u64 start, u32 len,
}
}
kfree(pages);
+
+ unlock_extent(&inode->io_tree, start_index << PAGE_SHIFT,
+ (last_index << PAGE_SHIFT) + PAGE_SIZE - 1,
+ &cached_state);
return ret;
}

--
2.39.2