Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 128859
b: refs/heads/master
c: 31153d8
h: refs/heads/master
i:
  128857: b02c32c
  128855: 6226783
v: v3
  • Loading branch information
Yan Zheng authored and Chris Mason committed Sep 25, 2008
1 parent 513c5b6 commit b85181d
Show file tree
Hide file tree
Showing 9 changed files with 477 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3a115f520f391b4ab14041bdd6eedb370d944fa6
refs/heads/master: 31153d81284934601d08110ac7698fd9a535e4c0
3 changes: 2 additions & 1 deletion trunk/fs/btrfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
hash.o file-item.o inode-item.o inode-map.o disk-io.o \
transaction.o bit-radix.o inode.o file.o tree-defrag.o \
extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o
extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
ref-cache.o

btrfs-$(CONFIG_FS_POSIX_ACL) += acl.o
else
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN);

WARN_ON(btrfs_header_generation(buf) > trans->transid);
ret = btrfs_inc_ref(trans, new_root, buf);
ret = btrfs_inc_ref(trans, new_root, buf, 0);
kfree(new_root);

if (ret)
Expand Down Expand Up @@ -232,7 +232,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
WARN_ON(btrfs_header_generation(buf) > trans->transid);
if (btrfs_header_generation(buf) != trans->transid) {
different_trans = 1;
ret = btrfs_inc_ref(trans, root, buf);
ret = btrfs_inc_ref(trans, root, buf, 1);
if (ret)
return ret;
} else {
Expand Down
8 changes: 7 additions & 1 deletion trunk/fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,10 @@ struct btrfs_fs_info {
u64 last_alloc;
u64 last_data_alloc;

spinlock_t ref_cache_lock;
u64 total_ref_cache_size;
u64 running_ref_cache_size;

u64 avail_data_alloc_bits;
u64 avail_metadata_alloc_bits;
u64 avail_system_alloc_bits;
Expand All @@ -613,6 +617,8 @@ struct btrfs_root {
spinlock_t node_lock;

struct extent_buffer *commit_root;
struct btrfs_leaf_ref_tree *ref_tree;

struct btrfs_root_item root_item;
struct btrfs_key root_key;
struct btrfs_fs_info *fs_info;
Expand Down Expand Up @@ -1430,7 +1436,7 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
u64 search_end, struct btrfs_key *ins,
u64 data);
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct extent_buffer *buf);
struct extent_buffer *buf, int cache_ref);
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 bytenr, u64 num_bytes,
u64 root_objectid, u64 ref_generation,
Expand Down
14 changes: 14 additions & 0 deletions trunk/fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
root->node = NULL;
root->inode = NULL;
root->commit_root = NULL;
root->ref_tree = NULL;
root->sectorsize = sectorsize;
root->nodesize = nodesize;
root->leafsize = leafsize;
Expand Down Expand Up @@ -1165,12 +1166,19 @@ static int transaction_kthread(void *arg)
vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
mutex_lock(&root->fs_info->transaction_kthread_mutex);

printk("btrfs: total reference cache size %Lu\n",
root->fs_info->total_ref_cache_size);

mutex_lock(&root->fs_info->trans_mutex);
cur = root->fs_info->running_transaction;
if (!cur) {
mutex_unlock(&root->fs_info->trans_mutex);
goto sleep;
}

printk("btrfs: running reference cache size %Lu\n",
root->fs_info->running_ref_cache_size);

now = get_seconds();
if (now < cur->start_time || now - cur->start_time < 30) {
mutex_unlock(&root->fs_info->trans_mutex);
Expand Down Expand Up @@ -1233,6 +1241,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
spin_lock_init(&fs_info->hash_lock);
spin_lock_init(&fs_info->delalloc_lock);
spin_lock_init(&fs_info->new_trans_lock);
spin_lock_init(&fs_info->ref_cache_lock);

init_completion(&fs_info->kobj_unregister);
fs_info->tree_root = tree_root;
Expand Down Expand Up @@ -1699,6 +1708,11 @@ int close_ctree(struct btrfs_root *root)
printk("btrfs: at unmount delalloc count %Lu\n",
fs_info->delalloc_bytes);
}
if (fs_info->total_ref_cache_size) {
printk("btrfs: at umount reference cache size %Lu\n",
fs_info->total_ref_cache_size);
}

if (fs_info->extent_root->node)
free_extent_buffer(fs_info->extent_root->node);

Expand Down
115 changes: 104 additions & 11 deletions trunk/fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "transaction.h"
#include "volumes.h"
#include "locking.h"
#include "ref-cache.h"

#define BLOCK_GROUP_DATA EXTENT_WRITEBACK
#define BLOCK_GROUP_METADATA EXTENT_UPTODATE
Expand Down Expand Up @@ -927,7 +928,7 @@ u32 btrfs_count_snapshots_in_path(struct btrfs_root *root,
}

