From e198c6674a440ec699e068c338e66b2632962197 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.com>
Date: Thu, 5 Nov 2020 03:38:00 +0100
Subject: [PATCH] btrfs-progs: add enqueue parameter for exclusive ops

The exclusive ops will not start if there's one already running. Now
that we have the sysfs export (since kernel 5.10) to check if there's
one already running, use it to allow enqueueing of the operations as a
convenience.

Supported enqueuing:

  btrfs balance start --enqueue
  btrfs filesystem resize --enqueue
  btrfs device add --enqueue
  btrfs device delete --enqueue
  btrfs replace start --enqueue

This patch implements the functionality based on Goldwyn's patch
https://lore.kernel.org/linux-btrfs/?q=20200825150338.32610-4-rgoldwyn%40suse.de
but on top of previous preparatory patches.

Note that 'filesystem resize' options could confuse getopt as the
negative size change looks like a series of short options and there's no
way to make getopt ignore the short options, so there's a custom option
parser.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.de>
Signed-off-by: David Sterba <dsterba@suse.com>

---
 Documentation/btrfs-balance.asciidoc    |    2 +
 Documentation/btrfs-device.asciidoc     |    9 ++++-
 Documentation/btrfs-filesystem.asciidoc |    7 +++-
 Documentation/btrfs-replace.asciidoc    |    4 +-
 cmds-balance.c                          |   30 ++++++++++-------
 cmds-device.c                           |   56 ++++++++++++++++++++++++--------
 cmds-filesystem.c                       |   35 +++++++++++++++-----
 cmds-replace.c                          |   30 ++++++++++++-----
 utils.c                                 |    5 +-
 utils.h                                 |    2 -
 10 files changed, 134 insertions(+), 46 deletions(-)

--- a/Documentation/btrfs-balance.asciidoc
+++ b/Documentation/btrfs-balance.asciidoc
@@ -105,6 +105,8 @@
 --background|--bg::::
 run the balance operation asynchronously in the background, uses `fork`(2) to
 start the process that calls the kernel ioctl
+--enqueue::::
+wait if there's another exclusive operation running, otherwise continue
 
 *status* [-v] <path>::
 Show status of running or paused balance.
--- a/Documentation/btrfs-device.asciidoc
+++ b/Documentation/btrfs-device.asciidoc
@@ -61,8 +61,10 @@
 do not perform discard (TRIM) by default
 -f|--force::::
 force overwrite of existing filesystem on the given disk(s)
+--enqueue::::
+wait if there's another exclusive operation running, otherwise continue
 
-*remove* <device>|<devid> [<device>|<devid>...] <path>::
+*remove* [options] <device>|<devid> [<device>|<devid>...] <path>::
 Remove device(s) from a filesystem identified by <path>
 +
 Device removal must satisfy the profile constraints, otherwise the command
@@ -85,6 +87,11 @@
 otherwise mount fails. If there are two or more devices missing (e.g. possible
 in RAID6), you need specify 'missing' as many times as the number of missing
 devices to remove all of them.
++
+`Options`
++
+--enqueue::::
+wait if there's another exclusive operation running, otherwise continue
 
 *delete* <device>|<devid> [<device>|<devid>...] <path>::
 Alias of remove kept for backward compatibility
--- a/Documentation/btrfs-filesystem.asciidoc
+++ b/Documentation/btrfs-filesystem.asciidoc
@@ -182,7 +182,7 @@
 a newline. The trailing newline is stripped automatically.
 
 // Some wording are extracted by the resize2fs man page
-*resize* [<devid>:][+/-]<size>[kKmMgGtTpPeE]|[<devid>:]max <path>::
+*resize* [options] [<devid>:][+/-]<size>[kKmMgGtTpPeE]|[<devid>:]max <path>::
 Resize a mounted filesystem identified by 'path'. A particular device
 can be resized by specifying a 'devid'.
 +
