Commit 5b84e8d6 authored by Yan Zheng's avatar Yan Zheng Committed by Chris Mason

Btrfs: Fix leaf reference cache miss

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: default avatarYan Zheng <zheng.yan@oracle.com>
parent 3bb1a1bc
...@@ -1151,6 +1151,14 @@ int btrfs_cache_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, ...@@ -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); 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); WARN_ON(ret);
btrfs_free_leaf_ref(root, ref); btrfs_free_leaf_ref(root, ref);
} }
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "xattr.h" #include "xattr.h"
#include "compat.h" #include "compat.h"
#include "tree-log.h" #include "tree-log.h"
#include "ref-cache.h"
struct btrfs_iget_args { struct btrfs_iget_args {
u64 ino; u64 ino;
...@@ -1416,6 +1417,9 @@ static noinline int drop_csum_leaves(struct btrfs_trans_handle *trans, ...@@ -1416,6 +1417,9 @@ static noinline int drop_csum_leaves(struct btrfs_trans_handle *trans,
int nritems; int nritems;
struct btrfs_key found_key; struct btrfs_key found_key;
struct btrfs_key other_key; struct btrfs_key other_key;
struct btrfs_leaf_ref *ref;
u64 leaf_gen;
u64 leaf_start;
path->lowest_level = 1; path->lowest_level = 1;
key.objectid = inode->i_ino; key.objectid = inode->i_ino;
...@@ -1509,15 +1513,31 @@ static noinline int drop_csum_leaves(struct btrfs_trans_handle *trans, ...@@ -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) if (other_key.objectid != inode->i_ino || other_key.type != key.type)
goto out; 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 * it is safe to delete this leaf, it contains only
* csum items from this inode at an offset >= new_size * csum items from this inode at an offset >= new_size
*/ */
ret = btrfs_del_leaf(trans, root, path, ret = btrfs_del_leaf(trans, root, path, leaf_start);
btrfs_node_blockptr(path->nodes[1],
path->slots[1]));
BUG_ON(ret); 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: next_key:
btrfs_release_path(root, path); btrfs_release_path(root, path);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment