Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a8dd150 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse
Browse files

Btrfs: Block sized tree extents and extent deletion

parent 5c680ed6
Loading
Loading
Loading
Loading
+198 −47
Original line number Original line Diff line number Diff line
@@ -8,9 +8,12 @@
#define SEARCH_READ 0
#define SEARCH_READ 0
#define SEARCH_WRITE 1
#define SEARCH_WRITE 1


static int refill_alloc_extent(struct ctree_root *root);
#define CTREE_EXTENT_PENDING 0

int split_node(struct ctree_root *root, struct ctree_path *path, int level);
int split_node(struct ctree_root *root, struct ctree_path *path, int level);
int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size);
int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size);
struct tree_buffer *alloc_free_block(struct ctree_root *root);
int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks);


static inline void init_path(struct ctree_path *p)
static inline void init_path(struct ctree_path *p)
{
{
@@ -682,8 +685,6 @@ int insert_item(struct ctree_root *root, struct key *key,
	unsigned int data_end;
	unsigned int data_end;
	struct ctree_path path;
	struct ctree_path path;


	refill_alloc_extent(root);

	/* create a root if there isn't one */
	/* create a root if there isn't one */
	if (!root->node)
	if (!root->node)
		BUG();
		BUG();
@@ -756,6 +757,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level)
	struct tree_buffer *t;
	struct tree_buffer *t;
	struct node *node;
	struct node *node;
	int nritems;
	int nritems;
	u64 blocknr;


	while(1) {
	while(1) {
		t = path->nodes[level];
		t = path->nodes[level];
@@ -774,6 +776,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level)
		}
		}
		node->header.nritems--;
		node->header.nritems--;
		write_tree_block(root, t);
		write_tree_block(root, t);
		blocknr = t->blocknr;
		if (node->header.nritems != 0) {
		if (node->header.nritems != 0) {
			int tslot;
			int tslot;
			if (slot == 0)
			if (slot == 0)
@@ -799,6 +802,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level)
			break;
			break;
		}
		}
		level++;
		level++;
		free_extent(root, blocknr, 1);
		if (!path->nodes[level])
		if (!path->nodes[level])
			BUG();
			BUG();
	}
	}
@@ -841,8 +845,10 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
		if (leaf_buf == root->node) {
		if (leaf_buf == root->node) {
			leaf->header.flags = node_level(0);
			leaf->header.flags = node_level(0);
			write_tree_block(root, leaf_buf);
			write_tree_block(root, leaf_buf);
		} else
		} else {
			del_ptr(root, path, 1);
			del_ptr(root, path, 1);
			free_extent(root, leaf_buf->blocknr, 1);
		}
	} else {
	} else {
		if (slot == 0)
		if (slot == 0)
			fixup_low_keys(root, path, &leaf->items[0].key, 1);
			fixup_low_keys(root, path, &leaf->items[0].key, 1);
@@ -867,6 +873,72 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
	return 0;
	return 0;
}
}


static int del_pending_extents(struct ctree_root *extent_root)
{
	int ret;
	struct key key;
	struct tree_buffer *gang[4];
	int i;
	struct ctree_path path;

	while(1) {
		ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix,
						 (void **)gang, 0, ARRAY_SIZE(gang),
						 CTREE_EXTENT_PENDING);
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
			key.objectid = gang[i]->blocknr;
			key.flags = 0;
			key.offset = 1;
			init_path(&path);
			ret = search_slot(extent_root, &key, &path, 0);
			if (ret) {
				BUG();
				// FIXME undo it and return sane
				return ret;
			}
			ret = del_item(extent_root, &path);
			if (ret) {
				BUG();
				return ret;
			}
			release_path(extent_root, &path);
			radix_tree_tag_clear(&extent_root->cache_radix, gang[i]->blocknr,
						CTREE_EXTENT_PENDING);
			tree_block_release(extent_root, gang[i]);
		}
	}
	return 0;
}

