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 02/17] btrfs: push all inline logic into cow_file_range
Date: Wed, 17 Apr 2024 10:35:46 -0400	[thread overview]
Message-ID: <2796fb5d2b04c3ff87c2ab5b285fd7e072a8e4a2.1713363472.git.josef@toxicpanda.com> (raw)
In-Reply-To: <cover.1713363472.git.josef@toxicpanda.com>

Currently we have a lot of duplicated checks of

if (start == 0 && fs_info->sectorsize == PAGE_SIZE)
	cow_file_range_inline();

Instead of duplicating this check everywhere, consolidate all of the
inline extent logic into a helper which documents all of the checks and
then use that helper inside of cow_file_range_inline().  With this we
can clean up all of the calls to either unconditionally call
cow_file_range_inline(), or at least reduce the checks we're doing
before we call cow_file_range_inline();

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

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 94d9a74a912c..925a53d886b4 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -614,14 +614,56 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
 	return ret;
 }
 
+static bool can_cow_file_range_inline(struct btrfs_inode *inode,
+				      u64 offset, u64 size,
+				      size_t compressed_size)
+{
+	struct btrfs_fs_info *fs_info = inode->root->fs_info;
+	u64 data_len = (compressed_size ?: size);
+
+	/* Inline extents must start at offset 0. */
+	if (offset != 0)
+		return false;
+
+	/*
+	 * Due to the page size limit, for subpage we can only trigger the
+	 * writeback for the dirty sectors of page, that means data writeback
+	 * is doing more writeback than what we want.
+	 *
+	 * This is especially unexpected for some call sites like fallocate,
+	 * where we only increase i_size after everything is done.
+	 * This means we can trigger inline extent even if we didn't want to.
+	 * So here we skip inline extent creation completely.
+	 */
+	if (fs_info->sectorsize != PAGE_SIZE)
+		return false;
+
+	/* Inline extents are limited to sectorsize. */
+	if (size > fs_info->sectorsize)
+		return false;
+
+	/* We cannot exceed the maximum inline data size. */
+	if (data_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info))
+		return false;
+
+	/* We cannot exceed the user specified max_inline size. */
+	if (data_len > fs_info->max_inline)
+		return false;
+
+	/* Inline extents must be the entirety of the file. */
+	if (size < i_size_read(&inode->vfs_inode))
+		return false;
+
+	return true;
+}
 
 /*
  * conditionally insert an inline extent into the file.  This
  * does the checks required to make sure the data is small enough
  * to fit as an inline extent.
  */
-static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size,
-					  size_t compressed_size,
+static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
+					  u64 size, size_t compressed_size,
 					  int compress_type,
 					  struct folio *compressed_folio,
 					  bool update_i_size)
@@ -634,16 +676,7 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size,
 	int ret;
 	struct btrfs_path *path;
 
-	/*
-	 * We can create an inline extent if it ends at or beyond the current
-	 * i_size, is no larger than a sector (decompressed), and the (possibly
-	 * compressed) data fits in a leaf and the configured maximum inline
-	 * size.
-	 */
-	if (size < i_size_read(&inode->vfs_inode) ||
-	    size > fs_info->sectorsize ||
-	    data_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info) ||
-	    data_len > fs_info->max_inline)
+	if (!can_cow_file_range_inline(inode, offset, size, compressed_size))
 		return 1;
 
 	path = btrfs_alloc_path();
@@ -971,43 +1004,38 @@ static void compress_file_range(struct btrfs_work *work)
 	 * Check cow_file_range() for why we don't even try to create inline
 	 * extent for the subpage case.
 	 */
