* [PATCH 0/3] btrfs: Enumerate and export exclusive operations @ 2020-07-27 22:04 Goldwyn Rodrigues 2020-07-27 22:04 ` [PATCH 1/3] btrfs: enumerate the type of exclusive operation in progress Goldwyn Rodrigues ` (3 more replies) 0 siblings, 4 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-07-27 22:04 UTC (permalink / raw) To: linux-btrfs This would enable our tools to specify precisely which operation is running on why starting an exclusive operation failed. The series also adds a sysfs_notify() to alert userspace when the state changes, so userspace can perform select() on it to get notified of the change. This would enable us to enqueue a command which will wait for current exclusive operation to complete before issuing the next exclusive operation. This has been done synchronously as opposed to a background process, or else error collection (if any) will become a nightmare. This third patch further expands the balance information such as the state and the current statistics. I am hoping that it could be used to move the logic of guessing/managing the right ioctls out of the kernel and into the tools. However, if you feel that it is inappropriate, the patch can be ignored. For backward compatibility, the tools ignore if the sys file is not present. Would you prefer an error if "--enqueue" option is issued on an older kernel? Regards, -- Goldwyn ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/3] btrfs: enumerate the type of exclusive operation in progress 2020-07-27 22:04 [PATCH 0/3] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues @ 2020-07-27 22:04 ` Goldwyn Rodrigues 2020-07-28 8:45 ` Johannes Thumshirn 2020-07-27 22:04 ` [PATCH 2/3] btrfs: export currently executing exclusive operation via sysfs Goldwyn Rodrigues ` (2 subsequent siblings) 3 siblings, 1 reply; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-07-27 22:04 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Instead of using a flag bit for exclusive operation, use an atomic_t variable to store if the exclusive operation is being performed. Introduce an API to start and finish an exclusive operation. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- fs/btrfs/ctree.h | 24 +++++++++++++++++++----- fs/btrfs/dev-replace.c | 4 ++-- fs/btrfs/inode.c | 4 ++-- fs/btrfs/ioctl.c | 36 +++++++++++++++++++++++------------- fs/btrfs/volumes.c | 8 ++++---- 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index d404cce8ae40..a56f383a7894 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -540,11 +540,6 @@ enum { BTRFS_FS_QUOTA_OVERRIDE, /* Used to record internally whether fs has been frozen */ BTRFS_FS_FROZEN, - /* - * Indicate that a whole-filesystem exclusive operation is running - * (device replace, resize, device add/delete, balance) - */ - BTRFS_FS_EXCL_OP, /* * To info transaction_kthread we need an immediate commit so it * doesn't need to wait for commit_interval @@ -570,6 +565,20 @@ enum { BTRFS_FS_DISCARD_RUNNING, }; +/* + * Exclusive operation values + * (device replace, resize, device add/remove, balance) + */ +enum btrfs_exclusive_operation_t { + BTRFS_EXCLOP_NONE = 0, + BTRFS_EXCLOP_BALANCE, + BTRFS_EXCLOP_DEV_ADD, + BTRFS_EXCLOP_DEV_REPLACE, + BTRFS_EXCLOP_DEV_REMOVE, + BTRFS_EXCLOP_SWAP_ACTIVATE, + BTRFS_EXCLOP_RESIZE, +}; + struct btrfs_fs_info { u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; unsigned long flags; @@ -939,6 +948,9 @@ struct btrfs_fs_info { */ int send_in_progress; + /* Type of exclusive operation running */ + atomic_t exclusive_operation; + #ifdef CONFIG_BTRFS_FS_REF_VERIFY spinlock_t ref_verify_lock; struct rb_root block_tree; @@ -2949,6 +2961,8 @@ void btrfs_get_block_group_info(struct list_head *groups_list, struct btrfs_ioctl_space_info *space); void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info, struct btrfs_ioctl_balance_args *bargs); +bool btrfs_exclop_start(struct btrfs_fs_info *fs_info, int type); +void btrfs_exclop_finish(struct btrfs_fs_info *fs_info); /* file.c */ int __init btrfs_auto_defrag_init(void); diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index db93909b25e0..b8406f5cc8ff 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -983,7 +983,7 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info) * should never allow both to start and pause. We don't want to allow * dev-replace to start anyway. */ - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { + if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_DEV_REPLACE)) { down_write(&dev_replace->rwsem); dev_replace->replace_state = BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED; @@ -1020,7 +1020,7 @@ static int btrfs_dev_replace_kthread(void *data) ret = btrfs_dev_replace_finishing(fs_info, ret); WARN_ON(ret && ret != -ECANCELED); - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); return 0; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 43c803c16b48..ba4e4b902b13 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10012,7 +10012,7 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file, * concurrent device add which isn't actually necessary, but it's not * really worth the trouble to allow it. */ - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { + if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_SWAP_ACTIVATE)) { btrfs_warn(fs_info, "cannot activate swapfile while exclusive operation is running"); return -EBUSY; @@ -10158,7 +10158,7 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file, if (ret) btrfs_swap_deactivate(file); - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); if (ret) return ret; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index e8f7c5f00894..2f45b88d7eed 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -364,6 +364,17 @@ static int check_xflags(unsigned int flags) return 0; } +bool btrfs_exclop_start(struct btrfs_fs_info *fs_info, int type) +{ + return !atomic_cmpxchg(&fs_info->exclusive_operation, BTRFS_EXCLOP_NONE, + type); +} + +void btrfs_exclop_finish(struct btrfs_fs_info *fs_info) +{ + atomic_set(&fs_info->exclusive_operation, BTRFS_EXCLOP_NONE); +} + /* * Set the xflags from the internal inode flags. The remaining items of fsxattr * are zeroed. @@ -1605,7 +1616,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, if (ret) return ret; - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { + if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_RESIZE)) { mnt_drop_write_file(file); return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; } @@ -1719,7 +1730,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, out_free: kfree(vol_args); out: - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); mnt_drop_write_file(file); return ret; } @@ -3079,7 +3090,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) + if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_DEV_ADD)) return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; vol_args = memdup_user(arg, sizeof(*vol_args)); @@ -3096,7 +3107,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg) kfree(vol_args); out: - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); return ret; } @@ -3125,7 +3136,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) goto out; } - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { + if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_DEV_REMOVE)) { ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; goto out; } @@ -3136,7 +3147,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; ret = btrfs_rm_device(fs_info, vol_args->name, 0); } - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); if (!ret) { if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID) @@ -3167,7 +3178,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) if (ret) return ret; - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { + if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_DEV_REMOVE)) { ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; goto out_drop_write; } @@ -3185,7 +3196,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) btrfs_info(fs_info, "disk deleted %s", vol_args->name); kfree(vol_args); out: - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); out_drop_write: mnt_drop_write_file(file); @@ -3668,11 +3679,11 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info, ret = -EROFS; goto out; } - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { + if (btrfs_exclop_start(fs_info, BTRFS_EXCLOP_DEV_REPLACE)) { ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; } else { ret = btrfs_dev_replace_by_ioctl(fs_info, p); - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); } break; case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS: @@ -3883,7 +3894,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) return ret; again: - if (!test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { + if (btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) { mutex_lock(&fs_info->balance_mutex); need_unlock = true; goto locked; @@ -3929,7 +3940,6 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) } locked: - BUG_ON(!test_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)); if (arg) { bargs = memdup_user(arg, sizeof(*bargs)); @@ -4006,7 +4016,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) out_unlock: mutex_unlock(&fs_info->balance_mutex); if (need_unlock) - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); out: mnt_drop_write_file(file); return ret; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 0d6e785bcb98..8a55ac7a0d3e 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -4150,7 +4150,7 @@ int btrfs_balance(struct btrfs_fs_info *fs_info, if ((ret && ret != -ECANCELED && ret != -ENOSPC) || balance_need_close(fs_info)) { reset_balance_state(fs_info); - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); } wake_up(&fs_info->balance_wait_q); @@ -4161,7 +4161,7 @@ int btrfs_balance(struct btrfs_fs_info *fs_info, reset_balance_state(fs_info); else kfree(bctl); - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); return ret; } @@ -4263,7 +4263,7 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info) * is in a paused state and must have fs_info::balance_ctl properly * set up. */ - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) + if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) btrfs_warn(fs_info, "balance: cannot set exclusive op status, resume manually"); @@ -4345,7 +4345,7 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info) if (fs_info->balance_ctl) { reset_balance_state(fs_info); - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + btrfs_exclop_finish(fs_info); btrfs_info(fs_info, "balance: canceled"); } } -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] btrfs: enumerate the type of exclusive operation in progress 2020-07-27 22:04 ` [PATCH 1/3] btrfs: enumerate the type of exclusive operation in progress Goldwyn Rodrigues @ 2020-07-28 8:45 ` Johannes Thumshirn 0 siblings, 0 replies; 12+ messages in thread From: Johannes Thumshirn @ 2020-07-28 8:45 UTC (permalink / raw) To: Goldwyn Rodrigues, linux-btrfs; +Cc: Goldwyn Rodrigues On 28/07/2020 00:05, Goldwyn Rodrigues wrote: > @@ -3668,11 +3679,11 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info, > ret = -EROFS; > goto out; > } > - if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { > + if (btrfs_exclop_start(fs_info, BTRFS_EXCLOP_DEV_REPLACE)) { > ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; > } else { > ret = btrfs_dev_replace_by_ioctl(fs_info, p); > - clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); > + btrfs_exclop_finish(fs_info); > } > break; > case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS: > @@ -3883,7 +3894,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) > return ret; > > again: > - if (!test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { > + if (btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) { > mutex_lock(&fs_info->balance_mutex); > need_unlock = true; > goto locked; Just looking at patterns in this patch, but shouldn't these be 'if (!btrfs_exclop_start())' like elsewhere in this patch? ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/3] btrfs: export currently executing exclusive operation via sysfs 2020-07-27 22:04 [PATCH 0/3] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues 2020-07-27 22:04 ` [PATCH 1/3] btrfs: enumerate the type of exclusive operation in progress Goldwyn Rodrigues @ 2020-07-27 22:04 ` Goldwyn Rodrigues 2020-07-27 22:04 ` [PATCH 3/3] btrfs: add more information for balance Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 3 siblings, 0 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-07-27 22:04 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> /sys/fs/<fsid>/exclusive_operation contains the currently executing exclusive operation. Add a sysfs_notify() when operation end, so userspace can be notified of exclusive operation is finished. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- fs/btrfs/ioctl.c | 2 ++ fs/btrfs/sysfs.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 2f45b88d7eed..a00d6d5c42c1 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -373,6 +373,8 @@ bool btrfs_exclop_start(struct btrfs_fs_info *fs_info, int type) void btrfs_exclop_finish(struct btrfs_fs_info *fs_info) { atomic_set(&fs_info->exclusive_operation, BTRFS_EXCLOP_NONE); + sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, + "exclusive_operation"); } /* diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index a39bff64ff24..71950c121588 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -808,6 +808,30 @@ static ssize_t btrfs_checksum_show(struct kobject *kobj, BTRFS_ATTR(, checksum, btrfs_checksum_show); +static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, + struct kobj_attribute *a, char *buf) +{ + struct btrfs_fs_info *fs_info = to_fs_info(kobj); + switch (atomic_read(&fs_info->exclusive_operation)) { + case BTRFS_EXCLOP_NONE: + return scnprintf(buf, PAGE_SIZE, "none\n"); + case BTRFS_EXCLOP_BALANCE: + return scnprintf(buf, PAGE_SIZE, "balance\n"); + case BTRFS_EXCLOP_DEV_ADD: + return scnprintf(buf, PAGE_SIZE, "device add\n"); + case BTRFS_EXCLOP_DEV_REPLACE: + return scnprintf(buf, PAGE_SIZE, "device replace\n"); + case BTRFS_EXCLOP_DEV_REMOVE: + return scnprintf(buf, PAGE_SIZE, "device remove\n"); + case BTRFS_EXCLOP_SWAP_ACTIVATE: + return scnprintf(buf, PAGE_SIZE, "swap activate\n"); + case BTRFS_EXCLOP_RESIZE: + return scnprintf(buf, PAGE_SIZE, "resize\n"); + } + return 0; +} +BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); + static const struct attribute *btrfs_attrs[] = { BTRFS_ATTR_PTR(, label), BTRFS_ATTR_PTR(, nodesize), @@ -816,6 +840,7 @@ static const struct attribute *btrfs_attrs[] = { BTRFS_ATTR_PTR(, quota_override), BTRFS_ATTR_PTR(, metadata_uuid), BTRFS_ATTR_PTR(, checksum), + BTRFS_ATTR_PTR(, exclusive_operation), NULL, }; -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/3] btrfs: add more information for balance 2020-07-27 22:04 [PATCH 0/3] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues 2020-07-27 22:04 ` [PATCH 1/3] btrfs: enumerate the type of exclusive operation in progress Goldwyn Rodrigues 2020-07-27 22:04 ` [PATCH 2/3] btrfs: export currently executing exclusive operation via sysfs Goldwyn Rodrigues @ 2020-07-27 22:04 ` Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 3 siblings, 0 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-07-27 22:04 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Include information about the state of the balance and expected, considered and completed statistics. Q: I am not sure of the cancelled state, and stopping seemed more appropriate since it was a transient state to cancelling the operation. Would you prefer to call it cancelled? This information is not used by user space as of now. We could use it for "btrfs balance status" or ignore this patch for inclusion at all. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- fs/btrfs/sysfs.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 71950c121588..001a7ae375d0 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -808,6 +808,33 @@ static ssize_t btrfs_checksum_show(struct kobject *kobj, BTRFS_ATTR(, checksum, btrfs_checksum_show); +static ssize_t btrfs_balance_show(struct btrfs_fs_info *fs_info, char *buf) +{ + ssize_t ret = 0; + struct btrfs_balance_control *bctl; + + ret += scnprintf(buf, PAGE_SIZE, "balance\n"); + spin_lock(&fs_info->balance_lock); + bctl = fs_info->balance_ctl; + if (!bctl) { + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + "State: stopping\n"); + goto out; + } + if (test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags)) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + "State: running\n"); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, + "State: paused\n"); + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%llu %llu %llu\n", + bctl->stat.expected, bctl->stat.considered, + bctl->stat.completed); +out: + spin_unlock(&fs_info->balance_lock); + return ret; +} + static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { @@ -816,7 +843,7 @@ static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, case BTRFS_EXCLOP_NONE: return scnprintf(buf, PAGE_SIZE, "none\n"); case BTRFS_EXCLOP_BALANCE: - return scnprintf(buf, PAGE_SIZE, "balance\n"); + return btrfs_balance_show(fs_info, buf); case BTRFS_EXCLOP_DEV_ADD: return scnprintf(buf, PAGE_SIZE, "device add\n"); case BTRFS_EXCLOP_DEV_REPLACE: -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd 2020-07-27 22:04 [PATCH 0/3] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues ` (2 preceding siblings ...) 2020-07-27 22:04 ` [PATCH 3/3] btrfs: add more information for balance Goldwyn Rodrigues @ 2020-07-27 22:08 ` Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 2/4] btrfs-progs: add sysfs file reading functions Goldwyn Rodrigues ` (3 more replies) 3 siblings, 4 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-07-27 22:08 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Add a function get_fsid_fd() to use an open file fd to get the fsid of the mounted filesystem. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- common/utils.c | 31 +++++++++++++++++-------------- common/utils.h | 1 + 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/common/utils.c b/common/utils.c index 9742c2e1..8a691846 100644 --- a/common/utils.c +++ b/common/utils.c @@ -1097,35 +1097,38 @@ out: return ret; } +int get_fsid_fd(int fd, u8 *fsid) +{ + int ret; + struct btrfs_ioctl_fs_info_args args; + + ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args); + if (ret < 0) + return -errno; + + memcpy(fsid, args.fsid, BTRFS_FSID_SIZE); + return 0; +} + int get_fsid(const char *path, u8 *fsid, int silent) { int ret; int fd; - struct btrfs_ioctl_fs_info_args args; fd = open(path, O_RDONLY); if (fd < 0) { - ret = -errno; if (!silent) error("failed to open %s: %m", path); - goto out; - } - - ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args); - if (ret < 0) { - ret = -errno; - goto out; + return -errno; } - memcpy(fsid, args.fsid, BTRFS_FSID_SIZE); - ret = 0; + ret = get_fsid_fd(fd, fsid); + close(fd); -out: - if (fd != -1) - close(fd); return ret; } + static int group_profile_devs_min(u64 flag) { switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) { diff --git a/common/utils.h b/common/utils.h index 43e7f471..e34bb5a4 100644 --- a/common/utils.h +++ b/common/utils.h @@ -75,6 +75,7 @@ void close_file_or_dir(int fd, DIR *dirstream); int get_fs_info(const char *path, struct btrfs_ioctl_fs_info_args *fi_args, struct btrfs_ioctl_dev_info_args **di_ret); int get_fsid(const char *path, u8 *fsid, int silent); +int get_fsid_fd(int fd, u8 *fsid); int get_label(const char *btrfs_dev, char *label); int set_label(const char *btrfs_dev, const char *label); -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/4] btrfs-progs: add sysfs file reading functions 2020-07-27 22:08 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues @ 2020-07-27 22:08 ` Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 3/4] btrfs-progs: Check for exclusive operation before issuing ioctl Goldwyn Rodrigues ` (2 subsequent siblings) 3 siblings, 0 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-07-27 22:08 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Functions to read and and open sysfs files. Given a fd, find the fsid associated with the mount and convert into the sysfs directory to look. Read the exclusive_operation file to find the current exclusive operation running. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- Makefile | 4 ++-- common/sysfs.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/utils.h | 3 +++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 common/sysfs.c diff --git a/Makefile b/Makefile index ee57d9f8..8a267c45 100644 --- a/Makefile +++ b/Makefile @@ -168,8 +168,8 @@ libbtrfs_objects = send-stream.o send-utils.o kernel-lib/rbtree.o btrfs-list.o \ kernel-shared/free-space-tree.o repair.o kernel-shared/inode-item.o \ kernel-shared/file-item.o \ kernel-lib/raid56.o kernel-lib/tables.o \ - common/device-scan.o common/path-utils.o \ - common/utils.o libbtrfsutil/subvolume.o libbtrfsutil/stubs.o \ + common/device-scan.o common/path-utils.o common/utils.o \ + common/sysfs.o libbtrfsutil/subvolume.o libbtrfsutil/stubs.o \ crypto/hash.o crypto/xxhash.o $(CRYPTO_OBJECTS) libbtrfs_headers = send-stream.h send-utils.h send.h kernel-lib/rbtree.h btrfs-list.h \ crypto/crc32c.h kernel-lib/list.h kerncompat.h \ diff --git a/common/sysfs.c b/common/sysfs.c new file mode 100644 index 00000000..91ed270c --- /dev/null +++ b/common/sysfs.c @@ -0,0 +1,60 @@ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <unistd.h> +#include <sys/select.h> +#include <uuid/uuid.h> + +#include "common/utils.h" + +static u8 fsid[BTRFS_UUID_SIZE] = {0}; + +int sysfs_open(int fd, const char *filename) +{ + char fsid_str[BTRFS_UUID_UNPARSED_SIZE]; + int ret; + char sysfs_file[128]; + + if (fsid[0] == 0) { + ret = get_fsid_fd(fd, fsid); + if (ret < 0) + return ret; + } + + uuid_unparse(fsid, fsid_str); + snprintf(sysfs_file, 128, "/sys/fs/btrfs/%s/%s", fsid_str, filename); + return open(sysfs_file, O_RDONLY); +} + +int sysfs_get_str_fd(int fd, char *val, int size) +{ + lseek(fd, 0, SEEK_SET); + memset(val, '\0', size); + return read(fd, val, size); +} + +int get_exclusive_operation(int mp_fd, char *val) +{ + char *s; + int fd; + int n; + + fd = sysfs_open(mp_fd, "exclusive_operation"); + if (fd < 0) + return fd; + + n = sysfs_get_str_fd(fd, val, BTRFS_SYSFS_EXOP_SIZE); + close(fd); + + if (n < 0) + return n; + + s = strchr(val, '\n'); + if (!s) + return n; + + *s = '\0'; + return strlen(val); +} diff --git a/common/utils.h b/common/utils.h index e34bb5a4..be8aab58 100644 --- a/common/utils.h +++ b/common/utils.h @@ -153,4 +153,7 @@ void init_rand_seed(u64 seed); char *btrfs_test_for_multiple_profiles(int fd); int btrfs_warn_multiple_profiles(int fd); +#define BTRFS_SYSFS_EXOP_SIZE 16 +int get_exclusive_operation(int fd, char *val); + #endif -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/4] btrfs-progs: Check for exclusive operation before issuing ioctl 2020-07-27 22:08 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 2/4] btrfs-progs: add sysfs file reading functions Goldwyn Rodrigues @ 2020-07-27 22:08 ` Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 4/4] btrfs-progs: Enqueue command if it can't be performed immediately Goldwyn Rodrigues 2020-07-28 8:38 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Johannes Thumshirn 3 siblings, 0 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-07-27 22:08 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Check if an exclusive operation is running and if it is, err with the name of the exclusive operation running. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- cmds/device.c | 14 ++++++++++++++ cmds/filesystem.c | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/cmds/device.c b/cmds/device.c index 99ceed93..6acd4ae6 100644 --- a/cmds/device.c +++ b/cmds/device.c @@ -61,6 +61,7 @@ static int cmd_device_add(const struct cmd_struct *cmd, int discard = 1; int force = 0; int last_dev; + char exop[BTRFS_SYSFS_EXOP_SIZE]; optind = 0; while (1) { @@ -96,6 +97,12 @@ static int cmd_device_add(const struct cmd_struct *cmd, if (fdmnt < 0) return 1; + if (get_exclusive_operation(fdmnt, exop) > 0 && strcmp(exop, "none")) { + error("unable to add device: %s in progress", exop); + close_file_or_dir(fdmnt, dirstream); + return 1; + } + for (i = optind; i < last_dev; i++){ struct btrfs_ioctl_vol_args ioctl_args; int devfd, res; @@ -155,6 +162,7 @@ static int _cmd_device_remove(const struct cmd_struct *cmd, char *mntpnt; int i, fdmnt, ret = 0; DIR *dirstream = NULL; + char exop[BTRFS_SYSFS_EXOP_SIZE]; clean_args_no_options(cmd, argc, argv); @@ -167,6 +175,12 @@ static int _cmd_device_remove(const struct cmd_struct *cmd, if (fdmnt < 0) return 1; + if (get_exclusive_operation(fdmnt, exop) > 0 && strcmp(exop, "none")) { + error("unable to remove device: %s in progress", exop); + close_file_or_dir(fdmnt, dirstream); + return 1; + } + for(i = optind; i < argc - 1; i++) { struct btrfs_ioctl_vol_args arg; struct btrfs_ioctl_vol_args_v2 argv2 = {0}; diff --git a/cmds/filesystem.c b/cmds/filesystem.c index 6c1b6908..c3efb405 100644 --- a/cmds/filesystem.c +++ b/cmds/filesystem.c @@ -1079,6 +1079,7 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd, char *amount, *path; DIR *dirstream = NULL; struct stat st; + char exop[BTRFS_SYSFS_EXOP_SIZE]; clean_args_no_options_relaxed(cmd, argc, argv); @@ -1110,6 +1111,12 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd, if (fd < 0) return 1; + if (get_exclusive_operation(fd, exop) > 0 && strcmp(exop, "none")) { + error("unable to resize: %s in progress", exop); + close_file_or_dir(fd, dirstream); + return 1; + } + printf("Resize '%s' of '%s'\n", path, amount); memset(&args, 0, sizeof(args)); strncpy_null(args.name, amount); -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/4] btrfs-progs: Enqueue command if it can't be performed immediately 2020-07-27 22:08 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 2/4] btrfs-progs: add sysfs file reading functions Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 3/4] btrfs-progs: Check for exclusive operation before issuing ioctl Goldwyn Rodrigues @ 2020-07-27 22:08 ` Goldwyn Rodrigues 2020-07-28 8:38 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Johannes Thumshirn 3 siblings, 0 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-07-27 22:08 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Wait for the current exclusive operation to finish before issuing the command ioctl, so we have a better chance of success. Q: The resize argument parsing is hackish. Is there a better way to do this? Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- cmds/device.c | 56 +++++++++++++++++++++++++++++++++++++++-------- cmds/filesystem.c | 25 +++++++++++++++++---- common/sysfs.c | 26 ++++++++++++++++++++++ common/utils.h | 1 + 4 files changed, 95 insertions(+), 13 deletions(-) diff --git a/cmds/device.c b/cmds/device.c index 6acd4ae6..12d92dac 100644 --- a/cmds/device.c +++ b/cmds/device.c @@ -49,6 +49,7 @@ static const char * const cmd_device_add_usage[] = { "", "-K|--nodiscard do not perform whole device TRIM on devices that report such capability", "-f|--force force overwrite existing filesystem on the disk", + "-q|--enqueue enqueue if an exclusive operation is running", NULL }; @@ -62,6 +63,7 @@ static int cmd_device_add(const struct cmd_struct *cmd, int force = 0; int last_dev; char exop[BTRFS_SYSFS_EXOP_SIZE]; + bool enqueue = false; optind = 0; while (1) { @@ -69,10 +71,11 @@ static int cmd_device_add(const struct cmd_struct *cmd, static const struct option long_options[] = { { "nodiscard", optional_argument, NULL, 'K'}, { "force", no_argument, NULL, 'f'}, + { "enqueue", no_argument, NULL, 'q'}, { NULL, 0, NULL, 0} }; - c = getopt_long(argc, argv, "Kf", long_options, NULL); + c = getopt_long(argc, argv, "Kfq", long_options, NULL); if (c < 0) break; switch (c) { @@ -82,6 +85,9 @@ static int cmd_device_add(const struct cmd_struct *cmd, case 'f': force = 1; break; + case 'q': + enqueue = true; + break; default: usage_unknown_option(cmd, argv); } @@ -98,9 +104,15 @@ static int cmd_device_add(const struct cmd_struct *cmd, return 1; if (get_exclusive_operation(fdmnt, exop) > 0 && strcmp(exop, "none")) { - error("unable to add device: %s in progress", exop); - close_file_or_dir(fdmnt, dirstream); - return 1; + if (enqueue) { + printf("%s in progress. Waiting for %s to finish.\n", + exop, exop); + wait_for_exclusive_operation(fdmnt); + } else { + error("unable to add: %s in progress", exop); + close_file_or_dir(fdmnt, dirstream); + return 1; + } } for (i = optind; i < last_dev; i++){ @@ -163,8 +175,27 @@ static int _cmd_device_remove(const struct cmd_struct *cmd, int i, fdmnt, ret = 0; DIR *dirstream = NULL; char exop[BTRFS_SYSFS_EXOP_SIZE]; + bool enqueue = false; - clean_args_no_options(cmd, argc, argv); + + while (1) { + int c; + static const struct option long_options[] = { + { "enqueue", no_argument, NULL, 'q'}, + { NULL, 0, NULL, 0} + }; + + c = getopt_long(argc, argv, "q", long_options, NULL); + if (c < 0) + break; + switch (c) { + case 'q': + enqueue = true; + break; + default: + usage_unknown_option(cmd, argv); + } + } if (check_argc_min(argc - optind, 2)) return 1; @@ -176,9 +207,15 @@ static int _cmd_device_remove(const struct cmd_struct *cmd, return 1; if (get_exclusive_operation(fdmnt, exop) > 0 && strcmp(exop, "none")) { - error("unable to remove device: %s in progress", exop); - close_file_or_dir(fdmnt, dirstream); - return 1; + if (enqueue) { + printf("%s in progress. Waiting for %s to finish.\n", + exop, exop); + wait_for_exclusive_operation(fdmnt); + } else { + error("unable to remove device: %s in progress", exop); + close_file_or_dir(fdmnt, dirstream); + return 1; + } } for(i = optind; i < argc - 1; i++) { @@ -251,7 +288,8 @@ static int _cmd_device_remove(const struct cmd_struct *cmd, "the device.", \ "If 'missing' is specified for <device>, the first device that is", \ "described by the filesystem metadata, but not present at the mount", \ - "time will be removed. (only in degraded mode)" + "time will be removed. (only in degraded mode)", \ + "-q|--enqueue enqueue if an exclusive operation is running" static const char * const cmd_device_remove_usage[] = { "btrfs device remove <device>|<devid> [<device>|<devid>...] <path>", diff --git a/cmds/filesystem.c b/cmds/filesystem.c index c3efb405..a584b1d3 100644 --- a/cmds/filesystem.c +++ b/cmds/filesystem.c @@ -1080,8 +1080,19 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd, DIR *dirstream = NULL; struct stat st; char exop[BTRFS_SYSFS_EXOP_SIZE]; + bool enqueue = false; - clean_args_no_options_relaxed(cmd, argc, argv); + while(1) { + int c = getopt(argc - 2, argv, "q"); + if (c < 0) + break; + + switch(c) { + case 'q': + enqueue = true; + break; + } + } if (check_argc_exact(argc - optind, 2)) return 1; @@ -1112,9 +1123,15 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd, return 1; if (get_exclusive_operation(fd, exop) > 0 && strcmp(exop, "none")) { - error("unable to resize: %s in progress", exop); - close_file_or_dir(fd, dirstream); - return 1; + if (enqueue) { + printf("%s in progress. Waiting for %s to finish.\n", + exop, exop); + wait_for_exclusive_operation(fd); + } else { + error("unable to resize: %s in progress", exop); + close_file_or_dir(fd, dirstream); + return 1; + } } printf("Resize '%s' of '%s'\n", path, amount); diff --git a/common/sysfs.c b/common/sysfs.c index 91ed270c..0067d098 100644 --- a/common/sysfs.c +++ b/common/sysfs.c @@ -58,3 +58,29 @@ int get_exclusive_operation(int mp_fd, char *val) *s = '\0'; return strlen(val); } + +int sysfs_wait(int fd, int seconds) +{ + fd_set fds; + struct timeval tv; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + tv.tv_sec = seconds; + tv.tv_usec = 0; + + return select(fd+1, NULL, NULL, &fds, &tv); +} + +void wait_for_exclusive_operation(int dirfd) +{ + char exop[BTRFS_SYSFS_EXOP_SIZE]; + int fd; + + fd = sysfs_open(dirfd, "exclusive_operation"); + while ((sysfs_get_str_fd(fd, exop, BTRFS_SYSFS_EXOP_SIZE) > 0) && + strncmp(exop, "none", 4)) + sysfs_wait(fd, 1); + close(fd); +} diff --git a/common/utils.h b/common/utils.h index be8aab58..f141edb6 100644 --- a/common/utils.h +++ b/common/utils.h @@ -155,5 +155,6 @@ int btrfs_warn_multiple_profiles(int fd); #define BTRFS_SYSFS_EXOP_SIZE 16 int get_exclusive_operation(int fd, char *val); +void wait_for_exclusive_operation(int fd); #endif -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd 2020-07-27 22:08 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues ` (2 preceding siblings ...) 2020-07-27 22:08 ` [PATCH 4/4] btrfs-progs: Enqueue command if it can't be performed immediately Goldwyn Rodrigues @ 2020-07-28 8:38 ` Johannes Thumshirn 3 siblings, 0 replies; 12+ messages in thread From: Johannes Thumshirn @ 2020-07-28 8:38 UTC (permalink / raw) To: Goldwyn Rodrigues, linux-btrfs; +Cc: Goldwyn Rodrigues On 28/07/2020 00:08, Goldwyn Rodrigues wrote: > } > > + > static int group_profile_devs_min(u64 flag) Nit: stray whitespace ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 0/3] btrfs: Enumerate and export exclusive operations @ 2020-08-03 20:29 Goldwyn Rodrigues 2020-08-03 20:30 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 0 siblings, 1 reply; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-08-03 20:29 UTC (permalink / raw) To: linux-btrfs This patch series enumerates the exlcusive operation currently being perfomed by the current filesystem and exports it in the sys filesytem at /sys/fs/btrfs/<fsid>/exclusive_operation. This would enable our tools to specify precisely which operation is running on why starting an exclusive operation failed. The series also adds a sysfs_notify() to alert userspace when the state changes, so userspace can perform select() on it to get notified of the change. This would enable us to enqueue a command which will wait for current exclusive operation to complete before issuing the next exclusive operation. This has been done synchronously as opposed to a background process, or else error collection (if any) will become a nightmare. This third patch further expands the balance information such as the state and the current statistics. I am hoping that it could be used to move the logic of guessing/managing the right ioctls out of the kernel and into the tools. For backward compatibility, the tools continue working as before if the sys file is not present. Changes since v1: - Corrected call for btrfs_start_exop() in btrfs_ioctl_dev_replace() - Use fsid_str[] instead of fsid[] to save on uuid_parse() ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd 2020-08-03 20:29 [PATCH v2 0/3] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues @ 2020-08-03 20:30 ` Goldwyn Rodrigues 2020-08-03 20:30 ` [PATCH 2/4] btrfs-progs: add sysfs file reading functions Goldwyn Rodrigues 0 siblings, 1 reply; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-08-03 20:30 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Add a function get_fsid_fd() to use an open file fd to get the fsid of the mounted filesystem. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- common/utils.c | 30 ++++++++++++++++-------------- common/utils.h | 1 + 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/common/utils.c b/common/utils.c index 9742c2e1..dbe1e806 100644 --- a/common/utils.c +++ b/common/utils.c @@ -1097,32 +1097,34 @@ out: return ret; } +int get_fsid_fd(int fd, u8 *fsid) +{ + int ret; + struct btrfs_ioctl_fs_info_args args; + + ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args); + if (ret < 0) + return -errno; + + memcpy(fsid, args.fsid, BTRFS_FSID_SIZE); + return 0; +} + int get_fsid(const char *path, u8 *fsid, int silent) { int ret; int fd; - struct btrfs_ioctl_fs_info_args args; fd = open(path, O_RDONLY); if (fd < 0) { - ret = -errno; if (!silent) error("failed to open %s: %m", path); - goto out; - } - - ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args); - if (ret < 0) { - ret = -errno; - goto out; + return -errno; } - memcpy(fsid, args.fsid, BTRFS_FSID_SIZE); - ret = 0; + ret = get_fsid_fd(fd, fsid); + close(fd); -out: - if (fd != -1) - close(fd); return ret; } diff --git a/common/utils.h b/common/utils.h index 43e7f471..e34bb5a4 100644 --- a/common/utils.h +++ b/common/utils.h @@ -75,6 +75,7 @@ void close_file_or_dir(int fd, DIR *dirstream); int get_fs_info(const char *path, struct btrfs_ioctl_fs_info_args *fi_args, struct btrfs_ioctl_dev_info_args **di_ret); int get_fsid(const char *path, u8 *fsid, int silent); +int get_fsid_fd(int fd, u8 *fsid); int get_label(const char *btrfs_dev, char *label); int set_label(const char *btrfs_dev, const char *label); -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/4] btrfs-progs: add sysfs file reading functions 2020-08-03 20:30 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues @ 2020-08-03 20:30 ` Goldwyn Rodrigues 0 siblings, 0 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-08-03 20:30 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Functions to read and and open sysfs files. Given a fd, find the fsid associated with the mount and convert into the sysfs directory to look. Read the exclusive_operation file to find the current exclusive operation running. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- Makefile | 4 ++-- common/sysfs.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/utils.h | 3 +++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 common/sysfs.c diff --git a/Makefile b/Makefile index ee57d9f8..8a267c45 100644 --- a/Makefile +++ b/Makefile @@ -168,8 +168,8 @@ libbtrfs_objects = send-stream.o send-utils.o kernel-lib/rbtree.o btrfs-list.o \ kernel-shared/free-space-tree.o repair.o kernel-shared/inode-item.o \ kernel-shared/file-item.o \ kernel-lib/raid56.o kernel-lib/tables.o \ - common/device-scan.o common/path-utils.o \ - common/utils.o libbtrfsutil/subvolume.o libbtrfsutil/stubs.o \ + common/device-scan.o common/path-utils.o common/utils.o \ + common/sysfs.o libbtrfsutil/subvolume.o libbtrfsutil/stubs.o \ crypto/hash.o crypto/xxhash.o $(CRYPTO_OBJECTS) libbtrfs_headers = send-stream.h send-utils.h send.h kernel-lib/rbtree.h btrfs-list.h \ crypto/crc32c.h kernel-lib/list.h kerncompat.h \ diff --git a/common/sysfs.c b/common/sysfs.c new file mode 100644 index 00000000..9a18c753 --- /dev/null +++ b/common/sysfs.c @@ -0,0 +1,60 @@ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <unistd.h> +#include <sys/select.h> +#include <uuid/uuid.h> + +#include "common/utils.h" + +static char fsid_str[BTRFS_UUID_UNPARSED_SIZE] = {'\0'}; + +int sysfs_open(int fd, const char *filename) +{ + u8 fsid[BTRFS_UUID_SIZE]; + int ret; + char sysfs_file[128]; + + if (fsid_str[0] == '\0') { + ret = get_fsid_fd(fd, fsid); + if (ret < 0) + return ret; + uuid_unparse(fsid, fsid_str); + } + + snprintf(sysfs_file, 128, "/sys/fs/btrfs/%s/%s", fsid_str, filename); + return open(sysfs_file, O_RDONLY); +} + +int sysfs_get_str_fd(int fd, char *val, int size) +{ + lseek(fd, 0, SEEK_SET); + memset(val, '\0', size); + return read(fd, val, size); +} + +int get_exclusive_operation(int mp_fd, char *val) +{ + char *s; + int fd; + int n; + + fd = sysfs_open(mp_fd, "exclusive_operation"); + if (fd < 0) + return fd; + + n = sysfs_get_str_fd(fd, val, BTRFS_SYSFS_EXOP_SIZE); + close(fd); + + if (n < 0) + return n; + + s = strchr(val, '\n'); + if (!s) + return n; + + *s = '\0'; + return strlen(val); +} diff --git a/common/utils.h b/common/utils.h index e34bb5a4..be8aab58 100644 --- a/common/utils.h +++ b/common/utils.h @@ -153,4 +153,7 @@ void init_rand_seed(u64 seed); char *btrfs_test_for_multiple_profiles(int fd); int btrfs_warn_multiple_profiles(int fd); +#define BTRFS_SYSFS_EXOP_SIZE 16 +int get_exclusive_operation(int fd, char *val); + #endif -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 0/2] btrfs: Enumerate and export exclusive operations @ 2020-08-25 15:02 Goldwyn Rodrigues 2020-08-25 15:03 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 0 siblings, 1 reply; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-08-25 15:02 UTC (permalink / raw) To: linux-btrfs This patch series enumerates the exlcusive operation currently being perfomed by the current filesystem and exports it in the sys filesytem at /sys/fs/btrfs/<fsid>/exclusive_operation. This would enable our tools to specify precisely which operation is running on why starting an exclusive operation failed. The series also adds a sysfs_notify() to alert userspace when the state changes, so userspace can perform select() on it to get notified of the change. This would enable us to enqueue a command which will wait for current exclusive operation to complete before issuing the next exclusive operation. This has been done synchronously as opposed to a background process, or else error collection (if any) will become a nightmare. For backward compatibility, the tools continue working as before if the sys file is not present. Changes since v1: - Corrected call for btrfs_start_exop() in btrfs_ioctl_dev_replace() - Use fsid_str[] instead of fsid[] to save on uuid_parse() Changes since v2: - Dropped patch to add additional balance information - modified (simplified) progs patches accordingly ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd 2020-08-25 15:02 [PATCH v3 0/2] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues @ 2020-08-25 15:03 ` Goldwyn Rodrigues 2020-08-25 15:03 ` [PATCH 2/4] btrfs-progs: add sysfs file reading functions Goldwyn Rodrigues 0 siblings, 1 reply; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-08-25 15:03 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Add a function get_fsid_fd() to use an open file fd to get the fsid of the mounted filesystem. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- common/utils.c | 30 ++++++++++++++++-------------- common/utils.h | 1 + 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/common/utils.c b/common/utils.c index 9742c2e1..dbe1e806 100644 --- a/common/utils.c +++ b/common/utils.c @@ -1097,32 +1097,34 @@ out: return ret; } +int get_fsid_fd(int fd, u8 *fsid) +{ + int ret; + struct btrfs_ioctl_fs_info_args args; + + ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args); + if (ret < 0) + return -errno; + + memcpy(fsid, args.fsid, BTRFS_FSID_SIZE); + return 0; +} + int get_fsid(const char *path, u8 *fsid, int silent) { int ret; int fd; - struct btrfs_ioctl_fs_info_args args; fd = open(path, O_RDONLY); if (fd < 0) { - ret = -errno; if (!silent) error("failed to open %s: %m", path); - goto out; - } - - ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args); - if (ret < 0) { - ret = -errno; - goto out; + return -errno; } - memcpy(fsid, args.fsid, BTRFS_FSID_SIZE); - ret = 0; + ret = get_fsid_fd(fd, fsid); + close(fd); -out: - if (fd != -1) - close(fd); return ret; } diff --git a/common/utils.h b/common/utils.h index 43e7f471..e34bb5a4 100644 --- a/common/utils.h +++ b/common/utils.h @@ -75,6 +75,7 @@ void close_file_or_dir(int fd, DIR *dirstream); int get_fs_info(const char *path, struct btrfs_ioctl_fs_info_args *fi_args, struct btrfs_ioctl_dev_info_args **di_ret); int get_fsid(const char *path, u8 *fsid, int silent); +int get_fsid_fd(int fd, u8 *fsid); int get_label(const char *btrfs_dev, char *label); int set_label(const char *btrfs_dev, const char *label); -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/4] btrfs-progs: add sysfs file reading functions 2020-08-25 15:03 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues @ 2020-08-25 15:03 ` Goldwyn Rodrigues 0 siblings, 0 replies; 12+ messages in thread From: Goldwyn Rodrigues @ 2020-08-25 15:03 UTC (permalink / raw) To: linux-btrfs; +Cc: Goldwyn Rodrigues From: Goldwyn Rodrigues <rgoldwyn@suse.com> Functions to read and and open sysfs files. Given a fd, find the fsid associated with the mount and convert into the sysfs directory to look. Read the exclusive_operation file to find the current exclusive operation running. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- Makefile | 4 ++-- common/sysfs.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/utils.h | 3 +++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 common/sysfs.c diff --git a/Makefile b/Makefile index ee57d9f8..8a267c45 100644 --- a/Makefile +++ b/Makefile @@ -168,8 +168,8 @@ libbtrfs_objects = send-stream.o send-utils.o kernel-lib/rbtree.o btrfs-list.o \ kernel-shared/free-space-tree.o repair.o kernel-shared/inode-item.o \ kernel-shared/file-item.o \ kernel-lib/raid56.o kernel-lib/tables.o \ - common/device-scan.o common/path-utils.o \ - common/utils.o libbtrfsutil/subvolume.o libbtrfsutil/stubs.o \ + common/device-scan.o common/path-utils.o common/utils.o \ + common/sysfs.o libbtrfsutil/subvolume.o libbtrfsutil/stubs.o \ crypto/hash.o crypto/xxhash.o $(CRYPTO_OBJECTS) libbtrfs_headers = send-stream.h send-utils.h send.h kernel-lib/rbtree.h btrfs-list.h \ crypto/crc32c.h kernel-lib/list.h kerncompat.h \ diff --git a/common/sysfs.c b/common/sysfs.c new file mode 100644 index 00000000..b2c95cfb --- /dev/null +++ b/common/sysfs.c @@ -0,0 +1,52 @@ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <unistd.h> +#include <sys/select.h> +#include <uuid/uuid.h> + +#include "common/utils.h" + +static char fsid_str[BTRFS_UUID_UNPARSED_SIZE] = {'\0'}; + +int sysfs_open(int fd, const char *filename) +{ + u8 fsid[BTRFS_UUID_SIZE]; + int ret; + char sysfs_file[128]; + + if (fsid_str[0] == '\0') { + ret = get_fsid_fd(fd, fsid); + if (ret < 0) + return ret; + uuid_unparse(fsid, fsid_str); + } + + snprintf(sysfs_file, 128, "/sys/fs/btrfs/%s/%s", fsid_str, filename); + return open(sysfs_file, O_RDONLY); +} + +int sysfs_get_str_fd(int fd, char *val, int size) +{ + lseek(fd, 0, SEEK_SET); + memset(val, '\0', size); + return read(fd, val, size); +} + +int get_exclusive_operation(int mp_fd, char *val) +{ + int fd; + int n; + + fd = sysfs_open(mp_fd, "exclusive_operation"); + if (fd < 0) + return fd; + + n = sysfs_get_str_fd(fd, val, BTRFS_SYSFS_EXOP_SIZE); + close(fd); + + val[n - 1] = '\0'; + return n; +} diff --git a/common/utils.h b/common/utils.h index e34bb5a4..be8aab58 100644 --- a/common/utils.h +++ b/common/utils.h @@ -153,4 +153,7 @@ void init_rand_seed(u64 seed); char *btrfs_test_for_multiple_profiles(int fd); int btrfs_warn_multiple_profiles(int fd); +#define BTRFS_SYSFS_EXOP_SIZE 16 +int get_exclusive_operation(int fd, char *val); + #endif -- 2.26.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2020-08-25 15:04 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-07-27 22:04 [PATCH 0/3] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues 2020-07-27 22:04 ` [PATCH 1/3] btrfs: enumerate the type of exclusive operation in progress Goldwyn Rodrigues 2020-07-28 8:45 ` Johannes Thumshirn 2020-07-27 22:04 ` [PATCH 2/3] btrfs: export currently executing exclusive operation via sysfs Goldwyn Rodrigues 2020-07-27 22:04 ` [PATCH 3/3] btrfs: add more information for balance Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 2/4] btrfs-progs: add sysfs file reading functions Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 3/4] btrfs-progs: Check for exclusive operation before issuing ioctl Goldwyn Rodrigues 2020-07-27 22:08 ` [PATCH 4/4] btrfs-progs: Enqueue command if it can't be performed immediately Goldwyn Rodrigues 2020-07-28 8:38 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Johannes Thumshirn 2020-08-03 20:29 [PATCH v2 0/3] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues 2020-08-03 20:30 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 2020-08-03 20:30 ` [PATCH 2/4] btrfs-progs: add sysfs file reading functions Goldwyn Rodrigues 2020-08-25 15:02 [PATCH v3 0/2] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues 2020-08-25 15:03 ` [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Goldwyn Rodrigues 2020-08-25 15:03 ` [PATCH 2/4] btrfs-progs: add sysfs file reading functions Goldwyn Rodrigues
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).