int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks)
{
	struct ctree_path path;
	struct key key;
	struct ctree_root *extent_root = root->extent_root;
	struct tree_buffer *t;
	int pending_ret;
	int ret;

	key.objectid = blocknr;
	key.flags = 0;
	key.offset = num_blocks;
	if (root == extent_root) {
		t = read_tree_block(root, key.objectid);
		radix_tree_tag_set(&root->cache_radix, key.objectid, CTREE_EXTENT_PENDING);
		return 0;
	}
	init_path(&path);
	ret = search_slot(extent_root, &key, &path, 0);
	if (ret)
		BUG();
	ret = del_item(extent_root, &path);
	release_path(extent_root, &path);
	pending_ret = del_pending_extents(root->extent_root);
	return ret ? ret : pending_ret;
}

int next_leaf(struct ctree_root *root, struct ctree_path *path)
int next_leaf(struct ctree_root *root, struct ctree_path *path)
{
{
	int slot;
	int slot;
@@ -904,8 +976,8 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path)
	return 0;
	return 0;
}
}


int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start,
int find_free_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start,
		 u64 search_end, u64 owner, struct key *ins)
			 u64 search_end, struct key *ins)
{
{
	struct ctree_path path;
	struct ctree_path path;
	struct key *key;
	struct key *key;
@@ -915,15 +987,13 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start,
	u64 last_block;
	u64 last_block;
	int start_found = 0;
	int start_found = 0;
	struct leaf *l;
	struct leaf *l;
	struct extent_item extent_item;
	struct ctree_root * root = orig_root->extent_root;
	struct ctree_root * root = orig_root->extent_root;


	init_path(&path);
	init_path(&path);
	ins->objectid = search_start;
	ins->objectid = search_start;
	ins->offset = 0;
	ins->offset = 0;
	ins->flags = 0;
	ins->flags = 0;

	ret = search_slot(root, ins, &path, 0);
	ret = search_slot(root, ins, &path, sizeof(struct extent_item));
	while (1) {
	while (1) {
		l = &path.nodes[0]->leaf;
		l = &path.nodes[0]->leaf;
		slot = path.slots[0];
		slot = path.slots[0];
@@ -938,6 +1008,7 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start,
				ins->objectid = search_start;
				ins->objectid = search_start;
				ins->offset = num_blocks;
				ins->offset = num_blocks;
				hole_size = search_end - search_start;
				hole_size = search_end - search_start;
				start_found = 1;
				goto insert;
				goto insert;
			}
			}
			ins->objectid = last_block;
			ins->objectid = last_block;
@@ -956,51 +1027,119 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start,
		} else
		} else
			start_found = 1;
			start_found = 1;
		last_block = key->objectid + key->offset;
		last_block = key->objectid + key->offset;
insert_failed:
		path.slots[0]++;
		path.slots[0]++;
	}
	}
	// FIXME -ENOSPC
	// FIXME -ENOSPC
insert:
insert:
	if (orig_root->extent_root == orig_root) {
		BUG_ON(num_blocks != 1);
		if ((root->current_insert.objectid <= ins->objectid &&
		    root->current_insert.objectid + root->current_insert.offset >
		    ins->objectid) ||
		   (root->current_insert.objectid > ins->objectid &&
		    root->current_insert.objectid <= ins->objectid + ins->offset) ||
		   radix_tree_tag_get(&root->cache_radix, ins->objectid,
				      CTREE_EXTENT_PENDING)) {
			last_block = ins->objectid + 1;
			search_start = last_block;
			goto insert_failed;
		}
	}
	release_path(root, &path);
	release_path(root, &path);
	extent_item.refs = 1;
	if (ins->offset != 1)
	extent_item.owner = owner;
		BUG();
	if (root == orig_root && root->reserve_extent->num_blocks == 0) {
	return 0;
		root->reserve_extent->blocknr = ins->objectid;
		root->reserve_extent->num_blocks = ins->offset;
		root->reserve_extent->num_used = 0;
}
}
	ret = insert_item(root->extent_root, ins, &extent_item, sizeof(extent_item));

static int insert_pending_extents(struct ctree_root *extent_root)
{
	int ret;
	struct key key;
	struct extent_item item;
	struct tree_buffer *gang[4];
	int i;

	// FIXME -ENOSPC
	item.refs = 1;
	item.owner = extent_root->node->node.header.parentid;
	while(1) {
		ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix,
						 (void **)gang, 0, ARRAY_SIZE(gang),
						 CTREE_EXTENT_PENDING);
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
			key.objectid = gang[i]->blocknr;
			key.flags = 0;
			key.offset = 1;
			ret = insert_item(extent_root, &key, &item, sizeof(item));
			if (ret) {
				BUG();
				// FIXME undo it and return sane
				return ret;
				return ret;
			}
			}
			radix_tree_tag_clear(&extent_root->cache_radix, gang[i]->blocknr,
						CTREE_EXTENT_PENDING);
			tree_block_release(extent_root, gang[i]);
		}
	}
	return 0;
}


