File 0004-btrfs-progs-check-for-exclusive-operation-before-iss.patch of Package btrfsprogs.24931
From 08065c0f019a25c948bfc0388e5b3f23d311ab21 Mon Sep 17 00:00:00 2001
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
Date: Tue, 25 Aug 2020 10:03:37 -0500
Subject: [PATCH] btrfs-progs: check for exclusive operation before issuing another
If the exclusive operation is available in sysfs file, check if there's
one already running. The check is done for:
- device add, remove, replace
- balance
- filesystem resize
All commands will validate arguments and check before the ioctl or
before any potentially irreversible operations (like clearing device
before replacing).
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
---
cmds-balance.c | 10 ++++++++++
cmds-device.c | 20 ++++++++++++++++++++
cmds-filesystem.c | 10 ++++++++++
cmds-replace.c | 12 ++++++++++++
4 files changed, 52 insertions(+)
--- a/cmds-balance.c
+++ b/cmds-balance.c
@@ -432,6 +432,7 @@
int fd;
int ret;
DIR *dirstream = NULL;
+ int exclop;
fd = btrfs_open_dir(path, &dirstream, 1);
if (fd < 0)
@@ -455,6 +456,15 @@
printf("\nStarting balance without any filters.\n");
}
+ exclop = get_fs_exclop(fd);
+ if (exclop > 0 ) {
+ error(
+ "unable to start balance, another exclusive operation '%s' in progress",
+ get_fs_exclop_name(exclop));
+ close_file_or_dir(fd, dirstream);
+ return 1;
+ }
+
ret = ioctl(fd, BTRFS_IOC_BALANCE_V2, args);
if (ret < 0) {
/*
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -56,6 +56,7 @@
int discard = 1;
int force = 0;
int last_dev;
+ int exclop;
optind = 0;
while (1) {
@@ -91,6 +92,15 @@
if (fdmnt < 0)
return 1;
+ exclop = get_fs_exclop(fdmnt);
+ if (exclop > 0) {
+ error(
+ "unable to start device add, another exclusive operation '%s' in progress",
+ get_fs_exclop_name(exclop));
+ 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;
@@ -148,6 +158,7 @@
char *mntpnt;
int i, fdmnt, ret = 0;
DIR *dirstream = NULL;
+ int exclop;
clean_args_no_options(argc, argv, usagestr);
@@ -160,6 +171,15 @@
if (fdmnt < 0)
return 1;
+ exclop = get_fs_exclop(fdmnt);
+ if (exclop > 0 ) {
+ error(
+ "unable to start device remove, another exclusive operation '%s' in progress",
+ get_fs_exclop_name(exclop));
+ 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};
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -1090,6 +1090,7 @@
char *amount, *path;
DIR *dirstream = NULL;
struct stat st;
+ int exclop;
clean_args_no_options_relaxed(argc, argv);
@@ -1121,6 +1122,15 @@
if (fd < 0)
return 1;
+ exclop = get_fs_exclop(fd);
+ if (exclop > 0) {
+ error(
+"unable to start filesystem resize, nother exclusive operation '%s' in progress",
+ get_fs_exclop_name(exclop));
+ 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);
--- a/cmds-replace.c
+++ b/cmds-replace.c
@@ -133,6 +133,7 @@
DIR *dirstream = NULL;
u64 srcdev_size;
u64 dstdev_size;
+ int exclop;
optind = 0;
while ((c = getopt(argc, argv, "Brf")) != -1) {
@@ -255,6 +256,17 @@
error("unable to open %s: %m", dstdev);
goto leave_with_error;
}
+
+ /* Check status before any potentially destructive operation */
+ exclop = get_fs_exclop(fdmnt);
+ if (exclop > 0) {
+ error(
+ "unable to start device replace, another exclusive operation '%s' in progress",
+ get_fs_exclop_name(exclop));
+ close_file_or_dir(fdmnt, dirstream);
+ goto leave_with_error;
+ }
+
strncpy((char *)start_args.start.tgtdev_name, dstdev,
BTRFS_DEVICE_PATH_NAME_MAX);
ret = btrfs_prepare_device(fddstdev, dstdev, &dstdev_block_count, 0,