diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 53 |
1 files changed, 14 insertions, 39 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 62e0cafd6e25..22e98e04c2ea 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -377,9 +377,13 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
377 | ret = read_extent_buffer_pages(io_tree, eb, start, | 377 | ret = read_extent_buffer_pages(io_tree, eb, start, |
378 | WAIT_COMPLETE, | 378 | WAIT_COMPLETE, |
379 | btree_get_extent, mirror_num); | 379 | btree_get_extent, mirror_num); |
380 | if (!ret && !verify_parent_transid(io_tree, eb, | 380 | if (!ret) { |
381 | if (!verify_parent_transid(io_tree, eb, | ||
381 | parent_transid, 0)) | 382 | parent_transid, 0)) |
382 | break; | 383 | break; |
384 | else | ||
385 | ret = -EIO; | ||
386 | } | ||
383 | 387 | ||
384 | /* | 388 | /* |
385 | * This buffer's crc is fine, but its contents are corrupted, so | 389 | * This buffer's crc is fine, but its contents are corrupted, so |
@@ -754,9 +758,7 @@ static void run_one_async_done(struct btrfs_work *work) | |||
754 | limit = btrfs_async_submit_limit(fs_info); | 758 | limit = btrfs_async_submit_limit(fs_info); |
755 | limit = limit * 2 / 3; | 759 | limit = limit * 2 / 3; |
756 | 760 | ||
757 | atomic_dec(&fs_info->nr_async_submits); | 761 | if (atomic_dec_return(&fs_info->nr_async_submits) < limit && |
758 | |||
759 | if (atomic_read(&fs_info->nr_async_submits) < limit && | ||
760 | waitqueue_active(&fs_info->async_submit_wait)) | 762 | waitqueue_active(&fs_info->async_submit_wait)) |
761 | wake_up(&fs_info->async_submit_wait); | 763 | wake_up(&fs_info->async_submit_wait); |
762 | 764 | ||
@@ -2032,8 +2034,6 @@ int open_ctree(struct super_block *sb, | |||
2032 | fs_info->free_chunk_space = 0; | 2034 | fs_info->free_chunk_space = 0; |
2033 | fs_info->tree_mod_log = RB_ROOT; | 2035 | fs_info->tree_mod_log = RB_ROOT; |
2034 | 2036 | ||
2035 | init_waitqueue_head(&fs_info->tree_mod_seq_wait); | ||
2036 | |||
2037 | /* readahead state */ | 2037 | /* readahead state */ |
2038 | INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT); | 2038 | INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT); |
2039 | spin_lock_init(&fs_info->reada_lock); | 2039 | spin_lock_init(&fs_info->reada_lock); |
@@ -2528,8 +2528,7 @@ retry_root_backup: | |||
2528 | goto fail_trans_kthread; | 2528 | goto fail_trans_kthread; |
2529 | 2529 | ||
2530 | /* do not make disk changes in broken FS */ | 2530 | /* do not make disk changes in broken FS */ |
2531 | if (btrfs_super_log_root(disk_super) != 0 && | 2531 | if (btrfs_super_log_root(disk_super) != 0) { |
2532 | !(fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)) { | ||
2533 | u64 bytenr = btrfs_super_log_root(disk_super); | 2532 | u64 bytenr = btrfs_super_log_root(disk_super); |
2534 | 2533 | ||
2535 | if (fs_devices->rw_devices == 0) { | 2534 | if (fs_devices->rw_devices == 0) { |
@@ -3189,30 +3188,14 @@ int close_ctree(struct btrfs_root *root) | |||
3189 | /* clear out the rbtree of defraggable inodes */ | 3188 | /* clear out the rbtree of defraggable inodes */ |
3190 | btrfs_run_defrag_inodes(fs_info); | 3189 | btrfs_run_defrag_inodes(fs_info); |
3191 | 3190 | ||
3192 | /* | ||
3193 | * Here come 2 situations when btrfs is broken to flip readonly: | ||
3194 | * | ||
3195 | * 1. when btrfs flips readonly somewhere else before | ||
3196 | * btrfs_commit_super, sb->s_flags has MS_RDONLY flag, | ||
3197 | * and btrfs will skip to write sb directly to keep | ||
3198 | * ERROR state on disk. | ||
3199 | * | ||
3200 | * 2. when btrfs flips readonly just in btrfs_commit_super, | ||
3201 | * and in such case, btrfs cannot write sb via btrfs_commit_super, | ||
3202 | * and since fs_state has been set BTRFS_SUPER_FLAG_ERROR flag, | ||
3203 | * btrfs will cleanup all FS resources first and write sb then. | ||
3204 | */ | ||
3205 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { | 3191 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { |
3206 | ret = btrfs_commit_super(root); | 3192 | ret = btrfs_commit_super(root); |
3207 | if (ret) | 3193 | if (ret) |
3208 | printk(KERN_ERR "btrfs: commit super ret %d\n", ret); | 3194 | printk(KERN_ERR "btrfs: commit super ret %d\n", ret); |
3209 | } | 3195 | } |
3210 | 3196 | ||
3211 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | 3197 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) |
3212 | ret = btrfs_error_commit_super(root); | 3198 | btrfs_error_commit_super(root); |
3213 | if (ret) | ||
3214 | printk(KERN_ERR "btrfs: commit super ret %d\n", ret); | ||
3215 | } | ||
3216 | 3199 | ||
3217 | btrfs_put_block_group_cache(fs_info); | 3200 | btrfs_put_block_group_cache(fs_info); |
3218 | 3201 | ||
@@ -3434,18 +3417,11 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | |||
3434 | if (read_only) | 3417 | if (read_only) |
3435 | return 0; | 3418 | return 0; |
3436 | 3419 | ||
3437 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | ||
3438 | printk(KERN_WARNING "warning: mount fs with errors, " | ||
3439 | "running btrfsck is recommended\n"); | ||
3440 | } | ||
3441 | |||
3442 | return 0; | 3420 | return 0; |
3443 | } | 3421 | } |
3444 | 3422 | ||
3445 | int btrfs_error_commit_super(struct btrfs_root *root) | 3423 | void btrfs_error_commit_super(struct btrfs_root *root) |
3446 | { | 3424 | { |
3447 | int ret; | ||
3448 | |||
3449 | mutex_lock(&root->fs_info->cleaner_mutex); | 3425 | mutex_lock(&root->fs_info->cleaner_mutex); |
3450 | btrfs_run_delayed_iputs(root); | 3426 | btrfs_run_delayed_iputs(root); |
3451 | mutex_unlock(&root->fs_info->cleaner_mutex); | 3427 | mutex_unlock(&root->fs_info->cleaner_mutex); |
@@ -3455,10 +3431,6 @@ int btrfs_error_commit_super(struct btrfs_root *root) | |||
3455 | 3431 | ||
3456 | /* cleanup FS via transaction */ | 3432 | /* cleanup FS via transaction */ |
3457 | btrfs_cleanup_transaction(root); | 3433 | btrfs_cleanup_transaction(root); |
3458 | |||
3459 | ret = write_ctree_super(NULL, root, 0); | ||
3460 | |||
3461 | return ret; | ||
3462 | } | 3434 | } |
3463 | 3435 | ||
3464 | static void btrfs_destroy_ordered_operations(struct btrfs_root *root) | 3436 | static void btrfs_destroy_ordered_operations(struct btrfs_root *root) |
@@ -3782,14 +3754,17 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3782 | /* FIXME: cleanup wait for commit */ | 3754 | /* FIXME: cleanup wait for commit */ |
3783 | t->in_commit = 1; | 3755 | t->in_commit = 1; |
3784 | t->blocked = 1; | 3756 | t->blocked = 1; |
3757 | smp_mb(); | ||
3785 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) | 3758 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) |
3786 | wake_up(&root->fs_info->transaction_blocked_wait); | 3759 | wake_up(&root->fs_info->transaction_blocked_wait); |
3787 | 3760 | ||
3788 | t->blocked = 0; | 3761 | t->blocked = 0; |
3762 | smp_mb(); | ||
3789 | if (waitqueue_active(&root->fs_info->transaction_wait)) | 3763 | if (waitqueue_active(&root->fs_info->transaction_wait)) |
3790 | wake_up(&root->fs_info->transaction_wait); | 3764 | wake_up(&root->fs_info->transaction_wait); |
3791 | 3765 | ||
3792 | t->commit_done = 1; | 3766 | t->commit_done = 1; |
3767 | smp_mb(); | ||
3793 | if (waitqueue_active(&t->commit_wait)) | 3768 | if (waitqueue_active(&t->commit_wait)) |
3794 | wake_up(&t->commit_wait); | 3769 | wake_up(&t->commit_wait); |
3795 | 3770 | ||