static int refill_alloc_extent(struct ctree_root *root)
int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start,
			 u64 search_end, u64 owner, struct key *ins, struct tree_buffer **buf)
{
{
	struct alloc_extent *ae = root->alloc_extent;
	struct key key;
	int ret;
	int ret;
	int min_blocks = MAX_LEVEL * 2;
	int pending_ret;
	struct extent_item extent_item;


	if (ae->num_blocks > ae->num_used && ae->num_blocks - ae->num_used >
	extent_item.refs = 1;
	    min_blocks)
	extent_item.owner = owner;

	ret = find_free_extent(root, num_blocks, search_start, search_end, ins);
	if (ret)
		return ret;

	if (root != root->extent_root) {
		memcpy(&root->extent_root->current_insert, ins, sizeof(*ins));
		ret = insert_item(root->extent_root, ins, &extent_item, sizeof(extent_item));
		memset(&root->extent_root->current_insert, 0, sizeof(struct key));
		pending_ret = insert_pending_extents(root->extent_root);
		if (ret)
			return ret;
		if (pending_ret)
			return pending_ret;
		*buf = find_tree_block(root, ins->objectid);
		return 0;
		return 0;
	ae = root->reserve_extent;
	if (ae->num_blocks > ae->num_used) {
		if (root->alloc_extent->num_blocks == 0) {
			/* we should swap reserve/alloc_extent when alloc
			 * fills up
			 */
			BUG();
	}
	}
		if (ae->num_blocks - ae->num_used < min_blocks)
	/* we're allocating an extent for the extent tree, don't recurse */
			BUG();
	BUG_ON(ins->offset != 1);
	*buf = find_tree_block(root, ins->objectid);
	BUG_ON(!*buf);
	radix_tree_tag_set(&root->cache_radix, ins->objectid, CTREE_EXTENT_PENDING);
	(*buf)->count++;
	return 0;
	return 0;

}
}
	ret = alloc_extent(root,

			   min_blocks * 2, 0, (unsigned long)-1,
struct tree_buffer *alloc_free_block(struct ctree_root *root)
			   root->node->node.header.parentid, &key);
{
	ae->blocknr = key.objectid;
	struct key ins;
	ae->num_blocks = key.offset;
	int ret;
	ae->num_used = 0;
	struct tree_buffer *buf = NULL;
	return ret;

	ret = alloc_extent(root, 1, 0, (unsigned long)-1, root->node->node.header.parentid,
			   &ins, &buf);

	if (ret) {
		BUG();
		return NULL;
	}
	if (root != root->extent_root)
		BUG_ON(radix_tree_tag_get(&root->extent_root->cache_radix, buf->blocknr,
					  CTREE_EXTENT_PENDING));
	return buf;
}
}


