diff options
| author | Jens Axboe <axboe@kernel.dk> | 2012-07-30 03:03:10 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2012-07-30 03:03:10 -0400 |
| commit | 72ea1f74fcdf874cca6d2c0962379523bbd99e2c (patch) | |
| tree | 4c67be6c73356086ff44ef1b8b1c9479702689ca /fs/btrfs/disk-io.c | |
| parent | b1af9be5ef77898c05667bb9dbf3b180d91d3292 (diff) | |
| parent | a73ff3231df59a4b92ccd0dd4e73897c5822489b (diff) | |
Merge branch 'for-jens' of git://git.drbd.org/linux-drbd into for-3.6/drivers
Diffstat (limited to 'fs/btrfs/disk-io.c')
| -rw-r--r-- | fs/btrfs/disk-io.c | 111 |
1 files changed, 70 insertions, 41 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7ae51decf6d3..2936ca49b3b4 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include "free-space-cache.h" | 44 | #include "free-space-cache.h" |
| 45 | #include "inode-map.h" | 45 | #include "inode-map.h" |
| 46 | #include "check-integrity.h" | 46 | #include "check-integrity.h" |
| 47 | #include "rcu-string.h" | ||
| 47 | 48 | ||
| 48 | static struct extent_io_ops btree_extent_io_ops; | 49 | static struct extent_io_ops btree_extent_io_ops; |
| 49 | static void end_workqueue_fn(struct btrfs_work *work); | 50 | static void end_workqueue_fn(struct btrfs_work *work); |
| @@ -2118,7 +2119,7 @@ int open_ctree(struct super_block *sb, | |||
| 2118 | 2119 | ||
| 2119 | features = btrfs_super_incompat_flags(disk_super); | 2120 | features = btrfs_super_incompat_flags(disk_super); |
| 2120 | features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; | 2121 | features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; |
| 2121 | if (tree_root->fs_info->compress_type & BTRFS_COMPRESS_LZO) | 2122 | if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO) |
| 2122 | features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; | 2123 | features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; |
| 2123 | 2124 | ||
| 2124 | /* | 2125 | /* |
| @@ -2353,12 +2354,17 @@ retry_root_backup: | |||
| 2353 | BTRFS_CSUM_TREE_OBJECTID, csum_root); | 2354 | BTRFS_CSUM_TREE_OBJECTID, csum_root); |
| 2354 | if (ret) | 2355 | if (ret) |
| 2355 | goto recovery_tree_root; | 2356 | goto recovery_tree_root; |
| 2356 | |||
| 2357 | csum_root->track_dirty = 1; | 2357 | csum_root->track_dirty = 1; |
| 2358 | 2358 | ||
| 2359 | fs_info->generation = generation; | 2359 | fs_info->generation = generation; |
| 2360 | fs_info->last_trans_committed = generation; | 2360 | fs_info->last_trans_committed = generation; |
| 2361 | 2361 | ||
| 2362 | ret = btrfs_recover_balance(fs_info); | ||
| 2363 | if (ret) { | ||
| 2364 | printk(KERN_WARNING "btrfs: failed to recover balance\n"); | ||
| 2365 | goto fail_block_groups; | ||
| 2366 | } | ||
| 2367 | |||
| 2362 | ret = btrfs_init_dev_stats(fs_info); | 2368 | ret = btrfs_init_dev_stats(fs_info); |
| 2363 | if (ret) { | 2369 | if (ret) { |
| 2364 | printk(KERN_ERR "btrfs: failed to init dev_stats: %d\n", | 2370 | printk(KERN_ERR "btrfs: failed to init dev_stats: %d\n", |
| @@ -2484,20 +2490,23 @@ retry_root_backup: | |||
| 2484 | goto fail_trans_kthread; | 2490 | goto fail_trans_kthread; |
| 2485 | } | 2491 | } |
| 2486 | 2492 | ||
| 2487 | if (!(sb->s_flags & MS_RDONLY)) { | 2493 | if (sb->s_flags & MS_RDONLY) |
| 2488 | down_read(&fs_info->cleanup_work_sem); | 2494 | return 0; |
| 2489 | err = btrfs_orphan_cleanup(fs_info->fs_root); | ||
| 2490 | if (!err) | ||
| 2491 | err = btrfs_orphan_cleanup(fs_info->tree_root); | ||
| 2492 | up_read(&fs_info->cleanup_work_sem); | ||
| 2493 | 2495 | ||
| 2494 | if (!err) | 2496 | down_read(&fs_info->cleanup_work_sem); |
| 2495 | err = btrfs_recover_balance(fs_info->tree_root); | 2497 | if ((ret = btrfs_orphan_cleanup(fs_info->fs_root)) || |
| 2498 | (ret = btrfs_orphan_cleanup(fs_info->tree_root))) { | ||
| 2499 | up_read(&fs_info->cleanup_work_sem); | ||
| 2500 | close_ctree(tree_root); | ||
| 2501 | return ret; | ||
| 2502 | } | ||
| 2503 | up_read(&fs_info->cleanup_work_sem); | ||
| 2496 | 2504 | ||
| 2497 | if (err) { | 2505 | ret = btrfs_resume_balance_async(fs_info); |
| 2498 | close_ctree(tree_root); | 2506 | if (ret) { |
| 2499 | return err; | 2507 | printk(KERN_WARNING "btrfs: failed to resume balance\n"); |
| 2500 | } | 2508 | close_ctree(tree_root); |
| 2509 | return ret; | ||
| 2501 | } | 2510 | } |
| 2502 | 2511 | ||
| 2503 | return 0; | 2512 | return 0; |
| @@ -2575,8 +2584,9 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate) | |||
| 2575 | struct btrfs_device *device = (struct btrfs_device *) | 2584 | struct btrfs_device *device = (struct btrfs_device *) |
| 2576 | bh->b_private; | 2585 | bh->b_private; |
| 2577 | 2586 | ||
| 2578 | printk_ratelimited(KERN_WARNING "lost page write due to " | 2587 | printk_ratelimited_in_rcu(KERN_WARNING "lost page write due to " |
| 2579 | "I/O error on %s\n", device->name); | 2588 | "I/O error on %s\n", |
| 2589 | rcu_str_deref(device->name)); | ||
| 2580 | /* note, we dont' set_buffer_write_io_error because we have | 2590 | /* note, we dont' set_buffer_write_io_error because we have |
| 2581 | * our own ways of dealing with the IO errors | 2591 | * our own ways of dealing with the IO errors |
| 2582 | */ | 2592 | */ |
| @@ -2749,8 +2759,8 @@ static int write_dev_flush(struct btrfs_device *device, int wait) | |||
| 2749 | wait_for_completion(&device->flush_wait); | 2759 | wait_for_completion(&device->flush_wait); |
| 2750 | 2760 | ||
| 2751 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) { | 2761 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) { |
| 2752 | printk("btrfs: disabling barriers on dev %s\n", | 2762 | printk_in_rcu("btrfs: disabling barriers on dev %s\n", |
| 2753 | device->name); | 2763 | rcu_str_deref(device->name)); |
| 2754 | device->nobarriers = 1; | 2764 | device->nobarriers = 1; |
| 2755 | } | 2765 | } |
| 2756 | if (!bio_flagged(bio, BIO_UPTODATE)) { | 2766 | if (!bio_flagged(bio, BIO_UPTODATE)) { |
| @@ -3400,7 +3410,6 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
| 3400 | 3410 | ||
| 3401 | delayed_refs = &trans->delayed_refs; | 3411 | delayed_refs = &trans->delayed_refs; |
| 3402 | 3412 | ||
| 3403 | again: | ||
| 3404 | spin_lock(&delayed_refs->lock); | 3413 | spin_lock(&delayed_refs->lock); |
| 3405 | if (delayed_refs->num_entries == 0) { | 3414 | if (delayed_refs->num_entries == 0) { |
| 3406 | spin_unlock(&delayed_refs->lock); | 3415 | spin_unlock(&delayed_refs->lock); |
| @@ -3408,31 +3417,37 @@ again: | |||
| 3408 | return ret; | 3417 | return ret; |
| 3409 | } | 3418 | } |
| 3410 | 3419 | ||
| 3411 | node = rb_first(&delayed_refs->root); | 3420 | while ((node = rb_first(&delayed_refs->root)) != NULL) { |
| 3412 | while (node) { | ||
| 3413 | ref = rb_entry(node, struct btrfs_delayed_ref_node, rb_node); | 3421 | ref = rb_entry(node, struct btrfs_delayed_ref_node, rb_node); |
| 3414 | node = rb_next(node); | ||
| 3415 | |||
| 3416 | ref->in_tree = 0; | ||
| 3417 | rb_erase(&ref->rb_node, &delayed_refs->root); | ||
| 3418 | delayed_refs->num_entries--; | ||
| 3419 | 3422 | ||
| 3420 | atomic_set(&ref->refs, 1); | 3423 | atomic_set(&ref->refs, 1); |
| 3421 | if (btrfs_delayed_ref_is_head(ref)) { | 3424 | if (btrfs_delayed_ref_is_head(ref)) { |
| 3422 | struct btrfs_delayed_ref_head *head; | 3425 | struct btrfs_delayed_ref_head *head; |
| 3423 | 3426 | ||
| 3424 | head = btrfs_delayed_node_to_head(ref); | 3427 | head = btrfs_delayed_node_to_head(ref); |
| 3425 | spin_unlock(&delayed_refs->lock); | 3428 | if (!mutex_trylock(&head->mutex)) { |
| 3426 | mutex_lock(&head->mutex); | 3429 | atomic_inc(&ref->refs); |
| 3430 | spin_unlock(&delayed_refs->lock); | ||
| 3431 | |||
| 3432 | /* Need to wait for the delayed ref to run */ | ||
| 3433 | mutex_lock(&head->mutex); | ||
| 3434 | mutex_unlock(&head->mutex); | ||
| 3435 | btrfs_put_delayed_ref(ref); | ||
| 3436 | |||
| 3437 | spin_lock(&delayed_refs->lock); | ||
| 3438 | continue; | ||
| 3439 | } | ||
| 3440 | |||
| 3427 | kfree(head->extent_op); | 3441 | kfree(head->extent_op); |
| 3428 | delayed_refs->num_heads--; | 3442 | delayed_refs->num_heads--; |
| 3429 | if (list_empty(&head->cluster)) | 3443 | if (list_empty(&head->cluster)) |
| 3430 | delayed_refs->num_heads_ready--; | 3444 | delayed_refs->num_heads_ready--; |
| 3431 | list_del_init(&head->cluster); | 3445 | list_del_init(&head->cluster); |
| 3432 | mutex_unlock(&head->mutex); | ||
| 3433 | btrfs_put_delayed_ref(ref); | ||
| 3434 | goto again; | ||
| 3435 | } | 3446 | } |
| 3447 | ref->in_tree = 0; | ||
| 3448 | rb_erase(&ref->rb_node, &delayed_refs->root); | ||
| 3449 | delayed_refs->num_entries--; | ||
| 3450 | |||
| 3436 | spin_unlock(&delayed_refs->lock); | 3451 | spin_unlock(&delayed_refs->lock); |
| 3437 | btrfs_put_delayed_ref(ref); | 3452 | btrfs_put_delayed_ref(ref); |
| 3438 | 3453 | ||
| @@ -3520,11 +3535,9 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, | |||
| 3520 | &(&BTRFS_I(page->mapping->host)->io_tree)->buffer, | 3535 | &(&BTRFS_I(page->mapping->host)->io_tree)->buffer, |
| 3521 | offset >> PAGE_CACHE_SHIFT); | 3536 | offset >> PAGE_CACHE_SHIFT); |
| 3522 | spin_unlock(&dirty_pages->buffer_lock); | 3537 | spin_unlock(&dirty_pages->buffer_lock); |
| 3523 | if (eb) { | 3538 | if (eb) |
| 3524 | ret = test_and_clear_bit(EXTENT_BUFFER_DIRTY, | 3539 | ret = test_and_clear_bit(EXTENT_BUFFER_DIRTY, |
| 3525 | &eb->bflags); | 3540 | &eb->bflags); |
| 3526 | atomic_set(&eb->refs, 1); | ||
| 3527 | } | ||
| 3528 | if (PageWriteback(page)) | 3541 | if (PageWriteback(page)) |
| 3529 | end_page_writeback(page); | 3542 | end_page_writeback(page); |
| 3530 | 3543 | ||
| @@ -3538,8 +3551,8 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, | |||
| 3538 | spin_unlock_irq(&page->mapping->tree_lock); | 3551 | spin_unlock_irq(&page->mapping->tree_lock); |
| 3539 | } | 3552 | } |
| 3540 | 3553 | ||
| 3541 | page->mapping->a_ops->invalidatepage(page, 0); | ||
| 3542 | unlock_page(page); | 3554 | unlock_page(page); |
| 3555 | page_cache_release(page); | ||
| 3543 | } | 3556 | } |
| 3544 | } | 3557 | } |
| 3545 | 3558 | ||
| @@ -3553,8 +3566,10 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, | |||
| 3553 | u64 start; | 3566 | u64 start; |
| 3554 | u64 end; | 3567 | u64 end; |
| 3555 | int ret; | 3568 | int ret; |
| 3569 | bool loop = true; | ||
| 3556 | 3570 | ||
| 3557 | unpin = pinned_extents; | 3571 | unpin = pinned_extents; |
| 3572 | again: | ||
| 3558 | while (1) { | 3573 | while (1) { |
| 3559 | ret = find_first_extent_bit(unpin, 0, &start, &end, | 3574 | ret = find_first_extent_bit(unpin, 0, &start, &end, |
| 3560 | EXTENT_DIRTY); | 3575 | EXTENT_DIRTY); |
| @@ -3572,6 +3587,15 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, | |||
| 3572 | cond_resched(); | 3587 | cond_resched(); |
| 3573 | } | 3588 | } |
| 3574 | 3589 | ||
| 3590 | if (loop) { | ||
| 3591 | if (unpin == &root->fs_info->freed_extents[0]) | ||
| 3592 | unpin = &root->fs_info->freed_extents[1]; | ||
| 3593 | else | ||
| 3594 | unpin = &root->fs_info->freed_extents[0]; | ||
| 3595 | loop = false; | ||
| 3596 | goto again; | ||
| 3597 | } | ||
| 3598 | |||
| 3575 | return 0; | 3599 | return 0; |
| 3576 | } | 3600 | } |
| 3577 | 3601 | ||
| @@ -3585,21 +3609,23 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, | |||
| 3585 | /* FIXME: cleanup wait for commit */ | 3609 | /* FIXME: cleanup wait for commit */ |
| 3586 | cur_trans->in_commit = 1; | 3610 | cur_trans->in_commit = 1; |
| 3587 | cur_trans->blocked = 1; | 3611 | cur_trans->blocked = 1; |
| 3588 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) | 3612 | wake_up(&root->fs_info->transaction_blocked_wait); |
| 3589 | wake_up(&root->fs_info->transaction_blocked_wait); | ||
| 3590 | 3613 | ||
| 3591 | cur_trans->blocked = 0; | 3614 | cur_trans->blocked = 0; |
| 3592 | if (waitqueue_active(&root->fs_info->transaction_wait)) | 3615 | wake_up(&root->fs_info->transaction_wait); |
| 3593 | wake_up(&root->fs_info->transaction_wait); | ||
| 3594 | 3616 | ||
| 3595 | cur_trans->commit_done = 1; | 3617 | cur_trans->commit_done = 1; |
| 3596 | if (waitqueue_active(&cur_trans->commit_wait)) | 3618 | wake_up(&cur_trans->commit_wait); |
| 3597 | wake_up(&cur_trans->commit_wait); | 3619 | |
| 3620 | btrfs_destroy_delayed_inodes(root); | ||
| 3621 | btrfs_assert_delayed_root_empty(root); | ||
| 3598 | 3622 | ||
| 3599 | btrfs_destroy_pending_snapshots(cur_trans); | 3623 | btrfs_destroy_pending_snapshots(cur_trans); |
| 3600 | 3624 | ||
| 3601 | btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, | 3625 | btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, |
| 3602 | EXTENT_DIRTY); | 3626 | EXTENT_DIRTY); |
| 3627 | btrfs_destroy_pinned_extent(root, | ||
| 3628 | root->fs_info->pinned_extents); | ||
| 3603 | 3629 | ||
| 3604 | /* | 3630 | /* |
| 3605 | memset(cur_trans, 0, sizeof(*cur_trans)); | 3631 | memset(cur_trans, 0, sizeof(*cur_trans)); |
| @@ -3648,6 +3674,9 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
| 3648 | if (waitqueue_active(&t->commit_wait)) | 3674 | if (waitqueue_active(&t->commit_wait)) |
| 3649 | wake_up(&t->commit_wait); | 3675 | wake_up(&t->commit_wait); |
| 3650 | 3676 | ||
| 3677 | btrfs_destroy_delayed_inodes(root); | ||
| 3678 | btrfs_assert_delayed_root_empty(root); | ||
| 3679 | |||
| 3651 | btrfs_destroy_pending_snapshots(t); | 3680 | btrfs_destroy_pending_snapshots(t); |
| 3652 | 3681 | ||
| 3653 | btrfs_destroy_delalloc_inodes(root); | 3682 | btrfs_destroy_delalloc_inodes(root); |
