aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-07-31 14:57:55 -0400
committerChris Mason <chris.mason@oracle.com>2009-07-31 14:57:55 -0400
commit013f1b12f4fc479f697acae2f31bad220162cd03 (patch)
treeb51225aa32f249de352840b31b49eb9799fdafe8
parent6606bb97e146a387932efee263745b7240a11193 (diff)
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>
-rw-r--r--fs/btrfs/extent-tree.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index dc84daee6bc4..72a2b9c28e9f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -265,10 +265,6 @@ static int caching_kthread(void *data)
265 265
266 atomic_inc(&block_group->space_info->caching_threads); 266 atomic_inc(&block_group->space_info->caching_threads);
267 last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); 267 last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET);
268again:
269 /* need to make sure the commit_root doesn't disappear */
270 down_read(&fs_info->extent_commit_sem);
271
272 /* 268 /*
273 * We don't want to deadlock with somebody trying to allocate a new 269 * 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 270 * extent for the extent root while also trying to search the extent
@@ -282,6 +278,10 @@ again:
282 key.objectid = last; 278 key.objectid = last;
283 key.offset = 0; 279 key.offset = 0;
284 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 280 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
281again:
282 /* need to make sure the commit_root doesn't disappear */
283 down_read(&fs_info->extent_commit_sem);
284
285 ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); 285 ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
286 if (ret < 0) 286 if (ret < 0)
287 goto err; 287 goto err;
@@ -304,6 +304,19 @@ again:
304 304
305 if (need_resched() || 305 if (need_resched() ||
306 btrfs_transaction_in_commit(fs_info)) { 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);
307 btrfs_release_path(fs_info->extent_root, path); 320 btrfs_release_path(fs_info->extent_root, path);
308 up_read(&fs_info->extent_commit_sem); 321 up_read(&fs_info->extent_commit_sem);
309 schedule_timeout(1); 322 schedule_timeout(1);