All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marcos Paulo de Souza <marcos@mpdesouza.com>
To: dsterba@suse.com, linux-btrfs@vger.kernel.org, wqu@suse.com
Cc: Marcos Paulo de Souza <mpdesouza@suse.com>
Subject: [PATCHv3 2/3] btrfs-progs: replace: New argument to resize the fs after replace
Date: Wed, 15 Apr 2020 21:46:41 -0300	[thread overview]
Message-ID: <20200416004642.9941-3-marcos@mpdesouza.com> (raw)
In-Reply-To: <20200416004642.9941-1-marcos@mpdesouza.com>

From: Marcos Paulo de Souza <mpdesouza@suse.com>

Add new --autoresize long opt to resize the fs automatically after
replace. The code now checks if the srcdev is a path, and translates it
to a devid, making it being consumed later on if auto resize is
specified.

By using the --autoresize flag on replace makes btrfs issue a resize ioctl after
the replace finishes. This argument is a shortcut for

btrfs replace start -f 3 /dev/sdf BTRFS/
btrfs fi resize 3:max BTRFS/

Fixes: #21

Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
---
 Documentation/btrfs-replace.asciidoc |   5 +-
 cmds/replace.c                       | 105 +++++++++++++++++----------
 2 files changed, 72 insertions(+), 38 deletions(-)

diff --git a/Documentation/btrfs-replace.asciidoc b/Documentation/btrfs-replace.asciidoc
index b73bf1b3..f6eb6d20 100644
--- a/Documentation/btrfs-replace.asciidoc
+++ b/Documentation/btrfs-replace.asciidoc
@@ -18,7 +18,7 @@ SUBCOMMAND
 *cancel* <mount_point>::
 Cancel a running device replace operation.
 
-*start* [-Bfr] <srcdev>|<devid> <targetdev> <path>::
+*start* [options] <srcdev>|<devid> <targetdev> <path>::
 Replace device of a btrfs filesystem.
 +
 On a live filesystem, duplicate the data to the target device which
@@ -53,6 +53,9 @@ never allowed to be used as the <targetdev>.
 +
 -B::::
 no background replace.
+--autoresize::::
+automatically resizes the filesystem to it's max size if the <targetdev> is
+bigger than <srcdev>.
 
 *status* [-1] <mount_point>::
 Print status and progress information of a running device replace operation.
