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,
openSUSE Build Service is sponsored by