@@ -216,6 +216,11 @@
 end. Relocation of the data takes time.
 +
 See also section 'EXAMPLES'.
++
+`Options`
++
+--enqueue::::
+wait if there's another exclusive operation running, otherwise continue
 
 *show* [options] [<path>|<uuid>|<device>|<label>]::
 Show the btrfs filesystem with some additional info about devices and space
--- a/Documentation/btrfs-replace.asciidoc
+++ b/Documentation/btrfs-replace.asciidoc
@@ -18,7 +18,7 @@
 *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,8 @@
 +
 -B::::
 no background replace.
+--enqueue::::
+wait if there's another exclusive operation running, otherwise continue
 
 *status* [-1] <mount_point>::
 Print status and progress information of a running device replace operation.
--- a/cmds-balance.c
+++ b/cmds-balance.c
@@ -427,12 +427,11 @@
 };
 
 static int do_balance(const char *path, struct btrfs_ioctl_balance_args *args,
-		      unsigned flags)
+		      unsigned flags, bool enqueue)
 {
 	int fd;
 	int ret;
 	DIR *dirstream = NULL;
-	int exclop;
 
 	fd = btrfs_open_dir(path, &dirstream, 1);
 	if (fd < 0)
@@ -456,11 +455,10 @@
 		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));
+	ret = check_running_fs_exclop(fd, BTRFS_EXCLOP_BALANCE, enqueue);
+	if (ret != 0) {
+		if (ret < 0)
+			error("unable to check status of exclusive operation: %m");
 		close_file_or_dir(fd, dirstream);
 		return 1;
 	}
@@ -522,6 +520,8 @@
 	"--full-balance do not print warning and do not delay start",
 	"--background|--bg",
 	"               run the balance as a background process",
+	"--enqueue      wait if there's another exclusive operation running,",
+	"               otherwise continue",
 	NULL
 };
 
@@ -533,6 +533,7 @@
 	int force = 0;
 	int verbose = 0;
 	int background = 0;
+	bool enqueue = false;
 	unsigned start_flags = 0;
 	int i;
 
@@ -541,7 +542,8 @@
 	optind = 0;
 	while (1) {
 		enum { GETOPT_VAL_FULL_BALANCE = 256,
-			GETOPT_VAL_BACKGROUND = 257 };
+			GETOPT_VAL_BACKGROUND = 257,
+			GETOPT_VAL_ENQUEUE };
 		static const struct option longopts[] = {
 			{ "data", optional_argument, NULL, 'd'},
 			{ "metadata", optional_argument, NULL, 'm' },
@@ -553,6 +555,7 @@
 			{ "background", no_argument, NULL,
 				GETOPT_VAL_BACKGROUND },
 			{ "bg", no_argument, NULL, GETOPT_VAL_BACKGROUND },
+			{ "enqueue", no_argument, NULL, GETOPT_VAL_ENQUEUE},
 			{ NULL, 0, NULL, 0 }
 		};
 
@@ -594,6 +597,9 @@
 		case GETOPT_VAL_BACKGROUND:
 			background = 1;
 			break;
+		case GETOPT_VAL_ENQUEUE:
+			enqueue = true;
+			break;
 		default:
 			usage(cmd_balance_start_usage);
 		}
@@ -681,7 +687,7 @@
 		}
 	}
 
-	return do_balance(argv[optind], &args, start_flags);
+	return do_balance(argv[optind], &args, start_flags, enqueue);
 }
 
 static const char * const cmd_balance_pause_usage[] = {
@@ -918,7 +924,8 @@
 	memset(&args, 0, sizeof(args));
 	args.flags |= BTRFS_BALANCE_TYPE_MASK;
 
-	return do_balance(argv[1], &args, BALANCE_START_NOWARN);
+	/* No enqueueing supported for the obsolete syntax */
+	return do_balance(argv[1], &args, BALANCE_START_NOWARN, false);
 }
 
 static const char balance_cmd_group_info[] =
