[Btrfs-devel][PATCH]Move general functions in mkfs.c to utils.c

Yan Zheng yanzheng at 21cn.com
Wed Dec 19 05:34:12 PST 2007


Hello,

This patch moves some general functions in mkfs.c to utils.c. These
functions are used by the ext2 to btrfs conversion program. The patch
also adds back reference support to  mkfs.

Regards
YZ
----
diff -r d44ee01dd214 Makefile
--- a/Makefile	Wed Dec 19 20:48:42 2007 +0800
+++ b/Makefile	Wed Dec 19 20:51:34 2007 +0800
@@ -35,8 +35,8 @@ btrfsck: $(objects) btrfsck.o bit-radix.
 btrfsck: $(objects) btrfsck.o bit-radix.o
 	gcc $(CFLAGS) -o btrfsck btrfsck.o $(objects) bit-radix.o $(LDFLAGS)

-mkfs.btrfs: $(objects) mkfs.o
-	gcc $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o -luuid $(LDFLAGS)
+mkfs.btrfs: $(objects) mkfs.o utils.o
+	gcc $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o utils.o -luuid $(LDFLAGS)

 debug-tree: $(objects) debug-tree.o
 	gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o -luuid $(LDFLAGS)
diff -r d44ee01dd214 extent-tree.c
--- a/extent-tree.c	Wed Dec 19 20:48:42 2007 +0800
+++ b/extent-tree.c	Wed Dec 19 20:51:34 2007 +0800
@@ -504,6 +504,7 @@ static int __free_extent(struct btrfs_tr
 	if (ret == 0) {
 		ret = btrfs_del_item(trans, extent_root, &path);
 	} else {
+		BUG();
 		// FIXME deal with missing references here
 	}

diff -r d44ee01dd214 mkfs.c
--- a/mkfs.c	Wed Dec 19 20:48:42 2007 +0800
+++ b/mkfs.c	Wed Dec 19 20:51:34 2007 +0800
@@ -33,111 +33,12 @@
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
+#include "utils.h"

 #ifdef __CHECKER__
 #define BLKGETSIZE64 0
 static inline int ioctl(int fd, int define, u64 *size) { return 0; }
 #endif
-
-static int __make_root_dir(struct btrfs_trans_handle *trans,
-			   struct btrfs_root *root, u64 objectid)
-{
-	int ret;
-	char buf[8];
-	struct btrfs_key inode_map;
-	struct btrfs_inode_item inode_item;
-
-	buf[0] = '.';
-	buf[1] = '.';
-
-	inode_map.objectid = objectid;
-	btrfs_set_key_type(&inode_map, BTRFS_INODE_ITEM_KEY);
-	inode_map.offset = 0;
-
-	memset(&inode_item, 0, sizeof(inode_item));
-	btrfs_set_inode_generation(&inode_item, root->fs_info->generation);
-	btrfs_set_inode_size(&inode_item, 0);
-	btrfs_set_inode_nlink(&inode_item, 1);
-	btrfs_set_inode_nblocks(&inode_item, 0);
-	btrfs_set_inode_mode(&inode_item, S_IFDIR | 0555);
-
-	if (root->fs_info->tree_root == root)
-		btrfs_set_super_root_dir(root->fs_info->disk_super, objectid);
-
-	ret = btrfs_insert_inode(trans, root, objectid, &inode_item);
-	if (ret)
-		goto error;
-
-	ret = btrfs_insert_inode_ref(trans, root, "..", 2, objectid, objectid);
-	if (ret)
-		goto error;
-	btrfs_set_root_dirid(&root->root_item, objectid);
-	ret = 0;
-error:
-	return ret;
-}
-
-static int make_block_groups(struct btrfs_trans_handle *trans,
-			     struct btrfs_root *root)
-{
-	u64 group_size;
-	u64 total_bytes;
-	u64 cur_start;
-	int ret;
-	u64 nr = 0;
-	struct btrfs_block_group_cache *cache;
-	struct cache_tree *bg_cache = &root->fs_info->block_group_cache;
-
-	root = root->fs_info->extent_root;
-
-	/* first we bootstrap the things into cache */
-	group_size = BTRFS_BLOCK_GROUP_SIZE;
-	cache = malloc(sizeof(*cache));
-	cache->key.objectid = 0;
-	cache->key.offset = group_size;
-	cache->cache.start = 0;
-	cache->cache.size = group_size;
-	btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
-
-	memset(&cache->item, 0, sizeof(cache->item));
-	btrfs_set_block_group_used(&cache->item,
-			   btrfs_super_bytes_used(root->fs_info->disk_super));
-	ret = insert_existing_cache_extent(bg_cache, &cache->cache);
-	BUG_ON(ret);
-
-	total_bytes = btrfs_super_total_bytes(root->fs_info->disk_super);
-	cur_start = group_size;
-	while(cur_start < total_bytes) {
-		cache = malloc(sizeof(*cache));
-		cache->key.objectid = cur_start;
-		cache->key.offset = group_size;
-		cache->cache.start = cur_start;
-		cache->cache.size = group_size;
-		btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
-		memset(&cache->item, 0, sizeof(cache->item));
-		if (nr % 3)
-			cache->item.flags |= BTRFS_BLOCK_GROUP_DATA;
-
-		ret = insert_existing_cache_extent(bg_cache, &cache->cache);
-		BUG_ON(ret);
-		cur_start += group_size;
-		nr++;
-	}
-	/* then insert all the items */
-	cur_start = 0;
-	while(cur_start < total_bytes) {
-		struct cache_extent *ce;
-		ce = find_first_cache_extent(bg_cache, cur_start);
-		BUG_ON(!ce);
-		cache = container_of(ce, struct btrfs_block_group_cache,
-					cache);
-		ret = btrfs_insert_block_group(trans, root, &cache->key,
-					       &cache->item);
-		BUG_ON(ret);
-		cur_start += group_size;
-	}
-	return 0;
-}

 static int make_root_dir(int fd) {
 	struct btrfs_root *root;
@@ -154,11 +55,11 @@ static int make_root_dir(int fd) {
 	}
 	trans = btrfs_start_transaction(root, 1);
 	ret = make_block_groups(trans, root);
-	ret = __make_root_dir(trans, root->fs_info->tree_root,
+	ret = btrfs_make_root_dir(trans, root->fs_info->tree_root,
 			      BTRFS_ROOT_TREE_DIR_OBJECTID);
 	if (ret)
 		goto err;
-	ret = __make_root_dir(trans, root, BTRFS_FIRST_FREE_OBJECTID);
+	ret = btrfs_make_root_dir(trans, root, BTRFS_FIRST_FREE_OBJECTID);
 	if (ret)
 		goto err;
 	memcpy(&location, &root->fs_info->fs_root->root_key, sizeof(location));
@@ -172,7 +73,7 @@ static int make_root_dir(int fd) {

 	ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root,
 			     "default", 7, location.objectid,
-			     BTRFS_ROOT_TREE_DIR_OBJECTID);
+			     btrfs_super_root_dir(root->fs_info->disk_super));
 	if (ret)
 		goto err;

@@ -180,148 +81,6 @@ static int make_root_dir(int fd) {
 	ret = close_ctree(root, &super);
 err:
 	return ret;
-}
-
-int mkfs(int fd, char *pathname, u64 num_bytes, u32 nodesize, u32 leafsize,
-	 u32 sectorsize, u32 stripesize)
-{
-	struct btrfs_super_block super;
-	struct btrfs_leaf *empty_leaf;
-	struct btrfs_root_item root_item;
-	struct btrfs_item item;
-	struct btrfs_extent_item extent_item;
-	struct btrfs_inode_item *inode_item;
-	char *block;
-	int ret;
-	u32 itemoff;
-	u32 start_block = BTRFS_SUPER_INFO_OFFSET;
-	u32 first_free = BTRFS_SUPER_INFO_OFFSET + sectorsize;
-
-	btrfs_set_super_generation(&super, 1);
-	btrfs_set_super_bytenr(&super, start_block);
-	btrfs_set_super_root_level(&super, 0);
-	btrfs_set_super_root(&super, first_free);
-	strcpy((char *)(&super.magic), BTRFS_MAGIC);
-
-printf("blocksize is %d\n", leafsize);
-	btrfs_set_super_sectorsize(&super, sectorsize);
-	btrfs_set_super_leafsize(&super, leafsize);
-	btrfs_set_super_nodesize(&super, nodesize);
-	btrfs_set_super_stripesize(&super, stripesize);
-
-	num_bytes = (num_bytes / sectorsize) * sectorsize;
-	btrfs_set_super_total_bytes(&super, num_bytes);
-	btrfs_set_super_bytes_used(&super, start_block + 3 * leafsize +
-				   sectorsize);
-	uuid_generate(super.fsid);
-
-	block = malloc(sectorsize);
-	memset(block, 0, sectorsize);
-	BUG_ON(sizeof(super) > sectorsize);
-	memcpy(block, &super, sizeof(super));
-	ret = pwrite(fd, block, sectorsize, BTRFS_SUPER_INFO_OFFSET);
-	BUG_ON(ret != sectorsize);
-
-	/* create the tree of root objects */
-	empty_leaf = malloc(leafsize);
-	memset(empty_leaf, 0, leafsize);
-	btrfs_set_header_bytenr(&empty_leaf->header, first_free);
-	btrfs_set_header_nritems(&empty_leaf->header, 2);
-	btrfs_set_header_generation(&empty_leaf->header, 1);
-	btrfs_set_header_owner(&empty_leaf->header, BTRFS_ROOT_TREE_OBJECTID);
-	memcpy(empty_leaf->header.fsid, super.fsid,
-	       sizeof(empty_leaf->header.fsid));
-
-	/* create the items for the root tree */
-	inode_item = &root_item.inode;
-	memset(inode_item, 0, sizeof(*inode_item));
-	btrfs_set_inode_generation(inode_item, 1);
-	btrfs_set_inode_size(inode_item, 3);
-	btrfs_set_inode_nlink(inode_item, 1);
-	btrfs_set_inode_nblocks(inode_item, 1);
-	btrfs_set_inode_mode(inode_item, S_IFDIR | 0755);
-
-	// memset(&root_item, 0, sizeof(root_item));
-	btrfs_set_root_dirid(&root_item, 0);
-	btrfs_set_root_refs(&root_item, 1);
-	btrfs_set_disk_key_offset(&item.key, 0);
-	btrfs_set_item_size(&item, sizeof(root_item));
-	btrfs_set_disk_key_type(&item.key, BTRFS_ROOT_ITEM_KEY);
-
-	itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) - sizeof(root_item);
-	btrfs_set_root_bytenr(&root_item, first_free + leafsize);
-	root_item.level = 0;
-	btrfs_set_item_offset(&item, itemoff);
-	btrfs_set_disk_key_objectid(&item.key, BTRFS_EXTENT_TREE_OBJECTID);
-	memcpy(empty_leaf->items, &item, sizeof(item));
-	memcpy(btrfs_leaf_data(empty_leaf) + itemoff,
-		&root_item, sizeof(root_item));
-
-	btrfs_set_root_bytenr(&root_item, first_free + leafsize * 2);
-	btrfs_set_root_bytes_used(&root_item, 1);
-	itemoff = itemoff - sizeof(root_item);
-	btrfs_set_item_offset(&item, itemoff);
-	btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID);
-	memcpy(empty_leaf->items + 1, &item, sizeof(item));
-	memcpy(btrfs_leaf_data(empty_leaf) + itemoff,
-		&root_item, sizeof(root_item));
-	ret = pwrite(fd, empty_leaf, leafsize, first_free);
-
-	/* create the items for the extent tree */
-	btrfs_set_header_bytenr(&empty_leaf->header, first_free + leafsize);
-	btrfs_set_header_nritems(&empty_leaf->header, 4);
-
-	/* item1, reserve blocks 0-16 */
-	btrfs_set_disk_key_objectid(&item.key, 0);
-	btrfs_set_disk_key_offset(&item.key, first_free);
-	btrfs_set_disk_key_type(&item.key, 0);
-	btrfs_set_disk_key_type(&item.key, BTRFS_EXTENT_ITEM_KEY);
-	itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) -
-			sizeof(struct btrfs_extent_item);
-	btrfs_set_item_offset(&item, itemoff);
-	btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item));
-	btrfs_set_extent_refs(&extent_item, 1);
-	memcpy(empty_leaf->items, &item, sizeof(item));
-	memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
-		&extent_item, btrfs_item_size(&item));
-
-	/* item2, give block 17 to the root */
-	btrfs_set_disk_key_objectid(&item.key, first_free);
-	btrfs_set_disk_key_offset(&item.key, leafsize);
-	itemoff = itemoff - sizeof(struct btrfs_extent_item);
-	btrfs_set_item_offset(&item, itemoff);
-	memcpy(empty_leaf->items + 1, &item, sizeof(item));
-	memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
-		&extent_item, btrfs_item_size(&item));
-
-	/* item3, give block 18 to the extent root */
-	btrfs_set_disk_key_objectid(&item.key, first_free + leafsize);
-	btrfs_set_disk_key_offset(&item.key, leafsize);
-	itemoff = itemoff - sizeof(struct btrfs_extent_item);
-	btrfs_set_item_offset(&item, itemoff);
-	memcpy(empty_leaf->items + 2, &item, sizeof(item));
-	memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
-		&extent_item, btrfs_item_size(&item));
-
-	/* item4, give block 19 to the FS root */
-	btrfs_set_disk_key_objectid(&item.key, first_free + leafsize * 2);
-	btrfs_set_disk_key_offset(&item.key, leafsize);
-	itemoff = itemoff - sizeof(struct btrfs_extent_item);
-	btrfs_set_item_offset(&item, itemoff);
-	memcpy(empty_leaf->items + 3, &item, sizeof(item));
-	memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
-		&extent_item, btrfs_item_size(&item));
-	ret = pwrite(fd, empty_leaf, leafsize, first_free + leafsize);
-	if (ret != leafsize)
-		return -1;
-
-	/* finally create the FS root */
-	btrfs_set_header_bytenr(&empty_leaf->header, first_free + leafsize * 2);
-	btrfs_set_header_nritems(&empty_leaf->header, 0);
-	ret = pwrite(fd, empty_leaf, leafsize, first_free + leafsize * 2);
-	if (ret != leafsize)
-		return -1;
-	return 0;
 }

 u64 device_size(int fd, struct stat *st)
