From: Goldwyn Rodrigues <rgoldwyn@suse.de>
To: linux-btrfs@vger.kernel.org
Cc: Goldwyn Rodrigues <rgoldwyn@suse.com>
Subject: [PATCH 4/4] btrfs-progs: Enqueue command if it can't be performed immediately
Date: Tue, 25 Aug 2020 10:03:38 -0500 [thread overview]
Message-ID: <20200825150338.32610-4-rgoldwyn@suse.de> (raw)
In-Reply-To: <20200825150338.32610-1-rgoldwyn@suse.de>
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 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
--
2.26.2
next prev parent reply other threads:[~2020-08-25 15:04 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-25 15:02 [PATCH v3 0/2] btrfs: Enumerate and export exclusive operations Goldwyn Rodrigues
2020-08-25 15:02 ` [PATCH 1/2] btrfs: enumerate the type of exclusive operation in progress Goldwyn Rodrigues
2020-09-02 13:42 ` David Sterba
2020-08-25 15:02 ` [PATCH 2/2] btrfs: export currently executing exclusive operation via sysfs 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
2020-08-25 15:03 ` [PATCH 3/4] btrfs-progs: Check for exclusive operation before issuing ioctl Goldwyn Rodrigues
2020-08-25 15:03 ` Goldwyn Rodrigues [this message]
2020-09-02 14:11 ` [PATCH 4/4] btrfs-progs: Enqueue command if it can't be performed immediately David Sterba
2020-09-02 20:45 ` Goldwyn Rodrigues
2020-09-02 20:11 ` [PATCH v3 0/2] btrfs: Enumerate and export exclusive operations David Sterba
-- strict thread matches above, loose matches on Subject: below --
2020-08-03 20:29 [PATCH v2 0/3] " 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 4/4] btrfs-progs: Enqueue command if it can't be performed immediately Goldwyn Rodrigues
2020-07-27 22:04 [PATCH 0/3] btrfs: Enumerate and export exclusive operations 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 4/4] btrfs-progs: Enqueue command if it can't be performed immediately Goldwyn Rodrigues
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200825150338.32610-4-rgoldwyn@suse.de \
--to=rgoldwyn@suse.de \
--cc=linux-btrfs@vger.kernel.org \
--cc=rgoldwyn@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).