@@ -945,7 +952,8 @@
 		memset(&args, 0, sizeof(args));
 		args.flags |= BTRFS_BALANCE_TYPE_MASK;
 
-		return do_balance(argv[1], &args, 0);
+		/* No enqueueing supported for the obsolete syntax */
+		return do_balance(argv[1], &args, 0, false);
 	}
 
 	return handle_command_group(&balance_cmd_group, argc, argv);
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -45,6 +45,8 @@
 	"Add a device to a filesystem",
 	"-K|--nodiscard    do not perform whole device TRIM",
 	"-f|--force        force overwrite existing filesystem on the disk",
+	"--enqueue         wait if there's another exclusive operation running,",
+	"                  otherwise continue",
 	NULL
 };
 
@@ -56,14 +58,16 @@
 	int discard = 1;
 	int force = 0;
 	int last_dev;
-	int exclop;
+	bool enqueue = false;
 
 	optind = 0;
 	while (1) {
 		int c;
+		enum { GETOPT_VAL_ENQUEUE = 256 };
 		static const struct option long_options[] = {
 			{ "nodiscard", optional_argument, NULL, 'K'},
 			{ "force", no_argument, NULL, 'f'},
+			{ "enqueue", no_argument, NULL, GETOPT_VAL_ENQUEUE},
 			{ NULL, 0, NULL, 0}
 		};
 
@@ -77,6 +81,9 @@
 		case 'f':
 			force = 1;
 			break;
+		case GETOPT_VAL_ENQUEUE:
+			enqueue = true;
+			break;
 		default:
 			usage(cmd_device_add_usage);
 		}
@@ -92,11 +99,10 @@
 	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));
+	ret = check_running_fs_exclop(fdmnt, BTRFS_EXCLOP_DEV_ADD, enqueue);
+	if (ret != 0) {
+		if (ret < 0)
+			error("unable to check status of exclusive operation: %m");
 		close_file_or_dir(fdmnt, dirstream);
 		return 1;
 	}
@@ -158,9 +164,28 @@
 	char	*mntpnt;
 	int i, fdmnt, ret = 0;
 	DIR	*dirstream = NULL;
-	int exclop;
+	bool enqueue = false;
 
-	clean_args_no_options(argc, argv, usagestr);
+	optind = 0;
+	while (1) {
+		int c;
+		enum { GETOPT_VAL_ENQUEUE = 256 };
+		static const struct option long_options[] = {
+			{ "enqueue", no_argument, NULL, GETOPT_VAL_ENQUEUE},
+			{ NULL, 0, NULL, 0}
+		};
+
+		c = getopt_long(argc, argv, "", long_options, NULL);
+		if (c < 0)
+			break;
+		switch (c) {
+			case GETOPT_VAL_ENQUEUE:
+				enqueue = true;
+				break;
+			default:
+				usage(usagestr);
+		}
+	}
 
 	if (check_argc_min(argc - optind, 2))
 		usage(usagestr);
@@ -171,11 +196,10 @@
 	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));
+	ret = check_running_fs_exclop(fdmnt, BTRFS_EXCLOP_DEV_REMOVE, enqueue);
+	if (ret != 0) {
+		if (ret < 0)
+			error("unable to check status of exclusive operation: %m");
 		close_file_or_dir(fdmnt, dirstream);
 		return 1;
 	}
@@ -253,6 +277,9 @@
 	"Remove a device from a filesystem",
 	"",
 	COMMON_USAGE_REMOVE_DELETE,
+	"",
+	"--enqueue         wait if there's another exclusive operation running,",
+	"                  otherwise continue",
 	NULL
 };
 
@@ -266,6 +293,9 @@
 	"Remove a device from a filesystem (alias of \"btrfs device remove\")",
 	"",
 	COMMON_USAGE_REMOVE_DELETE,