void print_leaf(struct leaf *l)
void print_leaf(struct leaf *l)
@@ -1096,6 +1235,7 @@ int main() {
	print_tree(root, root->node);
	print_tree(root, root->node);
	printf("map tree\n");
	printf("map tree\n");
	print_tree(root->extent_root, root->extent_root->node);
	print_tree(root->extent_root, root->extent_root->node);
	fflush(stdout);


	srand(55);
	srand(55);
	for (i = 0; i < run_size; i++) {
	for (i = 0; i < run_size; i++) {
@@ -1111,12 +1251,6 @@ int main() {
		if (!ret)
		if (!ret)
			tree_size++;
			tree_size++;
	}
	}
	printf("root used: %lu\n", root->alloc_extent->num_used);
	printf("root tree\n");
	// print_tree(root, root->node);
	printf("map tree\n");
	printf("map used: %lu\n", root->extent_root->alloc_extent->num_used);
	// print_tree(root->extent_root, root->extent_root->node);
	write_ctree_super(root, &super);
	write_ctree_super(root, &super);
	close_ctree(root);
	close_ctree(root);


@@ -1167,12 +1301,27 @@ int main() {
		ret = insert_item(root, &ins, buf, strlen(buf));
		ret = insert_item(root, &ins, buf, strlen(buf));
		if (!ret)
		if (!ret)
			tree_size++;
			tree_size++;
		if (i >= 5) {
			struct key ugh;
			ugh.objectid = 5;
			ugh.flags = 0;
			ugh.offset = 0;
			init_path(&path);
			ret = search_slot(root, &ugh, &path, 0);
			if (ret) {
				print_tree(root, root->node);
				printf("unable to find 5 %d\n", num);
				exit(1);
			}
			release_path(root, &path);

		}
	}
	}
	write_ctree_super(root, &super);
	write_ctree_super(root, &super);
	close_ctree(root);
	close_ctree(root);
	root = open_ctree("dbfile", &super);
	root = open_ctree("dbfile", &super);
	printf("starting search2\n");
	srand(128);
	srand(128);
	printf("starting search2\n");
	for (i = 0; i < run_size; i++) {
	for (i = 0; i < run_size; i++) {
		num = next_key(i, max_key);
		num = next_key(i, max_key);
		ins.objectid = num;
		ins.objectid = num;
@@ -1219,5 +1368,7 @@ int main() {
	write_ctree_super(root, &super);
	write_ctree_super(root, &super);
	close_ctree(root);
	close_ctree(root);
	printf("tree size is now %d\n", tree_size);
	printf("tree size is now %d\n", tree_size);
	printf("map tree\n");
	print_tree(root->extent_root, root->extent_root->node);
	return 0;
	return 0;
}
}
+1 −12
Original line number Original line Diff line number Diff line
@@ -28,21 +28,12 @@ struct header {


struct tree_buffer;
struct tree_buffer;


struct alloc_extent {
	u64 blocknr;
	u64 num_blocks;
	u64 num_used;
} __attribute__ ((__packed__));

struct ctree_root {
struct ctree_root {
	struct tree_buffer *node;
	struct tree_buffer *node;
	struct ctree_root *extent_root;
	struct ctree_root *extent_root;
	struct alloc_extent *alloc_extent;
	struct key current_insert;
	struct alloc_extent *reserve_extent;
	int fp;
	int fp;
	struct radix_tree_root cache_radix;
	struct radix_tree_root cache_radix;
	struct alloc_extent ai1;
	struct alloc_extent ai2;
};
};


struct ctree_root_info {
struct ctree_root_info {
@@ -52,8 +43,6 @@ struct ctree_root_info {
	u64 tree_root; /* the tree root */
	u64 tree_root; /* the tree root */
	u32 csum;
	u32 csum;
	u32 ham;
	u32 ham;
	struct alloc_extent alloc_extent;
	struct alloc_extent reserve_extent;
	u64 snapuuid[2]; /* root specific uuid */
	u64 snapuuid[2]; /* root specific uuid */
} __attribute__ ((__packed__));
} __attribute__ ((__packed__));


+31 −59
Original line number Original line Diff line number Diff line
@@ -12,33 +12,13 @@


static int allocated_blocks = 0;
static int allocated_blocks = 0;


static int get_free_block(struct ctree_root *root, u64 *block)
static int check_tree_block(struct ctree_root *root, struct tree_buffer *buf)
{
{
	struct stat st;
	if (buf->blocknr != buf->node.header.blocknr)
	int ret = 0;
		BUG();

	if (root->node && buf->node.header.parentid != root->node->node.header.parentid)
	if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks)
		BUG();
		return -1;
	return 0;

	*block = root->alloc_extent->blocknr + root->alloc_extent->num_used;
	root->alloc_extent->num_used += 1;
	if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) {
		struct alloc_extent *ae = root->alloc_extent;
		root->alloc_extent = root->reserve_extent;
		root->reserve_extent = ae;
		ae->num_blocks = 0;
	}
	st.st_size = 0;
	ret = fstat(root->fp, &st);
	if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) {
		ret = ftruncate(root->fp,
				(*block + 1) * CTREE_BLOCKSIZE);
		if (ret) {
			perror("ftruncate");
			exit(1);
		}
	}
	return ret;
}
}


struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr)
struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr)
@@ -61,22 +41,23 @@ struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr)
	return buf;
	return buf;
}
}


