You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Btrfs: initial move to kernel module land
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
committed by
David Woodhouse
parent
1261ec42b3
commit
2e635a2783
+15
-35
@@ -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
|
||||
|
||||
+1
-5
@@ -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);
|
||||
|
||||
+12
-3
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
+7
-5
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+11
-6
@@ -266,20 +266,25 @@ 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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
* License.
|
||||
*/
|
||||
|
||||
#include "kerncompat.h"
|
||||
#define DELTA 0x9E3779B9
|
||||
|
||||
static void TEA_transform(__u32 buf[2], __u32 const in[])
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
-418
@@ -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
|
||||
-255
@@ -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;
|
||||
}
|
||||
|
||||
+14
-16
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user