diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 8 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 26 |
2 files changed, 31 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index ab36769c356c..280ac1aa9b6d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1151,6 +1151,14 @@ int btrfs_cache_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | ret = btrfs_add_leaf_ref(root, ref, shared); | 1153 | ret = btrfs_add_leaf_ref(root, ref, shared); |
1154 | if (ret == -EEXIST && shared) { | ||
1155 | struct btrfs_leaf_ref *old; | ||
1156 | old = btrfs_lookup_leaf_ref(root, ref->bytenr); | ||
1157 | BUG_ON(!old); | ||
1158 | btrfs_remove_leaf_ref(root, old); | ||
1159 | btrfs_free_leaf_ref(root, old); | ||
1160 | ret = btrfs_add_leaf_ref(root, ref, shared); | ||
1161 | } | ||
1154 | WARN_ON(ret); | 1162 | WARN_ON(ret); |
1155 | btrfs_free_leaf_ref(root, ref); | 1163 | btrfs_free_leaf_ref(root, ref); |
1156 | } | 1164 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3ab147dc3c05..11bfe131fde6 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include "xattr.h" | 48 | #include "xattr.h" |
49 | #include "compat.h" | 49 | #include "compat.h" |
50 | #include "tree-log.h" | 50 | #include "tree-log.h" |
51 | #include "ref-cache.h" | ||
51 | 52 | ||
52 | struct btrfs_iget_args { | 53 | struct btrfs_iget_args { |
53 | u64 ino; | 54 | u64 ino; |
@@ -1416,6 +1417,9 @@ static noinline int drop_csum_leaves(struct btrfs_trans_handle *trans, | |||
1416 | int nritems; | 1417 | int nritems; |
1417 | struct btrfs_key found_key; | 1418 | struct btrfs_key found_key; |
1418 | struct btrfs_key other_key; | 1419 | struct btrfs_key other_key; |
1420 | struct btrfs_leaf_ref *ref; | ||
1421 | u64 leaf_gen; | ||
1422 | u64 leaf_start; | ||
1419 | 1423 | ||
1420 | path->lowest_level = 1; | 1424 | path->lowest_level = 1; |
1421 | key.objectid = inode->i_ino; | 1425 | key.objectid = inode->i_ino; |
@@ -1509,15 +1513,31 @@ next_node: | |||
1509 | if (other_key.objectid != inode->i_ino || other_key.type != key.type) | 1513 | if (other_key.objectid != inode->i_ino || other_key.type != key.type) |
1510 | goto out; | 1514 | goto out; |
1511 | 1515 | ||
1516 | leaf_start = btrfs_node_blockptr(path->nodes[1], path->slots[1]); | ||
1517 | leaf_gen = btrfs_node_ptr_generation(path->nodes[1], path->slots[1]); | ||
1512 | /* | 1518 | /* |
1513 | * it is safe to delete this leaf, it contains only | 1519 | * it is safe to delete this leaf, it contains only |
1514 | * csum items from this inode at an offset >= new_size | 1520 | * csum items from this inode at an offset >= new_size |
1515 | */ | 1521 | */ |
1516 | ret = btrfs_del_leaf(trans, root, path, | 1522 | ret = btrfs_del_leaf(trans, root, path, leaf_start); |
1517 | btrfs_node_blockptr(path->nodes[1], | ||
1518 | path->slots[1])); | ||
1519 | BUG_ON(ret); | 1523 | BUG_ON(ret); |
1520 | 1524 | ||
1525 | if (root->ref_cows && leaf_gen < trans->transid) { | ||
1526 | ref = btrfs_alloc_leaf_ref(root, 0); | ||
1527 | if (ref) { | ||
1528 | ref->root_gen = root->root_key.offset; | ||
1529 | ref->bytenr = leaf_start; | ||
1530 | ref->owner = 0; | ||
1531 | ref->generation = leaf_gen; | ||
1532 | ref->nritems = 0; | ||
1533 | |||
1534 | ret = btrfs_add_leaf_ref(root, ref, 0); | ||
1535 | WARN_ON(ret); | ||
1536 | btrfs_free_leaf_ref(root, ref); | ||
1537 | } else { | ||
1538 | WARN_ON(1); | ||
1539 | } | ||
1540 | } | ||
1521 | next_key: | 1541 | next_key: |
1522 | btrfs_release_path(root, path); | 1542 | btrfs_release_path(root, path); |
1523 | 1543 | ||