All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josef Bacik <josef@toxicpanda.com>
To: linux-btrfs@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH 09/17] btrfs: push extent lock down in run_delalloc_nocow
Date: Wed, 17 Apr 2024 10:35:53 -0400	[thread overview]
Message-ID: <be4f89a0ad01fc580a11bfe52300a0c2e7669cc4.1713363472.git.josef@toxicpanda.com> (raw)
In-Reply-To: <cover.1713363472.git.josef@toxicpanda.com>

run_delalloc_nocow is a little special because we use the file extents
to see if we can nocow a range.  We don't actually need the protection
of the extent lock to look at the file extents at this point however.
We are currently holding the page lock for this range, so we are
protected from anybody who would simultaneously be modifying the file
extent items for this range.

* mmap() - we're holding the page lock.
* buffered writes - we're holding the page lock.
* direct writes - we're holding the page lock and direct IO has to flush
  page cache before it's able to continue.
* fallocate() - all callers flush the range and wait on ordered extents
  while holding the inode lock and the mmap lock, so we are again saved
  by the page lock.

We want to use the extent lock to protect

1) The mapping tree for the given range.
2) The ordered extents for the given range.
3) The io_tree for the given range.

Push the extent lock down to cover these operations.  In the
fallback_to_cow() case we simply lock before doing anything and rely on
the cow_file_range() helper to handle it's range properly.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/inode.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 80e92d37af34..ab3d6ebbce6a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1747,6 +1747,8 @@ static int fallback_to_cow(struct btrfs_inode *inode, struct page *locked_page,
 	u64 count;
 	int ret;
 
+	lock_extent(io_tree, start, end, NULL);
+
 	/*
 	 * If EXTENT_NORESERVE is set it means that when the buffered write was
 	 * made we had not enough available data space and therefore we did not
@@ -1977,8 +1979,6 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
 	 */
 	ASSERT(!btrfs_is_zoned(fs_info) || btrfs_is_data_reloc_root(root));
 
-	lock_extent(&inode->io_tree, start, end, NULL);
-
 	path = btrfs_alloc_path();
 	if (!path) {
 		ret = -ENOMEM;
@@ -1994,6 +1994,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
 		struct btrfs_key found_key;
 		struct btrfs_file_extent_item *fi;
 		struct extent_buffer *leaf;
+		struct extent_state *cached_state = NULL;
 		u64 extent_end;
 		u64 ram_bytes;
 		u64 nocow_end;
@@ -2131,6 +2132,8 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
 		}
 
 		nocow_end = cur_offset + nocow_args.num_bytes - 1;
+		lock_extent(&inode->io_tree, cur_offset, nocow_end, &cached_state);
+
 		is_prealloc = extent_type == BTRFS_FILE_EXTENT_PREALLOC;
 		if (is_prealloc) {
 			u64 orig_start = found_key.offset - nocow_args.extent_offset;
@@ -2144,6 +2147,8 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
 					  ram_bytes, BTRFS_COMPRESS_NONE,
 					  BTRFS_ORDERED_PREALLOC);
 			if (IS_ERR(em)) {
+				unlock_extent(&inode->io_tree, cur_offset,
+					      nocow_end, &cached_state);
 				btrfs_dec_nocow_writers(nocow_bg);
 				ret = PTR_ERR(em);
 				goto error;
@@ -2164,6 +2169,8 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
 				btrfs_drop_extent_map_range(inode, cur_offset,
 							    nocow_end, false);
 			}
+			unlock_extent(&inode->io_tree, cur_offset,
+				      nocow_end, &cached_state);
 			ret = PTR_ERR(ordered);
 			goto error;
 		}
@@ -2182,6 +2189,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
 					     EXTENT_DELALLOC |
 					     EXTENT_CLEAR_DATA_RESV,
 					     PAGE_UNLOCK | PAGE_SET_ORDERED);
+		free_extent_state(cached_state);
 
 		cur_offset = extent_end;
 
@@ -2217,13 +2225,20 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,
 	 */
 	if (cow_start != (u64)-1)
 		cur_offset = cow_start;
