Thread (9 messages) 9 messages, 7 authors, 2012-01-20

Re: [RFC][PATCH 1/2] Btrfs: try to allocate new chunks with degenerated profile

From: Arne Jansen <hidden>
Date: 2012-01-18 10:14:23

On 17.01.2012 11:02, Miao Xie wrote:
If there is no free space, the free space allocator will try to get space from
the block group with the degenerated profile. For example, if there is no free
space in the RAID1 block groups, the allocator will try to allocate space from
the DUP block groups. And besides that, the space reservation has the similar
behaviour: if there is no enough space in the space cache to reserve, it will
reserve the space according to the disk space, and it just take mirror storage
into account, no RAID0, RAID1, or RAID10.

So we'd better make the behaviour of chunk allocation correspond with space
reservation and free space allocation, if there is no enough disk space to
allocate RAID(RAID0, RAID1, RAID10) chunks, we degenerate the profile and try
to allocate chunks again. Otherwise, enospc will happen though we reserve
the space successfully and BUG_ON() will be triggered.

Degenerating rule:
  RAID10 -> RAID1 -> DUP
  RAID0 -> SINGLE
Instead of changing the profile, wouldn't it be easier to just allow
RAID10 go down to 2 disks and RAID0 to 1? That would make things easier
in many places.
What I'm strongly opposed to is changing a RAID1 to DUP, as this loses
the protection against a single disk failure.

-Arne
quoted hunk ↗ jump to hunk
Signed-off-by: Miao Xie <redacted>
---
 fs/btrfs/extent-tree.c |   43 +++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3e68e2b..87cd611 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3065,6 +3065,30 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
 	return flags;
 }
 
+/*
+ * Degenerate the alloc profile:
+ *   RAID10 -> RAID1 -> DUP
+ *   RAID0 -> SINGLE
+ *
+ * This is used when there is no enough disk space to do chunk allocation.
+ * After degenerating the profile, we will try to allocate new chunks again.
+ */
+static u64 btrfs_degenerate_alloc_profile(u64 flags)
+{
+	if (flags & BTRFS_BLOCK_GROUP_RAID10) {
+		flags &= ~BTRFS_BLOCK_GROUP_RAID10;
+		flags |= BTRFS_BLOCK_GROUP_RAID1;
+	} else if (flags & BTRFS_BLOCK_GROUP_RAID1) {
+		flags &= ~BTRFS_BLOCK_GROUP_RAID1;
+		flags |= BTRFS_BLOCK_GROUP_DUP;
+	} else if (flags & BTRFS_BLOCK_GROUP_RAID0) {
+		flags &= ~BTRFS_BLOCK_GROUP_RAID0;
+	} else
+		flags = ULLONG_MAX;
+
+	return flags;
+}
+
 static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
 {
 	if (flags & BTRFS_BLOCK_GROUP_DATA)
@@ -3356,8 +3380,23 @@ again:
 	}
 
 	ret = btrfs_alloc_chunk(trans, extent_root, flags);
-	if (ret < 0 && ret != -ENOSPC)
-		goto out;
+	if (ret < 0) {
+		if (ret != -ENOSPC)
+			goto out;
+
+		/*
+		 * Degenerate the alloc profile:
+		 *   RAID10 -> RAID1 -> DUP
+		 *   RAID0 -> SINGLE
+		 * then we will try to allocate new chunks again. By this way,
+		 * we can utilize the whole disk spacem and make the behaviour
+		 * of the chunk allocation correspond with the space reservation
+		 * and the free space allocation.
+		 */
+		flags = btrfs_degenerate_alloc_profile(flags);
+		if (flags != ULLONG_MAX)
+			goto again;
+	}
 
 	spin_lock(&space_info->lock);
 	if (ret)
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help