All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] support all option for resize command
@ 2022-08-15 12:36 Sidong Yang
  2022-08-15 12:36 ` [RFC PATCH 1/2] btrfs-progs: fi resize: refactor function check_resize_args() Sidong Yang
  2022-08-15 12:36 ` [RFC PATCH 2/2] btrfs-progs: fi resize: support all option for resize Sidong Yang
  0 siblings, 2 replies; 3+ messages in thread
From: Sidong Yang @ 2022-08-15 12:36 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Sidong Yang

Hi,

This patch series is for supporting resize command in btrfs-progs.
It resolves btrfs-progs github issue #471

This is prototype for work. It also needs to add manual for option.
I want to know that it's good way to implement the option.

If there is better way, I'd appreciate it.

Sidong Yang (2):
  btrfs-progs: fi resize: refactor function check_resize_args()
  btrfs-progs: fi resize: support all option for resize

 cmds/filesystem.c | 218 +++++++++++++++++++++++++++-------------------
 1 file changed, 127 insertions(+), 91 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [RFC PATCH 1/2] btrfs-progs: fi resize: refactor function check_resize_args()
  2022-08-15 12:36 [RFC PATCH 0/2] support all option for resize command Sidong Yang
@ 2022-08-15 12:36 ` Sidong Yang
  2022-08-15 12:36 ` [RFC PATCH 2/2] btrfs-progs: fi resize: support all option for resize Sidong Yang
  1 sibling, 0 replies; 3+ messages in thread
From: Sidong Yang @ 2022-08-15 12:36 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Sidong Yang

This patch removes check_resize_args() and makes resize_with_args() for
supporting "all" option for resize function. The old code checks user
arguments and execute resizing with ioctl call. For new option, we
need to check user arguments and make new arguments if it needs multiple
ioctl calls. So it needs a function that checks argument and resize at
once. In a new function resize_with_args(), we will need to check each
sizestr for each device in "all" option. This patch also make
check_resize_args_sizestr() for checking sizestr.

Signed-off-by: Sidong Yang <realwakka@gmail.com>
---
 cmds/filesystem.c | 177 ++++++++++++++++++++++++----------------------
 1 file changed, 94 insertions(+), 83 deletions(-)

diff --git a/cmds/filesystem.c b/cmds/filesystem.c
index 7cd08fcd..ea1b0c84 100644
--- a/cmds/filesystem.c
+++ b/cmds/filesystem.c
@@ -1087,17 +1087,77 @@ static const char * const cmd_filesystem_resize_usage[] = {
 	NULL
 };
 
