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

Commit 934d375b authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Use map_private_extent_buffer during generic_bin_search



It is possible that generic_bin_search will be called on a tree block
that has not been locked.  This happens because cache_block_block skips
locking on the tree blocks.

Since the tree block isn't locked, we aren't allowed to change
the extent_buffer->map_token field.  Using map_private_extent_buffer
avoids any changes to the internal extent buffer fields.

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent a512bbf8
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -813,7 +813,8 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
				unmap_extent_buffer(eb, map_token, KM_USER0);
				map_token = NULL;
			}
			err = map_extent_buffer(eb, offset,

			err = map_private_extent_buffer(eb, offset,
						sizeof(struct btrfs_disk_key),
						&map_token, &kaddr,
						&map_start, &map_len, KM_USER0);
@@ -3585,6 +3586,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
	int level;
	int ret = 1;

	WARN_ON(!path->keep_locks);
again:
	cur = btrfs_lock_root_node(root);
	level = btrfs_header_level(cur);
@@ -3708,6 +3710,7 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
	int slot;
	struct extent_buffer *c;

	WARN_ON(!path->keep_locks);
	while(level < BTRFS_MAX_LEVEL) {
		if (!path->nodes[level])
			return 1;
+1 −0
Original line number Diff line number Diff line
@@ -3471,6 +3471,7 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
		unmap_extent_buffer(eb, eb->map_token, km);
		eb->map_token = NULL;
		save = 1;
		WARN_ON(!mutex_is_locked(&eb->mutex));
	}
	err = map_private_extent_buffer(eb, start, min_len, token, map,
				       map_start, map_len, km);
+4 −1
Original line number Diff line number Diff line
@@ -2594,13 +2594,16 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
			stripe_nr = stripe_nr * map->num_stripes + i;
		}
		bytenr = chunk_start + stripe_nr * map->stripe_len;
		WARN_ON(nr >= map->num_stripes);
		for (j = 0; j < nr; j++) {
			if (buf[j] == bytenr)
				break;
		}
		if (j == nr)
		if (j == nr) {
			WARN_ON(nr >= map->num_stripes);
			buf[nr++] = bytenr;
		}
	}

	for (i = 0; i > nr; i++) {
		struct btrfs_multi_bio *multi;