From patchwork Tue Aug 25 15:03:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Goldwyn Rodrigues X-Patchwork-Id: 11735873 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 134DF16B1 for ; Tue, 25 Aug 2020 15:04:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0495D2076C for ; Tue, 25 Aug 2020 15:04:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726753AbgHYPEC (ORCPT ); Tue, 25 Aug 2020 11:04:02 -0400 Received: from mx2.suse.de ([195.135.220.15]:52810 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726570AbgHYPDx (ORCPT ); Tue, 25 Aug 2020 11:03:53 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id B9F41AEAA; Tue, 25 Aug 2020 15:04:22 +0000 (UTC) From: Goldwyn Rodrigues To: linux-btrfs@vger.kernel.org Cc: Goldwyn Rodrigues Subject: [PATCH 1/4] btrfs-progs: get_fsid_fd() for getting fsid using fd Date: Tue, 25 Aug 2020 10:03:35 -0500 Message-Id: <20200825150338.32610-1-rgoldwyn@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200825150233.30294-1-rgoldwyn@suse.de> References: <20200825150233.30294-1-rgoldwyn@suse.de> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org From: Goldwyn Rodrigues 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 --- 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); From patchwork Tue Aug 25 15:03:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Goldwyn Rodrigues X-Patchwork-Id: 11735877 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B75ED138A for ; Tue, 25 Aug 2020 15:04:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9FAFA2076C for ; Tue, 25 Aug 2020 15:04:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726826AbgHYPEH (ORCPT ); Tue, 25 Aug 2020 11:04:07 -0400 Received: from mx2.suse.de ([195.135.220.15]:52824 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726790AbgHYPD5 (ORCPT ); Tue, 25 Aug 2020 11:03:57 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id E086EADDB; Tue, 25 Aug 2020 15:04:25 +0000 (UTC) From: Goldwyn Rodrigues To: linux-btrfs@vger.kernel.org Cc: Goldwyn Rodrigues Subject: [PATCH 2/4] btrfs-progs: add sysfs file reading functions Date: Tue, 25 Aug 2020 10:03:36 -0500 Message-Id: <20200825150338.32610-2-rgoldwyn@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200825150338.32610-1-rgoldwyn@suse.de> References: <20200825150233.30294-1-rgoldwyn@suse.de> <20200825150338.32610-1-rgoldwyn@suse.de> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org From: Goldwyn Rodrigues 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 --- 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 +#include +#include + +#include +#include +#include + +#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 From patchwork Tue Aug 25 15:03:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Goldwyn Rodrigues X-Patchwork-Id: 11735875 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6FF4116B1 for ; Tue, 25 Aug 2020 15:04:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5871E2076C for ; Tue, 25 Aug 2020 15:04:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726820AbgHYPEE (ORCPT ); Tue, 25 Aug 2020 11:04:04 -0400 Received: from mx2.suse.de ([195.135.220.15]:52844 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726798AbgHYPD7 (ORCPT ); Tue, 25 Aug 2020 11:03:59 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 209C3AEAA; Tue, 25 Aug 2020 15:04:28 +0000 (UTC) From: Goldwyn Rodrigues To: linux-btrfs@vger.kernel.org Cc: Goldwyn Rodrigues Subject: [PATCH 3/4] btrfs-progs: Check for exclusive operation before issuing ioctl Date: Tue, 25 Aug 2020 10:03:37 -0500 Message-Id: <20200825150338.32610-3-rgoldwyn@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200825150338.32610-1-rgoldwyn@suse.de> References: <20200825150233.30294-1-rgoldwyn@suse.de> <20200825150338.32610-1-rgoldwyn@suse.de> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org From: Goldwyn Rodrigues 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 --- 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); From patchwork Tue Aug 25 15:03:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Goldwyn Rodrigues X-Patchwork-Id: 11735879 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D903B16B1 for ; Tue, 25 Aug 2020 15:04:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CB0BB2076C for ; Tue, 25 Aug 2020 15:04:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726856AbgHYPEJ (ORCPT ); Tue, 25 Aug 2020 11:04:09 -0400 Received: from mx2.suse.de ([195.135.220.15]:52890 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726799AbgHYPEB (ORCPT ); Tue, 25 Aug 2020 11:04:01 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 8A334AECA; Tue, 25 Aug 2020 15:04:30 +0000 (UTC) From: Goldwyn Rodrigues To: linux-btrfs@vger.kernel.org Cc: Goldwyn Rodrigues Subject: [PATCH 4/4] btrfs-progs: Enqueue command if it can't be performed immediately Date: Tue, 25 Aug 2020 10:03:38 -0500 Message-Id: <20200825150338.32610-4-rgoldwyn@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200825150338.32610-1-rgoldwyn@suse.de> References: <20200825150233.30294-1-rgoldwyn@suse.de> <20200825150338.32610-1-rgoldwyn@suse.de> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org From: Goldwyn Rodrigues 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 --- 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 , 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 | [|...] ", 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 b2c95cfb..3b6df52e 100644 --- a/common/sysfs.c +++ b/common/sysfs.c @@ -50,3 +50,29 @@ int get_exclusive_operation(int mp_fd, char *val) val[n - 1] = '\0'; return n; } + +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