diff mbox

[4/7] btrfs-progs: extent-tree: Introduce functions to free chunk items

Message ID 1436256928-23812-5-git-send-email-quwenruo@cn.fujitsu.com (mailing list archive)
State Accepted
Headers show

Commit Message

Qu Wenruo July 7, 2015, 8:15 a.m. UTC
Introduce two functions, free_chunk_item and free_system_chunk_item.
First one will free chunk item in chunk tree.
The latter one will free a system chunk in super block.

They are used for later chunk/block group free function.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
 extent-tree.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)
diff mbox

Patch

diff --git a/extent-tree.c b/extent-tree.c
index afc7822..499838c 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -3557,6 +3557,92 @@  out:
 	return ret;
 }
 
+static int free_system_chunk_item(struct btrfs_super_block *super,
+				  struct btrfs_key *key)
+{
+	struct btrfs_disk_key *disk_key;
+	struct btrfs_key cpu_key;
+	u32 array_size = btrfs_super_sys_array_size(super);
+	char *ptr = (char *)super->sys_chunk_array;
+	int cur = 0;
+	int ret = -ENOENT;
+
+	while (cur < btrfs_super_sys_array_size(super)) {
+		struct btrfs_chunk *chunk;
+		u32 num_stripes;
+		u32 chunk_len;
+
+		disk_key = (struct btrfs_disk_key *)(ptr + cur);
+		btrfs_disk_key_to_cpu(&cpu_key, disk_key);
+		if (cpu_key.type != BTRFS_CHUNK_ITEM_KEY) {
+			/* just in case */
+			ret = -EIO;
+			goto out;
+		}
+
+		chunk = (struct btrfs_chunk *)(ptr + cur + sizeof(*disk_key));
+		num_stripes = btrfs_stack_chunk_num_stripes(chunk);
+		chunk_len = btrfs_chunk_item_size(num_stripes) +
+			    sizeof(*disk_key);
+
+		if (key->objectid == cpu_key.objectid &&
+		    key->offset == cpu_key.offset &&
+		    key->type == cpu_key.type) {
+			memmove(ptr + cur, ptr + cur + chunk_len,
+				array_size - cur - chunk_len);
+			array_size -= chunk_len;
+			btrfs_set_super_sys_array_size(super, array_size);
+			ret = 0;
+			goto out;
+		}
+
+		cur += chunk_len;
+	}
+out:
+	return ret;
+}
+
+static int free_chunk_item(struct btrfs_trans_handle *trans,
+			   struct btrfs_fs_info *fs_info,
+			   u64 bytenr, u64 len)
+{
+	struct btrfs_path *path;
+	struct btrfs_key key;
+	struct btrfs_root *root = fs_info->chunk_root;
+	struct btrfs_chunk *chunk;
+	u64 chunk_type;
+	int ret;
+
+	key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
+	key.offset = bytenr;
+	key.type = BTRFS_CHUNK_ITEM_KEY;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+
+	ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
+	if (ret > 0) {
+		ret = -ENOENT;
+		goto out;
+	}
+	if (ret < 0)
+		goto out;
+	chunk = btrfs_item_ptr(path->nodes[0], path->slots[0],
+			       struct btrfs_chunk);
+	chunk_type = btrfs_chunk_type(path->nodes[0], chunk);
+
+	ret = btrfs_del_item(trans, root, path);
+	if (ret < 0)
+		goto out;
+
+	if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM)
+		ret = free_system_chunk_item(fs_info->super_copy, &key);
+out:
+	btrfs_free_path(path);
+	return ret;
+}
+
 /*
  * Fixup block accounting. The initial block accounting created by
  * make_block_groups isn't accuracy in this case.