forked from Minki/linux
Btrfs: return failure if btrfs_dev_replace_finishing() failed
device replace could fail due to another running scrub process or any other errors btrfs_scrub_dev() may hit, but this failure doesn't get returned to userspace. The following steps could reproduce this issue mkfs -t btrfs -f /dev/sdb1 /dev/sdb2 mount /dev/sdb1 /mnt/btrfs while true; do btrfs scrub start -B /mnt/btrfs >/dev/null 2>&1; done & btrfs replace start -Bf /dev/sdb2 /dev/sdb3 /mnt/btrfs # if this replace succeeded, do the following and repeat until # you see this log in dmesg # BTRFS: btrfs_scrub_dev(/dev/sdb2, 2, /dev/sdb3) failed -115 #btrfs replace start -Bf /dev/sdb3 /dev/sdb2 /mnt/btrfs # once you see the error log in dmesg, check return value of # replace echo $? Introduce a new dev replace result BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS to catch -EINPROGRESS explicitly and return other errors directly to userspace. Signed-off-by: Eryu Guan <guaneryu@gmail.com> Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
parent
6b3a4d60db
commit
2fc9f6baa2
@ -422,9 +422,15 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
|
||||
&dev_replace->scrub_progress, 0, 1);
|
||||
|
||||
ret = btrfs_dev_replace_finishing(root->fs_info, ret);
|
||||
WARN_ON(ret);
|
||||
/* don't warn if EINPROGRESS, someone else might be running scrub */
|
||||
if (ret == -EINPROGRESS) {
|
||||
args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS;
|
||||
ret = 0;
|
||||
} else {
|
||||
WARN_ON(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
|
||||
leave:
|
||||
dev_replace->srcdev = NULL;
|
||||
@ -542,7 +548,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||
btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device);
|
||||
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
|
||||
|
||||
return 0;
|
||||
return scrub_ret;
|
||||
}
|
||||
|
||||
printk_in_rcu(KERN_INFO
|
||||
|
@ -157,6 +157,7 @@ struct btrfs_ioctl_dev_replace_status_params {
|
||||
#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR 0
|
||||
#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED 1
|
||||
#define BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED 2
|
||||
#define BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS 3
|
||||
struct btrfs_ioctl_dev_replace_args {
|
||||
__u64 cmd; /* in */
|
||||
__u64 result; /* out */
|
||||
|
Loading…
Reference in New Issue
Block a user