@@ -357,8 +116,8 @@ int main(int ac, char **av)
 	u32 sectorsize = 4096;
 	u32 nodesize = 16 * 1024;
 	u32 stripesize = 4096;
+	u64 blocks[4];
 	char *buf = malloc(sectorsize);
-	char *realpath_name;

 	while(1) {
 		int c;
@@ -431,9 +190,11 @@ int main(int ac, char **av)
 			exit(1);
 		}
 	}
-	realpath_name = realpath(file, NULL);
-	ret = mkfs(fd, realpath_name, block_count, nodesize, leafsize,
-		   sectorsize, stripesize);
+	for(i = 0; i < 4; i++) {
+		blocks[i] = BTRFS_SUPER_INFO_OFFSET + leafsize * i;
+	}
+	ret = make_btrfs(fd, blocks, block_count, nodesize, leafsize,
+			 sectorsize, stripesize);
 	if (ret) {
 		fprintf(stderr, "error during mkfs %d\n", ret);
 		exit(1);
diff -r d44ee01dd214 utils.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils.c	Wed Dec 19 20:51:34 2007 +0800
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#define _XOPEN_SOURCE 600
+#define __USE_XOPEN2K
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <uuid/uuid.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "kerncompat.h"
+#include "radix-tree.h"
+#include "ctree.h"
+#include "disk-io.h"
+#include "transaction.h"
+#include "crc32c.h"
+#include "utils.h"
+
+int make_btrfs(int fd, u64 new_blocks[4], u64 num_bytes, u32 nodesize,
+	       u32 leafsize, u32 sectorsize, u32 stripesize)
+{
+	struct btrfs_super_block super;
+	struct btrfs_root_item root_item;
+	struct btrfs_item item;
+	struct btrfs_extent_ref extent_ref;
+	struct btrfs_extent_item extent_item;
+	struct btrfs_inode_item *inode_item;
+	struct btrfs_leaf *empty_leaf = NULL;
+	char *buffer = NULL;
+	int i;
+	int ret;
+	u32 itemoff;
+	u32 nritems = 0;
+	u64 hash;
+	u64 first_free;
+
+	first_free = BTRFS_SUPER_INFO_OFFSET + sectorsize * 2 - 1;
+	first_free &= ~((u64)sectorsize - 1);
+
+	BUG_ON(sizeof(super) > sectorsize);
+
+	num_bytes = (num_bytes / sectorsize) * sectorsize;
+	uuid_generate(super.fsid);
+	btrfs_set_super_bytenr(&super, new_blocks[0]);
+	strcpy((char *)(&super.magic), BTRFS_MAGIC);
+	btrfs_set_super_generation(&super, 1);
+	btrfs_set_super_root(&super, new_blocks[1]);
+	btrfs_set_super_total_bytes(&super, num_bytes);
+	btrfs_set_super_bytes_used(&super, first_free + 3 * leafsize);
+	btrfs_set_super_root_dir(&super, BTRFS_ROOT_TREE_DIR_OBJECTID);
+	btrfs_set_super_sectorsize(&super, sectorsize);
+	btrfs_set_super_leafsize(&super, leafsize);
+	btrfs_set_super_nodesize(&super, nodesize);
+	btrfs_set_super_stripesize(&super, stripesize);
+	btrfs_set_super_root_level(&super, 0);
+
+	buffer = malloc((sectorsize > leafsize) ? sectorsize : leafsize);
+	if (!buffer)
+		return -ENOMEM;
+	memset(buffer, 0, sectorsize);
+	memcpy(buffer, &super, sizeof(super));
+	ret = pwrite(fd, buffer, sectorsize, new_blocks[0]);
+	if (ret != sectorsize)
+		goto fail;
+
+	/* create the tree of root objects */
+	empty_leaf = (struct btrfs_leaf *)buffer;
+	memset(&empty_leaf->header, 0, sizeof(empty_leaf->header));
+	memcpy(empty_leaf->header.fsid, super.fsid,
+	       sizeof(empty_leaf->header.fsid));
+	btrfs_set_header_bytenr(&empty_leaf->header, new_blocks[1]);
+	btrfs_set_header_generation(&empty_leaf->header, 0);
+	btrfs_set_header_owner(&empty_leaf->header, BTRFS_ROOT_TREE_OBJECTID);
+	btrfs_set_header_nritems(&empty_leaf->header, 2);
+	btrfs_set_header_flags(&empty_leaf->header, 0);
+	btrfs_set_header_level(&empty_leaf->header, 0);
+
+	/* create the items for the root tree */
+	inode_item = &root_item.inode;
+	memset(inode_item, 0, sizeof(*inode_item));
+	btrfs_set_inode_generation(inode_item, 1);
+	btrfs_set_inode_size(inode_item, 3);
+	btrfs_set_inode_nlink(inode_item, 1);
+	btrfs_set_inode_nblocks(inode_item, 1);
+	btrfs_set_inode_mode(inode_item, S_IFDIR | 0755);
+
+	btrfs_set_root_dirid(&root_item, 0);
+	btrfs_set_root_bytenr(&root_item, new_blocks[2]);
+	btrfs_set_root_byte_limit(&root_item, 0);
+	btrfs_set_root_bytes_used(&root_item, leafsize);
+	btrfs_set_root_flags(&root_item, 0);
+	btrfs_set_root_refs(&root_item, 1);
+	memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
+	root_item.drop_level = 0;
+	root_item.level = 0;
+
+	btrfs_set_disk_key_objectid(&item.key, BTRFS_EXTENT_TREE_OBJECTID);
+	btrfs_set_disk_key_type(&item.key, BTRFS_ROOT_ITEM_KEY);
+	btrfs_set_disk_key_offset(&item.key, 0);
+	itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) - sizeof(root_item);
+	btrfs_set_item_offset(&item, itemoff);
+	btrfs_set_item_size(&item, sizeof(root_item));
+	memcpy(empty_leaf->items, &item, sizeof(item));
+	memcpy(btrfs_leaf_data(empty_leaf) + itemoff,
+			&root_item, sizeof(root_item));
+
+	btrfs_set_root_dirid(&root_item, BTRFS_FIRST_FREE_OBJECTID);
+	btrfs_set_root_bytenr(&root_item, new_blocks[3]);
+	itemoff = itemoff - sizeof(root_item);
+	btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID);
+	btrfs_set_item_offset(&item, itemoff);
+	memcpy(empty_leaf->items + 1, &item, sizeof(item));
+	memcpy(btrfs_leaf_data(empty_leaf) + itemoff,
+			&root_item, sizeof(root_item));
+
+	ret = pwrite(fd, empty_leaf, leafsize, new_blocks[1]);
+        if (ret != leafsize)
+		goto fail;
+
+	/* create the items for the extent tree */
+	btrfs_set_extent_refs(&extent_item, 1);
+
+	/* create extent item */
+	btrfs_set_disk_key_objectid(&item.key, 0);
+	btrfs_set_disk_key_offset(&item.key, first_free);
+	btrfs_set_disk_key_type(&item.key, BTRFS_EXTENT_ITEM_KEY);
+	itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) -
+		  sizeof(struct btrfs_extent_item);
+	btrfs_set_item_offset(&item, itemoff);
+	btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item));
+	memcpy(empty_leaf->items + nritems++, &item, sizeof(item));
+	memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
+			&extent_item, btrfs_item_size(&item));
+
+	btrfs_set_ref_root(&extent_ref, 0);
+	btrfs_set_ref_generation(&extent_ref, 0);
+	btrfs_set_ref_objectid(&extent_ref, 0);
+	btrfs_set_ref_offset(&extent_ref, 0);
+	for (i = 0; i < 4; i++) {
+		if (new_blocks[i] < first_free) {
+			BUG_ON(i != 0);
+			continue;
+		}
+		/* create extent item */
+		btrfs_set_disk_key_objectid(&item.key, new_blocks[i]);
+		btrfs_set_disk_key_offset(&item.key, leafsize);
+		btrfs_set_disk_key_type(&item.key, BTRFS_EXTENT_ITEM_KEY);
+		itemoff = itemoff - sizeof(struct btrfs_extent_item);
+		btrfs_set_item_offset(&item, itemoff);
+		btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item));
+		memcpy(empty_leaf->items + nritems++, &item, sizeof(item));
+		memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
+				&extent_item, btrfs_item_size(&item));
+		/* create extent ref */
+		hash = hash_extent_ref(i, 0, 0, 0);
+		btrfs_set_disk_key_objectid(&item.key, new_blocks[i]);
+		btrfs_set_disk_key_offset(&item.key, hash);
+		btrfs_set_disk_key_type(&item.key, BTRFS_EXTENT_REF_KEY);
+		itemoff = itemoff - sizeof(struct btrfs_extent_ref);
+		btrfs_set_item_offset(&item, itemoff);
+		btrfs_set_item_size(&item, sizeof(struct btrfs_extent_ref));
+		btrfs_set_ref_root(&extent_ref, i);
+		memcpy(empty_leaf->items + nritems++, &item, sizeof(item));
+		memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
+				&extent_ref, btrfs_item_size(&item));
+	}
+
+	btrfs_set_header_bytenr(&empty_leaf->header, new_blocks[2]);
+	btrfs_set_header_owner(&empty_leaf->header, BTRFS_EXTENT_TREE_OBJECTID);
+	btrfs_set_header_nritems(&empty_leaf->header, nritems);
+	ret = pwrite(fd, empty_leaf, leafsize, new_blocks[2]);
+        if (ret != leafsize)
+		goto fail;
+
+	/* finally create the FS root */
+	btrfs_set_header_bytenr(&empty_leaf->header, new_blocks[3]);
+	btrfs_set_header_owner(&empty_leaf->header, BTRFS_FS_TREE_OBJECTID);
+	btrfs_set_header_nritems(&empty_leaf->header, 0);
+	ret = pwrite(fd, empty_leaf, leafsize, new_blocks[3]);
+        if (ret != leafsize)
+		goto fail;
+	ret = 0;
+fail:
+	free(buffer);
+	return 0;
+}
+
+int btrfs_make_root_dir(struct btrfs_trans_handle *trans,
+			struct btrfs_root *root, u64 objectid)
+{
+	int ret;
+	struct btrfs_inode_item inode_item;
+
+	memset(&inode_item, 0, sizeof(inode_item));
+	btrfs_set_inode_generation(&inode_item, trans->transid);
+	btrfs_set_inode_size(&inode_item, 0);
+	btrfs_set_inode_nlink(&inode_item, 1);
+	btrfs_set_inode_nblocks(&inode_item, 1);
+	btrfs_set_inode_mode(&inode_item, S_IFDIR | 0555);
+
+	if (root->fs_info->tree_root == root)
+		btrfs_set_super_root_dir(root->fs_info->disk_super, objectid);
+
+	ret = btrfs_insert_inode(trans, root, objectid, &inode_item);
+	if (ret)
+		goto error;
+	
+	ret = btrfs_insert_inode_ref(trans, root, "..", 2, objectid, objectid);
+	if (ret)
+		goto error;
+
+	btrfs_set_root_dirid(&root->root_item, objectid);
+	ret = 0;
+error:
+	return ret;
+}
+
+int make_block_groups(struct btrfs_trans_handle *trans,
+		      struct btrfs_root *root)
+{
+	u64 group_size;
+	u64 total_bytes;
+	u64 cur_start;
+	int ret;
+	u64 nr = 0;
+	struct btrfs_block_group_cache *cache;
+	struct cache_tree *bg_cache = &root->fs_info->block_group_cache;
+
+	root = root->fs_info->extent_root;
+
+	/* first we bootstrap the things into cache */
+	group_size = BTRFS_BLOCK_GROUP_SIZE;
+	cache = malloc(sizeof(*cache));
+	cache->key.objectid = 0;
+	cache->key.offset = group_size;
+	cache->cache.start = 0;
+	cache->cache.size = group_size;
+	btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
+
+	memset(&cache->item, 0, sizeof(cache->item));
+	btrfs_set_block_group_used(&cache->item,
+			   btrfs_super_bytes_used(root->fs_info->disk_super));
+	ret = insert_existing_cache_extent(bg_cache, &cache->cache);
+	BUG_ON(ret);
+
+	total_bytes = btrfs_super_total_bytes(root->fs_info->disk_super);
+	cur_start = group_size;
+	while(cur_start < total_bytes) {
+		cache = malloc(sizeof(*cache));
+		cache->key.objectid = cur_start;
+		cache->key.offset = group_size;
+		cache->cache.start = cur_start;
+		cache->cache.size = group_size;
+		btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
+		memset(&cache->item, 0, sizeof(cache->item));
+		if (nr % 3)
+			cache->item.flags |= BTRFS_BLOCK_GROUP_DATA;
+
+		ret = insert_existing_cache_extent(bg_cache, &cache->cache);
+		BUG_ON(ret);
+		cur_start += group_size;
+		nr++;
+	}
+	/* then insert all the items */
+	cur_start = 0;
+	while(cur_start < total_bytes) {
+		struct cache_extent *ce;
+		ce = find_first_cache_extent(bg_cache, cur_start);
+		BUG_ON(!ce);
+		cache = container_of(ce, struct btrfs_block_group_cache,
+					cache);
+		ret = btrfs_insert_block_group(trans, root, &cache->key,
+					       &cache->item);
+		BUG_ON(ret);
+		cur_start += group_size;
+	}
+	return 0;
+}
diff -r d44ee01dd214 utils.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils.h	Wed Dec 19 20:51:34 2007 +0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#ifndef __UTILS__
+#define __UTILS__
+int make_btrfs(int fd, u64 new_blocks[4], u64 num_bytes, u32 nodesize,
+		u32 leafsize, u32 sectorsize, u32 stripesize);
+int btrfs_make_empty_dir(struct btrfs_trans_handle *trans,
+		struct btrfs_root *root, u64 objectid, u64 dirid);
+int btrfs_make_root_dir(struct btrfs_trans_handle *trans,
+			struct btrfs_root *root, u64 objectid);
+int make_block_groups(struct btrfs_trans_handle *trans,
+		      struct btrfs_root *root);
+#endif
+



More information about the Btrfs-devel mailing list