diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index bd0f752b797b..029d46c2e170 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -329,6 +329,8 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
329 | { | 329 | { |
330 | struct extent_state *cached_state = NULL; | 330 | struct extent_state *cached_state = NULL; |
331 | int ret; | 331 | int ret; |
332 | bool need_lock = (current->journal_info == | ||
333 | (void *)BTRFS_SEND_TRANS_STUB); | ||
332 | 334 | ||
333 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) | 335 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) |
334 | return 0; | 336 | return 0; |
@@ -336,6 +338,11 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
336 | if (atomic) | 338 | if (atomic) |
337 | return -EAGAIN; | 339 | return -EAGAIN; |
338 | 340 | ||
341 | if (need_lock) { | ||
342 | btrfs_tree_read_lock(eb); | ||
343 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
344 | } | ||
345 | |||
339 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, | 346 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
340 | 0, &cached_state); | 347 | 0, &cached_state); |
341 | if (extent_buffer_uptodate(eb) && | 348 | if (extent_buffer_uptodate(eb) && |
@@ -347,10 +354,21 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
347 | "found %llu\n", | 354 | "found %llu\n", |
348 | eb->start, parent_transid, btrfs_header_generation(eb)); | 355 | eb->start, parent_transid, btrfs_header_generation(eb)); |
349 | ret = 1; | 356 | ret = 1; |
350 | clear_extent_buffer_uptodate(eb); | 357 | |
358 | /* | ||
359 | * Things reading via commit roots that don't have normal protection, | ||
360 | * like send, can have a really old block in cache that may point at a | ||
361 | * block that has been free'd and re-allocated. So don't clear uptodate | ||
362 | * if we find an eb that is under IO (dirty/writeback) because we could | ||
363 | * end up reading in the stale data and then writing it back out and | ||
364 | * making everybody very sad. | ||
365 | */ | ||
366 | if (!extent_buffer_under_io(eb)) | ||
367 | clear_extent_buffer_uptodate(eb); | ||
351 | out: | 368 | out: |
352 | unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, | 369 | unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, |
353 | &cached_state, GFP_NOFS); | 370 | &cached_state, GFP_NOFS); |
371 | btrfs_tree_read_unlock_blocking(eb); | ||
354 | return ret; | 372 | return ret; |
355 | } | 373 | } |
356 | 374 | ||
@@ -1546,7 +1564,6 @@ int btrfs_init_fs_root(struct btrfs_root *root) | |||
1546 | root->subv_writers = writers; | 1564 | root->subv_writers = writers; |
1547 | 1565 | ||
1548 | btrfs_init_free_ino_ctl(root); | 1566 | btrfs_init_free_ino_ctl(root); |
1549 | mutex_init(&root->fs_commit_mutex); | ||
1550 | spin_lock_init(&root->cache_lock); | 1567 | spin_lock_init(&root->cache_lock); |
1551 | init_waitqueue_head(&root->cache_wait); | 1568 | init_waitqueue_head(&root->cache_wait); |
1552 | 1569 | ||
@@ -2324,7 +2341,7 @@ int open_ctree(struct super_block *sb, | |||
2324 | mutex_init(&fs_info->transaction_kthread_mutex); | 2341 | mutex_init(&fs_info->transaction_kthread_mutex); |
2325 | mutex_init(&fs_info->cleaner_mutex); | 2342 | mutex_init(&fs_info->cleaner_mutex); |
2326 | mutex_init(&fs_info->volume_mutex); | 2343 | mutex_init(&fs_info->volume_mutex); |
2327 | init_rwsem(&fs_info->extent_commit_sem); | 2344 | init_rwsem(&fs_info->commit_root_sem); |
2328 | init_rwsem(&fs_info->cleanup_work_sem); | 2345 | init_rwsem(&fs_info->cleanup_work_sem); |
2329 | init_rwsem(&fs_info->subvol_sem); | 2346 | init_rwsem(&fs_info->subvol_sem); |
2330 | sema_init(&fs_info->uuid_tree_rescan_sem, 1); | 2347 | sema_init(&fs_info->uuid_tree_rescan_sem, 1); |