aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@fusionio.com>2012-10-25 15:53:10 -0400
committerChris Mason <chris.mason@fusionio.com>2012-10-25 15:53:10 -0400
commitc657c3ef1adb2585ed7d2a6db73d0002926a6726 (patch)
tree5a53c8a58d5be5986d72fd2da8613aac118cf15c
parentbe6aef604920406b348acf3be6e6e8db55696386 (diff)
parent01763a2e37425ae3f37a3dc051e0703fdade5956 (diff)
Merge branch 'for-chris-fixed' of git://git.jan-o-sch.net/btrfs-unstable
-rw-r--r--fs/btrfs/backref.c4
-rw-r--r--fs/btrfs/ctree.c68
-rw-r--r--fs/btrfs/ctree.h1
3 files changed, 55 insertions, 18 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index b8b69266393a..208d8aa5b07e 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
283 goto out; 283 goto out;
284 } 284 }
285 285
286 rcu_read_lock(); 286 root_level = btrfs_old_root_level(root, time_seq);
287 root_level = btrfs_header_level(root->node);
288 rcu_read_unlock();
289 287
290 if (root_level + 1 == level) 288 if (root_level + 1 == level)
291 goto out; 289 goto out;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index b33436211000..eba44b076829 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
596 if (tree_mod_dont_log(fs_info, eb)) 596 if (tree_mod_dont_log(fs_info, eb))
597 return 0; 597 return 0;
598 598
599 /*
600 * When we override something during the move, we log these removals.
601 * This can only happen when we move towards the beginning of the
602 * buffer, i.e. dst_slot < src_slot.
603 */
599 for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { 604 for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) {
600 ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot, 605 ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot,
601 MOD_LOG_KEY_REMOVE_WHILE_MOVING); 606 MOD_LOG_KEY_REMOVE_WHILE_MOVING);
@@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
647 if (tree_mod_dont_log(fs_info, NULL)) 652 if (tree_mod_dont_log(fs_info, NULL))
648 return 0; 653 return 0;
649 654
650 __tree_mod_log_free_eb(fs_info, old_root);
651
652 ret = tree_mod_alloc(fs_info, flags, &tm); 655 ret = tree_mod_alloc(fs_info, flags, &tm);
653 if (ret < 0) 656 if (ret < 0)
654 goto out; 657 goto out;
@@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
926 ret = btrfs_dec_ref(trans, root, buf, 1, 1); 929 ret = btrfs_dec_ref(trans, root, buf, 1, 1);
927 BUG_ON(ret); /* -ENOMEM */ 930 BUG_ON(ret); /* -ENOMEM */
928 } 931 }
929 /* 932 tree_mod_log_free_eb(root->fs_info, buf);
930 * don't log freeing in case we're freeing the root node, this
931 * is done by tree_mod_log_set_root_pointer later
932 */
933 if (buf != root->node && btrfs_header_level(buf) != 0)
934 tree_mod_log_free_eb(root->fs_info, buf);
935 clean_tree_block(trans, root, buf); 933 clean_tree_block(trans, root, buf);
936 *last_ref = 1; 934 *last_ref = 1;
937 } 935 }
@@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
1225 free_extent_buffer(eb); 1223 free_extent_buffer(eb);
1226 1224
1227 __tree_mod_log_rewind(eb_rewin, time_seq, tm); 1225 __tree_mod_log_rewind(eb_rewin, time_seq, tm);
1226 WARN_ON(btrfs_header_nritems(eb_rewin) >
1227 BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root));
1228 1228
1229 return eb_rewin; 1229 return eb_rewin;
1230} 1230}
@@ -1244,6 +1244,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
1244 struct tree_mod_root *old_root = NULL; 1244 struct tree_mod_root *old_root = NULL;
1245 u64 old_generation = 0; 1245 u64 old_generation = 0;
1246 u64 logical; 1246 u64 logical;
1247 u32 blocksize;
1247 1248
1248 eb = btrfs_read_lock_root_node(root); 1249 eb = btrfs_read_lock_root_node(root);
1249 tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); 1250 tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
@@ -1259,14 +1260,31 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
1259 } 1260 }
1260 1261
1261 tm = tree_mod_log_search(root->fs_info, logical, time_seq); 1262 tm = tree_mod_log_search(root->fs_info, logical, time_seq);
1262 if (old_root) 1263 if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
1264 btrfs_tree_read_unlock(root->node);
1265 free_extent_buffer(root->node);
1266 blocksize = btrfs_level_size(root, old_root->level);
1267 eb = read_tree_block(root, logical, blocksize, 0);
1268 if (!eb) {
1269 pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
1270 logical);
1271 WARN_ON(1);
1272 } else {
1273 eb = btrfs_clone_extent_buffer(eb);
1274 }
1275 } else if (old_root) {
1276 btrfs_tree_read_unlock(root->node);
1277 free_extent_buffer(root->node);
1263 eb = alloc_dummy_extent_buffer(logical, root->nodesize); 1278 eb = alloc_dummy_extent_buffer(logical, root->nodesize);
1264 else 1279 } else {
1265 eb = btrfs_clone_extent_buffer(root->node); 1280 eb = btrfs_clone_extent_buffer(root->node);
1266 btrfs_tree_read_unlock(root->node); 1281 btrfs_tree_read_unlock(root->node);
1267 free_extent_buffer(root->node); 1282 free_extent_buffer(root->node);
1283 }
1284
1268 if (!eb) 1285 if (!eb)
1269 return NULL; 1286 return NULL;
1287 extent_buffer_get(eb);
1270 btrfs_tree_read_lock(eb); 1288 btrfs_tree_read_lock(eb);
1271 if (old_root) { 1289 if (old_root) {
1272 btrfs_set_header_bytenr(eb, eb->start); 1290 btrfs_set_header_bytenr(eb, eb->start);
@@ -1279,11 +1297,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
1279 __tree_mod_log_rewind(eb, time_seq, tm); 1297 __tree_mod_log_rewind(eb, time_seq, tm);
1280 else 1298 else
1281 WARN_ON(btrfs_header_level(eb) != 0); 1299 WARN_ON(btrfs_header_level(eb) != 0);
1282 extent_buffer_get(eb); 1300 WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));
1283 1301
1284 return eb; 1302 return eb;
1285} 1303}
1286 1304
1305int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq)
1306{
1307 struct tree_mod_elem *tm;
1308 int level;
1309
1310 tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
1311 if (tm && tm->op == MOD_LOG_ROOT_REPLACE) {
1312 level = tm->old_root.level;
1313 } else {
1314 rcu_read_lock();
1315 level = btrfs_header_level(root->node);
1316 rcu_read_unlock();
1317 }
1318
1319 return level;
1320}
1321
1287static inline int should_cow_block(struct btrfs_trans_handle *trans, 1322static inline int should_cow_block(struct btrfs_trans_handle *trans,
1288 struct btrfs_root *root, 1323 struct btrfs_root *root,
1289 struct extent_buffer *buf) 1324 struct extent_buffer *buf)
@@ -1725,6 +1760,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1725 goto enospc; 1760 goto enospc;
1726 } 1761 }
1727 1762
1763 tree_mod_log_free_eb(root->fs_info, root->node);
1728 tree_mod_log_set_root_pointer(root, child); 1764 tree_mod_log_set_root_pointer(root, child);
1729 rcu_assign_pointer(root->node, child); 1765 rcu_assign_pointer(root->node, child);
1730 1766
@@ -2970,8 +3006,10 @@ static int push_node_left(struct btrfs_trans_handle *trans,
2970 push_items * sizeof(struct btrfs_key_ptr)); 3006 push_items * sizeof(struct btrfs_key_ptr));
2971 3007
2972 if (push_items < src_nritems) { 3008 if (push_items < src_nritems) {
2973 tree_mod_log_eb_move(root->fs_info, src, 0, push_items, 3009 /*
2974 src_nritems - push_items); 3010 * don't call tree_mod_log_eb_move here, key removal was already
3011 * fully logged by tree_mod_log_eb_copy above.
3012 */
2975 memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), 3013 memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
2976 btrfs_node_key_ptr_offset(push_items), 3014 btrfs_node_key_ptr_offset(push_items),
2977 (src_nritems - push_items) * 3015 (src_nritems - push_items) *
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 8a92ab1632a2..2ce1135400cf 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info)
3120{ 3120{
3121 return atomic_inc_return(&fs_info->tree_mod_seq); 3121 return atomic_inc_return(&fs_info->tree_mod_seq);
3122} 3122}
3123int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);
3123 3124
3124/* root-item.c */ 3125/* root-item.c */
3125int btrfs_find_root_ref(struct btrfs_root *tree_root, 3126int btrfs_find_root_ref(struct btrfs_root *tree_root,