Btrfs: change how we wait for pending ordered extents
[cascardo/linux.git] / fs / btrfs / disk-io.c
index 295795a..dceabb1 100644 (file)
@@ -319,9 +319,9 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info,
                        memcpy(&found, result, csum_size);
 
                        read_extent_buffer(buf, &val, 0, csum_size);
-                       printk_ratelimited(KERN_WARNING
-                               "BTRFS: %s checksum verify failed on %llu wanted %X found %X "
-                               "level %d\n",
+                       btrfs_warn_rl(fs_info,
+                               "%s checksum verify failed on %llu wanted %X found %X "
+                               "level %d",
                                fs_info->sb->s_id, buf->start,
                                val, found, btrfs_header_level(buf));
                        if (result != (char *)&inline_result)
@@ -368,9 +368,9 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
                ret = 0;
                goto out;
        }
-       printk_ratelimited(KERN_ERR
-           "BTRFS (device %s): parent transid verify failed on %llu wanted %llu found %llu\n",
-                       eb->fs_info->sb->s_id, eb->start,
+       btrfs_err_rl(eb->fs_info,
+               "parent transid verify failed on %llu wanted %llu found %llu",
+                       eb->start,
                        parent_transid, btrfs_header_generation(eb));
        ret = 1;
 
@@ -629,15 +629,14 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 
        found_start = btrfs_header_bytenr(eb);
        if (found_start != eb->start) {
-               printk_ratelimited(KERN_ERR "BTRFS (device %s): bad tree block start "
-                              "%llu %llu\n",
-                              eb->fs_info->sb->s_id, found_start, eb->start);
+               btrfs_err_rl(eb->fs_info, "bad tree block start %llu %llu",
+                              found_start, eb->start);
                ret = -EIO;
                goto err;
        }
        if (check_tree_block_fsid(root->fs_info, eb)) {
-               printk_ratelimited(KERN_ERR "BTRFS (device %s): bad fsid on block %llu\n",
-                              eb->fs_info->sb->s_id, eb->start);
+               btrfs_err_rl(eb->fs_info, "bad fsid on block %llu",
+                              eb->start);
                ret = -EIO;
                goto err;
        }
@@ -802,6 +801,9 @@ static void run_one_async_done(struct btrfs_work *work)
        limit = btrfs_async_submit_limit(fs_info);
        limit = limit * 2 / 3;
 
+       /*
+        * atomic_dec_return implies a barrier for waitqueue_active
+        */
        if (atomic_dec_return(&fs_info->nr_async_submits) < limit &&
            waitqueue_active(&fs_info->async_submit_wait))
                wake_up(&fs_info->async_submit_wait);
@@ -2348,8 +2350,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
        u64 bytenr = btrfs_super_log_root(disk_super);
 
        if (fs_devices->rw_devices == 0) {
-               printk(KERN_WARNING "BTRFS: log replay required "
-                      "on RO media\n");
+               btrfs_warn(fs_info, "log replay required on RO media");
                return -EIO;
        }
 
@@ -2364,12 +2365,12 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
        log_tree_root->node = read_tree_block(tree_root, bytenr,
                        fs_info->generation + 1);
        if (IS_ERR(log_tree_root->node)) {
-               printk(KERN_ERR "BTRFS: failed to read log tree\n");
+               btrfs_warn(fs_info, "failed to read log tree");
                ret = PTR_ERR(log_tree_root->node);
                kfree(log_tree_root);
                return ret;
        } else if (!extent_buffer_uptodate(log_tree_root->node)) {
-               printk(KERN_ERR "BTRFS: failed to read log tree\n");
+               btrfs_err(fs_info, "failed to read log tree");
                free_extent_buffer(log_tree_root->node);
                kfree(log_tree_root);
                return -EIO;
@@ -2377,7 +2378,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
        /* returns with log_tree_root freed on success */
        ret = btrfs_recover_log_trees(log_tree_root);
        if (ret) {
-               btrfs_error(tree_root->fs_info, ret,
+               btrfs_std_error(tree_root->fs_info, ret,
                            "Failed to recover log tree");
                free_extent_buffer(log_tree_root->node);
                kfree(log_tree_root);
@@ -2653,8 +2654,8 @@ int open_ctree(struct super_block *sb,
         * Read super block and check the signature bytes only
         */
        bh = btrfs_read_dev_super(fs_devices->latest_bdev);
-       if (!bh) {
-               err = -EINVAL;
+       if (IS_ERR(bh)) {
+               err = PTR_ERR(bh);
                goto fail_alloc;
        }
 
@@ -2847,6 +2848,8 @@ int open_ctree(struct super_block *sb,
            !extent_buffer_uptodate(chunk_root->node)) {
                printk(KERN_ERR "BTRFS: failed to read chunk root on %s\n",
                       sb->s_id);
+               if (!IS_ERR(chunk_root->node))
+                       free_extent_buffer(chunk_root->node);
                chunk_root->node = NULL;
                goto fail_tree_roots;
        }
@@ -2885,6 +2888,8 @@ retry_root_backup:
            !extent_buffer_uptodate(tree_root->node)) {
                printk(KERN_WARNING "BTRFS: failed to read tree root on %s\n",
                       sb->s_id);
+               if (!IS_ERR(tree_root->node))
+                       free_extent_buffer(tree_root->node);
                tree_root->node = NULL;
                goto recovery_tree_root;
        }
@@ -2933,7 +2938,7 @@ retry_root_backup:
                goto fail_fsdev_sysfs;
        }
 
-       ret = btrfs_sysfs_add_one(fs_info);
+       ret = btrfs_sysfs_add_mounted(fs_info);
        if (ret) {
                pr_err("BTRFS: failed to init sysfs interface: %d\n", ret);
                goto fail_fsdev_sysfs;
@@ -3113,7 +3118,7 @@ fail_cleaner:
        filemap_write_and_wait(fs_info->btree_inode->i_mapping);
 
 fail_sysfs:
-       btrfs_sysfs_remove_one(fs_info);
+       btrfs_sysfs_remove_mounted(fs_info);
 
 fail_fsdev_sysfs:
        btrfs_sysfs_remove_fsid(fs_info->fs_devices);
@@ -3175,8 +3180,8 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
                struct btrfs_device *device = (struct btrfs_device *)
                        bh->b_private;
 
-               printk_ratelimited_in_rcu(KERN_WARNING "BTRFS: lost page write due to "
-                                         "I/O error on %s\n",
+               btrfs_warn_rl_in_rcu(device->dev_root->fs_info,
+                               "lost page write due to IO error on %s",
                                          rcu_str_deref(device->name));
                /* note, we dont' set_buffer_write_io_error because we have
                 * our own ways of dealing with the IO errors
@@ -3188,6 +3193,37 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
        put_bh(bh);
 }
 
+int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num,
+                       struct buffer_head **bh_ret)
+{
+       struct buffer_head *bh;
+       struct btrfs_super_block *super;
+       u64 bytenr;
+
+       bytenr = btrfs_sb_offset(copy_num);
+       if (bytenr + BTRFS_SUPER_INFO_SIZE >= i_size_read(bdev->bd_inode))
+               return -EINVAL;
+
+       bh = __bread(bdev, bytenr / 4096, BTRFS_SUPER_INFO_SIZE);
+       /*
+        * If we fail to read from the underlying devices, as of now
+        * the best option we have is to mark it EIO.
+        */
+       if (!bh)
+               return -EIO;
+
+       super = (struct btrfs_super_block *)bh->b_data;
+       if (btrfs_super_bytenr(super) != bytenr ||
+                   btrfs_super_magic(super) != BTRFS_MAGIC) {
+               brelse(bh);
+               return -EINVAL;
+       }
+
+       *bh_ret = bh;
+       return 0;
+}
+
+
 struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
 {
        struct buffer_head *bh;
@@ -3195,7 +3231,7 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
        struct btrfs_super_block *super;
        int i;
        u64 transid = 0;
-       u64 bytenr;
+       int ret = -EINVAL;
 
        /* we would like to check all the supers, but that would make
         * a btrfs mount succeed after a mkfs from a different FS.
@@ -3203,21 +3239,11 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
         * later supers, using BTRFS_SUPER_MIRROR_MAX instead
         */
        for (i = 0; i < 1; i++) {
-               bytenr = btrfs_sb_offset(i);
-               if (bytenr + BTRFS_SUPER_INFO_SIZE >=
-                                       i_size_read(bdev->bd_inode))
-                       break;
-               bh = __bread(bdev, bytenr / 4096,
-                                       BTRFS_SUPER_INFO_SIZE);
-               if (!bh)
+               ret = btrfs_read_dev_one_super(bdev, i, &bh);
+               if (ret)
                        continue;
 
                super = (struct btrfs_super_block *)bh->b_data;
-               if (btrfs_super_bytenr(super) != bytenr ||
-                   btrfs_super_magic(super) != BTRFS_MAGIC) {
-                       brelse(bh);
-                       continue;
-               }
 
                if (!latest || btrfs_super_generation(super) > transid) {
                        brelse(latest);
@@ -3227,6 +3253,10 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
                        brelse(bh);
                }
        }
+
+       if (!latest)
+               return ERR_PTR(ret);
+
        return latest;
 }
 
@@ -3295,8 +3325,9 @@ static int write_dev_supers(struct btrfs_device *device,
                        bh = __getblk(device->bdev, bytenr / 4096,
                                      BTRFS_SUPER_INFO_SIZE);
                        if (!bh) {
-                               printk(KERN_ERR "BTRFS: couldn't get super "
-                                      "buffer head for bytenr %Lu\n", bytenr);
+                               btrfs_err(device->dev_root->fs_info,
+                                   "couldn't get super buffer head for bytenr %llu",
+                                   bytenr);
                                errors++;
                                continue;
                        }
@@ -3445,22 +3476,31 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 
 int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags)
 {
-       if ((flags & (BTRFS_BLOCK_GROUP_DUP |
-                     BTRFS_BLOCK_GROUP_RAID0 |
-                     BTRFS_AVAIL_ALLOC_BIT_SINGLE)) ||
-           ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0))
-               return 0;
+       int raid_type;
+       int min_tolerated = INT_MAX;
 
-       if (flags & (BTRFS_BLOCK_GROUP_RAID1 |
-                    BTRFS_BLOCK_GROUP_RAID5 |
-                    BTRFS_BLOCK_GROUP_RAID10))
-               return 1;
+       if ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 ||
+           (flags & BTRFS_AVAIL_ALLOC_BIT_SINGLE))
+               min_tolerated = min(min_tolerated,
+                                   btrfs_raid_array[BTRFS_RAID_SINGLE].
+                                   tolerated_failures);
 
-       if (flags & BTRFS_BLOCK_GROUP_RAID6)
-               return 2;
+       for (raid_type = 0; raid_type < BTRFS_NR_RAID_TYPES; raid_type++) {
+               if (raid_type == BTRFS_RAID_SINGLE)
+                       continue;
+               if (!(flags & btrfs_raid_group[raid_type]))
+                       continue;
+               min_tolerated = min(min_tolerated,
+                                   btrfs_raid_array[raid_type].
+                                   tolerated_failures);
+       }
 
-       pr_warn("BTRFS: unknown raid type: %llu\n", flags);
-       return 0;
+       if (min_tolerated == INT_MAX) {
+               pr_warn("BTRFS: unknown raid flag: %llu\n", flags);
+               min_tolerated = 0;
+       }
+
+       return min_tolerated;
 }
 
 int btrfs_calc_num_tolerated_disk_barrier_failures(
@@ -3544,7 +3584,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
                if (ret) {
                        mutex_unlock(
                                &root->fs_info->fs_devices->device_list_mutex);
-                       btrfs_error(root->fs_info, ret,
+                       btrfs_std_error(root->fs_info, ret,
                                    "errors while submitting device barriers.");
                        return ret;
                }
@@ -3584,7 +3624,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
                mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
 
                /* FUA is masked off if unsupported and can't be the reason */
-               btrfs_error(root->fs_info, -EIO,
+               btrfs_std_error(root->fs_info, -EIO,
                            "%d errors while writing supers", total_errors);
                return -EIO;
        }
@@ -3602,7 +3642,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
        }
        mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
        if (total_errors > max_errors) {
-               btrfs_error(root->fs_info, -EIO,
+               btrfs_std_error(root->fs_info, -EIO,
                            "%d errors while writing supers", total_errors);
                return -EIO;
        }
@@ -3788,7 +3828,7 @@ void close_ctree(struct btrfs_root *root)
                       percpu_counter_sum(&fs_info->delalloc_bytes));
        }
 
-       btrfs_sysfs_remove_one(fs_info);
+       btrfs_sysfs_remove_mounted(fs_info);
        btrfs_sysfs_remove_fsid(fs_info->fs_devices);
 
        btrfs_free_fs_roots(fs_info);
@@ -4286,25 +4326,6 @@ again:
        return 0;
 }
 
-static void btrfs_free_pending_ordered(struct btrfs_transaction *cur_trans,
-                                      struct btrfs_fs_info *fs_info)
-{
-       struct btrfs_ordered_extent *ordered;
-
-       spin_lock(&fs_info->trans_lock);
-       while (!list_empty(&cur_trans->pending_ordered)) {
-               ordered = list_first_entry(&cur_trans->pending_ordered,
-                                          struct btrfs_ordered_extent,
-                                          trans_list);
-               list_del_init(&ordered->trans_list);
-               spin_unlock(&fs_info->trans_lock);
-
-               btrfs_put_ordered_extent(ordered);
-               spin_lock(&fs_info->trans_lock);
-       }
-       spin_unlock(&fs_info->trans_lock);
-}
-
 void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
                                   struct btrfs_root *root)
 {
@@ -4316,7 +4337,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
        cur_trans->state = TRANS_STATE_UNBLOCKED;
        wake_up(&root->fs_info->transaction_wait);
 
-       btrfs_free_pending_ordered(cur_trans, root->fs_info);
        btrfs_destroy_delayed_inodes(root);
        btrfs_assert_delayed_root_empty(root);