struct tree_buffer *alloc_free_block(struct ctree_root *root)
struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr)
{
{
	u64 free_block;
	int ret;
	struct tree_buffer *buf;
	struct tree_buffer *buf;
	ret = get_free_block(root, &free_block);
	buf = radix_tree_lookup(&root->cache_radix, blocknr);
	if (ret) {
	if (buf) {
		buf->count++;
	} else {
		buf = alloc_tree_block(root, blocknr);
		if (!buf) {
			BUG();
			BUG();
			return NULL;
			return NULL;
		}
		}
	buf = alloc_tree_block(root, free_block);
	}
	if (!buf)
		BUG();
	return buf;
	return buf;
}
}



struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
{
{
	loff_t offset = blocknr * CTREE_BLOCKSIZE;
	loff_t offset = blocknr * CTREE_BLOCKSIZE;
@@ -86,8 +67,7 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
	buf = radix_tree_lookup(&root->cache_radix, blocknr);
	buf = radix_tree_lookup(&root->cache_radix, blocknr);
	if (buf) {
	if (buf) {
		buf->count++;
		buf->count++;
		goto test;
	} else {
	}
		buf = alloc_tree_block(root, blocknr);
		buf = alloc_tree_block(root, blocknr);
		if (!buf)
		if (!buf)
			return NULL;
			return NULL;
@@ -96,10 +76,8 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
			free(buf);
			free(buf);
			return NULL;
			return NULL;
		}
		}
test:
	}
	if (buf->blocknr != buf->node.header.blocknr)
	if (check_tree_block(root, buf))
		BUG();
	if (root->node && buf->node.header.parentid != root->node->node.header.parentid)
		BUG();
		BUG();
	return buf;
	return buf;
}
}
@@ -121,17 +99,10 @@ int write_tree_block(struct ctree_root *root, struct tree_buffer *buf)
static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
			struct ctree_root_info *info, int fp)
			struct ctree_root_info *info, int fp)
{
{
	INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
	root->fp = fp;
	root->fp = fp;
	root->node = NULL;
	root->node = NULL;
	root->node = read_tree_block(root, info->tree_root);
	root->node = read_tree_block(root, info->tree_root);
	root->extent_root = extent_root;
	root->extent_root = extent_root;
	memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent));
	memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent));
	root->alloc_extent = &root->ai1;
	root->reserve_extent = &root->ai2;
	printf("setup done reading root %p, used %lu available %lu\n", root, root->alloc_extent->num_used, root->alloc_extent->num_blocks);
	printf("setup done reading root %p, reserve used %lu available %lu\n", root, root->reserve_extent->num_used, root->reserve_extent->num_blocks);
	return 0;
	return 0;
}
}


@@ -147,6 +118,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
		free(root);
		free(root);
		return NULL;
		return NULL;
	}
	}
	INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
	INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL);
	ret = pread(fp, super, sizeof(struct ctree_super_block),
	ret = pread(fp, super, sizeof(struct ctree_super_block),
		     CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
		     CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
	if (ret == 0 || super->root_info.tree_root == 0) {
	if (ret == 0 || super->root_info.tree_root == 0) {
@@ -168,8 +141,6 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
static int __update_root(struct ctree_root *root, struct ctree_root_info *info)
static int __update_root(struct ctree_root *root, struct ctree_root_info *info)
{
{
	info->tree_root = root->node->blocknr;
	info->tree_root = root->node->blocknr;
	memcpy(&info->alloc_extent, root->alloc_extent, sizeof(struct alloc_extent));
	memcpy(&info->reserve_extent, root->reserve_extent, sizeof(struct alloc_extent));
	return 0;
	return 0;
}
}


@@ -201,6 +172,7 @@ int close_ctree(struct ctree_root *root)
void tree_block_release(struct ctree_root *root, struct tree_buffer *buf)
void tree_block_release(struct ctree_root *root, struct tree_buffer *buf)
{
{
	buf->count--;
	buf->count--;
	write_tree_block(root, buf);
	if (buf->count < 0)
	if (buf->count < 0)
		BUG();
		BUG();
	if (buf->count == 0) {
	if (buf->count == 0) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -11,11 +11,11 @@ struct tree_buffer {
};
};


struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr);
struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr);
struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr);
int write_tree_block(struct ctree_root *root, struct tree_buffer *buf);
int write_tree_block(struct ctree_root *root, struct tree_buffer *buf);
struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s);
struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s);
int close_ctree(struct ctree_root *root);
int close_ctree(struct ctree_root *root);
void tree_block_release(struct ctree_root *root, struct tree_buffer *buf);
void tree_block_release(struct ctree_root *root, struct tree_buffer *buf);
struct tree_buffer *alloc_free_block(struct ctree_root *root);
int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s);
int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s);
int mkfs(int fd);
int mkfs(int fd);


