diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7ae51decf6d3..7b845ff4af99 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 | /* |
@@ -2575,8 +2576,9 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate) | |||
2575 | struct btrfs_device *device = (struct btrfs_device *) | 2576 | struct btrfs_device *device = (struct btrfs_device *) |
2576 | bh->b_private; | 2577 | bh->b_private; |
2577 | 2578 | ||
2578 | printk_ratelimited(KERN_WARNING "lost page write due to " | 2579 | printk_ratelimited_in_rcu(KERN_WARNING "lost page write due to " |
2579 | "I/O error on %s\n", device->name); | 2580 | "I/O error on %s\n", |
2581 | rcu_str_deref(device->name)); | ||
2580 | /* note, we dont' set_buffer_write_io_error because we have | 2582 | /* note, we dont' set_buffer_write_io_error because we have |
2581 | * our own ways of dealing with the IO errors | 2583 | * our own ways of dealing with the IO errors |
2582 | */ | 2584 | */ |
@@ -2749,8 +2751,8 @@ static int write_dev_flush(struct btrfs_device *device, int wait) | |||
2749 | wait_for_completion(&device->flush_wait); | 2751 | wait_for_completion(&device->flush_wait); |
2750 | 2752 | ||
2751 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) { | 2753 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) { |
2752 | printk("btrfs: disabling barriers on dev %s\n", | 2754 | printk_in_rcu("btrfs: disabling barriers on dev %s\n", |
2753 | device->name); | 2755 | rcu_str_deref(device->name)); |
2754 | device->nobarriers = 1; | 2756 | device->nobarriers = 1; |
2755 | } | 2757 | } |
2756 | if (!bio_flagged(bio, BIO_UPTODATE)) { | 2758 | if (!bio_flagged(bio, BIO_UPTODATE)) { |
@@ -3400,7 +3402,6 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
3400 | 3402 | ||
3401 | delayed_refs = &trans->delayed_refs; | 3403 | delayed_refs = &trans->delayed_refs; |
3402 | 3404 | ||
3403 | again: | ||
3404 | spin_lock(&delayed_refs->lock); | 3405 | spin_lock(&delayed_refs->lock); |
3405 | if (delayed_refs->num_entries == 0) { | 3406 | if (delayed_refs->num_entries == 0) { |
3406 | spin_unlock(&delayed_refs->lock); | 3407 | spin_unlock(&delayed_refs->lock); |
@@ -3408,31 +3409,37 @@ again: | |||
3408 | return ret; | 3409 | return ret; |
3409 | } | 3410 | } |
3410 | 3411 | ||
3411 | node = rb_first(&delayed_refs->root); | 3412 | while ((node = rb_first(&delayed_refs->root)) != NULL) { |
3412 | while (node) { | ||
3413 | ref = rb_entry(node, struct btrfs_delayed_ref_node, rb_node); | 3413 | 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 | 3414 | ||
3420 | atomic_set(&ref->refs, 1); | 3415 | atomic_set(&ref->refs, 1); |
3421 | if (btrfs_delayed_ref_is_head(ref)) { | 3416 | if (btrfs_delayed_ref_is_head(ref)) { |
3422 | struct btrfs_delayed_ref_head *head; | 3417 | struct btrfs_delayed_ref_head *head; |
3423 | 3418 | ||
3424 | head = btrfs_delayed_node_to_head(ref); | 3419 | head = btrfs_delayed_node_to_head(ref); |
3425 | spin_unlock(&delayed_refs->lock); | 3420 | if (!mutex_trylock(&head->mutex)) { |
3426 | mutex_lock(&head->mutex); | 3421 | atomic_inc(&ref->refs); |
3422 | spin_unlock(&delayed_refs->lock); | ||
3423 | |||
3424 | /* Need to wait for the delayed ref to run */ | ||
3425 | mutex_lock(&head->mutex); | ||
3426 | mutex_unlock(&head->mutex); | ||
3427 | btrfs_put_delayed_ref(ref); | ||
3428 | |||
3429 | spin_lock(&delayed_refs->lock); | ||
3430 | continue; | ||
3431 | } | ||
3432 | |||
3427 | kfree(head->extent_op); | 3433 | kfree(head->extent_op); |
3428 | delayed_refs->num_heads--; | 3434 | delayed_refs->num_heads--; |
3429 | if (list_empty(&head->cluster)) | 3435 | if (list_empty(&head->cluster)) |
3430 | delayed_refs->num_heads_ready--; | 3436 | delayed_refs->num_heads_ready--; |
3431 | list_del_init(&head->cluster); | 3437 | list_del_init(&head->cluster); |
3432 | mutex_unlock(&head->mutex); | ||
3433 | btrfs_put_delayed_ref(ref); | ||
3434 | goto again; | ||
3435 | } | 3438 | } |
3439 | ref->in_tree = 0; | ||
3440 | rb_erase(&ref->rb_node, &delayed_refs->root); | ||
3441 | delayed_refs->num_entries--; | ||
3442 | |||
3436 | spin_unlock(&delayed_refs->lock); | 3443 | spin_unlock(&delayed_refs->lock); |
3437 | btrfs_put_delayed_ref(ref); | 3444 | btrfs_put_delayed_ref(ref); |
3438 | 3445 | ||
@@ -3520,11 +3527,9 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, | |||
3520 | &(&BTRFS_I(page->mapping->host)->io_tree)->buffer, | 3527 | &(&BTRFS_I(page->mapping->host)->io_tree)->buffer, |
3521 | offset >> PAGE_CACHE_SHIFT); | 3528 | offset >> PAGE_CACHE_SHIFT); |
3522 | spin_unlock(&dirty_pages->buffer_lock); | 3529 | spin_unlock(&dirty_pages->buffer_lock); |
3523 | if (eb) { | 3530 | if (eb) |
3524 | ret = test_and_clear_bit(EXTENT_BUFFER_DIRTY, | 3531 | ret = test_and_clear_bit(EXTENT_BUFFER_DIRTY, |
3525 | &eb->bflags); | 3532 | &eb->bflags); |
3526 | atomic_set(&eb->refs, 1); | ||
3527 | } | ||
3528 | if (PageWriteback(page)) | 3533 | if (PageWriteback(page)) |
3529 | end_page_writeback(page); | 3534 | end_page_writeback(page); |
3530 | 3535 | ||
@@ -3538,8 +3543,8 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, | |||
3538 | spin_unlock_irq(&page->mapping->tree_lock); | 3543 | spin_unlock_irq(&page->mapping->tree_lock); |
3539 | } | 3544 | } |
3540 | 3545 | ||
3541 | page->mapping->a_ops->invalidatepage(page, 0); | ||
3542 | unlock_page(page); | 3546 | unlock_page(page); |
3547 | page_cache_release(page); | ||
3543 | } | 3548 | } |
3544 | } | 3549 | } |
3545 | 3550 | ||
@@ -3553,8 +3558,10 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, | |||
3553 | u64 start; | 3558 | u64 start; |
3554 | u64 end; | 3559 | u64 end; |
3555 | int ret; | 3560 | int ret; |
3561 | bool loop = true; | ||
3556 | 3562 | ||
3557 | unpin = pinned_extents; | 3563 | unpin = pinned_extents; |
3564 | again: | ||
3558 | while (1) { | 3565 | while (1) { |
3559 | ret = find_first_extent_bit(unpin, 0, &start, &end, | 3566 | ret = find_first_extent_bit(unpin, 0, &start, &end, |
3560 | EXTENT_DIRTY); | 3567 | EXTENT_DIRTY); |
@@ -3572,6 +3579,15 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, | |||
3572 | cond_resched(); | 3579 | cond_resched(); |
3573 | } | 3580 | } |
3574 | 3581 | ||
3582 | if (loop) { | ||
3583 | if (unpin == &root->fs_info->freed_extents[0]) | ||
3584 | unpin = &root->fs_info->freed_extents[1]; | ||
3585 | else | ||
3586 | unpin = &root->fs_info->freed_extents[0]; | ||
3587 | loop = false; | ||
3588 | goto again; | ||
3589 | } | ||
3590 | |||
3575 | return 0; | 3591 | return 0; |
3576 | } | 3592 | } |
3577 | 3593 | ||
@@ -3585,21 +3601,23 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, | |||
3585 | /* FIXME: cleanup wait for commit */ | 3601 | /* FIXME: cleanup wait for commit */ |
3586 | cur_trans->in_commit = 1; | 3602 | cur_trans->in_commit = 1; |
3587 | cur_trans->blocked = 1; | 3603 | cur_trans->blocked = 1; |
3588 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) | 3604 | wake_up(&root->fs_info->transaction_blocked_wait); |
3589 | wake_up(&root->fs_info->transaction_blocked_wait); | ||
3590 | 3605 | ||
3591 | cur_trans->blocked = 0; | 3606 | cur_trans->blocked = 0; |
3592 | if (waitqueue_active(&root->fs_info->transaction_wait)) | 3607 | wake_up(&root->fs_info->transaction_wait); |
3593 | wake_up(&root->fs_info->transaction_wait); | ||
3594 | 3608 | ||
3595 | cur_trans->commit_done = 1; | 3609 | cur_trans->commit_done = 1; |
3596 | if (waitqueue_active(&cur_trans->commit_wait)) | 3610 | wake_up(&cur_trans->commit_wait); |
3597 | wake_up(&cur_trans->commit_wait); | 3611 | |
3612 | btrfs_destroy_delayed_inodes(root); | ||
3613 | btrfs_assert_delayed_root_empty(root); | ||
3598 | 3614 | ||
3599 | btrfs_destroy_pending_snapshots(cur_trans); | 3615 | btrfs_destroy_pending_snapshots(cur_trans); |
3600 | 3616 | ||
3601 | btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, | 3617 | btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, |
3602 | EXTENT_DIRTY); | 3618 | EXTENT_DIRTY); |
3619 | btrfs_destroy_pinned_extent(root, | ||
3620 | root->fs_info->pinned_extents); | ||
3603 | 3621 | ||
3604 | /* | 3622 | /* |
3605 | memset(cur_trans, 0, sizeof(*cur_trans)); | 3623 | memset(cur_trans, 0, sizeof(*cur_trans)); |
@@ -3648,6 +3666,9 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3648 | if (waitqueue_active(&t->commit_wait)) | 3666 | if (waitqueue_active(&t->commit_wait)) |
3649 | wake_up(&t->commit_wait); | 3667 | wake_up(&t->commit_wait); |
3650 | 3668 | ||
3669 | btrfs_destroy_delayed_inodes(root); | ||
3670 | btrfs_assert_delayed_root_empty(root); | ||
3671 | |||
3651 | btrfs_destroy_pending_snapshots(t); | 3672 | btrfs_destroy_pending_snapshots(t); |
3652 | 3673 | ||
3653 | btrfs_destroy_delalloc_inodes(root); | 3674 | btrfs_destroy_delalloc_inodes(root); |