All of lore.kernel.org
 help / color / mirror / Atom feed
From: fdmanana@kernel.org
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 3/3] Btrfs: only allocate necessary space when relocating a data block group
Date: Tue,  9 Jun 2020 11:19:53 +0100	[thread overview]
Message-ID: <20200609101953.29559-1-fdmanana@kernel.org> (raw)

From: Filipe Manana <fdmanana@suse.com>

When relocating a data block group we group extents from the block group
into a cluster and when the cluster reaches a certain number of extents
we do the relocation.

The first step is reserving data space and we try to reserve more space
than we need if the block group is not full, when there are gaps between
the collected extents. What happens is we attempt to reserve an amount of
space that corresponds to the different between the end offset of the last
extent and the start offset of the first extent. This can cause us to fail
with -ENOSPC even when we have enough free space for relocating all the
extents. We should skip space reservation for any gaps which always exist
for block groups that are not full. Non full block groups are the ones
which are useful to relocate, therefore a common use case.

So fix this by tracking the total number of bytes used for all the extents
in the cluster and then reserving an amount of space that matches exactly
the sum of the sizes of all the collected extents.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/relocation.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 11d156995446..7ec75229d86f 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -108,6 +108,7 @@ struct tree_block {
 struct file_extent_cluster {
 	u64 start;
 	u64 end;
+	u64 total_bytes;
 	u64 boundary[MAX_EXTENTS];
 	unsigned int nr;
 };
@@ -2583,14 +2584,14 @@ int prealloc_file_extent_cluster(struct inode *inode,
 	int nr = 0;
 	int ret = 0;
 	u64 prealloc_start = cluster->start - offset;
-	u64 prealloc_end = cluster->end - offset;
 	u64 cur_offset;
+	u64 allocated = 0;
 
 	BUG_ON(cluster->start != cluster->boundary[0]);
 	inode_lock(inode);
 
 	ret = btrfs_alloc_data_chunk_ondemand(BTRFS_I(inode),
-					      prealloc_end + 1 - prealloc_start);
+					      cluster->total_bytes);
 	if (ret)
 		goto out;
 
@@ -2604,21 +2605,19 @@ int prealloc_file_extent_cluster(struct inode *inode,
 
 		lock_extent(&BTRFS_I(inode)->io_tree, start, end);
 		num_bytes = end + 1 - start;
-		if (cur_offset < start)
-			btrfs_free_reserved_data_space_noquota(inode,
-						       start - cur_offset);
 		ret = btrfs_prealloc_file_range(inode, 0, start,
 						num_bytes, num_bytes,
 						end + 1, &alloc_hint);
 		cur_offset = end + 1;
+		allocated += num_bytes;
 		unlock_extent(&BTRFS_I(inode)->io_tree, start, end);
 		if (ret)
 			break;
 		nr++;
 	}
-	if (cur_offset < prealloc_end)
+	if (allocated < cluster->total_bytes)
 		btrfs_free_reserved_data_space_noquota(inode,
-					       prealloc_end + 1 - cur_offset);
+				       cluster->total_bytes - allocated);
 out:
 	inode_unlock(inode);
 	return ret;
@@ -2809,6 +2808,7 @@ int relocate_data_extent(struct inode *inode, struct btrfs_key *extent_key,
 		if (ret)
 			return ret;
 		cluster->nr = 0;
+		cluster->total_bytes = 0;
 	}
 
 	if (!cluster->nr)
@@ -2818,12 +2818,14 @@ int relocate_data_extent(struct inode *inode, struct btrfs_key *extent_key,
 	cluster->end = extent_key->objectid + extent_key->offset - 1;
 	cluster->boundary[cluster->nr] = extent_key->objectid;
 	cluster->nr++;
+	cluster->total_bytes += extent_key->offset;
 
 	if (cluster->nr >= MAX_EXTENTS) {
 		ret = relocate_file_extent_cluster(inode, cluster);
 		if (ret)
 			return ret;
 		cluster->nr = 0;
+		cluster->total_bytes = 0;
 	}
 	return 0;
 }
-- 
2.11.0


             reply	other threads:[~2020-06-09 10:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-09 10:19 fdmanana [this message]
2020-06-09 10:50 ` [PATCH 3/3] Btrfs: only allocate necessary space when relocating a data block group Nikolay Borisov
2020-06-09 10:57   ` Filipe Manana
2020-06-09 11:28     ` Nikolay Borisov
2020-06-09 12:07 ` kernel test robot

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=20200609101953.29559-1-fdmanana@kernel.org \
    --to=fdmanana@kernel.org \
    --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.