int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct extent_buffer *buf)
struct extent_buffer *buf, int cache_ref)
{
u64 bytenr;
u32 nritems;
Expand All @@ -937,6 +938,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int level;
int ret;
int faili;
int nr_file_extents = 0;

if (!root->ref_cows)
return 0;
Expand All @@ -959,6 +961,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (disk_bytenr == 0)
continue;

if (buf != root->commit_root)
nr_file_extents++;

mutex_lock(&root->fs_info->alloc_mutex);
ret = __btrfs_inc_extent_ref(trans, root, disk_bytenr,
btrfs_file_extent_disk_num_bytes(buf, fi),
Expand Down Expand Up @@ -988,6 +993,53 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
}
}
}
/* cache orignal leaf block's references */
if (level == 0 && cache_ref && buf != root->commit_root) {
struct btrfs_leaf_ref *ref;
struct btrfs_extent_info *info;

ref = btrfs_alloc_leaf_ref(nr_file_extents);
if (!ref) {
WARN_ON(1);
goto out;
}

btrfs_item_key_to_cpu(buf, &ref->key, 0);

ref->bytenr = buf->start;
ref->owner = btrfs_header_owner(buf);
ref->generation = btrfs_header_generation(buf);
ref->nritems = nr_file_extents;
info = ref->extents;

for (i = 0; nr_file_extents > 0 && i < nritems; i++) {
u64 disk_bytenr;
btrfs_item_key_to_cpu(buf, &key, i);
if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
continue;
fi = btrfs_item_ptr(buf, i,
struct btrfs_file_extent_item);
if (btrfs_file_extent_type(buf, fi) ==
BTRFS_FILE_EXTENT_INLINE)
continue;
disk_bytenr = btrfs_file_extent_disk_bytenr(buf, fi);
if (disk_bytenr == 0)
continue;

info->bytenr = disk_bytenr;
info->num_bytes =
btrfs_file_extent_disk_num_bytes(buf, fi);
info->objectid = key.objectid;
info->offset = key.offset;
info++;
}

BUG_ON(!root->ref_tree);
ret = btrfs_add_leaf_ref(root, ref);
WARN_ON(ret);
btrfs_free_leaf_ref(ref);
}
out:
return 0;
fail:
WARN_ON(1);
Expand Down Expand Up @@ -2215,9 +2267,9 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
return buf;
}

static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct extent_buffer *leaf)
static int noinline drop_leaf_ref_no_cache(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct extent_buffer *leaf)
{
u64 leaf_owner;
u64 leaf_generation;
Expand Down Expand Up @@ -2266,6 +2318,30 @@ static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans,
return 0;
}

static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_leaf_ref *ref)
{
int i;
int ret;
struct btrfs_extent_info *info = ref->extents;

mutex_unlock(&root->fs_info->alloc_mutex);
for (i = 0; i < ref->nritems; i++) {
mutex_lock(&root->fs_info->alloc_mutex);
ret = __btrfs_free_extent(trans, root,
info->bytenr, info->num_bytes,
ref->owner, ref->generation,
info->objectid, info->offset, 0);
mutex_unlock(&root->fs_info->alloc_mutex);
BUG_ON(ret);
info++;
}
mutex_lock(&root->fs_info->alloc_mutex);

return 0;
}

static void noinline reada_walk_down(struct btrfs_root *root,
struct extent_buffer *node,
int slot)
Expand Down Expand Up @@ -2341,6 +2417,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
struct extent_buffer *next;
struct extent_buffer *cur;
struct extent_buffer *parent;
struct btrfs_leaf_ref *ref;
u32 blocksize;
int ret;
u32 refs;
Expand Down Expand Up @@ -2370,7 +2447,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
btrfs_header_nritems(cur))
break;
if (*level == 0) {
ret = drop_leaf_ref(trans, root, cur);
ret = drop_leaf_ref_no_cache(trans, root, cur);
BUG_ON(ret);
break;
}
Expand All @@ -2391,14 +2468,28 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
BUG_ON(ret);
continue;
}

if (*level == 1) {
struct btrfs_key key;
btrfs_node_key_to_cpu(cur, &key, path->slots[*level]);
ref = btrfs_lookup_leaf_ref(root, &key);
if (ref) {
ret = drop_leaf_ref(trans, root, ref);
BUG_ON(ret);
btrfs_remove_leaf_ref(root, ref);
btrfs_free_leaf_ref(ref);
*level = 0;
break;
}
}

next = btrfs_find_tree_block(root, bytenr, blocksize);
if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
free_extent_buffer(next);
mutex_unlock(&root->fs_info->alloc_mutex);

if (path->slots[*level] == 0)
reada_walk_down(root, cur, path->slots[*level]);

next = read_tree_block(root, bytenr, blocksize,
ptr_gen);
cond_resched();
Expand Down Expand Up @@ -2435,17 +2526,19 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
WARN_ON(*level >= BTRFS_MAX_LEVEL);

if (path->nodes[*level] == root->node) {
root_owner = root->root_key.objectid;
parent = path->nodes[*level];
bytenr = path->nodes[*level]->start;
} else {
parent = path->nodes[*level + 1];
root_owner = btrfs_header_owner(parent);
bytenr = btrfs_node_blockptr(parent, path->slots[*level + 1]);
}

blocksize = btrfs_level_size(root, *level);
root_owner = btrfs_header_owner(parent);
root_gen = btrfs_header_generation(parent);
ret = __btrfs_free_extent(trans, root, path->nodes[*level]->start,
path->nodes[*level]->len,
root_owner, root_gen, 0, 0, 1);

ret = __btrfs_free_extent(trans, root, bytenr, blocksize,
root_owner, root_gen, 0, 0, 1);
free_extent_buffer(path->nodes[*level]);
path->nodes[*level] = NULL;
*level += 1;
Expand Down
Loading

0 comments on commit b85181d

Please sign in to comment.