Skip to content

Commit

Permalink
Btrfs: Fix leaf reference cache miss
Browse files Browse the repository at this point in the history
Due to the optimization for truncate, tree leaves only containing
checksum items can be deleted without being COW'ed first. This causes
reference cache misses. The way to fix the miss is create cache
entries for tree leaves only contain checksum.

This patch also fixes a -EEXIST issue in shared reference cache.

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
  • Loading branch information
Yan Zheng authored and Chris Mason committed Oct 9, 2008
1 parent 3bb1a1b commit 5b84e8d
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
8 changes: 8 additions & 0 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,14 @@ int btrfs_cache_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
}

ret = btrfs_add_leaf_ref(root, ref, shared);
if (ret == -EEXIST && shared) {
struct btrfs_leaf_ref *old;
old = btrfs_lookup_leaf_ref(root, ref->bytenr);
BUG_ON(!old);
btrfs_remove_leaf_ref(root, old);
btrfs_free_leaf_ref(root, old);
ret = btrfs_add_leaf_ref(root, ref, shared);
}
WARN_ON(ret);
btrfs_free_leaf_ref(root, ref);
}
Expand Down
26 changes: 23 additions & 3 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "xattr.h"
#include "compat.h"
#include "tree-log.h"
#include "ref-cache.h"

struct btrfs_iget_args {
u64 ino;
Expand Down Expand Up @@ -1416,6 +1417,9 @@ static noinline int drop_csum_leaves(struct btrfs_trans_handle *trans,
int nritems;
struct btrfs_key found_key;
struct btrfs_key other_key;
struct btrfs_leaf_ref *ref;
u64 leaf_gen;
u64 leaf_start;

path->lowest_level = 1;
key.objectid = inode->i_ino;
Expand Down Expand Up @@ -1509,15 +1513,31 @@ static noinline int drop_csum_leaves(struct btrfs_trans_handle *trans,
if (other_key.objectid != inode->i_ino || other_key.type != key.type)
goto out;

leaf_start = btrfs_node_blockptr(path->nodes[1], path->slots[1]);
leaf_gen = btrfs_node_ptr_generation(path->nodes[1], path->slots[1]);
/*
* it is safe to delete this leaf, it contains only
* csum items from this inode at an offset >= new_size
*/
ret = btrfs_del_leaf(trans, root, path,
btrfs_node_blockptr(path->nodes[1],
path->slots[1]));
ret = btrfs_del_leaf(trans, root, path, leaf_start);
BUG_ON(ret);

if (root->ref_cows && leaf_gen < trans->transid) {
ref = btrfs_alloc_leaf_ref(root, 0);
if (ref) {
ref->root_gen = root->root_key.offset;
ref->bytenr = leaf_start;
ref->owner = 0;
ref->generation = leaf_gen;
ref->nritems = 0;

ret = btrfs_add_leaf_ref(root, ref, 0);
WARN_ON(ret);
btrfs_free_leaf_ref(root, ref);
} else {
WARN_ON(1);
}
}
next_key:
btrfs_release_path(root, path);

Expand Down

0 comments on commit 5b84e8d

Please sign in to comment.