-static int check_resize_args(const char *amount, const char *path) {
+static int check_resize_args_sizestr(const char *sizestr, u64 devid, int dev_idx,
+									 struct btrfs_ioctl_dev_info_args *di_args,
+									 struct btrfs_ioctl_fs_info_args *fi_args) {
+	const char *res_str;
+	int ret;
+
+	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");
+		ret = 0;
+	} else {
+		int mod = 0;
+		u64 diff = 0, old_size = 0, new_size = 0;
+		if (sizestr[0] == '-') {
+			mod = -1;
+			sizestr++;
+		} else if (sizestr[0] == '+') {
+			mod = 1;
+			sizestr++;
+		}
+		diff = parse_size_from_string(sizestr);
+		if (!diff) {
+			error("failed to parse size %s", sizestr);
+			ret = 1;
+			goto out;
+		}
+		old_size = di_args[dev_idx].total_bytes;
+
+		/* For target sizes without +/- sign prefix (e.g. 1:150g) */
+		if (mod == 0) {
+			new_size = diff;
+		} else if (mod < 0) {
+			if (diff > old_size) {
+				error("current size is %s which is smaller than %s",
+				      pretty_size_mode(old_size, UNITS_DEFAULT),
+				      pretty_size_mode(diff, UNITS_DEFAULT));
+				ret = 1;
+				goto out;
+			}
+			new_size = old_size - diff;
+		} else if (mod > 0) {
+			if (diff > ULLONG_MAX - old_size) {
+				error("increasing %s is out of range",
+				      pretty_size_mode(diff, UNITS_DEFAULT));
+				ret = 1;
+				goto out;
+			}
+			new_size = old_size + diff;
+		}
+		new_size = round_down(new_size, fi_args->sectorsize);
+		res_str = pretty_size_mode(new_size, UNITS_DEFAULT);
+	}
+
+	printf("Resize device id %lld (%s) from %s to %s\n", devid,
+		di_args[dev_idx].path,
+		pretty_size_mode(di_args[dev_idx].total_bytes, UNITS_DEFAULT),
+		res_str);
+out:
+	return ret;
+}
+
+static int resize_with_args(const char *amount, const char *path, int fd) {
 	struct btrfs_ioctl_fs_info_args fi_args;
 	struct btrfs_ioctl_dev_info_args *di_args = NULL;
-	int ret, i, dev_idx = -1;
+	int ret, i, e, dev_idx = -1;
 	u64 devid = 1;
-	const char *res_str = NULL;
 	char *devstr = NULL, *sizestr = NULL;
-	u64 new_size = 0, old_size = 0, diff = 0;
-	int mod = 0;
 	char amount_dup[BTRFS_VOL_NAME_MAX];
-
+	struct btrfs_ioctl_vol_args	args;
 	ret = get_fs_info(path, &fi_args, &di_args);
 
 	if (ret) {
@@ -1149,58 +1209,37 @@ static int check_resize_args(const char *amount, const char *path) {
 		goto out;
 	}
 
-	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;
-			sizestr++;
-		} else if (sizestr[0] == '+') {
-			mod = 1;
-			sizestr++;
-		}
-		diff = parse_size_from_string(sizestr);
-		if (!diff) {
-			error("failed to parse size %s", sizestr);
-			ret = 1;
-			goto out;
+	ret = check_resize_args_sizestr(sizestr, devid, dev_idx, di_args, &fi_args);
+	if (ret)
+		return 1;
+
+	memset(&args, 0, sizeof(args));
+	strncpy_null(args.name, amount);
+	ret = ioctl(fd, BTRFS_IOC_RESIZE, &args);
+	e = errno;
+	if(ret < 0){
+		switch (e) {
+		case EFBIG:
+			error("unable to resize '%s': no enough free space",
+				  path);
+			break;
+		default:
+			error("unable to resize '%s': %m", path);
+			break;
 		}
-		old_size = di_args[dev_idx].total_bytes;
+		return 1;
+	} else if (ret > 0) {
+		const char *err_str = btrfs_err_str(ret);
 
-		/* For target sizes without +/- sign prefix (e.g. 1:150g) */
-		if (mod == 0) {
-			new_size = diff;
-		} else if (mod < 0) {
-			if (diff > old_size) {
-				error("current size is %s which is smaller than %s",
-				      pretty_size_mode(old_size, UNITS_DEFAULT),
-				      pretty_size_mode(diff, UNITS_DEFAULT));
-				ret = 1;
-				goto out;
-			}
-			new_size = old_size - diff;
-		} else if (mod > 0) {
-			if (diff > ULLONG_MAX - old_size) {
-				error("increasing %s is out of range",
-				      pretty_size_mode(diff, UNITS_DEFAULT));
-				ret = 1;
-				goto out;
-			}
-			new_size = old_size + diff;
+		if (err_str) {
+			error("resizing of '%s' failed: %s", path, err_str);
+		} else {
+			error("resizing of '%s' failed: unknown error %d",
+				  path, ret);
 		}
-		new_size = round_down(new_size, fi_args.sectorsize);
-		res_str = pretty_size_mode(new_size, UNITS_DEFAULT);
+		return 1;
 	}
 
-	printf("Resize device id %lld (%s) from %s to %s\n", devid,
-		di_args[dev_idx].path,
-		pretty_size_mode(di_args[dev_idx].total_bytes, UNITS_DEFAULT),
-		res_str);
-
 out:
 	free(di_args);
 	return 0;
@@ -1209,8 +1248,7 @@ out:
 static int cmd_filesystem_resize(const struct cmd_struct *cmd,
 				 int argc, char **argv)
 {
-	struct btrfs_ioctl_vol_args	args;
-	int	fd, res, len, e;
+	int	fd, len;
 	char	*amount, *path;
 	DIR	*dirstream = NULL;
 	int ret;
@@ -1277,39 +1315,12 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd,
 		}
 	}
 
-	ret = check_resize_args(amount, path);
+	ret = resize_with_args(amount, path, fd);
 	if (ret != 0) {
 		close_file_or_dir(fd, dirstream);
 		return 1;
 	}
-
-	memset(&args, 0, sizeof(args));
-	strncpy_null(args.name, amount);
-	res = ioctl(fd, BTRFS_IOC_RESIZE, &args);
-	e = errno;
 	close_file_or_dir(fd, dirstream);
-	if( res < 0 ){
-		switch (e) {
-		case EFBIG:
-			error("unable to resize '%s': no enough free space",
-				path);
-			break;
-		default:
-			error("unable to resize '%s': %m", path);
-			break;
-		}
-		return 1;
-	} else if (res > 0) {
-		const char *err_str = btrfs_err_str(res);
-
-		if (err_str) {
-			error("resizing of '%s' failed: %s", path, err_str);
-		} else {
-			error("resizing of '%s' failed: unknown error %d",
-				path, res);
-		}
-		return 1;
-	}
 	return 0;
 }
 static DEFINE_SIMPLE_COMMAND(filesystem_resize, "resize");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC PATCH 2/2] btrfs-progs: fi resize: support all option for resize
  2022-08-15 12:36 [RFC PATCH 0/2] support all option for resize command Sidong Yang
  2022-08-15 12:36 ` [RFC PATCH 1/2] btrfs-progs: fi resize: refactor function check_resize_args() Sidong Yang
@ 2022-08-15 12:36 ` Sidong Yang
  1 sibling, 0 replies; 3+ messages in thread
