diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/Makefile | 50 | ||||
| -rw-r--r-- | fs/btrfs/ctree.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 15 | ||||
| -rw-r--r-- | fs/btrfs/debug-tree.c | 38 | ||||
| -rw-r--r-- | fs/btrfs/dir-item.c | 12 | ||||
| -rw-r--r-- | fs/btrfs/dir-test.c | 494 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 17 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 10 | ||||
| -rw-r--r-- | fs/btrfs/file-item.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/hash.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/hasher.c | 23 | ||||
| -rw-r--r-- | fs/btrfs/inode-item.c | 5 | ||||
| -rw-r--r-- | fs/btrfs/inode-map.c | 5 | ||||
| -rw-r--r-- | fs/btrfs/kerncompat.h | 96 | ||||
| -rw-r--r-- | fs/btrfs/list.h | 418 | ||||
| -rw-r--r-- | fs/btrfs/mkfs.c | 255 | ||||
| -rw-r--r-- | fs/btrfs/print-tree.c | 30 | ||||
| -rw-r--r-- | fs/btrfs/quick-test.c | 179 | ||||
| -rw-r--r-- | fs/btrfs/radix-tree.c | 836 | ||||
| -rw-r--r-- | fs/btrfs/radix-tree.h | 73 | ||||
| -rw-r--r-- | fs/btrfs/random-test.c | 405 | ||||
| -rw-r--r-- | fs/btrfs/root-tree.c | 5 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 205 | 
24 files changed, 274 insertions, 2911 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 0720169b6d6..99e45a54ebd 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile @@ -1,40 +1,20 @@ -CC=gcc -CFLAGS = -g -Wall -Werror -headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h \ -	  transaction.h -objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ -	  root-tree.o dir-item.o hash.o file-item.o inode-item.o \ -	  inode-map.o \ +ifneq ($(KERNELRELEASE),) +# kbuild part of makefile -# if you don't have sparse installed, use ls instead -CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ -		-Wcontext -Wcast-truncate -Wuninitialized -Wshadow -Wundef -check=sparse $(CHECKFLAGS) -#check=ls +obj-m  := btrfs.o +btrfs-y := super.o -.c.o: -	$(check) $< -	$(CC) $(CFLAGS) -c $< +#btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ +#	  root-tree.o dir-item.o hash.o file-item.o inode-item.o \ +#	  inode-map.o \ -all: tester debug-tree quick-test dir-test tags mkfs.btrfs - -mkfs.btrfs: $(objects) mkfs.o -	gcc $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o - -debug-tree: $(objects) debug-tree.o -	gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o - -tester: $(objects) random-test.o -	gcc $(CFLAGS) -o tester $(objects) random-test.o - -dir-test: $(objects) dir-test.o -	gcc $(CFLAGS) -o dir-test $(objects) dir-test.o -quick-test: $(objects) quick-test.o -	gcc $(CFLAGS) -o quick-test $(objects) quick-test.o - -$(objects): $(headers) - -clean : -	rm debug-tree tester *.o +else +# Normal Makefile +KERNELDIR := /lib/modules/`uname -r`/build +all:: +	$(MAKE) -C $(KERNELDIR) M=`pwd` modules +clean:: +	rm *.o btrfs.ko +endif diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 32922643b5b..9fbd07c37fd 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1,10 +1,6 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" +#include <linux/module.h>  #include "ctree.h"  #include "disk-io.h" -#include "print-tree.h"  static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root  		      *root, struct btrfs_path *path, int level); diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 1a4d1d6fa40..ae8518cb94b 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1,9 +1,6 @@  #ifndef __BTRFS__  #define __BTRFS__ -#include "list.h" -#include "kerncompat.h" -  struct btrfs_trans_handle;  #define BTRFS_MAGIC "_BtRfS_M" @@ -75,6 +72,7 @@ struct btrfs_super_block {  	__le64 root;  	__le64 total_blocks;  	__le64 blocks_used; +	__le64 root_dir_objectid;  } __attribute__ ((__packed__));  /* @@ -693,6 +691,17 @@ static inline void btrfs_set_super_blocksize(struct btrfs_super_block *s,  	s->blocksize = cpu_to_le32(val);  } +static inline u64 btrfs_super_root_dir(struct btrfs_super_block *s) +{ +	return le64_to_cpu(s->root_dir_objectid); +} + +static inline void btrfs_set_super_root_dir(struct btrfs_super_block *s, u64 +					    val) +{ +	s->root_dir_objectid = cpu_to_le64(val); +} +  static inline u8 *btrfs_leaf_data(struct btrfs_leaf *l)  {  	return (u8 *)l->items; diff --git a/fs/btrfs/debug-tree.c b/fs/btrfs/debug-tree.c deleted file mode 100644 index fd07969600c..00000000000 --- a/fs/btrfs/debug-tree.c +++ /dev/null @@ -1,38 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" -#include "ctree.h" -#include "disk-io.h" -#include "print-tree.h" -#include "transaction.h" - -int main(int ac, char **av) { -	struct btrfs_super_block super; -	struct btrfs_root *root; - -	if (ac != 2) { -		fprintf(stderr, "usage: %s device\n", av[0]); -		exit(1); -	} -	radix_tree_init(); -	root = open_ctree(av[1], &super); -	if (!root) { -		fprintf(stderr, "unable to open %s\n", av[1]); -		exit(1); -	} -	printf("fs tree\n"); -	btrfs_print_tree(root, root->node); -	printf("map tree\n"); -	btrfs_print_tree(root->fs_info->extent_root, -			 root->fs_info->extent_root->node); -	printf("inode tree\n"); -	btrfs_print_tree(root->fs_info->inode_root, -			 root->fs_info->inode_root->node); -	printf("root tree\n"); -	btrfs_print_tree(root->fs_info->tree_root, -			 root->fs_info->tree_root->node); -	printf("total blocks %Lu\n", btrfs_super_total_blocks(&super)); -	printf("blocks used %Lu\n", btrfs_super_blocks_used(&super)); -	return 0; -} diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 949c4e52679..4d8083d92fa 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -1,7 +1,4 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" +#include <linux/module.h>  #include "ctree.h"  #include "disk-io.h"  #include "hash.h" @@ -21,7 +18,12 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root  	key.objectid = dir;  	key.flags = 0;  	btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); -	ret = btrfs_name_hash(name, name_len, &key.offset); +	if (name_len == 1 && *name == '.') +		key.offset = 1; +	else if (name_len == 2 && name[0] == '.' && name[1] == '.') +		key.offset = 2; +	else +		ret = btrfs_name_hash(name, name_len, &key.offset);  	BUG_ON(ret);  	btrfs_init_path(&path);  	data_size = sizeof(*dir_item) + name_len; diff --git a/fs/btrfs/dir-test.c b/fs/btrfs/dir-test.c deleted file mode 100644 index b673982a1f3..00000000000 --- a/fs/btrfs/dir-test.c +++ /dev/null @@ -1,494 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include "kerncompat.h" -#include "radix-tree.h" -#include "ctree.h" -#include "disk-io.h" -#include "print-tree.h" -#include "hash.h" -#include "transaction.h" - -int keep_running = 1; -struct btrfs_super_block super; -static u64 dir_oid = 44556; -static u64 file_oid = 33778; - -static int find_num(struct radix_tree_root *root, unsigned long *num_ret, -		     int exists) -{ -	unsigned long num = rand(); -	unsigned long res[2]; -	int ret; - -again: -	ret = radix_tree_gang_lookup(root, (void **)res, num, 2); -	if (exists) { -		if (ret == 0) -			return -1; -		num = res[0]; -	} else if (ret != 0 && num == res[0]) { -		num++; -		if (ret > 1 && num == res[1]) { -			num++; -			goto again; -		} -	} -	*num_ret = num; -	return 0; -} - -static void initial_inode_init(struct btrfs_root *root, -			       struct btrfs_inode_item *inode_item) -{ -	memset(inode_item, 0, sizeof(*inode_item)); -	btrfs_set_inode_generation(inode_item, root->fs_info->generation); -} - -static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, -		   struct radix_tree_root *radix) -{ -	int ret; -	char buf[128]; -	unsigned long oid; -	u64 objectid; -	struct btrfs_path path; -	struct btrfs_key inode_map; -	struct btrfs_inode_item inode_item; - -	find_num(radix, &oid, 0); -	sprintf(buf, "str-%lu", oid); - -	ret = btrfs_find_free_objectid(trans, root, dir_oid + 1, &objectid); -	if (ret) -		goto error; - -	inode_map.objectid = objectid; -	inode_map.flags = 0; -	inode_map.offset = 0; - -	ret = btrfs_insert_inode_map(trans, root, objectid, &inode_map); -	if (ret) -		goto error; - -	initial_inode_init(root, &inode_item); -	ret = btrfs_insert_inode(trans, root, objectid, &inode_item); -	if (ret) -		goto error; -	ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, -				    objectid, 1); -	if (ret) -		goto error; - -	radix_tree_preload(GFP_KERNEL); -	ret = radix_tree_insert(radix, oid, (void *)oid); -	radix_tree_preload_end(); -	if (ret) -		goto error; -	return ret; -error: -	if (ret != -EEXIST) -		goto fatal; - -	/* -	 * if we got an EEXIST, it may be due to hash collision, double -	 * check -	 */ -	btrfs_init_path(&path); -	ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, -				    strlen(buf), 0); -	if (ret) -		goto fatal_release; -	if (!btrfs_match_dir_item_name(root, &path, buf, strlen(buf))) { -		struct btrfs_dir_item *di; -		char *found; -		u32 found_len; -		u64 myhash; -		u64 foundhash; - -		di = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], -				    struct btrfs_dir_item); -		found = (char *)(di + 1); -		found_len = btrfs_dir_name_len(di); -		btrfs_name_hash(buf, strlen(buf), &myhash); -		btrfs_name_hash(found, found_len, &foundhash); -		if (myhash != foundhash) -			goto fatal_release; -		btrfs_release_path(root, &path); -		return 0; -	} -fatal_release: -	btrfs_release_path(root, &path); -fatal: -	printf("failed to insert %lu ret %d\n", oid, ret); -	return -1; -} - -static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root -		      *root, struct radix_tree_root *radix) -{ -	int ret; -	char buf[128]; -	unsigned long oid; - -	ret = find_num(radix, &oid, 1); -	if (ret < 0) -		return 0; -	sprintf(buf, "str-%lu", oid); - -	ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, -				    file_oid, 1); -	if (ret != -EEXIST) { -		printf("insert on %s gave us %d\n", buf, ret); -		return 1; -	} -	return 0; -} - -static int del_dir_item(struct btrfs_trans_handle *trans, -			struct btrfs_root *root, -			struct radix_tree_root *radix, -			unsigned long radix_index, -			struct btrfs_path *path) -{ -	int ret; -	unsigned long *ptr; -	u64 file_objectid; -	struct btrfs_dir_item *di; - -	/* find the inode number of the file */ -	di = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0], -			    struct btrfs_dir_item); -	file_objectid = btrfs_dir_objectid(di); - -	/* delete the directory item */ -	ret = btrfs_del_item(trans, root, path); -	if (ret) -		goto out_release; -	btrfs_release_path(root, path); - -	/* delete the inode */ -	btrfs_init_path(path); -	ret = btrfs_lookup_inode(trans, root, path, file_objectid, -1); -	if (ret) -		goto out_release; -	ret = btrfs_del_item(trans, root, path); -	if (ret) -		goto out_release; -	btrfs_release_path(root, path); - -	/* delete the inode mapping */ -	btrfs_init_path(path); -	ret = btrfs_lookup_inode_map(trans, root, path, file_objectid, -1); -	if (ret) -		goto out_release; -	ret = btrfs_del_item(trans, root->fs_info->inode_root, path); -	if (ret) -		goto out_release; - -	if (root->fs_info->last_inode_alloc > file_objectid) -		root->fs_info->last_inode_alloc = file_objectid; -	btrfs_release_path(root, path); -	ptr = radix_tree_delete(radix, radix_index); -	if (!ptr) { -		ret = -5555; -		goto out; -	} -	return 0; -out_release: -	btrfs_release_path(root, path); -out: -	printf("failed to delete %lu %d\n", radix_index, ret); -	return -1; -} - -static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, -		   struct radix_tree_root *radix) -{ -	int ret; -	char buf[128]; -	unsigned long oid; -	struct btrfs_path path; - -	ret = find_num(radix, &oid, 1); -	if (ret < 0) -		return 0; -	sprintf(buf, "str-%lu", oid); -	btrfs_init_path(&path); -	ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, -				    strlen(buf), -1); -	if (ret) -		goto out_release; - -	ret = del_dir_item(trans, root, radix, oid, &path); -	if (ret) -		goto out_release; -	return ret; -out_release: -	btrfs_release_path(root, &path); -	printf("failed to delete %lu %d\n", oid, ret); -	return -1; -} - -static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root -		       *root, struct radix_tree_root *radix) -{ -	struct btrfs_path path; -	char buf[128]; -	int ret; -	unsigned long oid; -	u64 objectid; -	struct btrfs_dir_item *di; - -	ret = find_num(radix, &oid, 1); -	if (ret < 0) -		return 0; -	sprintf(buf, "str-%lu", oid); -	btrfs_init_path(&path); -	ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, -				    strlen(buf), 0); -	if (!ret) { -		di = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], -				    struct btrfs_dir_item); -		objectid = btrfs_dir_objectid(di); -		btrfs_release_path(root, &path); -		btrfs_init_path(&path); -		ret = btrfs_lookup_inode_map(trans, root, &path, objectid, 0); -	} -	btrfs_release_path(root, &path); -	if (ret) { -		printf("unable to find key %lu\n", oid); -		return -1; -	} -	return 0; -} - -static int lookup_enoent(struct btrfs_trans_handle *trans, struct btrfs_root -			 *root, struct radix_tree_root *radix) -{ -	struct btrfs_path path; -	char buf[128]; -	int ret; -	unsigned long oid; - -	ret = find_num(radix, &oid, 0); -	if (ret < 0) -		return 0; -	sprintf(buf, "str-%lu", oid); -	btrfs_init_path(&path); -	ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, -				    strlen(buf), 0); -	btrfs_release_path(root, &path); -	if (!ret) { -		printf("able to find key that should not exist %lu\n", oid); -		return -1; -	} -	return 0; -} - -static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root -		      *root, struct radix_tree_root *radix, int nr) -{ -	struct btrfs_path path; -	struct btrfs_key key; -	unsigned long found = 0; -	u32 found_len; -	int ret; -	int slot; -	int count = 0; -	char buf[128]; -	struct btrfs_dir_item *di; - -	key.offset = (u64)-1; -	key.flags = 0; -	btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); -	key.objectid = dir_oid; -	while(nr-- >= 0) { -		btrfs_init_path(&path); -		ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); -		if (ret < 0) { -			btrfs_release_path(root, &path); -			return ret; -		} -		if (ret != 0) { -			if (path.slots[0] == 0) { -				btrfs_release_path(root, &path); -				break; -			} -			path.slots[0] -= 1; -		} -		slot = path.slots[0]; -		di = btrfs_item_ptr(&path.nodes[0]->leaf, slot, -				    struct btrfs_dir_item); -		found_len = btrfs_dir_name_len(di); -		memcpy(buf, (char *)(di + 1), found_len); -		BUG_ON(found_len > 128); -		buf[found_len] = '\0'; -		found = atoi(buf + 4); -		ret = del_dir_item(trans, root, radix, found, &path); -		count++; -		if (ret) { -			fprintf(stderr, -				"failed to remove %lu from tree\n", -				found); -			return -1; -		} -		if (!keep_running) -			break; -	} -	return 0; -	fprintf(stderr, "failed to delete from the radix %lu\n", found); -	return -1; -} - -static int fill_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root, -		     struct radix_tree_root *radix, int count) -{ -	int i; -	int ret = 0; -	for (i = 0; i < count; i++) { -		ret = ins_one(trans, root, radix); -		if (ret) { -			fprintf(stderr, "fill failed\n"); -			goto out; -		} -		if (i % 1000 == 0) { -			ret = btrfs_commit_transaction(trans, root, &super); -			if (ret) { -				fprintf(stderr, "fill commit failed\n"); -				return ret; -			} -		} -		if (i && i % 10000 == 0) { -			printf("bigfill %d\n", i); -		} -		if (!keep_running) -			break; -	} -out: -	return ret; -} - -static int bulk_op(struct btrfs_trans_handle *trans, struct btrfs_root *root, -		   struct radix_tree_root *radix) -{ -	int ret; -	int nr = rand() % 5000; -	static int run_nr = 0; - -	/* do the bulk op much less frequently */ -	if (run_nr++ % 100) -		return 0; -	ret = empty_tree(trans, root, radix, nr); -	if (ret) -		return ret; -	ret = fill_tree(trans, root, radix, nr); -	if (ret) -		return ret; -	return 0; -} - - -int (*ops[])(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct -	     radix_tree_root *radix) = -	{ ins_one, insert_dup, del_one, lookup_item, -	  lookup_enoent, bulk_op }; - -void sigstopper(int ignored) -{ -	keep_running = 0; -	fprintf(stderr, "caught exit signal, stopping\n"); -} - -int print_usage(void) -{ -	printf("usage: tester [-ih] [-c count] [-f count]\n"); -	printf("\t -c count -- iteration count after filling\n"); -	printf("\t -f count -- run this many random inserts before starting\n"); -	printf("\t -i       -- only do initial fill\n"); -	printf("\t -h       -- this help text\n"); -	exit(1); -} -int main(int ac, char **av) -{ -	RADIX_TREE(radix, GFP_KERNEL); -	struct btrfs_root *root; -	int i; -	int ret; -	int count; -	int op; -	int iterations = 20000; -	int init_fill_count = 800000; -	int err = 0; -	int initial_only = 0; -	struct btrfs_trans_handle *trans; -	radix_tree_init(); - -	root = open_ctree("dbfile", &super); -	trans = btrfs_start_transaction(root, 1); - -	signal(SIGTERM, sigstopper); -	signal(SIGINT, sigstopper); - -	for (i = 1 ; i < ac ; i++) { -		if (strcmp(av[i], "-i") == 0) { -			initial_only = 1; -		} else if (strcmp(av[i], "-c") == 0) { -			iterations = atoi(av[i+1]); -			i++; -		} else if (strcmp(av[i], "-f") == 0) { -			init_fill_count = atoi(av[i+1]); -			i++; -		} else { -			print_usage(); -		} -	} -	printf("initial fill\n"); -	ret = fill_tree(trans, root, &radix, init_fill_count); -	printf("starting run\n"); -	if (ret) { -		err = ret; -		goto out; -	} -	if (initial_only == 1) { -		goto out; -	} -	for (i = 0; i < iterations; i++) { -		op = rand() % ARRAY_SIZE(ops); -		count = rand() % 128; -		if (i % 2000 == 0) { -			printf("%d\n", i); -			fflush(stdout); -		} -		if (i && i % 5000 == 0) { -			printf("open & close, root level %d nritems %d\n", -				btrfs_header_level(&root->node->node.header), -				btrfs_header_nritems(&root->node->node.header)); -			close_ctree(root, &super); -			root = open_ctree("dbfile", &super); -		} -		while(count--) { -			ret = ops[op](trans, root, &radix); -			if (ret) { -				fprintf(stderr, "op %d failed %d:%d\n", -					op, i, iterations); -				btrfs_print_tree(root, root->node); -				fprintf(stderr, "op %d failed %d:%d\n", -					op, i, iterations); -				err = ret; -				goto out; -			} -			if (ops[op] == bulk_op) -				break; -			if (keep_running == 0) { -				err = 0; -				goto out; -			} -		} -	} -out: -	close_ctree(root, &super); -	return err; -} - diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0322c55162c..05637f9fd7c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -267,19 +267,24 @@ static int find_and_setup_root(struct btrfs_super_block *super,  struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super)  { +	int fp; + +	fp = open(filename, O_CREAT | O_RDWR, 0600); +	if (fp < 0) { +		return NULL; +	} +	return open_ctree_fd(fp, super); +} + +struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) +{  	struct btrfs_root *root = malloc(sizeof(struct btrfs_root));  	struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root));  	struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root));  	struct btrfs_root *inode_root = malloc(sizeof(struct btrfs_root));  	struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); -	int fp;  	int ret; -	fp = open(filename, O_CREAT | O_RDWR, 0600); -	if (fp < 0) { -		free(root); -		return NULL; -	}  	INIT_RADIX_TREE(&fs_info->cache_radix, GFP_KERNEL);  	INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL);  	INIT_LIST_HEAD(&fs_info->trans); diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 24a9e77c831..d888cf5c350 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -24,6 +24,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans,  int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_root  			     *root, struct btrfs_super_block *s);  struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *s); +struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super);  int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s);  void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf);  int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root, diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 9bc4ad38876..53a7550b5c1 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1,7 +1,5 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" +#include <linux/module.h> +#include <linux/radix-tree.h>  #include "ctree.h"  #include "disk-io.h"  #include "print-tree.h" @@ -183,9 +181,9 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root  	btrfs_init_path(&path);  	ret = btrfs_search_slot(trans, extent_root, &key, &path, -1, 1);  	if (ret) { -		printf("failed to find %Lu\n", key.objectid); +		printk("failed to find %Lu\n", key.objectid);  		btrfs_print_tree(extent_root, extent_root->node); -		printf("failed to find %Lu\n", key.objectid); +		printk("failed to find %Lu\n", key.objectid);  		BUG();  	}  	ei = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 24cfd6d8524..8e1e5b4ccfa 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -1,9 +1,5 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" +#include <linux/module.h>  #include "ctree.h" -#include "disk-io.h"  #include "transaction.h"  int btrfs_create_file(struct btrfs_trans_handle *trans, diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c index 92c37eece1f..6c2a71a46c7 100644 --- a/fs/btrfs/hash.c +++ b/fs/btrfs/hash.c @@ -10,7 +10,6 @@   * License.   */ -#include "kerncompat.h"  #define DELTA 0x9E3779B9  static void TEA_transform(__u32 buf[2], __u32 const in[]) diff --git a/fs/btrfs/hasher.c b/fs/btrfs/hasher.c deleted file mode 100644 index 96702da4329..00000000000 --- a/fs/btrfs/hasher.c +++ /dev/null @@ -1,23 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "kerncompat.h" -#include "hash.h" - -int main() { -	u64 result; -	int ret; -	char line[255]; -	char *p; -	while(1) { -		p = fgets(line, 255, stdin); -		if (!p) -			break; -		if (strlen(line) == 0) -			continue; -		ret = btrfs_name_hash(line, strlen(line), &result); -		BUG_ON(ret); -		printf("hash returns %Lu\n", result); -	} -	return 0; -} diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c index 7caeb11e875..8d8c26a6c1a 100644 --- a/fs/btrfs/inode-item.c +++ b/fs/btrfs/inode-item.c @@ -1,7 +1,4 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" +#include <linux/module.h>  #include "ctree.h"  #include "disk-io.h"  #include "transaction.h" diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index f412b339213..c7fda3bf7b2 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -1,7 +1,4 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" +#include <linux/module.h>  #include "ctree.h"  #include "disk-io.h"  #include "transaction.h" diff --git a/fs/btrfs/kerncompat.h b/fs/btrfs/kerncompat.h deleted file mode 100644 index 105d3f58408..00000000000 --- a/fs/btrfs/kerncompat.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef __KERNCOMPAT -#define __KERNCOMPAT -#define gfp_t int -#define get_cpu_var(p) (p) -#define __get_cpu_var(p) (p) -#define BITS_PER_LONG 64 -#define __GFP_BITS_SHIFT 20 -#define __GFP_BITS_MASK ((int)((1 << __GFP_BITS_SHIFT) - 1)) -#define GFP_KERNEL 0 -#define __read_mostly -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#define PAGE_SHIFT 12 -#define ULONG_MAX       (~0UL) -#define BUG() abort() -#ifdef __CHECKER__ -#define __force    __attribute__((force)) -#define __bitwise__ __attribute__((bitwise)) -#else -#define __force -#define __bitwise__ -#endif - -typedef unsigned int u32; -typedef u32 __u32; -typedef unsigned long long u64; -typedef unsigned char u8; -typedef unsigned short u16; - -typedef unsigned long pgoff_t; - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -struct vma_shared { int prio_tree_node; }; -struct vm_area_struct { -	unsigned long vm_pgoff; -	unsigned long vm_start; -	unsigned long vm_end; -	struct vma_shared shared; -}; - -struct page { -	unsigned long index; -}; - -static inline void preempt_enable(void) { do {; } while(0);} -static inline void preempt_disable(void) { do {; } while(0);} - -static inline void __set_bit(int bit, unsigned long *map) { -	unsigned long *p = map + bit / BITS_PER_LONG; -	bit = bit & (BITS_PER_LONG -1); -	*p |= 1UL << bit; -} - -static inline int test_bit(int bit, unsigned long *map) { -	unsigned long *p = map + bit / BITS_PER_LONG; -	bit = bit & (BITS_PER_LONG -1); -	return *p & (1UL << bit) ? 1 : 0; -} - -static inline void __clear_bit(int bit, unsigned long *map) { -	unsigned long *p = map + bit / BITS_PER_LONG; -	bit = bit & (BITS_PER_LONG -1); -	*p &= ~(1UL << bit); -} -#define BUG_ON(c) do { if (c) abort(); } while (0) - -#define container_of(ptr, type, member) ({                      \ -        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \ -	        (type *)( (char *)__mptr - __builtin_offsetof(type,member) );}) - -#define ENOMEM 5 -#define EEXIST 6 - -#define __CHECK_ENDIAN__ -#ifdef __CHECK_ENDIAN__ -#define __bitwise __bitwise__ -#else -#define __bitwise -#endif - -typedef u16 __bitwise __le16; -typedef u16 __bitwise __be16; -typedef u32 __bitwise __le32; -typedef u32 __bitwise __be32; -typedef u64 __bitwise __le64; -typedef u64 __bitwise __be64; - -#define cpu_to_le64(x) ((__force __le64)(u64)(x)) -#define le64_to_cpu(x) ((__force u64)(__le64)(x)) -#define cpu_to_le32(x) ((__force __le32)(u32)(x)) -#define le32_to_cpu(x) ((__force u32)(__le32)(x)) -#define cpu_to_le16(x) ((__force __le16)(u16)(x)) -#define le16_to_cpu(x) ((__force u16)(__le16)(x)) -#endif diff --git a/fs/btrfs/list.h b/fs/btrfs/list.h deleted file mode 100644 index 1aafafb1337..00000000000 --- a/fs/btrfs/list.h +++ /dev/null @@ -1,418 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -#define LIST_POISON1  ((void *) 0x00100100) -#define LIST_POISON2  ((void *) 0x00200200) - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { -	struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ -	struct list_head name = LIST_HEAD_INIT(name) - -static inline void INIT_LIST_HEAD(struct list_head *list) -{ -	list->next = list; -	list->prev = list; -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -#ifndef CONFIG_DEBUG_LIST -static inline void __list_add(struct list_head *new, -			      struct list_head *prev, -			      struct list_head *next) -{ -	next->prev = new; -	new->next = next; -	new->prev = prev; -	prev->next = new; -} -#else -extern void __list_add(struct list_head *new, -			      struct list_head *prev, -			      struct list_head *next); -#endif - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -#ifndef CONFIG_DEBUG_LIST -static inline void list_add(struct list_head *new, struct list_head *head) -{ -	__list_add(new, head, head->next); -} -#else -extern void list_add(struct list_head *new, struct list_head *head); -#endif - - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ -	__list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ -	next->prev = prev; -	prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -#ifndef CONFIG_DEBUG_LIST -static inline void list_del(struct list_head *entry) -{ -	__list_del(entry->prev, entry->next); -	entry->next = LIST_POISON1; -	entry->prev = LIST_POISON2; -} -#else -extern void list_del(struct list_head *entry); -#endif - -/** - * list_replace - replace old entry by new one - * @old : the element to be replaced - * @new : the new element to insert - * Note: if 'old' was empty, it will be overwritten. - */ -static inline void list_replace(struct list_head *old, -				struct list_head *new) -{ -	new->next = old->next; -	new->next->prev = new; -	new->prev = old->prev; -	new->prev->next = new; -} - -static inline void list_replace_init(struct list_head *old, -					struct list_head *new) -{ -	list_replace(old, new); -	INIT_LIST_HEAD(old); -} -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ -	__list_del(entry->prev, entry->next); -	INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ -        __list_del(list->prev, list->next); -        list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, -				  struct list_head *head) -{ -        __list_del(list->prev, list->next); -        list_add_tail(list, head); -} - -/** - * list_is_last - tests whether @list is the last entry in list @head - * @list: the entry to test - * @head: the head of the list - */ -static inline int list_is_last(const struct list_head *list, -				const struct list_head *head) -{ -	return list->next == head; -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ -	return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is empty and not being modified - * @head: the list to test - * - * Description: - * tests whether a list is empty _and_ checks that no other CPU might be - * in the process of modifying either member (next or prev) - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - */ -static inline int list_empty_careful(const struct list_head *head) -{ -	struct list_head *next = head->next; -	return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, -				 struct list_head *head) -{ -	struct list_head *first = list->next; -	struct list_head *last = list->prev; -	struct list_head *at = head->next; - -	first->prev = head; -	head->next = first; - -	last->next = at; -	at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ -	if (!list_empty(list)) -		__list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, -				    struct list_head *head) -{ -	if (!list_empty(list)) { -		__list_splice(list, head); -		INIT_LIST_HEAD(list); -	} -} - -/** - * list_entry - get the struct for this entry - * @ptr:	the &struct list_head pointer. - * @type:	the type of the struct this is embedded in. - * @member:	the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ -	container_of(ptr, type, member) - -/** - * list_for_each	-	iterate over a list - * @pos:	the &struct list_head to use as a loop cursor. - * @head:	the head for your list. - */ -#define list_for_each(pos, head) \ -	for (pos = (head)->next; prefetch(pos->next), pos != (head); \ -        	pos = pos->next) - -/** - * __list_for_each	-	iterate over a list - * @pos:	the &struct list_head to use as a loop cursor. - * @head:	the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ -	for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev	-	iterate over a list backwards - * @pos:	the &struct list_head to use as a loop cursor. - * @head:	the head for your list. - */ -#define list_for_each_prev(pos, head) \ -	for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ -        	pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos:	the &struct list_head to use as a loop cursor. - * @n:		another &struct list_head to use as temporary storage - * @head:	the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ -	for (pos = (head)->next, n = pos->next; pos != (head); \ -		pos = n, n = pos->next) - -/** - * list_for_each_entry	-	iterate over list of given type - * @pos:	the type * to use as a loop cursor. - * @head:	the head for your list. - * @member:	the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member)				\ -	for (pos = list_entry((head)->next, typeof(*pos), member);	\ -	     prefetch(pos->member.next), &pos->member != (head); 	\ -	     pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos:	the type * to use as a loop cursor. - * @head:	the head for your list. - * @member:	the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member)			\ -	for (pos = list_entry((head)->prev, typeof(*pos), member);	\ -	     prefetch(pos->member.prev), &pos->member != (head); 	\ -	     pos = list_entry(pos->member.prev, typeof(*pos), member)) - -/** - * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue - * @pos:	the type * to use as a start point - * @head:	the head of the list - * @member:	the name of the list_struct within the struct. - * - * Prepares a pos entry for use as a start point in list_for_each_entry_continue. - */ -#define list_prepare_entry(pos, head, member) \ -	((pos) ? : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - continue iteration over list of given type - * @pos:	the type * to use as a loop cursor. - * @head:	the head for your list. - * @member:	the name of the list_struct within the struct. - * - * Continue to iterate over list of given type, continuing after - * the current position. - */ -#define list_for_each_entry_continue(pos, head, member) 		\ -	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\ -	     prefetch(pos->member.next), &pos->member != (head);	\ -	     pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_from - iterate over list of given type from the current point - * @pos:	the type * to use as a loop cursor. - * @head:	the head for your list. - * @member:	the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing from current position. - */ -#define list_for_each_entry_from(pos, head, member) 			\ -	for (; prefetch(pos->member.next), &pos->member != (head);	\ -	     pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos:	the type * to use as a loop cursor. - * @n:		another type * to use as temporary storage - * @head:	the head for your list. - * @member:	the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member)			\ -	for (pos = list_entry((head)->next, typeof(*pos), member),	\ -		n = list_entry(pos->member.next, typeof(*pos), member);	\ -	     &pos->member != (head); 					\ -	     pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_continue - * @pos:	the type * to use as a loop cursor. - * @n:		another type * to use as temporary storage - * @head:	the head for your list. - * @member:	the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing after current point, - * safe against removal of list entry. - */ -#define list_for_each_entry_safe_continue(pos, n, head, member) 		\ -	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\ -		n = list_entry(pos->member.next, typeof(*pos), member);		\ -	     &pos->member != (head);						\ -	     pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_from - * @pos:	the type * to use as a loop cursor. - * @n:		another type * to use as temporary storage - * @head:	the head for your list. - * @member:	the name of the list_struct within the struct. - * - * Iterate over list of given type from current point, safe against - * removal of list entry. - */ -#define list_for_each_entry_safe_from(pos, n, head, member) 			\ -	for (n = list_entry(pos->member.next, typeof(*pos), member);		\ -	     &pos->member != (head);						\ -	     pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_reverse - * @pos:	the type * to use as a loop cursor. - * @n:		another type * to use as temporary storage - * @head:	the head for your list. - * @member:	the name of the list_struct within the struct. - * - * Iterate backwards over list of given type, safe against removal - * of list entry. - */ -#define list_for_each_entry_safe_reverse(pos, n, head, member)		\ -	for (pos = list_entry((head)->prev, typeof(*pos), member),	\ -		n = list_entry(pos->member.prev, typeof(*pos), member);	\ -	     &pos->member != (head); 					\ -	     pos = n, n = list_entry(n->member.prev, typeof(*n), member)) - -#endif diff --git a/fs/btrfs/mkfs.c b/fs/btrfs/mkfs.c deleted file mode 100644 index f7efc8a5fb1..00000000000 --- a/fs/btrfs/mkfs.c +++ /dev/null @@ -1,255 +0,0 @@ -#define _XOPEN_SOURCE 500 -#ifndef __CHECKER__ -#include <sys/ioctl.h> -#include <sys/mount.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include "kerncompat.h" -#include "radix-tree.h" -#include "ctree.h" -#include "disk-io.h" - -#ifdef __CHECKER__ -#define BLKGETSIZE64 0 -static inline int ioctl(int fd, int define, u64 *size) { return 0; } -#endif - -#if 0 -#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) -#   define BLKGETSIZE64 _IOR(0x12, 114, __u64) -#endif -#endif - -int mkfs(int fd, u64 num_blocks, u32 blocksize) -{ -	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; -	char *block; -	int ret; -	u32 itemoff; -	u32 start_block = BTRFS_SUPER_INFO_OFFSET / blocksize; - -	btrfs_set_super_blocknr(&super, start_block); -	btrfs_set_super_root(&super, start_block + 1); -	strcpy((char *)(&super.magic), BTRFS_MAGIC); -	btrfs_set_super_blocksize(&super, blocksize); -	btrfs_set_super_total_blocks(&super, num_blocks); -	btrfs_set_super_blocks_used(&super, start_block + 5); - -	block = malloc(blocksize); -	memset(block, 0, blocksize); -	BUG_ON(sizeof(super) > blocksize); -	memcpy(block, &super, sizeof(super)); -	ret = pwrite(fd, block, blocksize, BTRFS_SUPER_INFO_OFFSET); -	BUG_ON(ret != blocksize); - -	/* create the tree of root objects */ -	empty_leaf = malloc(blocksize); -	memset(empty_leaf, 0, blocksize); -	btrfs_set_header_parentid(&empty_leaf->header, -				  BTRFS_ROOT_TREE_OBJECTID); -	btrfs_set_header_blocknr(&empty_leaf->header, start_block + 1); -	btrfs_set_header_nritems(&empty_leaf->header, 3); - -	/* create the items for the root tree */ -	btrfs_set_root_blocknr(&root_item, start_block + 2); -	btrfs_set_root_refs(&root_item, 1); -	itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) - sizeof(root_item); -	btrfs_set_item_offset(&item, itemoff); -	btrfs_set_item_size(&item, sizeof(root_item)); -	btrfs_set_disk_key_objectid(&item.key, BTRFS_EXTENT_TREE_OBJECTID); -	btrfs_set_disk_key_offset(&item.key, 0); -	btrfs_set_disk_key_flags(&item.key, 0); -	btrfs_set_disk_key_type(&item.key, BTRFS_ROOT_ITEM_KEY); -	memcpy(empty_leaf->items, &item, sizeof(item)); -	memcpy(btrfs_leaf_data(empty_leaf) + itemoff, -		&root_item, sizeof(root_item)); - -	btrfs_set_root_blocknr(&root_item, start_block + 3); -	itemoff = itemoff - sizeof(root_item); -	btrfs_set_item_offset(&item, itemoff); -	btrfs_set_disk_key_objectid(&item.key, BTRFS_INODE_MAP_OBJECTID); -	memcpy(empty_leaf->items + 1, &item, sizeof(item)); -	memcpy(btrfs_leaf_data(empty_leaf) + itemoff, -		&root_item, sizeof(root_item)); - -	btrfs_set_root_blocknr(&root_item, start_block + 4); -	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 + 2, &item, sizeof(item)); -	memcpy(btrfs_leaf_data(empty_leaf) + itemoff, -		&root_item, sizeof(root_item)); -	ret = pwrite(fd, empty_leaf, blocksize, (start_block + 1) * blocksize); - -	/* create the items for the extent tree */ -	btrfs_set_header_parentid(&empty_leaf->header, -				  BTRFS_EXTENT_TREE_OBJECTID); -	btrfs_set_header_blocknr(&empty_leaf->header, start_block + 2); -	btrfs_set_header_nritems(&empty_leaf->header, 5); - -	/* item1, reserve blocks 0-16 */ -	btrfs_set_disk_key_objectid(&item.key, 0); -	btrfs_set_disk_key_offset(&item.key, start_block + 1); -	btrfs_set_disk_key_flags(&item.key, 0); -	btrfs_set_disk_key_type(&item.key, BTRFS_EXTENT_ITEM_KEY); -	itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) - -			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); -	btrfs_set_extent_owner(&extent_item, 0); -	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, start_block + 1); -	btrfs_set_disk_key_offset(&item.key, 1); -	itemoff = itemoff - sizeof(struct btrfs_extent_item); -	btrfs_set_item_offset(&item, itemoff); -	btrfs_set_extent_owner(&extent_item, BTRFS_ROOT_TREE_OBJECTID); -	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, start_block + 2); -	btrfs_set_disk_key_offset(&item.key, 1); -	itemoff = itemoff - sizeof(struct btrfs_extent_item); -	btrfs_set_item_offset(&item, itemoff); -	btrfs_set_extent_owner(&extent_item, BTRFS_EXTENT_TREE_OBJECTID); -	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 inode map */ -	btrfs_set_disk_key_objectid(&item.key, start_block + 3); -	btrfs_set_disk_key_offset(&item.key, 1); -	itemoff = itemoff - sizeof(struct btrfs_extent_item); -	btrfs_set_item_offset(&item, itemoff); -	btrfs_set_extent_owner(&extent_item, BTRFS_INODE_MAP_OBJECTID); -	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, blocksize, (start_block + 2) * blocksize); -	if (ret != blocksize) -		return -1; - -	/* item5, give block 20 to the FS root */ -	btrfs_set_disk_key_objectid(&item.key, start_block + 4); -	btrfs_set_disk_key_offset(&item.key, 1); -	itemoff = itemoff - sizeof(struct btrfs_extent_item); -	btrfs_set_item_offset(&item, itemoff); -	btrfs_set_extent_owner(&extent_item, BTRFS_FS_TREE_OBJECTID); -	memcpy(empty_leaf->items + 4, &item, sizeof(item)); -	memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), -		&extent_item, btrfs_item_size(&item)); -	ret = pwrite(fd, empty_leaf, blocksize, (start_block + 2) * blocksize); -	if (ret != blocksize) -		return -1; - -	/* create the inode map */ -	btrfs_set_header_parentid(&empty_leaf->header, -				  BTRFS_INODE_MAP_OBJECTID); -	btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3); -	btrfs_set_header_nritems(&empty_leaf->header, 0); -	ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize); -	if (ret != blocksize) -		return -1; - -	/* finally create the FS root */ -	btrfs_set_header_parentid(&empty_leaf->header, BTRFS_FS_TREE_OBJECTID); -	btrfs_set_header_blocknr(&empty_leaf->header, start_block + 4); -	btrfs_set_header_nritems(&empty_leaf->header, 0); -	ret = pwrite(fd, empty_leaf, blocksize, (start_block + 4) * blocksize); -	if (ret != blocksize) -		return -1; -	return 0; -} - -u64 device_size(int fd, struct stat *st) -{ -	u64 size; -	if (S_ISREG(st->st_mode)) { -		return st->st_size; -	} -	if (!S_ISBLK(st->st_mode)) { -		return 0; -	} -	if (ioctl(fd, BLKGETSIZE64, &size) >= 0) { -		return size; -	} -	return 0; -} - -int main(int ac, char **av) -{ -	char *file; -	u64 block_count = 0; -	int fd; -	struct stat st; -	int ret; -	int i; -	char *buf = malloc(4096); -	if (ac >= 2) { -		file = av[1]; -		if (ac == 3) { -			block_count = atoi(av[2]); -			if (!block_count) { -				fprintf(stderr, "error finding block count\n"); -				exit(1); -			} -		} -	} else { -		fprintf(stderr, "usage: mkfs.btrfs file [block count]\n"); -		exit(1); -	} -	fd = open(file, O_RDWR); -	if (fd < 0) { -		fprintf(stderr, "unable to open %s\n", file); -		exit(1); -	} -	ret = fstat(fd, &st); -	if (ret < 0) { -		fprintf(stderr, "unable to stat %s\n", file); -		exit(1); -	} -	if (block_count == 0) { -		block_count = device_size(fd, &st); -		if (block_count == 0) { -			fprintf(stderr, "unable to find %s size\n", file); -			exit(1); -		} -	} -	block_count /= 4096; -	if (block_count < 256) { -		fprintf(stderr, "device %s is too small\n", file); -		exit(1); -	} -	memset(buf, 0, 4096); -	for(i = 0; i < 6; i++) { -		ret = write(fd, buf, 4096); -		if (ret != 4096) { -			fprintf(stderr, "unable to zero fill device\n"); -			exit(1); -		} -	} -	ret = mkfs(fd, block_count, 4096); -	if (ret) { -		fprintf(stderr, "error during mkfs %d\n", ret); -		exit(1); -	} -	printf("fs created on %s blocksize %d blocks %Lu\n", -	       file, 4096, block_count); -	return 0; -} - diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index f53b99da12f..aa2d3fac880 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c @@ -1,7 +1,4 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" +#include <linux/module.h>  #include "ctree.h"  #include "disk-io.h" @@ -17,14 +14,14 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)  	struct btrfs_inode_item *ii;  	u32 type; -	printf("leaf %Lu total ptrs %d free space %d\n", +	printk("leaf %Lu total ptrs %d free space %d\n",  		btrfs_header_blocknr(&l->header), nr,  		btrfs_leaf_free_space(root, l));  	fflush(stdout);  	for (i = 0 ; i < nr ; i++) {  		item = l->items + i;  		type = btrfs_disk_key_type(&item->key); -		printf("\titem %d key (%Lu %u %Lu) itemoff %d itemsize %d\n", +		printk("\titem %d key (%Lu %u %Lu) itemoff %d itemsize %d\n",  			i,  			btrfs_disk_key_objectid(&item->key),  			btrfs_disk_key_flags(&item->key), @@ -34,38 +31,39 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)  		switch (type) {  		case BTRFS_INODE_ITEM_KEY:  			ii = btrfs_item_ptr(l, i, struct btrfs_inode_item); -			printf("\t\tinode generation %Lu size %Lu\n", +			printk("\t\tinode generation %Lu size %Lu mode %o\n",  			       btrfs_inode_generation(ii), -			       btrfs_inode_size(ii)); +			       btrfs_inode_size(ii), +			       btrfs_inode_mode(ii));  			break;  		case BTRFS_DIR_ITEM_KEY:  			di = btrfs_item_ptr(l, i, struct btrfs_dir_item); -			printf("\t\tdir oid %Lu flags %u type %u\n", +			printk("\t\tdir oid %Lu flags %u type %u\n",  				btrfs_dir_objectid(di),  				btrfs_dir_flags(di),  				btrfs_dir_type(di)); -			printf("\t\tname %.*s\n", +			printk("\t\tname %.*s\n",  			       btrfs_dir_name_len(di),(char *)(di + 1));  			break;  		case BTRFS_ROOT_ITEM_KEY:  			ri = btrfs_item_ptr(l, i, struct btrfs_root_item); -			printf("\t\troot data blocknr %Lu refs %u\n", +			printk("\t\troot data blocknr %Lu refs %u\n",  				btrfs_root_blocknr(ri), btrfs_root_refs(ri));  			break;  		case BTRFS_EXTENT_ITEM_KEY:  			ei = btrfs_item_ptr(l, i, struct btrfs_extent_item); -			printf("\t\textent data refs %u owner %Lu\n", +			printk("\t\textent data refs %u owner %Lu\n",  				btrfs_extent_refs(ei), btrfs_extent_owner(ei));  			break;  		case BTRFS_INODE_MAP_ITEM_KEY:  			mi = btrfs_item_ptr(l, i, struct btrfs_inode_map_item); -			printf("\t\tinode map key %Lu %u %Lu\n", +			printk("\t\tinode map key %Lu %u %Lu\n",  			       btrfs_disk_key_objectid(&mi->key),  			       btrfs_disk_key_flags(&mi->key),  			       btrfs_disk_key_offset(&mi->key));  			break;  		case BTRFS_STRING_ITEM_KEY: -			printf("\t\titem data %.*s\n", btrfs_item_size(item), +			printk("\t\titem data %.*s\n", btrfs_item_size(item),  				btrfs_leaf_data(l) + btrfs_item_offset(item));  			break;  		}; @@ -86,12 +84,12 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t)  		btrfs_print_leaf(root, (struct btrfs_leaf *)c);  		return;  	} -	printf("node %Lu level %d total ptrs %d free spc %u\n", t->blocknr, +	printk("node %Lu level %d total ptrs %d free spc %u\n", t->blocknr,  	        btrfs_header_level(&c->header), nr,  		(u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr);  	fflush(stdout);  	for (i = 0; i < nr; i++) { -		printf("\tkey %d (%Lu %u %Lu) block %Lu\n", +		printk("\tkey %d (%Lu %u %Lu) block %Lu\n",  		       i,  		       c->ptrs[i].key.objectid,  		       c->ptrs[i].key.flags, diff --git a/fs/btrfs/quick-test.c b/fs/btrfs/quick-test.c deleted file mode 100644 index ef12cf88878..00000000000 --- a/fs/btrfs/quick-test.c +++ /dev/null @@ -1,179 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" -#include "ctree.h" -#include "disk-io.h" -#include "print-tree.h" -#include "transaction.h" - -/* for testing only */ -int next_key(int i, int max_key) { -	return rand() % max_key; -	// return i; -} - -int main(int ac, char **av) { -	struct btrfs_key ins; -	struct btrfs_key last = { (u64)-1, 0, 0}; -	char *buf; -	int i; -	int num; -	int ret; -	int run_size = 100000; -	int max_key =  100000000; -	int tree_size = 0; -	struct btrfs_path path; -	struct btrfs_super_block super; -	struct btrfs_root *root; -	struct btrfs_trans_handle *trans; - -	radix_tree_init(); - -	root = open_ctree("dbfile", &super); -	trans = btrfs_start_transaction(root, 1); -	srand(55); -	ins.flags = 0; -	btrfs_set_key_type(&ins, BTRFS_STRING_ITEM_KEY); -	for (i = 0; i < run_size; i++) { -		buf = malloc(64); -		num = next_key(i, max_key); -		// num = i; -		sprintf(buf, "string-%d", num); -		if (i % 10000 == 0) -			fprintf(stderr, "insert %d:%d\n", num, i); -		ins.objectid = num; -		ins.offset = 0; -		ret = btrfs_insert_item(trans, root, &ins, buf, strlen(buf)); -		if (!ret) -			tree_size++; -		free(buf); -		if (i == run_size - 5) { -			btrfs_commit_transaction(trans, root, &super); -		} - -	} -	close_ctree(root, &super); - -	root = open_ctree("dbfile", &super); -	printf("starting search\n"); -	srand(55); -	for (i = 0; i < run_size; i++) { -		num = next_key(i, max_key); -		ins.objectid = num; -		btrfs_init_path(&path); -		if (i % 10000 == 0) -			fprintf(stderr, "search %d:%d\n", num, i); -		ret = btrfs_search_slot(trans, root, &ins, &path, 0, 0); -		if (ret) { -			btrfs_print_tree(root, root->node); -			printf("unable to find %d\n", num); -			exit(1); -		} -		btrfs_release_path(root, &path); -	} -	close_ctree(root, &super); -	root = open_ctree("dbfile", &super); -	printf("node %p level %d total ptrs %d free spc %lu\n", root->node, -	        btrfs_header_level(&root->node->node.header), -		btrfs_header_nritems(&root->node->node.header), -		BTRFS_NODEPTRS_PER_BLOCK(root) - -		btrfs_header_nritems(&root->node->node.header)); -	printf("all searches good, deleting some items\n"); -	i = 0; -	srand(55); -	for (i = 0 ; i < run_size/4; i++) { -		num = next_key(i, max_key); -		ins.objectid = num; -		btrfs_init_path(&path); -		ret = btrfs_search_slot(trans, root, &ins, &path, -1, 1); -		if (!ret) { -			if (i % 10000 == 0) -				fprintf(stderr, "del %d:%d\n", num, i); -			ret = btrfs_del_item(trans, root, &path); -			if (ret != 0) -				BUG(); -			tree_size--; -		} -		btrfs_release_path(root, &path); -	} -	close_ctree(root, &super); -	root = open_ctree("dbfile", &super); -	srand(128); -	for (i = 0; i < run_size; i++) { -		buf = malloc(64); -		num = next_key(i, max_key); -		sprintf(buf, "string-%d", num); -		ins.objectid = num; -		if (i % 10000 == 0) -			fprintf(stderr, "insert %d:%d\n", num, i); -		ret = btrfs_insert_item(trans, root, &ins, buf, strlen(buf)); -		if (!ret) -			tree_size++; -		free(buf); -	} -	close_ctree(root, &super); -	root = open_ctree("dbfile", &super); -	srand(128); -	printf("starting search2\n"); -	for (i = 0; i < run_size; i++) { -		num = next_key(i, max_key); -		ins.objectid = num; -		btrfs_init_path(&path); -		if (i % 10000 == 0) -			fprintf(stderr, "search %d:%d\n", num, i); -		ret = btrfs_search_slot(trans, root, &ins, &path, 0, 0); -		if (ret) { -			btrfs_print_tree(root, root->node); -			printf("unable to find %d\n", num); -			exit(1); -		} -		btrfs_release_path(root, &path); -	} -	printf("starting big long delete run\n"); -	while(root->node && -	      btrfs_header_nritems(&root->node->node.header) > 0) { -		struct btrfs_leaf *leaf; -		int slot; -		ins.objectid = (u64)-1; -		btrfs_init_path(&path); -		ret = btrfs_search_slot(trans, root, &ins, &path, -1, 1); -		if (ret == 0) -			BUG(); - -		leaf = &path.nodes[0]->leaf; -		slot = path.slots[0]; -		if (slot != btrfs_header_nritems(&leaf->header)) -			BUG(); -		while(path.slots[0] > 0) { -			path.slots[0] -= 1; -			slot = path.slots[0]; -			leaf = &path.nodes[0]->leaf; - -			btrfs_disk_key_to_cpu(&last, &leaf->items[slot].key); -			if (tree_size % 10000 == 0) -				printf("big del %d:%d\n", tree_size, i); -			ret = btrfs_del_item(trans, root, &path); -			if (ret != 0) { -				printf("del_item returned %d\n", ret); -				BUG(); -			} -			tree_size--; -		} -		btrfs_release_path(root, &path); -	} -	/* -	printf("previous tree:\n"); -	btrfs_print_tree(root, root->commit_root); -	printf("map before commit\n"); -	btrfs_print_tree(root->extent_root, root->extent_root->node); -	*/ -	btrfs_commit_transaction(trans, root, &super); -	printf("tree size is now %d\n", tree_size); -	printf("root %p commit root %p\n", root->node, root->commit_root); -	printf("map tree\n"); -	btrfs_print_tree(root->fs_info->extent_root, -			 root->fs_info->extent_root->node); -	close_ctree(root, &super); -	return 0; -} diff --git a/fs/btrfs/radix-tree.c b/fs/btrfs/radix-tree.c deleted file mode 100644 index baa25ca1c2a..00000000000 --- a/fs/btrfs/radix-tree.c +++ /dev/null @@ -1,836 +0,0 @@ -/* - * Copyright (C) 2001 Momchil Velikov - * Portions Copyright (C) 2001 Christoph Hellwig - * Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2, or (at - * your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "kerncompat.h" -#include "radix-tree.h" -#ifdef __KERNEL__ -#define RADIX_TREE_MAP_SHIFT	(CONFIG_BASE_SMALL ? 4 : 6) -#else -#define RADIX_TREE_MAP_SHIFT	3	/* For more stressful testing */ -#endif - -#define RADIX_TREE_MAP_SIZE	(1UL << RADIX_TREE_MAP_SHIFT) -#define RADIX_TREE_MAP_MASK	(RADIX_TREE_MAP_SIZE-1) - -#define RADIX_TREE_TAG_LONGS	\ -	((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG) - -struct radix_tree_node { -	unsigned int	count; -	void		*slots[RADIX_TREE_MAP_SIZE]; -	unsigned long	tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS]; -}; - -struct radix_tree_path { -	struct radix_tree_node *node; -	int offset; -}; - -#define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long)) -#define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2) - -static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH] __read_mostly; - -/* - * Per-cpu pool of preloaded nodes - */ -struct radix_tree_preload { -	int nr; -	struct radix_tree_node *nodes[RADIX_TREE_MAX_PATH]; -}; -struct radix_tree_preload radix_tree_preloads = { 0, }; - -static inline gfp_t root_gfp_mask(struct radix_tree_root *root) -{ -	return root->gfp_mask & __GFP_BITS_MASK; -} - -static int internal_nodes = 0; -/* - * This assumes that the caller has performed appropriate preallocation, and - * that the caller has pinned this thread of control to the current CPU. - */ -static struct radix_tree_node * -radix_tree_node_alloc(struct radix_tree_root *root) -{ -	struct radix_tree_node *ret; -	ret = malloc(sizeof(struct radix_tree_node)); -	if (ret) { -		memset(ret, 0, sizeof(struct radix_tree_node)); -		internal_nodes++; -	} -	return ret; -} - -static inline void -radix_tree_node_free(struct radix_tree_node *node) -{ -	internal_nodes--; -	free(node); -} - -/* - * Load up this CPU's radix_tree_node buffer with sufficient objects to - * ensure that the addition of a single element in the tree cannot fail.  On - * success, return zero, with preemption disabled.  On error, return -ENOMEM - * with preemption not disabled. - */ -int radix_tree_preload(gfp_t gfp_mask) -{ -	struct radix_tree_preload *rtp; -	struct radix_tree_node *node; -	int ret = -ENOMEM; - -	preempt_disable(); -	rtp = &__get_cpu_var(radix_tree_preloads); -	while (rtp->nr < ARRAY_SIZE(rtp->nodes)) { -		preempt_enable(); -		node = radix_tree_node_alloc(NULL); -		if (node == NULL) -			goto out; -		preempt_disable(); -		rtp = &__get_cpu_var(radix_tree_preloads); -		if (rtp->nr < ARRAY_SIZE(rtp->nodes)) -			rtp->nodes[rtp->nr++] = node; -		else -			radix_tree_node_free(node); -	} -	ret = 0; -out: -	return ret; -} - -static inline void tag_set(struct radix_tree_node *node, unsigned int tag, -		int offset) -{ -	__set_bit(offset, node->tags[tag]); -} - -static inline void tag_clear(struct radix_tree_node *node, unsigned int tag, -		int offset) -{ -	__clear_bit(offset, node->tags[tag]); -} - -static inline int tag_get(struct radix_tree_node *node, unsigned int tag, -		int offset) -{ -	return test_bit(offset, node->tags[tag]); -} - -static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag) -{ -	root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT)); -} - - -static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag) -{ -	root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT)); -} - -static inline void root_tag_clear_all(struct radix_tree_root *root) -{ -	root->gfp_mask &= __GFP_BITS_MASK; -} - -static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag) -{ -	return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT)); -} - -/* - * Returns 1 if any slot in the node has this tag set. - * Otherwise returns 0. - */ -static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag) -{ -	int idx; -	for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { -		if (node->tags[tag][idx]) -			return 1; -	} -	return 0; -} - -/* - *	Return the maximum key which can be store into a - *	radix tree with height HEIGHT. - */ -static inline unsigned long radix_tree_maxindex(unsigned int height) -{ -	return height_to_maxindex[height]; -} - -/* - *	Extend a radix tree so it can store key @index. - */ -static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) -{ -	struct radix_tree_node *node; -	unsigned int height; -	int tag; - -	/* Figure out what the height should be.  */ -	height = root->height + 1; -	while (index > radix_tree_maxindex(height)) -		height++; - -	if (root->rnode == NULL) { -		root->height = height; -		goto out; -	} - -	do { -		if (!(node = radix_tree_node_alloc(root))) -			return -ENOMEM; - -		/* Increase the height.  */ -		node->slots[0] = root->rnode; - -		/* Propagate the aggregated tag info into the new root */ -		for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { -			if (root_tag_get(root, tag)) -				tag_set(node, tag, 0); -		} - -		node->count = 1; -		root->rnode = node; -		root->height++; -	} while (height > root->height); -out: -	return 0; -} - -/** - *	radix_tree_insert    -    insert into a radix tree - *	@root:		radix tree root - *	@index:		index key - *	@item:		item to insert - * - *	Insert an item into the radix tree at position @index. - */ -int radix_tree_insert(struct radix_tree_root *root, -			unsigned long index, void *item) -{ -	struct radix_tree_node *node = NULL, *slot; -	unsigned int height, shift; -	int offset; -	int error; - -	/* Make sure the tree is high enough.  */ -	if (index > radix_tree_maxindex(root->height)) { -		error = radix_tree_extend(root, index); -		if (error) -			return error; -	} - -	slot = root->rnode; -	height = root->height; -	shift = (height-1) * RADIX_TREE_MAP_SHIFT; - -	offset = 0;			/* uninitialised var warning */ -	while (height > 0) { -		if (slot == NULL) { -			/* Have to add a child node.  */ -			if (!(slot = radix_tree_node_alloc(root))) -				return -ENOMEM; -			if (node) { -				node->slots[offset] = slot; -				node->count++; -			} else -				root->rnode = slot; -		} - -		/* Go a level down */ -		offset = (index >> shift) & RADIX_TREE_MAP_MASK; -		node = slot; -		slot = node->slots[offset]; -		shift -= RADIX_TREE_MAP_SHIFT; -		height--; -	} - -	if (slot != NULL) -		return -EEXIST; - -	if (node) { -		node->count++; -		node->slots[offset] = item; -		BUG_ON(tag_get(node, 0, offset)); -		BUG_ON(tag_get(node, 1, offset)); -	} else { -		root->rnode = item; -		BUG_ON(root_tag_get(root, 0)); -		BUG_ON(root_tag_get(root, 1)); -	} - -	return 0; -} - -static inline void **__lookup_slot(struct radix_tree_root *root, -				   unsigned long index) -{ -	unsigned int height, shift; -	struct radix_tree_node **slot; - -	height = root->height; - -	if (index > radix_tree_maxindex(height)) -		return NULL; - -	if (height == 0 && root->rnode) -		return (void **)&root->rnode; - -	shift = (height-1) * RADIX_TREE_MAP_SHIFT; -	slot = &root->rnode; - -	while (height > 0) { -		if (*slot == NULL) -			return NULL; - -		slot = (struct radix_tree_node **) -			((*slot)->slots + -				((index >> shift) & RADIX_TREE_MAP_MASK)); -		shift -= RADIX_TREE_MAP_SHIFT; -		height--; -	} - -	return (void **)slot; -} - -/** - *	radix_tree_lookup_slot    -    lookup a slot in a radix tree - *	@root:		radix tree root - *	@index:		index key - * - *	Lookup the slot corresponding to the position @index in the radix tree - *	@root. This is useful for update-if-exists operations. - */ -void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index) -{ -	return __lookup_slot(root, index); -} - -/** - *	radix_tree_lookup    -    perform lookup operation on a radix tree - *	@root:		radix tree root - *	@index:		index key - * - *	Lookup the item at the position @index in the radix tree @root. - */ -void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) -{ -	void **slot; - -	slot = __lookup_slot(root, index); -	return slot != NULL ? *slot : NULL; -} - -/** - *	radix_tree_tag_set - set a tag on a radix tree node - *	@root:		radix tree root - *	@index:		index key - *	@tag: 		tag index - * - *	Set the search tag (which must be < RADIX_TREE_MAX_TAGS) - *	corresponding to @index in the radix tree.  From - *	the root all the way down to the leaf node. - * - *	Returns the address of the tagged item.   Setting a tag on a not-present - *	item is a bug. - */ -void *radix_tree_tag_set(struct radix_tree_root *root, -			unsigned long index, unsigned int tag) -{ -	unsigned int height, shift; -	struct radix_tree_node *slot; - -	height = root->height; -	BUG_ON(index > radix_tree_maxindex(height)); - -	slot = root->rnode; -	shift = (height - 1) * RADIX_TREE_MAP_SHIFT; - -	while (height > 0) { -		int offset; - -		offset = (index >> shift) & RADIX_TREE_MAP_MASK; -		if (!tag_get(slot, tag, offset)) -			tag_set(slot, tag, offset); -		slot = slot->slots[offset]; -		BUG_ON(slot == NULL); -		shift -= RADIX_TREE_MAP_SHIFT; -		height--; -	} - -	/* set the root's tag bit */ -	if (slot && !root_tag_get(root, tag)) -		root_tag_set(root, tag); - -	return slot; -} - -/** - *	radix_tree_tag_clear - clear a tag on a radix tree node - *	@root:		radix tree root - *	@index:		index key - *	@tag: 		tag index - * - *	Clear the search tag (which must be < RADIX_TREE_MAX_TAGS) - *	corresponding to @index in the radix tree.  If - *	this causes the leaf node to have no tags set then clear the tag in the - *	next-to-leaf node, etc. - * - *	Returns the address of the tagged item on success, else NULL.  ie: - *	has the same return value and semantics as radix_tree_lookup(). - */ -void *radix_tree_tag_clear(struct radix_tree_root *root, -			unsigned long index, unsigned int tag) -{ -	struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; -	struct radix_tree_node *slot = NULL; -	unsigned int height, shift; - -	height = root->height; -	if (index > radix_tree_maxindex(height)) -		goto out; - -	shift = (height - 1) * RADIX_TREE_MAP_SHIFT; -	pathp->node = NULL; -	slot = root->rnode; - -	while (height > 0) { -		int offset; - -		if (slot == NULL) -			goto out; - -		offset = (index >> shift) & RADIX_TREE_MAP_MASK; -		pathp[1].offset = offset; -		pathp[1].node = slot; -		slot = slot->slots[offset]; -		pathp++; -		shift -= RADIX_TREE_MAP_SHIFT; -		height--; -	} - -	if (slot == NULL) -		goto out; - -	while (pathp->node) { -		if (!tag_get(pathp->node, tag, pathp->offset)) -			goto out; -		tag_clear(pathp->node, tag, pathp->offset); -		if (any_tag_set(pathp->node, tag)) -			goto out; -		pathp--; -	} - -	/* clear the root's tag bit */ -	if (root_tag_get(root, tag)) -		root_tag_clear(root, tag); - -out: -	return slot; -} - -#ifndef __KERNEL__	/* Only the test harness uses this at present */ -/** - * radix_tree_tag_get - get a tag on a radix tree node - * @root:		radix tree root - * @index:		index key - * @tag: 		tag index (< RADIX_TREE_MAX_TAGS) - * - * Return values: - * - *  0: tag not present or not set - *  1: tag set - */ -int radix_tree_tag_get(struct radix_tree_root *root, -			unsigned long index, unsigned int tag) -{ -	unsigned int height, shift; -	struct radix_tree_node *slot; -	int saw_unset_tag = 0; - -	height = root->height; -	if (index > radix_tree_maxindex(height)) -		return 0; - -	/* check the root's tag bit */ -	if (!root_tag_get(root, tag)) -		return 0; - -	if (height == 0) -		return 1; - -	shift = (height - 1) * RADIX_TREE_MAP_SHIFT; -	slot = root->rnode; - -	for ( ; ; ) { -		int offset; - -		if (slot == NULL) -			return 0; - -		offset = (index >> shift) & RADIX_TREE_MAP_MASK; - -		/* -		 * This is just a debug check.  Later, we can bale as soon as -		 * we see an unset tag. -		 */ -		if (!tag_get(slot, tag, offset)) -			saw_unset_tag = 1; -		if (height == 1) { -			int ret = tag_get(slot, tag, offset); - -			BUG_ON(ret && saw_unset_tag); -			return !!ret; -		} -		slot = slot->slots[offset]; -		shift -= RADIX_TREE_MAP_SHIFT; -		height--; -	} -} -#endif - -static unsigned int -__lookup(struct radix_tree_root *root, void **results, unsigned long index, -	unsigned int max_items, unsigned long *next_index) -{ -	unsigned int nr_found = 0; -	unsigned int shift, height; -	struct radix_tree_node *slot; -	unsigned long i; - -	height = root->height; -	if (height == 0) { -		if (root->rnode && index == 0) -			results[nr_found++] = root->rnode; -		goto out; -	} - -	shift = (height-1) * RADIX_TREE_MAP_SHIFT; -	slot = root->rnode; - -	for ( ; height > 1; height--) { - -		for (i = (index >> shift) & RADIX_TREE_MAP_MASK ; -				i < RADIX_TREE_MAP_SIZE; i++) { -			if (slot->slots[i] != NULL) -				break; -			index &= ~((1UL << shift) - 1); -			index += 1UL << shift; -			if (index == 0) -				goto out;	/* 32-bit wraparound */ -		} -		if (i == RADIX_TREE_MAP_SIZE) -			goto out; - -		shift -= RADIX_TREE_MAP_SHIFT; -		slot = slot->slots[i]; -	} - -	/* Bottom level: grab some items */ -	for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) { -		index++; -		if (slot->slots[i]) { -			results[nr_found++] = slot->slots[i]; -			if (nr_found == max_items) -				goto out; -		} -	} -out: -	*next_index = index; -	return nr_found; -} - -/** - *	radix_tree_gang_lookup - perform multiple lookup on a radix tree - *	@root:		radix tree root - *	@results:	where the results of the lookup are placed - *	@first_index:	start the lookup from this key - *	@max_items:	place up to this many items at *results - * - *	Performs an index-ascending scan of the tree for present items.  Places - *	them at *@results and returns the number of items which were placed at - *	*@results. - * - *	The implementation is naive. - */ -unsigned int -radix_tree_gang_lookup(struct radix_tree_root *root, void **results, -			unsigned long first_index, unsigned int max_items) -{ -	const unsigned long max_index = radix_tree_maxindex(root->height); -	unsigned long cur_index = first_index; -	unsigned int ret = 0; - -	while (ret < max_items) { -		unsigned int nr_found; -		unsigned long next_index;	/* Index of next search */ - -		if (cur_index > max_index) -			break; -		nr_found = __lookup(root, results + ret, cur_index, -					max_items - ret, &next_index); -		ret += nr_found; -		if (next_index == 0) -			break; -		cur_index = next_index; -	} -	return ret; -} - -/* - * FIXME: the two tag_get()s here should use find_next_bit() instead of - * open-coding the search. - */ -static unsigned int -__lookup_tag(struct radix_tree_root *root, void **results, unsigned long index, -	unsigned int max_items, unsigned long *next_index, unsigned int tag) -{ -	unsigned int nr_found = 0; -	unsigned int shift; -	unsigned int height = root->height; -	struct radix_tree_node *slot; - -	if (height == 0) { -		if (root->rnode && index == 0) -			results[nr_found++] = root->rnode; -		goto out; -	} - -	shift = (height - 1) * RADIX_TREE_MAP_SHIFT; -	slot = root->rnode; - -	do { -		unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK; - -		for ( ; i < RADIX_TREE_MAP_SIZE; i++) { -			if (tag_get(slot, tag, i)) { -				BUG_ON(slot->slots[i] == NULL); -				break; -			} -			index &= ~((1UL << shift) - 1); -			index += 1UL << shift; -			if (index == 0) -				goto out;	/* 32-bit wraparound */ -		} -		if (i == RADIX_TREE_MAP_SIZE) -			goto out; -		height--; -		if (height == 0) {	/* Bottom level: grab some items */ -			unsigned long j = index & RADIX_TREE_MAP_MASK; - -			for ( ; j < RADIX_TREE_MAP_SIZE; j++) { -				index++; -				if (tag_get(slot, tag, j)) { -					BUG_ON(slot->slots[j] == NULL); -					results[nr_found++] = slot->slots[j]; -					if (nr_found == max_items) -						goto out; -				} -			} -		} -		shift -= RADIX_TREE_MAP_SHIFT; -		slot = slot->slots[i]; -	} while (height > 0); -out: -	*next_index = index; -	return nr_found; -} - -/** - *	radix_tree_gang_lookup_tag - perform multiple lookup on a radix tree - *	                             based on a tag - *	@root:		radix tree root - *	@results:	where the results of the lookup are placed - *	@first_index:	start the lookup from this key - *	@max_items:	place up to this many items at *results - *	@tag:		the tag index (< RADIX_TREE_MAX_TAGS) - * - *	Performs an index-ascending scan of the tree for present items which - *	have the tag indexed by @tag set.  Places the items at *@results and - *	returns the number of items which were placed at *@results. - */ -unsigned int -radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, -		unsigned long first_index, unsigned int max_items, -		unsigned int tag) -{ -	const unsigned long max_index = radix_tree_maxindex(root->height); -	unsigned long cur_index = first_index; -	unsigned int ret = 0; - -	/* check the root's tag bit */ -	if (!root_tag_get(root, tag)) -		return 0; - -	while (ret < max_items) { -		unsigned int nr_found; -		unsigned long next_index;	/* Index of next search */ - -		if (cur_index > max_index) -			break; -		nr_found = __lookup_tag(root, results + ret, cur_index, -					max_items - ret, &next_index, tag); -		ret += nr_found; -		if (next_index == 0) -			break; -		cur_index = next_index; -	} -	return ret; -} - -/** - *	radix_tree_shrink    -    shrink height of a radix tree to minimal - *	@root		radix tree root - */ -static inline void radix_tree_shrink(struct radix_tree_root *root) -{ -	/* try to shrink tree height */ -	while (root->height > 0 && -			root->rnode->count == 1 && -			root->rnode->slots[0]) { -		struct radix_tree_node *to_free = root->rnode; - -		root->rnode = to_free->slots[0]; -		root->height--; -		/* must only free zeroed nodes into the slab */ -		tag_clear(to_free, 0, 0); -		tag_clear(to_free, 1, 0); -		to_free->slots[0] = NULL; -		to_free->count = 0; -		radix_tree_node_free(to_free); -	} -} - -/** - *	radix_tree_delete    -    delete an item from a radix tree - *	@root:		radix tree root - *	@index:		index key - * - *	Remove the item at @index from the radix tree rooted at @root. - * - *	Returns the address of the deleted item, or NULL if it was not present. - */ -void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) -{ -	struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; -	struct radix_tree_node *slot = NULL; -	unsigned int height, shift; -	int tag; -	int offset; - -	height = root->height; -	if (index > radix_tree_maxindex(height)) -		goto out; - -	slot = root->rnode; -	if (height == 0 && root->rnode) { -		root_tag_clear_all(root); -		root->rnode = NULL; -		goto out; -	} - -	shift = (height - 1) * RADIX_TREE_MAP_SHIFT; -	pathp->node = NULL; - -	do { -		if (slot == NULL) -			goto out; - -		pathp++; -		offset = (index >> shift) & RADIX_TREE_MAP_MASK; -		pathp->offset = offset; -		pathp->node = slot; -		slot = slot->slots[offset]; -		shift -= RADIX_TREE_MAP_SHIFT; -		height--; -	} while (height > 0); - -	if (slot == NULL) -		goto out; - -	/* -	 * Clear all tags associated with the just-deleted item -	 */ -	for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { -		if (tag_get(pathp->node, tag, pathp->offset)) -			radix_tree_tag_clear(root, index, tag); -	} - -	/* Now free the nodes we do not need anymore */ -	while (pathp->node) { -		pathp->node->slots[pathp->offset] = NULL; -		pathp->node->count--; - -		if (pathp->node->count) { -			if (pathp->node == root->rnode) -				radix_tree_shrink(root); -			goto out; -		} - -		/* Node with zero slots in use so free it */ -		radix_tree_node_free(pathp->node); - -		pathp--; -	} -	root_tag_clear_all(root); -	root->height = 0; -	root->rnode = NULL; - -out: -	return slot; -} - -/** - *	radix_tree_tagged - test whether any items in the tree are tagged - *	@root:		radix tree root - *	@tag:		tag to test - */ -int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag) -{ -	return root_tag_get(root, tag); -} - -static unsigned long __maxindex(unsigned int height) -{ -	unsigned int tmp = height * RADIX_TREE_MAP_SHIFT; -	unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1; - -	if (tmp >= RADIX_TREE_INDEX_BITS) -		index = ~0UL; -	return index; -} - -static void radix_tree_init_maxindex(void) -{ -	unsigned int i; - -	for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++) -		height_to_maxindex[i] = __maxindex(i); -} - -void radix_tree_init(void) -{ -	radix_tree_init_maxindex(); -} diff --git a/fs/btrfs/radix-tree.h b/fs/btrfs/radix-tree.h deleted file mode 100644 index c3ce88137f7..00000000000 --- a/fs/btrfs/radix-tree.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2001 Momchil Velikov - * Portions Copyright (C) 2001 Christoph Hellwig - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2, or (at - * your option) any later version. - *  - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef _LINUX_RADIX_TREE_H -#define _LINUX_RADIX_TREE_H - -#define RADIX_TREE_MAX_TAGS 2 - -/* root tags are stored in gfp_mask, shifted by __GFP_BITS_SHIFT */ -struct radix_tree_root { -	unsigned int		height; -	gfp_t			gfp_mask; -	struct radix_tree_node	*rnode; -}; - -#define RADIX_TREE_INIT(mask)	{					\ -	.height = 0,							\ -	.gfp_mask = (mask),						\ -	.rnode = NULL,							\ -} - -#define RADIX_TREE(name, mask) \ -	struct radix_tree_root name = RADIX_TREE_INIT(mask) - -#define INIT_RADIX_TREE(root, mask)					\ -do {									\ -	(root)->height = 0;						\ -	(root)->gfp_mask = (mask);					\ -	(root)->rnode = NULL;						\ -} while (0) - -int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); -void *radix_tree_lookup(struct radix_tree_root *, unsigned long); -void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); -void *radix_tree_delete(struct radix_tree_root *, unsigned long); -unsigned int -radix_tree_gang_lookup(struct radix_tree_root *root, void **results, -			unsigned long first_index, unsigned int max_items); -int radix_tree_preload(gfp_t gfp_mask); -void radix_tree_init(void); -void *radix_tree_tag_set(struct radix_tree_root *root, -			unsigned long index, unsigned int tag); -void *radix_tree_tag_clear(struct radix_tree_root *root, -			unsigned long index, unsigned int tag); -int radix_tree_tag_get(struct radix_tree_root *root, -			unsigned long index, unsigned int tag); -unsigned int -radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, -		unsigned long first_index, unsigned int max_items, -		unsigned int tag); -int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag); - -static inline void radix_tree_preload_end(void) -{ -	preempt_enable(); -} - -#endif /* _LINUX_RADIX_TREE_H */ diff --git a/fs/btrfs/random-test.c b/fs/btrfs/random-test.c deleted file mode 100644 index 3a38ae7a886..00000000000 --- a/fs/btrfs/random-test.c +++ /dev/null @@ -1,405 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include "kerncompat.h" -#include "radix-tree.h" -#include "ctree.h" -#include "disk-io.h" -#include "print-tree.h" -#include "transaction.h" - -int keep_running = 1; -struct btrfs_super_block super; - -static int setup_key(struct radix_tree_root *root, struct btrfs_key *key, -		     int exists) -{ -	int num = rand(); -	unsigned long res[2]; -	int ret; - -	key->flags = 0; -	btrfs_set_key_type(key, BTRFS_STRING_ITEM_KEY); -	key->offset = 0; -again: -	ret = radix_tree_gang_lookup(root, (void **)res, num, 2); -	if (exists) { -		if (ret == 0) -			return -1; -		num = res[0]; -	} else if (ret != 0 && num == res[0]) { -		num++; -		if (ret > 1 && num == res[1]) { -			num++; -			goto again; -		} -	} -	key->objectid = num; -	return 0; -} - -static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, -		   struct radix_tree_root *radix) -{ -	struct btrfs_path path; -	struct btrfs_key key; -	int ret; -	char buf[128]; -	unsigned long oid; -	btrfs_init_path(&path); -	ret = setup_key(radix, &key, 0); -	sprintf(buf, "str-%Lu\n", key.objectid); -	ret = btrfs_insert_item(trans, root, &key, buf, strlen(buf)); -	if (ret) -		goto error; -	oid = (unsigned long)key.objectid; -	radix_tree_preload(GFP_KERNEL); -	ret = radix_tree_insert(radix, oid, (void *)oid); -	radix_tree_preload_end(); -	if (ret) -		goto error; -	return ret; -error: -	printf("failed to insert %Lu\n", key.objectid); -	return -1; -} - -static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root -		      *root, struct radix_tree_root *radix) -{ -	struct btrfs_path path; -	struct btrfs_key key; -	int ret; -	char buf[128]; -	btrfs_init_path(&path); -	ret = setup_key(radix, &key, 1); -	if (ret < 0) -		return 0; -	sprintf(buf, "str-%Lu\n", key.objectid); -	ret = btrfs_insert_item(trans, root, &key, buf, strlen(buf)); -	if (ret != -EEXIST) { -		printf("insert on %Lu gave us %d\n", key.objectid, ret); -		return 1; -	} -	return 0; -} - -static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, -		   struct radix_tree_root *radix) -{ -	struct btrfs_path path; -	struct btrfs_key key; -	int ret; -	unsigned long *ptr; -	btrfs_init_path(&path); -	ret = setup_key(radix, &key, 1); -	if (ret < 0) -		return 0; -	ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); -	if (ret) -		goto error; -	ret = btrfs_del_item(trans, root, &path); -	btrfs_release_path(root, &path); -	if (ret != 0) -		goto error; -	ptr = radix_tree_delete(radix, key.objectid); -	if (!ptr) -		goto error; -	return 0; -error: -	printf("failed to delete %Lu\n", key.objectid); -	return -1; -} - -static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root -		       *root, struct radix_tree_root *radix) -{ -	struct btrfs_path path; -	struct btrfs_key key; -	int ret; -	btrfs_init_path(&path); -	ret = setup_key(radix, &key, 1); -	if (ret < 0) -		return 0; -	ret = btrfs_search_slot(trans, root, &key, &path, 0, 1); -	btrfs_release_path(root, &path); -	if (ret) -		goto error; -	return 0; -error: -	printf("unable to find key %Lu\n", key.objectid); -	return -1; -} - -static int lookup_enoent(struct btrfs_trans_handle *trans, struct btrfs_root -			 *root, struct radix_tree_root *radix) -{ -	struct btrfs_path path; -	struct btrfs_key key; -	int ret; -	btrfs_init_path(&path); -	ret = setup_key(radix, &key, 0); -	if (ret < 0) -		return ret; -	ret = btrfs_search_slot(trans, root, &key, &path, 0, 0); -	btrfs_release_path(root, &path); -	if (ret <= 0) -		goto error; -	return 0; -error: -	printf("able to find key that should not exist %Lu\n", key.objectid); -	return -1; -} - -static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root -		      *root, struct radix_tree_root *radix, int nr) -{ -	struct btrfs_path path; -	struct btrfs_key key; -	unsigned long found = 0; -	int ret; -	int slot; -	int *ptr; -	int count = 0; - -	key.offset = 0; -	key.flags = 0; -	btrfs_set_key_type(&key, BTRFS_STRING_ITEM_KEY); -	key.objectid = (unsigned long)-1; -	while(nr-- >= 0) { -		btrfs_init_path(&path); -		ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); -		if (ret < 0) { -			btrfs_release_path(root, &path); -			return ret; -		} -		if (ret != 0) { -			if (path.slots[0] == 0) { -				btrfs_release_path(root, &path); -				break; -			} -			path.slots[0] -= 1; -		} -		slot = path.slots[0]; -		found = btrfs_disk_key_objectid( -					&path.nodes[0]->leaf.items[slot].key); -		ret = btrfs_del_item(trans, root, &path); -		count++; -		if (ret) { -			fprintf(stderr, -				"failed to remove %lu from tree\n", -				found); -			return -1; -		} -		btrfs_release_path(root, &path); -		ptr = radix_tree_delete(radix, found); -		if (!ptr) -			goto error; -		if (!keep_running) -			break; -	} -	return 0; -error: -	fprintf(stderr, "failed to delete from the radix %lu\n", found); -	return -1; -} - -static int fill_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root, -		     struct radix_tree_root *radix, int count) -{ -	int i; -	int ret = 0; -	for (i = 0; i < count; i++) { -		ret = ins_one(trans, root, radix); -		if (ret) { -			fprintf(stderr, "fill failed\n"); -			goto out; -		} -		if (i % 1000 == 0) { -			ret = btrfs_commit_transaction(trans, root, &super); -			if (ret) { -				fprintf(stderr, "fill commit failed\n"); -				return ret; -			} -		} -		if (i && i % 10000 == 0) { -			printf("bigfill %d\n", i); -		} -		if (!keep_running) -			break; -	} -out: -	return ret; -} - -static int bulk_op(struct btrfs_trans_handle *trans, struct btrfs_root *root, -		   struct radix_tree_root *radix) -{ -	int ret; -	int nr = rand() % 5000; -	static int run_nr = 0; - -	/* do the bulk op much less frequently */ -	if (run_nr++ % 100) -		return 0; -	ret = empty_tree(trans, root, radix, nr); -	if (ret) -		return ret; -	ret = fill_tree(trans, root, radix, nr); -	if (ret) -		return ret; -	return 0; -} - - -int (*ops[])(struct btrfs_trans_handle *, -	     struct btrfs_root *root, struct radix_tree_root *radix) = -	{ ins_one, insert_dup, del_one, lookup_item, -	  lookup_enoent, bulk_op }; - -static int fill_radix(struct btrfs_root *root, struct radix_tree_root *radix) -{ -	struct btrfs_path path; -	struct btrfs_key key; -	unsigned long found; -	int ret; -	int slot; -	int i; - -	key.offset = 0; -	key.flags = 0; -	btrfs_set_key_type(&key, BTRFS_STRING_ITEM_KEY); -	key.objectid = (unsigned long)-1; -	while(1) { -		btrfs_init_path(&path); -		ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); -		if (ret < 0) { -			btrfs_release_path(root, &path); -			return ret; -		} -		slot = path.slots[0]; -		if (ret != 0) { -			if (slot == 0) { -				btrfs_release_path(root, &path); -				break; -			} -			slot -= 1; -		} -		for (i = slot; i >= 0; i--) { -			found = btrfs_disk_key_objectid(&path.nodes[0]-> -							leaf.items[i].key); -			radix_tree_preload(GFP_KERNEL); -			ret = radix_tree_insert(radix, found, (void *)found); -			if (ret) { -				fprintf(stderr, -					"failed to insert %lu into radix\n", -					found); -				exit(1); -			} - -			radix_tree_preload_end(); -		} -		btrfs_release_path(root, &path); -		key.objectid = found - 1; -		if (key.objectid > found) -			break; -	} -	return 0; -} -void sigstopper(int ignored) -{ -	keep_running = 0; -	fprintf(stderr, "caught exit signal, stopping\n"); -} - -int print_usage(void) -{ -	printf("usage: tester [-ih] [-c count] [-f count]\n"); -	printf("\t -c count -- iteration count after filling\n"); -	printf("\t -f count -- run this many random inserts before starting\n"); -	printf("\t -i       -- only do initial fill\n"); -	printf("\t -h       -- this help text\n"); -	exit(1); -} -int main(int ac, char **av) -{ -	RADIX_TREE(radix, GFP_KERNEL); -	struct btrfs_root *root; -	int i; -	int ret; -	int count; -	int op; -	int iterations = 20000; -	int init_fill_count = 800000; -	int err = 0; -	int initial_only = 0; -	struct btrfs_trans_handle *trans; -	radix_tree_init(); -	root = open_ctree("dbfile", &super); -	fill_radix(root, &radix); - -	signal(SIGTERM, sigstopper); -	signal(SIGINT, sigstopper); - -	for (i = 1 ; i < ac ; i++) { -		if (strcmp(av[i], "-i") == 0) { -			initial_only = 1; -		} else if (strcmp(av[i], "-c") == 0) { -			iterations = atoi(av[i+1]); -			i++; -		} else if (strcmp(av[i], "-f") == 0) { -			init_fill_count = atoi(av[i+1]); -			i++; -		} else { -			print_usage(); -		} -	} -	printf("initial fill\n"); -	trans = btrfs_start_transaction(root, 1); -	ret = fill_tree(trans, root, &radix, init_fill_count); -	printf("starting run\n"); -	if (ret) { -		err = ret; -		goto out; -	} -	if (initial_only == 1) { -		goto out; -	} -	for (i = 0; i < iterations; i++) { -		op = rand() % ARRAY_SIZE(ops); -		count = rand() % 128; -		if (i % 2000 == 0) { -			printf("%d\n", i); -			fflush(stdout); -		} -		if (i && i % 5000 == 0) { -			printf("open & close, root level %d nritems %d\n", -				btrfs_header_level(&root->node->node.header), -				btrfs_header_nritems(&root->node->node.header)); -			close_ctree(root, &super); -			root = open_ctree("dbfile", &super); -		} -		while(count--) { -			ret = ops[op](trans, root, &radix); -			if (ret) { -				fprintf(stderr, "op %d failed %d:%d\n", -					op, i, iterations); -				btrfs_print_tree(root, root->node); -				fprintf(stderr, "op %d failed %d:%d\n", -					op, i, iterations); -				err = ret; -				goto out; -			} -			if (ops[op] == bulk_op) -				break; -			if (keep_running == 0) { -				err = 0; -				goto out; -			} -		} -	} -out: -	close_ctree(root, &super); -	return err; -} - diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 9cccecc0f43..52c83be4b30 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -1,7 +1,4 @@ -#include <stdio.h> -#include <stdlib.h> -#include "kerncompat.h" -#include "radix-tree.h" +#include <linux/module.h>  #include "ctree.h"  #include "disk-io.h"  #include "print-tree.h" diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c new file mode 100644 index 00000000000..4ae76044aea --- /dev/null +++ b/fs/btrfs/super.c @@ -0,0 +1,205 @@ +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/pagemap.h> +#include <linux/highmem.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/smp_lock.h> +#include <linux/backing-dev.h> +#include "ctree.h" + +#define BTRFS_SUPER_MAGIC 0x9123682E +#if 0 +/* some random number */ + +static struct super_operations ramfs_ops; +static struct inode_operations ramfs_dir_inode_operations; + +static struct backing_dev_info ramfs_backing_dev_info = { +	.ra_pages	= 0,	/* No readahead */ +	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK | +			  BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY | +			  BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP, +}; + +struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev) +{ +	struct inode * inode = new_inode(sb); + +	if (inode) { +		inode->i_mode = mode; +		inode->i_uid = current->fsuid; +		inode->i_gid = current->fsgid; +		inode->i_blocks = 0; +		inode->i_mapping->a_ops = &ramfs_aops; +		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info; +		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; +		switch (mode & S_IFMT) { +		default: +			init_special_inode(inode, mode, dev); +			break; +		case S_IFREG: +			inode->i_op = &ramfs_file_inode_operations; +			inode->i_fop = &ramfs_file_operations; +			break; +		case S_IFDIR: +			inode->i_op = &ramfs_dir_inode_operations; +			inode->i_fop = &simple_dir_operations; + +			/* directory inodes start off with i_nlink == 2 (for "." entry) */ +			inc_nlink(inode); +			break; +		case S_IFLNK: +			inode->i_op = &page_symlink_inode_operations; +			break; +		} +	} +	return inode; +} + +/* + * File creation. Allocate an inode, and we're done.. + */ +/* SMP-safe */ +static int +ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +{ +	struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev); +	int error = -ENOSPC; + +	if (inode) { +		if (dir->i_mode & S_ISGID) { +			inode->i_gid = dir->i_gid; +			if (S_ISDIR(mode)) +				inode->i_mode |= S_ISGID; +		} +		d_instantiate(dentry, inode); +		dget(dentry);	/* Extra count - pin the dentry in core */ +		error = 0; +		dir->i_mtime = dir->i_ctime = CURRENT_TIME; +	} +	return error; +} + +static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) +{ +	int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0); +	if (!retval) +		inc_nlink(dir); +	return retval; +} + +static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) +{ +	return ramfs_mknod(dir, dentry, mode | S_IFREG, 0); +} + +static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) +{ +	struct inode *inode; +	int error = -ENOSPC; + +	inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); +	if (inode) { +		int l = strlen(symname)+1; +		error = page_symlink(inode, symname, l); +		if (!error) { +			if (dir->i_mode & S_ISGID) +				inode->i_gid = dir->i_gid; +			d_instantiate(dentry, inode); +			dget(dentry); +			dir->i_mtime = dir->i_ctime = CURRENT_TIME; +		} else +			iput(inode); +	} +	return error; +} + +static struct inode_operations ramfs_dir_inode_operations = { +	.create		= ramfs_create, +	.lookup		= simple_lookup, +	.link		= simple_link, +	.unlink		= simple_unlink, +	.symlink	= ramfs_symlink, +	.mkdir		= ramfs_mkdir, +	.rmdir		= simple_rmdir, +	.mknod		= ramfs_mknod, +	.rename		= simple_rename, +}; +#endif + +struct inode *btrfs_get_inode(struct super_block *sb, int mode, dev_t dev) +{ +	struct inode * inode = new_inode(sb); + +	if (inode) { +		inode->i_mode = mode; +		inode->i_uid = current->fsuid; +		inode->i_gid = current->fsgid; +		inode->i_blocks = 0; +		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; +	} +	return inode; +} + +static struct super_operations btrfs_ops = { +	.statfs		= simple_statfs, +	.drop_inode	= generic_delete_inode, +}; + +static int btrfs_fill_super(struct super_block * sb, void * data, int silent) +{ +	struct inode * inode; +	struct dentry * root; + +	sb->s_maxbytes = MAX_LFS_FILESIZE; +	sb->s_blocksize = PAGE_CACHE_SIZE; +	sb->s_blocksize_bits = PAGE_CACHE_SHIFT; +	sb->s_magic = BTRFS_SUPER_MAGIC; +	sb->s_op = &btrfs_ops; +	sb->s_time_gran = 1; +	inode = btrfs_get_inode(sb, S_IFDIR | 0755, 0); +	if (!inode) +		return -ENOMEM; + +	root = d_alloc_root(inode); +	if (!root) { +		iput(inode); +		return -ENOMEM; +	} +	sb->s_root = root; +	return 0; +} + +static int btrfs_get_sb(struct file_system_type *fs_type, +	int flags, const char *dev_name, void *data, struct vfsmount *mnt) +{ +	return get_sb_bdev(fs_type, flags, dev_name, data, +			   btrfs_fill_super, mnt); +} + +static struct file_system_type btrfs_fs_type = { +	.owner		= THIS_MODULE, +	.name		= "btrfs", +	.get_sb		= btrfs_get_sb, +	.kill_sb	= kill_block_super, +	.fs_flags	= FS_REQUIRES_DEV, +}; + +static int __init init_btrfs_fs(void) +{ +	printk("btrfs loaded!\n"); +	return register_filesystem(&btrfs_fs_type); +} + +static void __exit exit_btrfs_fs(void) +{ +	unregister_filesystem(&btrfs_fs_type); +	printk("btrfs unloaded\n"); +} + +module_init(init_btrfs_fs) +module_exit(exit_btrfs_fs) + +MODULE_LICENSE("GPL");  |