-	if (start == 0 && fs_info->sectorsize == PAGE_SIZE) {
-		if (total_in < actual_end) {
-			ret = cow_file_range_inline(inode, actual_end, 0,
-						    BTRFS_COMPRESS_NONE, NULL,
-						    false);
-		} else {
-			ret = cow_file_range_inline(inode, actual_end,
-						    total_compressed,
-						    compress_type, folios[0],
-						    false);
-		}
-		if (ret <= 0) {
-			unsigned long clear_flags = EXTENT_DELALLOC |
-				EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
-				EXTENT_DO_ACCOUNTING;
+	if (total_in < actual_end)
+		ret = cow_file_range_inline(inode, start, actual_end, 0,
+					    BTRFS_COMPRESS_NONE, NULL, false);
+	else
+		ret = cow_file_range_inline(inode, start, actual_end,
+					    total_compressed, compress_type,
+					    folios[0], false);
+	if (ret <= 0) {
+		unsigned long clear_flags = EXTENT_DELALLOC |
+			EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
+			EXTENT_DO_ACCOUNTING;
 
-			if (ret < 0)
-				mapping_set_error(mapping, -EIO);
+		if (ret < 0)
+			mapping_set_error(mapping, -EIO);
 
-			/*
-			 * inline extent creation worked or returned error,
-			 * we don't need to create any more async work items.
-			 * Unlock and free up our temp pages.
-			 *
-			 * We use DO_ACCOUNTING here because we need the
-			 * delalloc_release_metadata to be done _after_ we drop
-			 * our outstanding extent for clearing delalloc for this
-			 * range.
-			 */
-			extent_clear_unlock_delalloc(inode, start, end,
-						     NULL,
-						     clear_flags,
-						     PAGE_UNLOCK |
-						     PAGE_START_WRITEBACK |
-						     PAGE_END_WRITEBACK);
-			goto free_pages;
-		}
+		/*
+		 * inline extent creation worked or returned error,
+		 * we don't need to create any more async work items.
+		 * Unlock and free up our temp pages.
+		 *
+		 * We use DO_ACCOUNTING here because we need the
+		 * delalloc_release_metadata to be done _after_ we drop
+		 * our outstanding extent for clearing delalloc for this
+		 * range.
+		 */
+		extent_clear_unlock_delalloc(inode, start, end,
+					     NULL,
+					     clear_flags,
+					     PAGE_UNLOCK |
+					     PAGE_START_WRITEBACK |
+					     PAGE_END_WRITEBACK);
+		goto free_pages;
 	}
 
 	/*
@@ -1315,22 +1343,12 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
 
 	inode_should_defrag(inode, start, end, num_bytes, SZ_64K);
 
-	/*
-	 * Due to the page size limit, for subpage we can only trigger the
-	 * writeback for the dirty sectors of page, that means data writeback
-	 * is doing more writeback than what we want.
-	 *
-	 * This is especially unexpected for some call sites like fallocate,
-	 * where we only increase i_size after everything is done.
-	 * This means we can trigger inline extent even if we didn't want to.
-	 * So here we skip inline extent creation completely.
-	 */
-	if (start == 0 && fs_info->sectorsize == PAGE_SIZE && !no_inline) {
+	if (!no_inline) {
 		u64 actual_end = min_t(u64, i_size_read(&inode->vfs_inode),
 				       end + 1);
 
 		/* lets try to make an inline extent */
-		ret = cow_file_range_inline(inode, actual_end, 0,
+		ret = cow_file_range_inline(inode, start, actual_end, 0,
 					    BTRFS_COMPRESS_NONE, NULL, false);
 		if (ret == 0) {
 			/*
@@ -10229,10 +10247,11 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
 		goto out_qgroup_free_data;
 
 	/* Try an inline extent first. */
-	if (start == 0 && encoded->unencoded_len == encoded->len &&
+	if (encoded->unencoded_len == encoded->len &&
 	    encoded->unencoded_offset == 0) {
-		ret = cow_file_range_inline(inode, encoded->len, orig_count,
-					    compression, folios[0], true);
+		ret = cow_file_range_inline(inode, start, encoded->len,
+					    orig_count, compression, folios[0],
+					    true);
 		if (ret <= 0) {
 			if (ret == 0)
 				ret = orig_count;
-- 
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 ` Josef Bacik [this message]
2024-04-24 17:23   ` [PATCH 02/17] btrfs: push all inline logic into cow_file_range 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 ` [PATCH 09/17] btrfs: push extent lock down " Josef Bacik
2024-04-24 17:41   ` 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=2796fb5d2b04c3ff87c2ab5b285fd7e072a8e4a2.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.