Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c657c3ef authored by Chris Mason's avatar Chris Mason
Browse files

Merge branch 'for-chris-fixed' of git://git.jan-o-sch.net/btrfs-unstable

parents be6aef60 01763a2e
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
		goto out;
	}

	rcu_read_lock();
	root_level = btrfs_header_level(root->node);
	rcu_read_unlock();
	root_level = btrfs_old_root_level(root, time_seq);

	if (root_level + 1 == level)
		goto out;
+53 −15
Original line number Diff line number Diff line
@@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
	if (tree_mod_dont_log(fs_info, eb))
		return 0;

	/*
	 * When we override something during the move, we log these removals.
	 * This can only happen when we move towards the beginning of the
	 * buffer, i.e. dst_slot < src_slot.
	 */
	for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) {
		ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot,
					      MOD_LOG_KEY_REMOVE_WHILE_MOVING);
@@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
	if (tree_mod_dont_log(fs_info, NULL))
		return 0;

	__tree_mod_log_free_eb(fs_info, old_root);

	ret = tree_mod_alloc(fs_info, flags, &tm);
	if (ret < 0)
		goto out;
@@ -926,11 +929,6 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
			ret = btrfs_dec_ref(trans, root, buf, 1, 1);
			BUG_ON(ret); /* -ENOMEM */
		}
		/*
		 * don't log freeing in case we're freeing the root node, this
		 * is done by tree_mod_log_set_root_pointer later
		 */
		if (buf != root->node && btrfs_header_level(buf) != 0)
		tree_mod_log_free_eb(root->fs_info, buf);
		clean_tree_block(trans, root, buf);
		*last_ref = 1;
@@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
	free_extent_buffer(eb);

	__tree_mod_log_rewind(eb_rewin, time_seq, tm);
	WARN_ON(btrfs_header_nritems(eb_rewin) >
		BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root));

	return eb_rewin;
}
@@ -1244,6 +1244,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
	struct tree_mod_root *old_root = NULL;
	u64 old_generation = 0;
	u64 logical;
	u32 blocksize;

	eb = btrfs_read_lock_root_node(root);
	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)
	}

	tm = tree_mod_log_search(root->fs_info, logical, time_seq);
	if (old_root)
	if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
		btrfs_tree_read_unlock(root->node);
		free_extent_buffer(root->node);
		blocksize = btrfs_level_size(root, old_root->level);
		eb = read_tree_block(root, logical, blocksize, 0);
		if (!eb) {
			pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
				logical);
			WARN_ON(1);
		} else {
			eb = btrfs_clone_extent_buffer(eb);
		}
	} else if (old_root) {
		btrfs_tree_read_unlock(root->node);
		free_extent_buffer(root->node);
		eb = alloc_dummy_extent_buffer(logical, root->nodesize);
	else
	} else {
		eb = btrfs_clone_extent_buffer(root->node);
		btrfs_tree_read_unlock(root->node);
		free_extent_buffer(root->node);
	}

	if (!eb)
		return NULL;
	extent_buffer_get(eb);
	btrfs_tree_read_lock(eb);
	if (old_root) {
		btrfs_set_header_bytenr(eb, eb->start);
@@ -1279,11 +1297,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
		__tree_mod_log_rewind(eb, time_seq, tm);
	else
		WARN_ON(btrfs_header_level(eb) != 0);
	extent_buffer_get(eb);
	WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));

	return eb;
}

int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq)
{
	struct tree_mod_elem *tm;
	int level;

	tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
	if (tm && tm->op == MOD_LOG_ROOT_REPLACE) {
		level = tm->old_root.level;
	} else {
		rcu_read_lock();
		level = btrfs_header_level(root->node);
		rcu_read_unlock();
	}

	return level;
}

static inline int should_cow_block(struct btrfs_trans_handle *trans,
				   struct btrfs_root *root,
				   struct extent_buffer *buf)
@@ -1725,6 +1760,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
			goto enospc;
		}

		tree_mod_log_free_eb(root->fs_info, root->node);
		tree_mod_log_set_root_pointer(root, child);
		rcu_assign_pointer(root->node, child);

@@ -2970,8 +3006,10 @@ static int push_node_left(struct btrfs_trans_handle *trans,
			   push_items * sizeof(struct btrfs_key_ptr));

	if (push_items < src_nritems) {
		tree_mod_log_eb_move(root->fs_info, src, 0, push_items,
				     src_nritems - push_items);
		/*
		 * don't call tree_mod_log_eb_move here, key removal was already
		 * fully logged by tree_mod_log_eb_copy above.
		 */
		memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
				      btrfs_node_key_ptr_offset(push_items),
				      (src_nritems - push_items) *
+1 −0
Original line number Diff line number Diff line
@@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info)
{
	return atomic_inc_return(&fs_info->tree_mod_seq);
}
int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);

/* root-item.c */
int btrfs_find_root_ref(struct btrfs_root *tree_root,