-	if (cur_offset < end)
+
+	/*
+	 * We need to lock the extent here because we're clearing DELALLOC and
+	 * we're not locked at this point.
+	 */
+	if (cur_offset < end) {
+		lock_extent(&inode->io_tree, cur_offset, end, NULL);
 		extent_clear_unlock_delalloc(inode, cur_offset, end,
 					     locked_page, EXTENT_LOCKED |
 					     EXTENT_DELALLOC | EXTENT_DEFRAG |
 					     EXTENT_DO_ACCOUNTING, PAGE_UNLOCK |
 					     PAGE_START_WRITEBACK |
 					     PAGE_END_WRITEBACK);
+	}
 	btrfs_free_path(path);
 	return ret;
 }
-- 
2.43.0


  parent reply	other threads:[~2024-04-17 14:36 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-17 14:35 [PATCH 00/17] btrfs: restrain lock extent usage during writeback Josef Bacik
2024-04-17 14:35 ` [PATCH 01/17] btrfs: handle errors in btrfs_reloc_clone_csums properly Josef Bacik
2024-04-17 16:01   ` Johannes Thumshirn
2024-04-29 14:38   ` David Sterba
2024-04-17 14:35 ` [PATCH 02/17] btrfs: push all inline logic into cow_file_range Josef Bacik
2024-04-24 17:23   ` Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 03/17] btrfs: unlock all the pages with successful inline extent creation Josef Bacik
2024-04-17 16:14   ` Johannes Thumshirn
2024-04-17 14:35 ` [PATCH 04/17] btrfs: move extent bit and page cleanup into cow_file_range_inline Josef Bacik
2024-04-17 16:24   ` Johannes Thumshirn
2024-04-17 14:35 ` [PATCH 05/17] btrfs: lock extent when doing inline extent in compression Josef Bacik
2024-04-17 16:29   ` Johannes Thumshirn
2024-04-19 18:52     ` Josef Bacik
2024-04-17 14:35 ` [PATCH 06/17] btrfs: push the extent lock into btrfs_run_delalloc_range Josef Bacik
2024-04-24 17:26   ` Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 07/17] btrfs: push extent lock into run_delalloc_nocow Josef Bacik
2024-04-23 11:33   ` Goldwyn Rodrigues
2024-04-23 16:49     ` Josef Bacik
2024-04-24 12:28       ` David Sterba
2024-04-24 17:53     ` Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 08/17] btrfs: adjust while loop condition in run_delalloc_nocow Josef Bacik
2024-04-18 14:05   ` Goldwyn Rodrigues
2024-04-17 14:35 ` Josef Bacik [this message]
2024-04-24 17:41   ` [PATCH 09/17] btrfs: push extent lock down " Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 10/17] btrfs: remove unlock_extent from run_delalloc_compressed Josef Bacik
2024-04-24 17:43   ` Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 11/17] btrfs: push extent lock into run_delalloc_cow Josef Bacik
2024-04-24 17:45   ` Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 12/17] btrfs: push extent lock into cow_file_range Josef Bacik
2024-04-24 17:46   ` Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 13/17] btrfs: push lock_extent into cow_file_range_inline Josef Bacik
2024-04-24 17:48   ` Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 14/17] btrfs: move can_cow_file_range_inline() outside of the extent lock Josef Bacik
2024-04-23 11:38   ` Goldwyn Rodrigues
2024-04-17 14:35 ` [PATCH 15/17] btrfs: push lock_extent down in cow_file_range() Josef Bacik
2024-04-24 17:49   ` Goldwyn Rodrigues
2024-04-17 14:36 ` [PATCH 16/17] btrfs: push extent lock down in submit_one_async_extent Josef Bacik
2024-04-23 11:39   ` Goldwyn Rodrigues
2024-04-17 14:36 ` [PATCH 17/17] btrfs: add a cached state to extent_clear_unlock_delalloc Josef Bacik
2024-04-23 11:42   ` Goldwyn Rodrigues
2024-04-24 17:21   ` Goldwyn Rodrigues
2024-04-18  5:54 ` [PATCH 00/17] btrfs: restrain lock extent usage during writeback Christoph Hellwig
2024-04-18 13:45   ` Goldwyn Rodrigues
2024-04-18 14:47     ` Christoph Hellwig
2024-04-19 18:54       ` Josef Bacik

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=be4f89a0ad01fc580a11bfe52300a0c2e7669cc4.1713363472.git.josef@toxicpanda.com \
    --to=josef@toxicpanda.com \
    --cc=kernel-team@fb.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.