diff options
author | Anand Jain <anand.jain@oracle.com> | 2016-02-12 21:01:39 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-04-28 04:59:13 -0400 |
commit | 6b526ed70cf189660d009ea6f17af77a9cca0f38 (patch) | |
tree | ff2c8182649b216537ee8fd3012746db750348e1 | |
parent | 42b674271566c26692c32f4ec1f4b4cf14d5046f (diff) |
btrfs: introduce device delete by devid
This introduces new ioctl BTRFS_IOC_RM_DEV_V2, which uses enhanced struct
btrfs_ioctl_vol_args_v2 to carry devid as an user argument.
The patch won't delete the old ioctl interface and so kernel remains
backward compatible with user land progs.
Test case/script:
echo "0 $(blockdev --getsz /dev/sdf) linear /dev/sdf 0" | dmsetup create bad_disk
mkfs.btrfs -f -d raid1 -m raid1 /dev/sdd /dev/sde /dev/mapper/bad_disk
mount /dev/sdd /btrfs
dmsetup suspend bad_disk
echo "0 $(blockdev --getsz /dev/sdf) error /dev/sdf 0" | dmsetup load bad_disk
dmsetup resume bad_disk
echo "bad disk failed. now deleting/replacing"
btrfs dev del 3 /btrfs
echo $?
btrfs fi show /btrfs
umount /btrfs
btrfs-show-super /dev/sdd | egrep num_device
dmsetup remove bad_disk
wipefs -a /dev/sdf
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reported-by: Martin <m_btrfs@ml1.co.uk>
[ adjust messages, s/disk/device/ ]
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | fs/btrfs/ioctl.c | 58 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 4 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 2 | ||||
-rw-r--r-- | include/uapi/linux/btrfs.h | 14 |
4 files changed, 73 insertions, 5 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5a23806ae418..7cf0f6328d99 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -2667,6 +2667,60 @@ out: | |||
2667 | return ret; | 2667 | return ret; |
2668 | } | 2668 | } |
2669 | 2669 | ||
2670 | static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) | ||
2671 | { | ||
2672 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; | ||
2673 | struct btrfs_ioctl_vol_args_v2 *vol_args; | ||
2674 | int ret; | ||
2675 | |||
2676 | if (!capable(CAP_SYS_ADMIN)) | ||
2677 | return -EPERM; | ||
2678 | |||
2679 | ret = mnt_want_write_file(file); | ||
2680 | if (ret) | ||
2681 | return ret; | ||
2682 | |||
2683 | vol_args = memdup_user(arg, sizeof(*vol_args)); | ||
2684 | if (IS_ERR(vol_args)) { | ||
2685 | ret = PTR_ERR(vol_args); | ||
2686 | goto err_drop; | ||
2687 | } | ||
2688 | |||
2689 | /* Check for compatibility reject unknown flags */ | ||
2690 | if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS) | ||
2691 | return -ENOTTY; | ||
2692 | |||
2693 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | ||
2694 | 1)) { | ||
2695 | ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; | ||
2696 | goto out; | ||
2697 | } | ||
2698 | |||
2699 | mutex_lock(&root->fs_info->volume_mutex); | ||
2700 | if (vol_args->flags & BTRFS_DEVICE_BY_ID) { | ||
2701 | ret = btrfs_rm_device(root, NULL, vol_args->devid); | ||
2702 | } else { | ||
2703 | vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; | ||
2704 | ret = btrfs_rm_device(root, vol_args->name, 0); | ||
2705 | } | ||
2706 | mutex_unlock(&root->fs_info->volume_mutex); | ||
2707 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | ||
2708 | |||
2709 | if (!ret) { | ||
2710 | if (vol_args->flags & BTRFS_DEVICE_BY_ID) | ||
2711 | btrfs_info(root->fs_info, "device deleted: id %llu", | ||
2712 | vol_args->devid); | ||
2713 | else | ||
2714 | btrfs_info(root->fs_info, "device deleted: %s", | ||
2715 | vol_args->name); | ||
2716 | } | ||
2717 | out: | ||
2718 | kfree(vol_args); | ||
2719 | err_drop: | ||
2720 | mnt_drop_write_file(file); | ||
2721 | return ret; | ||
2722 | } | ||
2723 | |||
2670 | static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | 2724 | static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) |
2671 | { | 2725 | { |
2672 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; | 2726 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
@@ -2695,7 +2749,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2695 | } | 2749 | } |
2696 | 2750 | ||
2697 | mutex_lock(&root->fs_info->volume_mutex); | 2751 | mutex_lock(&root->fs_info->volume_mutex); |
2698 | ret = btrfs_rm_device(root, vol_args->name); | 2752 | ret = btrfs_rm_device(root, vol_args->name, 0); |
2699 | mutex_unlock(&root->fs_info->volume_mutex); | 2753 | mutex_unlock(&root->fs_info->volume_mutex); |
2700 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | 2754 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); |
2701 | 2755 | ||
@@ -5459,6 +5513,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
5459 | return btrfs_ioctl_add_dev(root, argp); | 5513 | return btrfs_ioctl_add_dev(root, argp); |
5460 | case BTRFS_IOC_RM_DEV: | 5514 | case BTRFS_IOC_RM_DEV: |
5461 | return btrfs_ioctl_rm_dev(file, argp); | 5515 | return btrfs_ioctl_rm_dev(file, argp); |
5516 | case BTRFS_IOC_RM_DEV_V2: | ||
5517 | return btrfs_ioctl_rm_dev_v2(file, argp); | ||
5462 | case BTRFS_IOC_FS_INFO: | 5518 | case BTRFS_IOC_FS_INFO: |
5463 | return btrfs_ioctl_fs_info(root, argp); | 5519 | return btrfs_ioctl_fs_info(root, argp); |
5464 | case BTRFS_IOC_DEV_INFO: | 5520 | case BTRFS_IOC_DEV_INFO: |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 8264b06756e6..1421d711629f 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1748,7 +1748,7 @@ static int __check_raid_min_devices(struct btrfs_fs_info *fs_info) | |||
1748 | return 0; | 1748 | return 0; |
1749 | } | 1749 | } |
1750 | 1750 | ||
1751 | int btrfs_rm_device(struct btrfs_root *root, char *device_path) | 1751 | int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid) |
1752 | { | 1752 | { |
1753 | struct btrfs_device *device; | 1753 | struct btrfs_device *device; |
1754 | struct btrfs_device *next_device; | 1754 | struct btrfs_device *next_device; |
@@ -1764,7 +1764,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1764 | if (ret) | 1764 | if (ret) |
1765 | goto out; | 1765 | goto out; |
1766 | 1766 | ||
1767 | ret = btrfs_find_device_by_user_input(root, 0, device_path, | 1767 | ret = btrfs_find_device_by_user_input(root, devid, device_path, |
1768 | &device); | 1768 | &device); |
1769 | if (ret) | 1769 | if (ret) |
1770 | goto out; | 1770 | goto out; |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 508739314e43..c73d027e2f8b 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -454,7 +454,7 @@ int btrfs_find_device_by_user_input(struct btrfs_root *root, u64 srcdevid, | |||
454 | struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, | 454 | struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, |
455 | const u64 *devid, | 455 | const u64 *devid, |
456 | const u8 *uuid); | 456 | const u8 *uuid); |
457 | int btrfs_rm_device(struct btrfs_root *root, char *device_path); | 457 | int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid); |
458 | void btrfs_cleanup_fs_uuids(void); | 458 | void btrfs_cleanup_fs_uuids(void); |
459 | int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len); | 459 | int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len); |
460 | int btrfs_grow_device(struct btrfs_trans_handle *trans, | 460 | int btrfs_grow_device(struct btrfs_trans_handle *trans, |
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index dea893199257..396a4efca775 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h | |||
@@ -36,6 +36,13 @@ struct btrfs_ioctl_vol_args { | |||
36 | #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) | 36 | #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) |
37 | #define BTRFS_SUBVOL_RDONLY (1ULL << 1) | 37 | #define BTRFS_SUBVOL_RDONLY (1ULL << 1) |
38 | #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) | 38 | #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) |
39 | #define BTRFS_DEVICE_BY_ID (1ULL << 3) | ||
40 | #define BTRFS_VOL_ARG_V2_FLAGS \ | ||
41 | (BTRFS_SUBVOL_CREATE_ASYNC | \ | ||
42 | BTRFS_SUBVOL_RDONLY | \ | ||
43 | BTRFS_SUBVOL_QGROUP_INHERIT | \ | ||
44 | BTRFS_DEVICE_BY_ID) | ||
45 | |||
39 | #define BTRFS_FSID_SIZE 16 | 46 | #define BTRFS_FSID_SIZE 16 |
40 | #define BTRFS_UUID_SIZE 16 | 47 | #define BTRFS_UUID_SIZE 16 |
41 | #define BTRFS_UUID_UNPARSED_SIZE 37 | 48 | #define BTRFS_UUID_UNPARSED_SIZE 37 |
@@ -76,7 +83,10 @@ struct btrfs_ioctl_vol_args_v2 { | |||
76 | }; | 83 | }; |
77 | __u64 unused[4]; | 84 | __u64 unused[4]; |
78 | }; | 85 | }; |
79 | char name[BTRFS_SUBVOL_NAME_MAX + 1]; | 86 | union { |
87 | char name[BTRFS_SUBVOL_NAME_MAX + 1]; | ||
88 | u64 devid; | ||
89 | }; | ||
80 | }; | 90 | }; |
81 | 91 | ||
82 | /* | 92 | /* |
@@ -659,5 +669,7 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code) | |||
659 | struct btrfs_ioctl_feature_flags[2]) | 669 | struct btrfs_ioctl_feature_flags[2]) |
660 | #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ | 670 | #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ |
661 | struct btrfs_ioctl_feature_flags[3]) | 671 | struct btrfs_ioctl_feature_flags[3]) |
672 | #define BTRFS_IOC_RM_DEV_V2 _IOW(BTRFS_IOCTL_MAGIC, 58, \ | ||
673 | struct btrfs_ioctl_vol_args_v2) | ||
662 | 674 | ||
663 | #endif /* _UAPI_LINUX_BTRFS_H */ | 675 | #endif /* _UAPI_LINUX_BTRFS_H */ |