diff --git a/cmds/replace.c b/cmds/replace.c
index 2321aa15..48017c04 100644
--- a/cmds/replace.c
+++ b/cmds/replace.c
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <getopt.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <errno.h>
@@ -91,7 +92,7 @@ static int dev_replace_handle_sigint(int fd)
 }
 
 static const char *const cmd_replace_start_usage[] = {
-	"btrfs replace start [-Bfr] <srcdev>|<devid> <targetdev> <mount_point>",
+	"btrfs replace start [options] <srcdev>|<devid> <targetdev> <mount_point>",
 	"Replace device of a btrfs filesystem.",
 	"On a live filesystem, duplicate the data to the target device which",
 	"is currently stored on the source device. If the source device is not",
@@ -104,15 +105,18 @@ static const char *const cmd_replace_start_usage[] = {
 	"from the system, you have to use the <devid> parameter format.",
 	"The <targetdev> needs to be same size or larger than the <srcdev>.",
 	"",
-	"-r     only read from <srcdev> if no other zero-defect mirror exists",
-	"       (enable this if your drive has lots of read errors, the access",
-	"       would be very slow)",
-	"-f     force using and overwriting <targetdev> even if it looks like",
-	"       containing a valid btrfs filesystem. A valid filesystem is",
-	"       assumed if a btrfs superblock is found which contains a",
-	"       correct checksum. Devices which are currently mounted are",
-	"       never allowed to be used as the <targetdev>",
-	"-B     do not background",
+	"Options:",
+	"--autoresize  automatically resizes the filesystem to it's max size if the",
+	"              <targetdev> is bigger than <srcdev>",
+	"-r            only read from <srcdev> if no other zero-defect mirror exists",
+	"              (enable this if your drive has lots of read errors, the access",
+	"              would be very slow)",
+	"-f            force using and overwriting <targetdev> even if it looks like",
+	"              containing a valid btrfs filesystem. A valid filesystem is",
+	"              assumed if a btrfs superblock is found which contains a",
+	"              correct checksum. Devices which are currently mounted are",
+	"              never allowed to be used as the <targetdev>",
+	"-B            do not background",
 	NULL
 };
 
@@ -121,6 +125,8 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
 {
 	struct btrfs_ioctl_dev_replace_args start_args = {0};
 	struct btrfs_ioctl_dev_replace_args status_args = {0};
+	struct btrfs_ioctl_fs_info_args fi_args;
+	struct btrfs_ioctl_dev_info_args *di_args = NULL;
 	int ret;
 	int i;
 	int c;
@@ -129,6 +135,7 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
 	char *path;
 	char *srcdev;
 	char *dstdev = NULL;
+	bool auto_resize = false;
 	int avoid_reading_from_srcdev = 0;
 	int force_using_targetdev = 0;
 	u64 dstdev_block_count;
@@ -137,8 +144,13 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
 	u64 srcdev_size;
 	u64 dstdev_size;
 
+	enum { GETOPT_VAL_AUTORESIZE = 257 };
+	static struct option long_opts[] = {
+		{"autoresize", no_argument, NULL, GETOPT_VAL_AUTORESIZE}
+	};
+
 	optind = 0;
-	while ((c = getopt(argc, argv, "Brf")) != -1) {
+	while ((c = getopt_long(argc, argv, "Brf", long_opts, NULL)) != -1) {
 		switch (c) {
 		case 'B':
 			do_not_background = 1;
@@ -149,6 +161,9 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
 		case 'f':
 			force_using_targetdev = 1;
 			break;
+		case GETOPT_VAL_AUTORESIZE:
+			auto_resize = true;
+			break;
 		default:
 			usage_unknown_option(cmd, argv);
 		}
@@ -202,45 +217,46 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
 		goto leave_with_error;
 	}
 
-	if (string_is_numerical(srcdev)) {
-		struct btrfs_ioctl_fs_info_args fi_args;
-		struct btrfs_ioctl_dev_info_args *di_args = NULL;
+	ret = get_fs_info(path, &fi_args, &di_args);
+	if (ret) {
+		errno = -ret;
+		error("failed to get device info: %m");
+		free(di_args);
+		goto leave_with_error;
+	}
+	if (!fi_args.num_devices) {
+		error("no devices found");
+		free(di_args);
+		goto leave_with_error;
+	}
 
+	if (string_is_numerical(srcdev)) {
 		start_args.start.srcdevid = arg_strtou64(srcdev);
 
-		ret = get_fs_info(path, &fi_args, &di_args);
-		if (ret) {
-			errno = -ret;
-			error("failed to get device info: %m");
-			free(di_args);
-			goto leave_with_error;
-		}
-		if (!fi_args.num_devices) {
-			error("no devices found");
-			free(di_args);
-			goto leave_with_error;
-		}
-
 		for (i = 0; i < fi_args.num_devices; i++)
 			if (start_args.start.srcdevid == di_args[i].devid)
 				break;
 		srcdev_size = di_args[i].total_bytes;
-		free(di_args);
-		if (i == fi_args.num_devices) {
-			error("'%s' is not a valid devid for filesystem '%s'",
-				srcdev, path);
-			goto leave_with_error;
-		}
 	} else if (path_is_block_device(srcdev) > 0) {
-		strncpy((char *)start_args.start.srcdev_name, srcdev,
-			BTRFS_DEVICE_PATH_NAME_MAX);
-		start_args.start.srcdevid = 0;
-		srcdev_size = get_partition_size(srcdev);
+		for (i = 0; i < fi_args.num_devices; i++)
+			if (strcmp(srcdev, (char *)di_args[i].path) == 0)
+				break;
+
+		start_args.start.srcdevid = di_args[i].devid;
+		srcdev_size = di_args[i].total_bytes;
 	} else {
 		error("source device must be a block device or a devid");
 		goto leave_with_error;
 	}
 
+	free(di_args);
+	di_args = NULL;
+	if (i == fi_args.num_devices) {
+		error("'%s' is not a valid devid for filesystem '%s'",
+			srcdev, path);
+		goto leave_with_error;
+	}
+
 	ret = test_dev_for_mkfs(dstdev, force_using_targetdev);
 	if (ret)
 		goto leave_with_error;
@@ -309,10 +325,25 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
 			goto leave_with_error;
 		}
 	}
+
+	if (ret == 0 && auto_resize && dstdev_size > srcdev_size) {
+		char amount[BTRFS_PATH_NAME_MAX + 1];
+		snprintf(amount, BTRFS_DEVICE_PATH_NAME_MAX, "%llu:max",
+						start_args.start.srcdevid);
+
+		if (resize_filesystem(amount, path)) {
+			warning("resize failed, please resize the filesystem manually by executing:"
+				"\nbtrfs fi resize %llu:max %s", start_args.start.srcdevid, path);
+			goto leave_with_error;
+		}
+	}
+
 	close_file_or_dir(fdmnt, dirstream);
 	return 0;
 
 leave_with_error:
+	if (di_args)
+		free(di_args);
 	if (dstdev)
 		free(dstdev);
 	if (fdmnt != -1)
-- 
2.25.1


  parent reply	other threads:[~2020-04-16  1:04 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-16  0:46 [PATCHv3 0/3] btrfs-progs: Auto resize fs after device replace Marcos Paulo de Souza
2020-04-16  0:46 ` [PATCHv3 1/3] btrfs-progs: Move resize into functionaly into utils.c Marcos Paulo de Souza
2020-04-16  0:46 ` Marcos Paulo de Souza [this message]
2020-04-16  0:46 ` [PATCHv3 3/3] btrfs-progs: tests: misc: Add some replace tests Marcos Paulo de Souza
     [not found] ` <706b6fae-94d6-62bf-d52e-d0db057e3bd3@casa-di-locascio.net>
2020-04-17  2:15   ` [PATCHv3 0/3] btrfs-progs: Auto resize fs after device replace Marcos Paulo de Souza
2020-05-31 19:11 ` Marcos Paulo de Souza

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=20200416004642.9941-3-marcos@mpdesouza.com \
    --to=marcos@mpdesouza.com \
    --cc=dsterba@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=mpdesouza@suse.com \
    --cc=wqu@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 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.