+	"",
+	"--enqueue         wait if there's another exclusive operation running,",
+	"                  otherwise continue",
 	NULL
 };
 
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -1075,11 +1075,14 @@
 }
 
 static const char * const cmd_filesystem_resize_usage[] = {
-	"btrfs filesystem resize [devid:][+/-]<newsize>[kKmMgGtTpPeE]|[devid:]max <path>",
+	"btrfs filesystem resize [options] [devid:][+/-]<newsize>[kKmMgGtTpPeE]|[devid:]max <path>",
 	"Resize a filesystem",
 	"If 'max' is passed, the filesystem will occupy all available space",
 	"on the device 'devid'.",
 	"[kK] means KiB, which denotes 1KiB = 1024B, 1MiB = 1024KiB, etc.",
+	"",
+	"--enqueue         wait if there's another exclusive operation running,",
+	"                  otherwise continue",
 	NULL
 };
 
@@ -1089,10 +1092,27 @@
 	int	fd, res, len, e;
 	char	*amount, *path;
 	DIR	*dirstream = NULL;
+	int ret;
 	struct stat st;
-	int exclop;
+	bool enqueue = false;
 
-	clean_args_no_options_relaxed(argc, argv);
+	/*
+	 * Simplified option parser, accept only long options, the resize value
+	 * could be negative and is recognized as short options by getopt
+	 */
+	for (optind = 1; optind < argc; optind++) {
+		if (strcmp(argv[optind], "--enqueue") == 0) {
+			enqueue = true;
+		} else if (strcmp(argv[optind], "--") == 0) {
+			/* Separator: options -- non-options */
+		} else if (strncmp(argv[optind], "--", 2) == 0) {
+			/* Emulate what getopt does on unkonwn option */
+			optind++;
+			usage(cmd_filesystem_resize_usage);
+		} else {
+			break;
+		}
+	}
 
 	if (check_argc_exact(argc - optind, 2))
 		usage(cmd_filesystem_resize_usage);
@@ -1122,11 +1142,10 @@
 	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));
+	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;
 	}
--- a/cmds-replace.c
+++ b/cmds-replace.c
@@ -28,6 +28,7 @@
 #include <assert.h>
 #include <inttypes.h>
 #include <sys/wait.h>
+#include <getopt.h>
 
 #include "kerncompat.h"
 #include "ctree.h"
@@ -111,6 +112,8 @@
 	"       correct checksum. Devices which are currently mounted are",
 	"       never allowed to be used as the <targetdev>",
 	"-B     do not background",
+	"--enqueue    wait if there's another exclusive operation running,",
+	"             otherwise continue",
 	NULL
 };
 
@@ -120,7 +123,6 @@
 	struct btrfs_ioctl_dev_replace_args status_args = {0};
 	int ret;
 	int i;
-	int c;
 	int fdmnt = -1;
 	int fddstdev = -1;
 	char *path;
@@ -133,10 +135,20 @@
 	DIR *dirstream = NULL;
 	u64 srcdev_size;
 	u64 dstdev_size;
-	int exclop;
+	bool enqueue = false;
 
 	optind = 0;
