diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
| -rw-r--r-- | fs/btrfs/ctree.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b0e18d986e0a..2e667868e0d2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -43,8 +43,6 @@ struct btrfs_path *btrfs_alloc_path(void) | |||
| 43 | { | 43 | { |
| 44 | struct btrfs_path *path; | 44 | struct btrfs_path *path; |
| 45 | path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS); | 45 | path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS); |
| 46 | if (path) | ||
| 47 | path->reada = 1; | ||
| 48 | return path; | 46 | return path; |
| 49 | } | 47 | } |
| 50 | 48 | ||
| @@ -1224,11 +1222,13 @@ static void reada_for_search(struct btrfs_root *root, | |||
| 1224 | u64 search; | 1222 | u64 search; |
| 1225 | u64 target; | 1223 | u64 target; |
| 1226 | u64 nread = 0; | 1224 | u64 nread = 0; |
| 1225 | u64 gen; | ||
| 1227 | int direction = path->reada; | 1226 | int direction = path->reada; |
| 1228 | struct extent_buffer *eb; | 1227 | struct extent_buffer *eb; |
| 1229 | u32 nr; | 1228 | u32 nr; |
| 1230 | u32 blocksize; | 1229 | u32 blocksize; |
| 1231 | u32 nscan = 0; | 1230 | u32 nscan = 0; |
| 1231 | bool map = true; | ||
| 1232 | 1232 | ||
| 1233 | if (level != 1) | 1233 | if (level != 1) |
| 1234 | return; | 1234 | return; |
| @@ -1250,7 +1250,19 @@ static void reada_for_search(struct btrfs_root *root, | |||
| 1250 | 1250 | ||
| 1251 | nritems = btrfs_header_nritems(node); | 1251 | nritems = btrfs_header_nritems(node); |
| 1252 | nr = slot; | 1252 | nr = slot; |
| 1253 | if (node->map_token || path->skip_locking) | ||
| 1254 | map = false; | ||
| 1255 | |||
| 1253 | while (1) { | 1256 | while (1) { |
| 1257 | if (map && !node->map_token) { | ||
| 1258 | unsigned long offset = btrfs_node_key_ptr_offset(nr); | ||
| 1259 | map_private_extent_buffer(node, offset, | ||
| 1260 | sizeof(struct btrfs_key_ptr), | ||
| 1261 | &node->map_token, | ||
| 1262 | &node->kaddr, | ||
| 1263 | &node->map_start, | ||
| 1264 | &node->map_len, KM_USER1); | ||
| 1265 | } | ||
| 1254 | if (direction < 0) { | 1266 | if (direction < 0) { |
| 1255 | if (nr == 0) | 1267 | if (nr == 0) |
| 1256 | break; | 1268 | break; |
| @@ -1268,14 +1280,23 @@ static void reada_for_search(struct btrfs_root *root, | |||
| 1268 | search = btrfs_node_blockptr(node, nr); | 1280 | search = btrfs_node_blockptr(node, nr); |
| 1269 | if ((search <= target && target - search <= 65536) || | 1281 | if ((search <= target && target - search <= 65536) || |
| 1270 | (search > target && search - target <= 65536)) { | 1282 | (search > target && search - target <= 65536)) { |
| 1271 | readahead_tree_block(root, search, blocksize, | 1283 | gen = btrfs_node_ptr_generation(node, nr); |
| 1272 | btrfs_node_ptr_generation(node, nr)); | 1284 | if (map && node->map_token) { |
| 1285 | unmap_extent_buffer(node, node->map_token, | ||
| 1286 | KM_USER1); | ||
| 1287 | node->map_token = NULL; | ||
| 1288 | } | ||
| 1289 | readahead_tree_block(root, search, blocksize, gen); | ||
| 1273 | nread += blocksize; | 1290 | nread += blocksize; |
| 1274 | } | 1291 | } |
| 1275 | nscan++; | 1292 | nscan++; |
| 1276 | if ((nread > 65536 || nscan > 32)) | 1293 | if ((nread > 65536 || nscan > 32)) |
| 1277 | break; | 1294 | break; |
| 1278 | } | 1295 | } |
| 1296 | if (map && node->map_token) { | ||
| 1297 | unmap_extent_buffer(node, node->map_token, KM_USER1); | ||
| 1298 | node->map_token = NULL; | ||
| 1299 | } | ||
| 1279 | } | 1300 | } |
| 1280 | 1301 | ||
| 1281 | /* | 1302 | /* |
| @@ -1648,9 +1669,6 @@ again: | |||
| 1648 | } | 1669 | } |
| 1649 | cow_done: | 1670 | cow_done: |
| 1650 | BUG_ON(!cow && ins_len); | 1671 | BUG_ON(!cow && ins_len); |
| 1651 | if (level != btrfs_header_level(b)) | ||
| 1652 | WARN_ON(1); | ||
| 1653 | level = btrfs_header_level(b); | ||
| 1654 | 1672 | ||
| 1655 | p->nodes[level] = b; | 1673 | p->nodes[level] = b; |
| 1656 | if (!p->skip_locking) | 1674 | if (!p->skip_locking) |
