Btrfs: make sure the async caching thread advances the key

The async caching thread can end up looping forever if a given
search puts it at the last key in a leaf. It will end up calling
btrfs_next_leaf and then checking if it needs to politely drop
the read semaphore.

Most of the time this looping isn't noticed because it is able to
make progress the next time around. But, during log replay,
we wait on the async caching thread to finish, and the async thread
is waiting on the commit, and no progress is really made.

The fix used here is to copy the key out of the next leaf,
that way our search lands there properly.

Signed-off-by: Chris Mason <chris.mason@oracle.com>

+17 -4
+17 -4
fs/btrfs/extent-tree.c
··· 265 266 atomic_inc(&block_group->space_info->caching_threads); 267 last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); 268 - again: 269 - /* need to make sure the commit_root doesn't disappear */ 270 - down_read(&fs_info->extent_commit_sem); 271 - 272 /* 273 * We don't want to deadlock with somebody trying to allocate a new 274 * extent for the extent root while also trying to search the extent ··· 278 key.objectid = last; 279 key.offset = 0; 280 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 281 ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); 282 if (ret < 0) 283 goto err; ··· 304 305 if (need_resched() || 306 btrfs_transaction_in_commit(fs_info)) { 307 btrfs_release_path(fs_info->extent_root, path); 308 up_read(&fs_info->extent_commit_sem); 309 schedule_timeout(1);
··· 265 266 atomic_inc(&block_group->space_info->caching_threads); 267 last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); 268 /* 269 * We don't want to deadlock with somebody trying to allocate a new 270 * extent for the extent root while also trying to search the extent ··· 282 key.objectid = last; 283 key.offset = 0; 284 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 285 + again: 286 + /* need to make sure the commit_root doesn't disappear */ 287 + down_read(&fs_info->extent_commit_sem); 288 + 289 ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); 290 if (ret < 0) 291 goto err; ··· 304 305 if (need_resched() || 306 btrfs_transaction_in_commit(fs_info)) { 307 + leaf = path->nodes[0]; 308 + 309 + /* this shouldn't happen, but if the 310 + * leaf is empty just move on. 311 + */ 312 + if (btrfs_header_nritems(leaf) == 0) 313 + break; 314 + /* 315 + * we need to copy the key out so that 316 + * we are sure the next search advances 317 + * us forward in the btree. 318 + */ 319 + btrfs_item_key_to_cpu(leaf, &key, 0); 320 btrfs_release_path(fs_info->extent_root, path); 321 up_read(&fs_info->extent_commit_sem); 322 schedule_timeout(1);