@@ -1151,6 +1151,10 @@ static int check_resize_args(const char *amount, const char *path) {
if (strcmp(sizestr, "max") == 0) {
res_str = "max";
+ } else if (strcmp(sizestr, "cancel") == 0) {
+ /* Different format, print and exit */
+ printf("Request to cancel resize\n");
+ goto out;
} else {
if (sizestr[0] == '-') {
mod = -1;
@@ -1211,6 +1215,7 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd,
DIR *dirstream = NULL;
int ret;
bool enqueue = false;
+ bool cancel = false;
/*
* Simplified option parser, accept only long options, the resize value
@@ -1242,6 +1247,8 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd,
return 1;
}
+ cancel = (strcmp("cancel", amount) == 0);
+
fd = btrfs_open_dir(path, &dirstream, 1);
if (fd < 0) {
/* The path is a directory */
@@ -1254,12 +1261,20 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd,
return 1;
}
- ret = check_running_fs_exclop(fd, BTRFS_EXCLOP_RESIZE, enqueue);
- if (ret != 0) {
- if (ret < 0)
- error("unable to check status of exclusive operation: %m");
- close_file_or_dir(fd, dirstream);
- return 1;
+ /*
+ * Check if there's an exclusive operation running if possible, otherwise
+ * let kernel handle it. Cancel request is completely handled in kernel
+ * so make it pass.
+ */
+ if (!cancel) {
+ ret = check_running_fs_exclop(fd, BTRFS_EXCLOP_RESIZE, enqueue);
+ if (ret != 0) {
+ if (ret < 0)
+ error(
+ "unable to check status of exclusive operation: %m");
+ close_file_or_dir(fd, dirstream);
+ return 1;
+ }
}
ret = check_resize_args(amount, path);
Recognize special resize amount 'cancel' for resize operation. This will request kernel to stop running any resize operation (most likely shrinking resize). This needs support in kernel, otherwise this will fail due to another exclusive operation running (though could be the same one). The command returns after kernel finishes any work that got interrupted, but this should not take long in kernels 5.10+ that allow interruptible relocation. The waiting inside kernel is interruptible so this command (and the waiting stage) can be interrupted. The resize operation could relocate block groups but the nominal filesystem size will be restored when resize won't finish. It's recommended to review the filesystem state. Note: in kernels 5.10+ sending a fatal signal (TERM, KILL, Ctrl-C) to the process running the resize will cancel it too. Example: $ btrfs fi resize -10G /mnt ... $ btrfs fi resize cancel /mnt Signed-off-by: David Sterba <dsterba@suse.com> --- cmds/filesystem.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)