From: Sidong Yang @ 2022-08-15 12:36 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Sidong Yang

This patch make resize command support "all" option. Also, it resolves
github issue #471. If user sets device as "all", it iterates all devices
with resizing for each device. For that, this patch make a function
do_resize_with_args() for avoiding duplicated code that call ioctl() and
handling an error.

Issue: #471

Signed-off-by: Sidong Yang <realwakka@gmail.com>
---
 cmds/filesystem.c | 91 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 58 insertions(+), 33 deletions(-)

diff --git a/cmds/filesystem.c b/cmds/filesystem.c
index ea1b0c84..9ce84f8f 100644
--- a/cmds/filesystem.c
+++ b/cmds/filesystem.c
@@ -1150,14 +1150,47 @@ out:
 	return ret;
 }
 
+static int do_resize_with_args(int fd, const char *amount, const char *path) {
+	int ret, e;
+	struct btrfs_ioctl_vol_args	args;
+
+	memset(&args, 0, sizeof(args));
+	strncpy_null(args.name, amount);
+	ret = ioctl(fd, BTRFS_IOC_RESIZE, &args);
+	e = errno;
+	if(ret < 0){
+		switch (e) {
+		case EFBIG:
+			error("unable to resize '%s': no enough free space",
+				  path);
+			break;
+		default:
+			error("unable to resize '%s': %m", path);
+			break;
+		}
+		return 1;
+	} else if (ret > 0) {
+		const char *err_str = btrfs_err_str(ret);
+
+		if (err_str) {
+			error("resizing of '%s' failed: %s", path, err_str);
+		} else {
+			error("resizing of '%s' failed: unknown error %d",
+				  path, ret);
+		}
+		return 1;
+	}
+
+	return 0;
+}
+
 static int resize_with_args(const char *amount, const char *path, int fd) {
 	struct btrfs_ioctl_fs_info_args fi_args;
 	struct btrfs_ioctl_dev_info_args *di_args = NULL;
-	int ret, i, e, dev_idx = -1;
+	int ret, i, dev_idx = -1;
 	u64 devid = 1;
 	char *devstr = NULL, *sizestr = NULL;
 	char amount_dup[BTRFS_VOL_NAME_MAX];
-	struct btrfs_ioctl_vol_args	args;
 	ret = get_fs_info(path, &fi_args, &di_args);
 
 	if (ret) {
@@ -1185,13 +1218,29 @@ static int resize_with_args(const char *amount, const char *path, int fd) {
 		*devstr = 0;
 		devstr = amount_dup;
 
-		errno = 0;
-		devid = strtoull(devstr, NULL, 10);
+		if (strncmp(devstr, "all", 3) == 0) {
+			for(i = 0; i < fi_args.num_devices; i++) {
+				char amount_tmp[BTRFS_VOL_NAME_MAX];
+				devid = di_args[i].devid;
+				ret = check_resize_args_sizestr(sizestr, devid, i, di_args, &fi_args);
+				if (ret)
+					return 1;
 
-		if (errno) {
-			error("failed to parse devid %s: %m", devstr);
-			ret = 1;
-			goto out;
+				snprintf(amount_tmp, BTRFS_VOL_NAME_MAX, "%llu:%s", devid, sizestr);
+				if (do_resize_with_args(fd, amount_tmp, path))
+					return 1;
+			}
+
+			return 0;
+		} else {
+			errno = 0;
+			devid = strtoull(devstr, NULL, 10);
+
+			if (errno) {
+				error("failed to parse devid %s: %m", devstr);
+				ret = 1;
+				goto out;
+			}
 		}
 	}
 
@@ -1213,32 +1262,8 @@ static int resize_with_args(const char *amount, const char *path, int fd) {
 	if (ret)
 		return 1;
 
-	memset(&args, 0, sizeof(args));
-	strncpy_null(args.name, amount);
-	ret = ioctl(fd, BTRFS_IOC_RESIZE, &args);
-	e = errno;
-	if(ret < 0){
-		switch (e) {
-		case EFBIG:
-			error("unable to resize '%s': no enough free space",
-				  path);
-			break;
-		default:
-			error("unable to resize '%s': %m", path);
-			break;
-		}
-		return 1;
-	} else if (ret > 0) {
-		const char *err_str = btrfs_err_str(ret);
-
-		if (err_str) {
-			error("resizing of '%s' failed: %s", path, err_str);
-		} else {
-			error("resizing of '%s' failed: unknown error %d",
-				  path, ret);
-		}
+	if (do_resize_with_args(fd, amount, path))
 		return 1;
-	}
 
 out:
 	free(di_args);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-08-15 12:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-15 12:36 [RFC PATCH 0/2] support all option for resize command Sidong Yang
2022-08-15 12:36 ` [RFC PATCH 1/2] btrfs-progs: fi resize: refactor function check_resize_args() Sidong Yang
2022-08-15 12:36 ` [RFC PATCH 2/2] btrfs-progs: fi resize: support all option for resize Sidong Yang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.