Merge branch 'work.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[sfrench/cifs-2.6.git] / fs / btrfs / dev-replace.c
index cd42d95e9e0589c7bdffc210a9fd8b48217a392e..7c655f9a7a504e5d758323e6be536cfb39753b2d 100644 (file)
@@ -639,11 +639,39 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
        write_unlock(&em_tree->lock);
 }
 
+/*
+ * Read progress of device replace status according to the state and last
+ * stored position. The value format is the same as for
+ * btrfs_dev_replace::progress_1000
+ */
+static u64 btrfs_dev_replace_progress(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
+       u64 ret = 0;
+
+       switch (dev_replace->replace_state) {
+       case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
+       case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
+               ret = 0;
+               break;
+       case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
+               ret = 1000;
+               break;
+       case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
+       case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
+               ret = div64_u64(dev_replace->cursor_left,
+                               div_u64(btrfs_device_get_total_bytes(
+                                               dev_replace->srcdev), 1000));
+               break;
+       }
+
+       return ret;
+}
+
 void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
                              struct btrfs_ioctl_dev_replace_args *args)
 {
        struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
-       struct btrfs_device *srcdev;
 
        btrfs_dev_replace_lock(dev_replace, 0);
        /* even if !dev_replace_is_valid, the values are good enough for
@@ -656,21 +684,7 @@ void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
                atomic64_read(&dev_replace->num_write_errors);
        args->status.num_uncorrectable_read_errors =
                atomic64_read(&dev_replace->num_uncorrectable_read_errors);
-       switch (dev_replace->replace_state) {
-       case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
-       case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
-               args->status.progress_1000 = 0;
-               break;
-       case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
-               args->status.progress_1000 = 1000;
-               break;
-       case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
-       case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
-               srcdev = dev_replace->srcdev;
-               args->status.progress_1000 = div64_u64(dev_replace->cursor_left,
-                       div_u64(btrfs_device_get_total_bytes(srcdev), 1000));
-               break;
-       }
+       args->status.progress_1000 = btrfs_dev_replace_progress(fs_info);
        btrfs_dev_replace_unlock(dev_replace, 0);
 }
 
@@ -795,25 +809,19 @@ static int btrfs_dev_replace_kthread(void *data)
 {
        struct btrfs_fs_info *fs_info = data;
        struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
-       struct btrfs_ioctl_dev_replace_args *status_args;
        u64 progress;
 
-       status_args = kzalloc(sizeof(*status_args), GFP_KERNEL);
-       if (status_args) {
-               btrfs_dev_replace_status(fs_info, status_args);
-               progress = status_args->status.progress_1000;
-               kfree(status_args);
-               progress = div_u64(progress, 10);
-               btrfs_info_in_rcu(fs_info,
-                       "continuing dev_replace from %s (devid %llu) to %s @%u%%",
-                       dev_replace->srcdev->missing ? "<missing disk>" :
-                       rcu_str_deref(dev_replace->srcdev->name),
-                       dev_replace->srcdev->devid,
-                       dev_replace->tgtdev ?
-                       rcu_str_deref(dev_replace->tgtdev->name) :
-                       "<missing target disk>",
-                       (unsigned int)progress);
-       }
+       progress = btrfs_dev_replace_progress(fs_info);
+       progress = div_u64(progress, 10);
+       btrfs_info_in_rcu(fs_info,
+               "continuing dev_replace from %s (devid %llu) to %s @%u%%",
+               dev_replace->srcdev->missing ? "<missing disk>"
+                       : rcu_str_deref(dev_replace->srcdev->name),
+               dev_replace->srcdev->devid,
+               dev_replace->tgtdev ? rcu_str_deref(dev_replace->tgtdev->name)
+                       : "<missing target disk>",
+               (unsigned int)progress);
+
        btrfs_dev_replace_continue_on_mount(fs_info);
        clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);