+21 −16
Original line number Original line Diff line number Diff line
@@ -23,17 +23,10 @@ int mkfs(int fd)
	info[0].blocknr = 16;
	info[0].blocknr = 16;
	info[0].objectid = 1;
	info[0].objectid = 1;
	info[0].tree_root = 17;
	info[0].tree_root = 17;
	info[0].alloc_extent.blocknr = 0;
	info[0].alloc_extent.num_blocks = 64;
	/* 0-17 are used (inclusive) */
	info[0].alloc_extent.num_used = 18;


	info[1].blocknr = 16;
	info[1].blocknr = 16;
	info[1].objectid = 2;
	info[1].objectid = 2;
	info[1].tree_root = 64;
	info[1].tree_root = 18;
	info[1].alloc_extent.blocknr = 64;
	info[1].alloc_extent.num_blocks = 64;
	info[1].alloc_extent.num_used = 1;
	ret = pwrite(fd, info, sizeof(info),
	ret = pwrite(fd, info, sizeof(info),
		     CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
		     CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
	if (ret != sizeof(info))
	if (ret != sizeof(info))
@@ -48,24 +41,36 @@ int mkfs(int fd)
		return -1;
		return -1;


	empty_leaf.header.parentid = 2;
	empty_leaf.header.parentid = 2;
	empty_leaf.header.blocknr = 64;
	empty_leaf.header.blocknr = 18;
	empty_leaf.header.nritems = 2;
	empty_leaf.header.nritems = 3;

	/* item1, reserve blocks 0-16 */
	item.key.objectid = 0;
	item.key.objectid = 0;
	item.key.offset = 64;
	item.key.offset = 17;
	item.key.flags = 0;
	item.key.flags = 0;
	item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item);
	item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item);
	item.size = sizeof(struct extent_item);
	item.size = sizeof(struct extent_item);
	extent_item.refs = 1;
	extent_item.refs = 1;
	extent_item.owner = 1;
	extent_item.owner = 0;
	memcpy(empty_leaf.items, &item, sizeof(item));
	memcpy(empty_leaf.items, &item, sizeof(item));
	memcpy(empty_leaf.data + item.offset, &extent_item, item.size);
	memcpy(empty_leaf.data + item.offset, &extent_item, item.size);
	item.key.objectid = 64;

	item.key.offset = 64;
	/* item2, give block 17 to the root */
	item.key.objectid = 17;
	item.key.offset = 1;
	item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 2;
	item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 2;
	extent_item.owner = 2;
	extent_item.owner = 1;
	memcpy(empty_leaf.items + 1, &item, sizeof(item));
	memcpy(empty_leaf.items + 1, &item, sizeof(item));
	memcpy(empty_leaf.data + item.offset, &extent_item, item.size);
	memcpy(empty_leaf.data + item.offset, &extent_item, item.size);
	ret = pwrite(fd, &empty_leaf, sizeof(empty_leaf), 64 * CTREE_BLOCKSIZE);

	/* item3, give block 18 for the extent root */
	item.key.objectid = 18;
	item.key.offset = 1;
	item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 3;
	extent_item.owner = 2;
	memcpy(empty_leaf.items + 2, &item, sizeof(item));
	memcpy(empty_leaf.data + item.offset, &extent_item, item.size);
	ret = pwrite(fd, &empty_leaf, sizeof(empty_leaf), 18 * CTREE_BLOCKSIZE);
	if (ret != sizeof(empty_leaf))
	if (ret != sizeof(empty_leaf))
		return -1;
		return -1;
	return 0;
	return 0;