-	while ((c = getopt(argc, argv, "Brf")) != -1) {
+	while (1) {
+		int c;
+		enum { GETOPT_VAL_ENQUEUE = 256 };
+		static const struct option long_options[] = {
+			{ "enqueue", no_argument, NULL, GETOPT_VAL_ENQUEUE},
+			{ NULL, 0, NULL, 0}
+		};
+
+		c = getopt_long(argc, argv, "Brf", long_options, NULL);
+		if (c < 0)
+			break;
 		switch (c) {
 		case 'B':
 			do_not_background = 1;
@@ -147,6 +159,9 @@
 		case 'f':
 			force_using_targetdev = 1;
 			break;
+		case GETOPT_VAL_ENQUEUE:
+			enqueue = true;
+			break;
 		case '?':
 		default:
 			usage(cmd_replace_start_usage);
@@ -258,11 +273,10 @@
 	}
 
 	/* 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));
+	ret = check_running_fs_exclop(fdmnt, BTRFS_EXCLOP_DEV_REPLACE, enqueue);
+	if (ret != 0) {
+		if (ret < 0)
+			error("unable to check status of exclusive operation: %m");
 		close_file_or_dir(fdmnt, dirstream);
 		goto leave_with_error;
 	}
--- a/utils.c
+++ b/utils.c
@@ -2693,7 +2693,7 @@
  * 1  - another operation running
  * <0 - there was another error
  */
-int check_running_fs_exclop(int fd, const char *desc, bool enqueue)
+int check_running_fs_exclop(int fd, enum exclusive_operation start, bool enqueue)
 {
 	int sysfs_fd;
 	int exclop;
@@ -2715,7 +2715,8 @@
 	if (!enqueue) {
 		error(
 	"unable to start %s, another exclusive operation '%s' in progress",
-			desc, get_fs_exclop_name(exclop));
+			get_fs_exclop_name(start),
+			get_fs_exclop_name(exclop));
 		ret = 1;
 		goto out;
 	}
--- a/utils.h
+++ b/utils.h
@@ -124,7 +124,7 @@
 int get_fsid(const char *path, u8 *fsid, int silent);
 int get_fsid_fd(int fd, u8 *fsid);
 int get_fs_exclop(int fd);
-int check_running_fs_exclop(int fd, const char *desc, bool enqueue);
+int check_running_fs_exclop(int fd, enum exclusive_operation start, bool enqueue);
 const char *get_fs_exclop_name(int op);
 
 int is_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[]);
--- a/Documentation/btrfs-balance.8
+++ b/Documentation/btrfs-balance.8
@@ -2,12 +2,12 @@
 .\"     Title: btrfs-balance
 .\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 12/05/2018
+.\"      Date: 12/10/2020
 .\"    Manual: Btrfs Manual
 .\"    Source: Btrfs v4.19.1
 .\"  Language: English
 .\"
-.TH "BTRFS\-BALANCE" "8" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual"
+.TH "BTRFS\-BALANCE" "8" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -240,6 +240,11 @@ to
 run the balance operation asynchronously in the background, uses
 \fBfork\fR(2) to start the process that calls the kernel ioctl
 .RE
+.PP
+\-\-enqueue
+.RS 4
+wait if there\(cqs another exclusive operation running, otherwise continue
+.RE
 .RE
 .PP
 \fBstatus\fR [\-v] \fI<path>\fR
--- a/Documentation/btrfs-device.8
+++ b/Documentation/btrfs-device.8
@@ -2,12 +2,12 @@
 .\"     Title: btrfs-device
 .\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 12/05/2018
+.\"      Date: 12/10/2020
 .\"    Manual: Btrfs Manual
 .\"    Source: Btrfs v4.19.1
 .\"  Language: English
 .\"
-.TH "BTRFS\-DEVICE" "8" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual"
+.TH "BTRFS\-DEVICE" "8" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -78,9 +78,14 @@ do not perform discard (TRIM) by default
 .RS 4
 force overwrite of existing filesystem on the given disk(s)
 .RE
+.PP
+\-\-enqueue
+.RS 4
+wait if there\(cqs another exclusive operation running, otherwise continue
+.RE
 .RE
 .PP
-\fBremove\fR \fI<device>\fR|\fI<devid>\fR [\fI<device>\fR|\fI<devid>\fR\&...] \fI<path>\fR
+\fBremove\fR [options] \fI<device>\fR|\fI<devid>\fR [\fI<device>\fR|\fI<devid>\fR\&...] \fI<path>\fR
 .RS 4
 Remove device(s) from a filesystem identified by
 \fI<path>\fR
@@ -114,6 +119,12 @@ In most cases, there is only one missing
 as many times as the number of missing devices to remove all of them\&.
 .sp .5v
 .RE
+\fBOptions\fR
+.PP
+\-\-enqueue
+.RS 4
+wait if there\(cqs another exclusive operation running, otherwise continue
+.RE
 .RE
 .PP
 \fBdelete\fR \fI<device>\fR|\fI<devid>\fR [\fI<device>\fR|\fI<devid>\fR\&...] \fI<path>\fR
--- a/Documentation/btrfs-filesystem.8
+++ b/Documentation/btrfs-filesystem.8
@@ -2,12 +2,12 @@
 .\"     Title: btrfs-filesystem
 .\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 12/05/2018
+.\"      Date: 12/10/2020
 .\"    Manual: Btrfs Manual
 .\"    Source: Btrfs v4.19.1
 .\"  Language: English
 .\"
-.TH "BTRFS\-FILESYSTEM" "8" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual"
+.TH "BTRFS\-FILESYSTEM" "8" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -401,7 +401,7 @@ the maximum allowable length shall be le
 .RE
 .RE
 .PP
-\fBresize\fR [\fI<devid>\fR:][+/\-]\fI<size>\fR[kKmMgGtTpPeE]|[\fI<devid>\fR:]max \fI<path>\fR
+\fBresize\fR [options] [\fI<devid>\fR:][+/\-]\fI<size>\fR[kKmMgGtTpPeE]|[\fI<devid>\fR:]max \fI<path>\fR
 .RS 4
 Resize a mounted filesystem identified by
 \fIpath\fR\&. A particular device can be resized by specifying a
@@ -451,6 +451,13 @@ Growing is usually instant as it only up
 .sp
 See also section
 \fIEXAMPLES\fR\&.
+.sp
+\fBOptions\fR
+.PP
+\-\-enqueue
+.RS 4
+wait if there\(cqs another exclusive operation running, otherwise continue
+.RE
 .RE
 .PP
 \fBshow\fR [options] [\fI<path>\fR|\fI<uuid>\fR|\fI<device>\fR|\fI<label>\fR]
--- a/Documentation/btrfs-replace.8
+++ b/Documentation/btrfs-replace.8
@@ -2,12 +2,12 @@
 .\"     Title: btrfs-replace
 .\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 12/05/2018
+.\"      Date: 12/10/2020
 .\"    Manual: Btrfs Manual
 .\"    Source: Btrfs v4.19.1
 .\"  Language: English
 .\"
-.TH "BTRFS\-REPLACE" "8" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual"
+.TH "BTRFS\-REPLACE" "8" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -42,7 +42,7 @@ btrfs-replace \- replace devices managed
 Cancel a running device replace operation\&.
 .RE
 .PP
-\fBstart\fR [\-Bfr] \fI<srcdev>\fR|\fI<devid>\fR \fI<targetdev>\fR \fI<path>\fR
+\fBstart\fR [options] \fI<srcdev>\fR|\fI<devid>\fR \fI<targetdev>\fR \fI<path>\fR
 .RS 4
 Replace device of a btrfs filesystem\&.
 .sp
@@ -92,6 +92,11 @@ A valid filesystem is assumed if a btrfs
 .RS 4
 no background replace\&.
 .RE
+.PP
+\-\-enqueue
+.RS 4
+wait if there\(cqs another exclusive operation running, otherwise continue
+.RE
 .RE
 .PP
 \fBstatus\fR [\-1] \fI<mount_point>\fR
--- a/Documentation/btrfs.5
+++ b/Documentation/btrfs.5
@@ -2,12 +2,12 @@
 .\"     Title: btrfs-man5
 .\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 12/05/2018
+.\"      Date: 12/10/2020
 .\"    Manual: Btrfs Manual
 .\"    Source: Btrfs v4.19.1
 .\"  Language: English
 .\"
-.TH "BTRFS\-MAN5" "5" "12/05/2018" "Btrfs v4\&.19\&.1" "Btrfs Manual"
+.TH "BTRFS\-MAN5" "5" "12/10/2020" "Btrfs v4\&.19\&.1" "Btrfs Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
