From: Chris Mason <chris.mason@oracle.com>
Date: Mon, 8 Dec 2008 21:43:10 +0000 (-0500)
Subject: Btrfs: Use map_private_extent_buffer during generic_bin_search
X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=934d375bacf9ea8a37fbfff5f3cf1c093f324095;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git

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: Chris Mason <chris.mason@oracle.com>
---

diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index a83cbdf1d8c4..19c0dd33b1e8 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -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;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 7449ecf32c50..607f5ff2791c 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -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);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index a79b3cc09e94..825364fae690 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2594,12 +2594,15 @@ 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++) {