Hi, Chris, This series is the userspace patches corresponding to the kernel-side balance management stuff. This iteration fixes a use-after-free bug in the filtering code, and tidies up some of the man pages/help. The patches are against the master branch of the tools repo. Hugo. Hugo Mills (8): Balance progress monitoring. Add --monitor option to btrfs balance progress. User-space tool for cancelling balance operations. Run userspace tool in background for balances. Initial implementation of userspace interface for filtered balancing. Balance filter by device ID Balance filter for virtual address range Interface for device range balance filter btrfs.c | 19 ++- btrfs_cmds.c | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- btrfs_cmds.h | 2 + ioctl.h | 46 ++++++ man/btrfs.8.in | 81 +++++++++- 5 files changed, 595 insertions(+), 13 deletions(-) -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
This patch introduces a basic form of progress monitoring for balance operations, by counting the number of block groups remaining. The information is exposed to userspace by an ioctl. We also add "btrfs balance start" as an alias for "btrfs filesystem balance", so that all balance-related functions are available under one prefix. Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs.c | 8 +++++++ btrfs_cmds.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ btrfs_cmds.h | 1 + ioctl.h | 7 ++++++ man/btrfs.8.in | 16 ++++++++++++-- 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/btrfs.c b/btrfs.c index 46314cf..3a24019 100644 --- a/btrfs.c +++ b/btrfs.c @@ -95,6 +95,14 @@ static struct Command commands[] = { "filesystem balance", "<path>\n" "Balance the chunks across the device." }, + { do_balance, 1, + "balance start", "<path>\n" + "Synonym for \"btrfs filesystem balance\"." + }, + { do_balance_progress, 1, + "balance progress", "<path>\n" + "Show progress of the balance operation running on <path>." + }, { do_scan, 999, "device scan", "[<device> [<device>..]\n" "Scan all device for or the passed device for a btrfs\n" diff --git a/btrfs_cmds.c b/btrfs_cmds.c index 8031c58..00dda0a 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -28,6 +28,7 @@ #include <limits.h> #include <uuid/uuid.h> #include <ctype.h> +#include <getopt.h> #undef ULONG_MAX @@ -776,6 +777,62 @@ int do_balance(int argc, char **argv) } return 0; } + +int get_balance_progress(char *path, struct btrfs_ioctl_balance_progress *bal) +{ + int fdmnt; + int ret = 0; + int err = 0; + + fdmnt = open_file_or_dir(path); + if(fdmnt < 0) { + return -1; + } + + ret = ioctl(fdmnt, BTRFS_IOC_BALANCE_PROGRESS, bal); + if(ret) + err = errno; + close(fdmnt); + + return err; +} + +int do_balance_progress(int argc, char **argv) +{ + char *path; + int ret = 0; + int err = 0; + struct btrfs_ioctl_balance_progress bal; + + path = argv[1]; + + ret = get_balance_progress(path, &bal); + if (!ret) + printf("\r%u/%u block groups moved, " + "%0.2f%% complete.\n", + bal.completed, + bal.expected, + (float)bal.completed/bal.expected*100.0); + + switch(ret) { + case 0: + break; + case -1: + fprintf(stderr, "ERROR: can''t access ''%s''\n", path); + return 13; + case EINVAL: + fprintf(stderr, + "No balance operation running on ''%s''.\n", + path); + return 20; + default: + fprintf(stderr, "ERROR: ioctl returned error %d.", err); + return 21; + } + + return 0; +} + int do_remove_volume(int nargs, char **args) { diff --git a/btrfs_cmds.h b/btrfs_cmds.h index 7bde191..47b0a27 100644 --- a/btrfs_cmds.h +++ b/btrfs_cmds.h @@ -23,6 +23,7 @@ int do_defrag(int argc, char **argv); int do_show_filesystem(int nargs, char **argv); int do_add_volume(int nargs, char **args); int do_balance(int nargs, char **argv); +int do_balance_progress(int nargs, char **argv); int do_remove_volume(int nargs, char **args); int do_scan(int nargs, char **argv); int do_resize(int nargs, char **argv); diff --git a/ioctl.h b/ioctl.h index 776d7a9..f07d3a2 100644 --- a/ioctl.h +++ b/ioctl.h @@ -132,6 +132,11 @@ struct btrfs_ioctl_space_args { struct btrfs_ioctl_space_info spaces[0]; }; +struct btrfs_ioctl_balance_progress { + __u32 expected; + __u32 completed; +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ @@ -169,4 +174,6 @@ struct btrfs_ioctl_space_args { #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64) #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ struct btrfs_ioctl_space_args) +#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 25, \ + struct btrfs_ioctl_balance_progress) #endif diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 26ef982..7b66fb7 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -21,11 +21,15 @@ btrfs \- control a btrfs filesystem .PP \fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP .PP +\fBbtrfs\fP \fBfilesystem balance\fP\fI <path> \fP +.PP \fBbtrfs\fP \fBdevice scan\fP\fI [<device> [<device>..]]\fP .PP -\fBbtrfs\fP \fBdevice show\fP\fI <dev>|<label> [<dev>|<label>...]\fP +\fBbtrfs\fP \fBbalance start\fP\fI <path> \fP +.PP +\fBbtrfs\fP \fBbalance progress\fP\fI <path>\fP .PP -\fBbtrfs\fP \fBdevice balance\fP\fI <path> \fP +\fBbtrfs\fP \fBdevice show\fP\fI <dev>|<label> [<dev>|<label>...]\fP .PP \fBbtrfs\fP \fBdevice add\fP\fI <dev> [<dev>..] <path> \fP .PP @@ -143,7 +147,9 @@ Show the btrfs filesystem with some additional info. If no UUID or label is passed, \fBbtrfs\fR show info of all the btrfs filesystem. .TP -\fBdevice balance\fR \fI<path>\fR +\fBbalance start\fR \fI<path>\fR +.TP +\fBfilesystem balance\fR \fI<path>\fR Balance the chunks of the filesystem identified by \fI<path>\fR across the devices. .TP @@ -156,6 +162,10 @@ Add device(s) to the filesystem identified by \fI<path>\fR. Remove device(s) from a filesystem identified by \fI<path>\fR. .PP +\fBbalance progress\fP \fI<path>\fP +Report progress on the currently-running balance operation on the +filesystem mounted at \fI<path>\fP. + .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in case of failure. -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hugo Mills
2011-May-01 15:47 UTC
[PATCH v6 2/8] Add --monitor option to btrfs balance progress.
For the impatient, this patch introduces the pot-watching --monitor option, which checks the balance progress at regular intervals, and updates a single status line with the current progress and an estimated completion time. Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs.c | 4 +- btrfs_cmds.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++----- ioctl.h | 2 +- man/btrfs.8.in | 7 ++-- 4 files changed, 106 insertions(+), 16 deletions(-) diff --git a/btrfs.c b/btrfs.c index 3a24019..0b6186c 100644 --- a/btrfs.c +++ b/btrfs.c @@ -99,8 +99,8 @@ static struct Command commands[] = { "balance start", "<path>\n" "Synonym for \"btrfs filesystem balance\"." }, - { do_balance_progress, 1, - "balance progress", "<path>\n" + { do_balance_progress, -1, + "balance progress", "[-m|--monitor] <path>\n" "Show progress of the balance operation running on <path>." }, { do_scan, diff --git a/btrfs_cmds.c b/btrfs_cmds.c index 00dda0a..ad2300d 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -797,22 +797,108 @@ int get_balance_progress(char *path, struct btrfs_ioctl_balance_progress *bal) return err; } +const struct option progress_options[] = { + { "monitor", 0, NULL, ''m'' }, + { NULL, 0, NULL, 0 } +}; + int do_balance_progress(int argc, char **argv) { char *path; int ret = 0; int err = 0; struct btrfs_ioctl_balance_progress bal; + __u64 last_completed = -1; + __u64 initial_completed = -1; + struct timeval now; + struct timeval started; + int monitor = 0; + + optind = 1; + while(1) { + int c = getopt_long(argc, argv, "m", progress_options, NULL); + if (c < 0) + break; + switch(c) { + case ''m'': + monitor = 1; + break; + default: + fprintf(stderr, "Invalid arguments for balance progress\n"); + free(argv); + return 1; + } + } + + if(optind >= argc) { + fprintf(stderr, "No filesystem path given for progress\n"); + return 1; + } + + path = argv[optind]; + do { + int prs = 0; - path = argv[1]; + ret = get_balance_progress(path, &bal); + if (ret) + break; - ret = get_balance_progress(path, &bal); - if (!ret) - printf("\r%u/%u block groups moved, " - "%0.2f%% complete.\n", - bal.completed, - bal.expected, - (float)bal.completed/bal.expected*100.0); + if (last_completed != bal.completed) { + printf("\r%u/%u block groups moved, " + "%0.2f%% complete.", + bal.completed, + bal.expected, + (float)bal.completed/bal.expected*100.0); + } + + if (initial_completed != -1 + && initial_completed != bal.completed) { + ret = gettimeofday(&now, NULL); + if (ret) { + fprintf(stderr, "Can''t read current time\n"); + return 22; + } + /* Seconds per block */ + float rate = (float)(now.tv_sec - started.tv_sec) + / (bal.completed - initial_completed); + int secs_remaining = rate + * (bal.expected - bal.completed); + printf(" Time remaining"); + if (secs_remaining >= 60*60*24) { + printf(" %dd", secs_remaining / (60*60*24)); + secs_remaining %= 60*60*24; + prs = 1; + } + if (prs || secs_remaining >= 60*60) { + printf(" %dh", secs_remaining / (60*60)); + secs_remaining %= 60*60; + prs = 1; + } + if (prs || secs_remaining > 60) { + printf(" %dm", secs_remaining / 60); + secs_remaining %= 60; + } + printf(" %ds\x1b[K", secs_remaining); + } + + if (last_completed != -1 && last_completed != bal.completed) { + initial_completed = bal.completed; + ret = gettimeofday(&started, NULL); + if (ret) { + fprintf(stderr, "Can''t read current time\n"); + return 22; + } + } + + last_completed = bal.completed; + + if (monitor) { + fflush(stdout); + sleep(1); + } else { + printf("\n"); + } + } while(monitor); switch(ret) { case 0: @@ -821,10 +907,13 @@ int do_balance_progress(int argc, char **argv) fprintf(stderr, "ERROR: can''t access ''%s''\n", path); return 13; case EINVAL: - fprintf(stderr, + if (!monitor) { + fprintf(stderr, "No balance operation running on ''%s''.\n", path); - return 20; + return 20; + } + break; default: fprintf(stderr, "ERROR: ioctl returned error %d.", err); return 21; diff --git a/ioctl.h b/ioctl.h index f07d3a2..3eeaa33 100644 --- a/ioctl.h +++ b/ioctl.h @@ -174,6 +174,6 @@ struct btrfs_ioctl_balance_progress { #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64) #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ struct btrfs_ioctl_space_args) -#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 25, \ +#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 27, \ struct btrfs_ioctl_balance_progress) #endif diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 7b66fb7..5fcad89 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -27,7 +27,7 @@ btrfs \- control a btrfs filesystem .PP \fBbtrfs\fP \fBbalance start\fP\fI <path> \fP .PP -\fBbtrfs\fP \fBbalance progress\fP\fI <path>\fP +\fBbtrfs\fP \fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP .PP \fBbtrfs\fP \fBdevice show\fP\fI <dev>|<label> [<dev>|<label>...]\fP .PP @@ -162,9 +162,10 @@ Add device(s) to the filesystem identified by \fI<path>\fR. Remove device(s) from a filesystem identified by \fI<path>\fR. .PP -\fBbalance progress\fP \fI<path>\fP +\fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP Report progress on the currently-running balance operation on the -filesystem mounted at \fI<path>\fP. +filesystem mounted at \fI<path>\fP. Use --monitor to report progress +continually, including an estimate of completion time. .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hugo Mills
2011-May-01 15:47 UTC
[PATCH v6 3/8] User-space tool for cancelling balance operations.
Add an option to the btrfs tool to use the ioctl for cancelling balance operations. Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs.c | 4 ++++ btrfs_cmds.c | 41 +++++++++++++++++++++++++++++++++++++++++ btrfs_cmds.h | 1 + ioctl.h | 1 + man/btrfs.8.in | 6 ++++++ 5 files changed, 53 insertions(+), 0 deletions(-) diff --git a/btrfs.c b/btrfs.c index 0b6186c..93f7886 100644 --- a/btrfs.c +++ b/btrfs.c @@ -103,6 +103,10 @@ static struct Command commands[] = { "balance progress", "[-m|--monitor] <path>\n" "Show progress of the balance operation running on <path>." }, + { do_balance_cancel, 1, + "balance cancel", "<path>\n" + "Cancel the balance operation running on <path>." + }, { do_scan, 999, "device scan", "[<device> [<device>..]\n" "Scan all device for or the passed device for a btrfs\n" diff --git a/btrfs_cmds.c b/btrfs_cmds.c index ad2300d..b1631a0 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -922,6 +922,47 @@ int do_balance_progress(int argc, char **argv) return 0; } +int do_balance_cancel(int nargs, char **argv) +{ + char *path = argv[1]; + int fdmnt; + int ret = 0; + int err = 0; + + fdmnt = open_file_or_dir(path); + if(fdmnt < 0) { + fprintf(stderr, "ERROR: can''t access ''%s''\n", path); + return 12; + } + + ret = ioctl(fdmnt, BTRFS_IOC_BALANCE_CANCEL, NULL); + err = errno; + + if(ret) { + switch(err) { + case 0: + break; + case EINVAL: + fprintf(stderr, "ERROR: no balance in progress.\n"); + err = 20; + break; + case ECANCELED: + fprintf(stderr, "ERROR: operation already cancelled.\n"); + err = 21; + break; + default: + fprintf(stderr, "ERROR: ioctl returned error ''%d''.\n", + err); + err = 22; + break; + } + } + + close(fdmnt); + + return err; +} + int do_remove_volume(int nargs, char **args) { diff --git a/btrfs_cmds.h b/btrfs_cmds.h index 47b0a27..5cb0d9c 100644 --- a/btrfs_cmds.h +++ b/btrfs_cmds.h @@ -24,6 +24,7 @@ int do_show_filesystem(int nargs, char **argv); int do_add_volume(int nargs, char **args); int do_balance(int nargs, char **argv); int do_balance_progress(int nargs, char **argv); +int do_balance_cancel(int nargs, char **argv); int do_remove_volume(int nargs, char **args); int do_scan(int nargs, char **argv); int do_resize(int nargs, char **argv); diff --git a/ioctl.h b/ioctl.h index 3eeaa33..40c0b57 100644 --- a/ioctl.h +++ b/ioctl.h @@ -176,4 +176,5 @@ struct btrfs_ioctl_balance_progress { struct btrfs_ioctl_space_args) #define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 27, \ struct btrfs_ioctl_balance_progress) +#define BTRFS_IOC_BALANCE_CANCEL _IO(BTRFS_IOCTL_MAGIC, 28) #endif diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 5fcad89..9c6bb69 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -29,6 +29,8 @@ btrfs \- control a btrfs filesystem .PP \fBbtrfs\fP \fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP .PP +\fBbtrfs\fP \fBbalance cancel\fP \fI<path>\fP +.PP \fBbtrfs\fP \fBdevice show\fP\fI <dev>|<label> [<dev>|<label>...]\fP .PP \fBbtrfs\fP \fBdevice add\fP\fI <dev> [<dev>..] <path> \fP @@ -167,6 +169,10 @@ Report progress on the currently-running balance operation on the filesystem mounted at \fI<path>\fP. Use --monitor to report progress continually, including an estimate of completion time. +\fbalance cancel\fP \fI<path>\fP +Cancel the balance currently running on the filesystem mounted at +\fI<path>\fP. + .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in case of failure. -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hugo Mills
2011-May-01 15:47 UTC
[PATCH v6 4/8] Run userspace tool in background for balances.
This patch makes a balance operation fork and detach from the current terminal, to run the userspace side of the balance in the background. Introduce a --wait switch so that a synchronous balance can be done if the user requires. Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs.c | 8 ++++---- btrfs_cmds.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- man/btrfs.8.in | 14 ++++++++------ 3 files changed, 62 insertions(+), 12 deletions(-) diff --git a/btrfs.c b/btrfs.c index 93f7886..7b42658 100644 --- a/btrfs.c +++ b/btrfs.c @@ -91,12 +91,12 @@ static struct Command commands[] = { "filesystem df", "<path>\n" "Show space usage information for a mount point\n." }, - { do_balance, 1, - "filesystem balance", "<path>\n" + { do_balance, -1, + "filesystem balance", "[-w|--wait] <path>\n" "Balance the chunks across the device." }, - { do_balance, 1, - "balance start", "<path>\n" + { do_balance, -1, + "balance start", "[-w|--wait] <path>\n" "Synonym for \"btrfs filesystem balance\"." }, { do_balance_progress, -1, diff --git a/btrfs_cmds.c b/btrfs_cmds.c index b1631a0..070b8a9 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -754,12 +754,41 @@ int do_add_volume(int nargs, char **args) } +const struct option balance_options[] = { + { "wait", 0, NULL, ''w'' }, + { NULL, 0, NULL, 0 } +}; + int do_balance(int argc, char **argv) { - int fdmnt, ret=0; + int background = 1; struct btrfs_ioctl_vol_args args; - char *path = argv[1]; + char *path; + int ttyfd; + + optind = 1; + while(1) { + int c = getopt_long(argc, argv, "w", balance_options, NULL); + if (c < 0) + break; + switch(c) { + case ''w'': + background = 0; + break; + default: + fprintf(stderr, "Invalid arguments for balance\n"); + free(argv); + return 1; + } + } + + if(optind >= argc) { + fprintf(stderr, "No filesystem path given for balance\n"); + return 1; + } + + path = argv[optind]; fdmnt = open_file_or_dir(path); if (fdmnt < 0) { @@ -767,6 +796,25 @@ int do_balance(int argc, char **argv) return 12; } + if (background) { + int pid = fork(); + if (pid == 0) { + /* We''re in the child, and can run in the background */ + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd > 0) + ioctl(ttyfd, TIOCNOTTY, 0); + /* Fall through to the BTRFS_IOC_BALANCE ioctl */ + } else if (pid > 0) { + /* We''re in the parent, and the fork succeeded */ + printf("Background balance started\n"); + return 0; + } else { + /* We''re in the parent, and the fork failed */ + fprintf(stderr, "ERROR: can''t start background process -- %s\n", + strerror(errno)); + } + } + memset(&args, 0, sizeof(args)); ret = ioctl(fdmnt, BTRFS_IOC_BALANCE, &args); close(fdmnt); diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 9c6bb69..77558fa 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -21,11 +21,11 @@ btrfs \- control a btrfs filesystem .PP \fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP .PP -\fBbtrfs\fP \fBfilesystem balance\fP\fI <path> \fP +\fBbtrfs\fP \fBfilesystem balance\fP [\fB-w\fP|\fB--wait\fP] \fI<path>\fP .PP \fBbtrfs\fP \fBdevice scan\fP\fI [<device> [<device>..]]\fP .PP -\fBbtrfs\fP \fBbalance start\fP\fI <path> \fP +\fBbtrfs\fP \fBbalance start\fP [\fB-w\fP|\fB--wait\fP] \fI<path>\fP .PP \fBbtrfs\fP \fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP .PP @@ -149,11 +149,13 @@ Show the btrfs filesystem with some additional info. If no UUID or label is passed, \fBbtrfs\fR show info of all the btrfs filesystem. .TP -\fBbalance start\fR \fI<path>\fR +\fBdevice balance\fR [\fB-w\fP|\fB--wait\fP] \fI<path>\fR .TP -\fBfilesystem balance\fR \fI<path>\fR -Balance the chunks of the filesystem identified by \fI<path>\fR -across the devices. +\fBbalance start\fR [\fB-w\fP|\fB--wait\fP] \fI<path>\fR + +Balance the chunks of the filesystem identified by \fI<path>\fR across +the devices. The process runs in the background. Use \fB--wait\fP to +wait in the foreground for completion of the balance. .TP \fBdevice add\fR\fI <dev> [<dev>..] <path>\fR -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hugo Mills
2011-May-01 15:47 UTC
[PATCH v6 5/8] Initial implementation of userspace interface for filtered balancing.
It is useful to be able to balance a subset of the full filesystem. This patch implements the infrastructure for filtering block groups on different criteria when balancing the filesystem. Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs.c | 5 +- btrfs_cmds.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- ioctl.h | 24 ++++++++ man/btrfs.8.in | 42 ++++++++++++--- 4 files changed, 224 insertions(+), 13 deletions(-) diff --git a/btrfs.c b/btrfs.c index 7b42658..a9aeb51 100644 --- a/btrfs.c +++ b/btrfs.c @@ -92,8 +92,9 @@ static struct Command commands[] = { "Show space usage information for a mount point\n." }, { do_balance, -1, - "filesystem balance", "[-w|--wait] <path>\n" - "Balance the chunks across the device." + "filesystem balance", "[-w|--wait] [-c|--count] [-v|--verbose] [-f|--filter=<filter>:...] <path>\n" + "Balance chunks across the devices. --filter=help for help on filters.\n" + "--count to count chunks only (no balance performed).\n" }, { do_balance, -1, "balance start", "[-w|--wait] <path>\n" diff --git a/btrfs_cmds.c b/btrfs_cmds.c index 070b8a9..279d93a 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -756,26 +756,171 @@ int do_add_volume(int nargs, char **args) const struct option balance_options[] = { { "wait", 0, NULL, ''w'' }, + { "filter", 1, NULL, ''f'' }, + { "count", 0, NULL, ''c'' }, + { "verbose", 0, NULL, ''v'' }, { NULL, 0, NULL, 0 } }; +struct filter_class_desc { + char *keyword; + char *description; + int flag; +}; + +const struct filter_class_desc filter_class[] = { + { "type", + "type=[~]<flagname>[,...]\n" + "\tWhere <flagname> is one of:\n" + "\t\tmeta, sys, data, raid0, raid1, raid10, dup\n" + "\tPrefix a <flagname> with ~ to negate the match.\n", + BTRFS_BALANCE_FILTER_CHUNK_TYPE }, + { NULL, NULL, 0 } +}; + +struct type_filter_desc { + char *keyword; + __u64 mask; + __u64 set; + __u64 unset; +}; + +#define BTRFS_BLOCK_GROUP_SINGLE \ + BTRFS_BLOCK_GROUP_RAID0 | \ + BTRFS_BLOCK_GROUP_RAID1 | \ + BTRFS_BLOCK_GROUP_RAID10 | \ + BTRFS_BLOCK_GROUP_DUP + +const struct type_filter_desc type_filters[] = { + { "data", BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_DATA, 0 }, + { "sys", BTRFS_BLOCK_GROUP_SYSTEM, BTRFS_BLOCK_GROUP_SYSTEM, 0 }, + { "meta", BTRFS_BLOCK_GROUP_METADATA, BTRFS_BLOCK_GROUP_METADATA, 0 }, + { "raid0", BTRFS_BLOCK_GROUP_RAID0, BTRFS_BLOCK_GROUP_RAID0, 0 }, + { "raid1", BTRFS_BLOCK_GROUP_RAID1, BTRFS_BLOCK_GROUP_RAID1, 0 }, + { "raid10", BTRFS_BLOCK_GROUP_RAID10, BTRFS_BLOCK_GROUP_RAID10, 0 }, + { "dup", BTRFS_BLOCK_GROUP_DUP, BTRFS_BLOCK_GROUP_DUP, 0 }, + { "single", BTRFS_BLOCK_GROUP_SINGLE, 0, BTRFS_BLOCK_GROUP_SINGLE }, + { NULL, 0, 0, 0 } +}; + +int parse_filter(struct btrfs_ioctl_balance_start *args, char *filters_string) +{ + char *this_filter_string; + char *saveptr; + + /* Parse the filters string, if there is one */ + this_filter_string = strtok_r(filters_string, ":", &saveptr); + while(this_filter_string) { + char *subsave; + char *part; + char *type = strtok_r(this_filter_string, "=,", &subsave); + int class_id = -1; + + /* Work out what filter type we''re looking at */ + if(strcmp(type, "help") == 0) { + while(filter_class[++class_id].keyword) { + printf("%s", filter_class[class_id].description); + } + return 1; + } + + while(filter_class[++class_id].keyword) { + if(strcmp(type, filter_class[class_id].keyword) == 0) + break; + } + if(filter_class[class_id].keyword == NULL) { + fprintf(stderr, "ERROR: Unknown filter type ''%s''\n", type); + free(args); + return 14; + } + + /* Mark this filter class as being in use */ + args->flags |= filter_class[class_id].flag; + + /* Parse the arguments for this filter */ + part = strtok_r(NULL, "=,", &subsave); + + switch(filter_class[class_id].flag) { + case BTRFS_BALANCE_FILTER_CHUNK_TYPE: + while(part) { + int negated = 0; + int i = 0; + if(part[0] == ''~'') { + negated = 1; + part += 1; + } + while(type_filters[i].keyword) { + if(strcmp(part, type_filters[i].keyword) == 0) + break; + i += 1; + } + if(type_filters[i].keyword == NULL) { + fprintf(stderr, "ERROR: Unknown chunk type ''%s''\n", part); + free(args); + return 15; + } + + args->chunk_type_mask |= type_filters[i].mask; + args->chunk_type &= ~type_filters[i].mask; + if (negated) + args->chunk_type |= type_filters[i].unset; + else + args->chunk_type |= type_filters[i].set; + + part = strtok_r(NULL, "=,", &subsave); + } + break; + } + + this_filter_string = strtok_r(NULL, ":", &saveptr); + } + + return 0; +} + int do_balance(int argc, char **argv) { int fdmnt, ret=0; int background = 1; - struct btrfs_ioctl_vol_args args; + struct btrfs_ioctl_balance_start *args; char *path; int ttyfd; + int verbose = 0; + int count_only = 0; + + args = malloc(4096); + if (!args) { + fprintf(stderr, "ERROR: Not enough memory\n"); + return 13; + } + + args->flags = 0; + args->chunk_type = 0; + args->chunk_type_mask = 0; optind = 1; while(1) { - int c = getopt_long(argc, argv, "w", balance_options, NULL); + int c = getopt_long(argc, argv, "wf:", balance_options, NULL); if (c < 0) break; switch(c) { case ''w'': background = 0; break; + case ''f'': + ret = parse_filter(args, optarg); + if (ret != 0) { + free(args); + return ret; + } + break; + case ''c'': + count_only = 1; + background = 0; + /* Counting is only sensible if we also print some output. */ + case ''v'': + verbose = 1; + break; default: fprintf(stderr, "Invalid arguments for balance\n"); free(argv); @@ -783,6 +928,9 @@ int do_balance(int argc, char **argv) } } + if (background) + verbose = 0; + if(optind >= argc) { fprintf(stderr, "No filesystem path given for balance\n"); return 1; @@ -796,6 +944,9 @@ int do_balance(int argc, char **argv) return 12; } + if (count_only) + args->flags |= BTRFS_BALANCE_FILTER_COUNT_ONLY; + if (background) { int pid = fork(); if (pid == 0) { @@ -815,14 +966,21 @@ int do_balance(int argc, char **argv) } } - memset(&args, 0, sizeof(args)); - ret = ioctl(fdmnt, BTRFS_IOC_BALANCE, &args); + ret = ioctl(fdmnt, BTRFS_IOC_BALANCE_FILTERED, args); close(fdmnt); if(ret<0){ fprintf(stderr, "ERROR: balancing ''%s''\n", path); return 19; } + + if (verbose) { + printf("%u chunks considered, %u chunks balanced\n", + args->examined, args->balanced); + } + + free(args); + return 0; } diff --git a/ioctl.h b/ioctl.h index 40c0b57..230c314 100644 --- a/ioctl.h +++ b/ioctl.h @@ -137,6 +137,28 @@ struct btrfs_ioctl_balance_progress { __u32 completed; }; +/* Types of balance filter */ +#define BTRFS_BALANCE_FILTER_COUNT_ONLY 0x1 + +#define BTRFS_BALANCE_FILTER_CHUNK_TYPE 0x2 +#define BTRFS_BALANCE_FILTER_MASK 0x3 + +/* All the possible options for a filter */ +struct btrfs_ioctl_balance_start { + __u64 flags; /* Bit field indicating which fields of this struct are filled */ + + /* Output values: chunk counts */ + __u32 examined; + __u32 balanced; + + /* For FILTER_CHUNK_TYPE */ + __u64 chunk_type; /* Flag bits required */ + __u64 chunk_type_mask; /* Mask of bits to examine */ + + __u64 spare[507]; /* Make up the size of the structure to 4088 + * bytes for future expansion */ +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ @@ -177,4 +199,6 @@ struct btrfs_ioctl_balance_progress { #define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 27, \ struct btrfs_ioctl_balance_progress) #define BTRFS_IOC_BALANCE_CANCEL _IO(BTRFS_IOCTL_MAGIC, 28) +#define BTRFS_IOC_BALANCE_FILTERED _IOWR(BTRFS_IOCTL_MAGIC, 29, \ + struct btrfs_ioctl_balance_start) #endif diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 77558fa..5ac0694 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -21,11 +21,11 @@ btrfs \- control a btrfs filesystem .PP \fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP .PP -\fBbtrfs\fP \fBfilesystem balance\fP [\fB-w\fP|\fB--wait\fP] \fI<path>\fP +\fBbtrfs\fP \fBfilesystem balance\fP [\fB-wcv\fP] [\fB--wait\fP] [\fB--count\fP] [\fB--verbose\fP] [\fB-f\fP|\fBfilter=\fP\fI<filter>\fP] \fI<path>\fP .PP \fBbtrfs\fP \fBdevice scan\fP\fI [<device> [<device>..]]\fP .PP -\fBbtrfs\fP \fBbalance start\fP [\fB-w\fP|\fB--wait\fP] \fI<path>\fP +\fBbtrfs\fP \fBbalance start\fP [\fB-wcv\fP] [\fB--wait\fP] [\fB--count\fP] [\fB--verbose\fP] [\fB-f\fP|\fBfilter=\fP\fI<filter>\fP] \fI<path>\fP .PP \fBbtrfs\fP \fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP .PP @@ -149,13 +149,18 @@ Show the btrfs filesystem with some additional info. If no UUID or label is passed, \fBbtrfs\fR show info of all the btrfs filesystem. .TP -\fBdevice balance\fR [\fB-w\fP|\fB--wait\fP] \fI<path>\fR +\fBdevice balance\fP [\fB-wcv\fP] [\fB--wait\fP] [\fB--count\fP] [\fB--verbose\fP] [\fB-f\fP|\fBfilter=\fP\fI<filter>\fP] \fI<path>\fP .TP -\fBbalance start\fR [\fB-w\fP|\fB--wait\fP] \fI<path>\fR +\fBbalance start\fR [\fB-wcv\fP] [\fB--wait\fP] [\fB--count\fP] [\fB--verbose\fP] [\fB-f\fP|\fBfilter=\fP\fI<filter>\fP] \fI<path>\fP Balance the chunks of the filesystem identified by \fI<path>\fR across -the devices. The process runs in the background. Use \fB--wait\fP to -wait in the foreground for completion of the balance. +the devices. The command returns immediately, and the balance +operation runs in the background. Use \fB--wait\fP to run +synchronously instead. Use \fB--count\fP to scan the filesystem and +report the number of chunks that would be processed. Use +\fB--verbose\fP in synchronous mode to report the number of chunks +examined and balanced. See \fBBALANCE FILTERS\fR, below, for details +of the different filter types and syntax. .TP \fBdevice add\fR\fI <dev> [<dev>..] <path>\fR @@ -171,10 +176,33 @@ Report progress on the currently-running balance operation on the filesystem mounted at \fI<path>\fP. Use --monitor to report progress continually, including an estimate of completion time. -\fbalance cancel\fP \fI<path>\fP +\fBbalance cancel\fP \fI<path>\fP Cancel the balance currently running on the filesystem mounted at \fI<path>\fP. +.SH BALANCE FILTERS +With balance filters, it is possible to perform a balance operation on +only a subset of the available chunks. Filters are specified with the +\fB--filter\fR option of \fBbtrfs device balance\fR or \fBbtrfs +balance start\fR. Multiple filters may be given, either with multiple +\fB--filter\fR options, or in a colon-separated list. When multiple +filters are given, only the chunks meeting all of the selection +critera are balanced. Help on the avaialble filters can be obtained +with \fB--filter=help\fR. + +.TP +\fBtype\fR=[\fB~\fR]\fI<flagname>\fR[\fB,\fR...] + +Select only the chunks with the given type flag(s). Requiring a flag +to be off can be specified with a \fB~\fR preceding the flag +name. Flag names are: + +\fBmeta\fR, \fBdata\fR, \fBsys\fR for metadata, file data and system +chunk types. + +\fBraid0\fR, \fBraid1\fR, \fBraid10\fR, \fBdup\fR for chunks of the +given replication levels. + .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in case of failure. -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Add the userspace implementation for filtering balances by device ID. Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs_cmds.c | 13 +++++++++++++ ioctl.h | 8 ++++++-- man/btrfs.8.in | 7 +++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/btrfs_cmds.c b/btrfs_cmds.c index 279d93a..0f1434f 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -775,6 +775,10 @@ const struct filter_class_desc filter_class[] = { "\t\tmeta, sys, data, raid0, raid1, raid10, dup\n" "\tPrefix a <flagname> with ~ to negate the match.\n", BTRFS_BALANCE_FILTER_CHUNK_TYPE }, + { "devid", + "devid=<n>\n" + "\tBalance only chunks which have a stripe on device <n>.\n", + BTRFS_BALANCE_FILTER_DEVID }, { NULL, NULL, 0 } }; @@ -870,6 +874,15 @@ int parse_filter(struct btrfs_ioctl_balance_start *args, char *filters_string) part = strtok_r(NULL, "=,", &subsave); } break; + + case BTRFS_BALANCE_FILTER_DEVID: + errno = 0; + args->devid = strtoull(part, NULL, 10); + if (errno != 0) { + fprintf(stderr, "ERROR: ''%s'' is not a valid device ID\n", part); + return 15; + } + break; } this_filter_string = strtok_r(NULL, ":", &saveptr); diff --git a/ioctl.h b/ioctl.h index 230c314..e30687c 100644 --- a/ioctl.h +++ b/ioctl.h @@ -141,7 +141,8 @@ struct btrfs_ioctl_balance_progress { #define BTRFS_BALANCE_FILTER_COUNT_ONLY 0x1 #define BTRFS_BALANCE_FILTER_CHUNK_TYPE 0x2 -#define BTRFS_BALANCE_FILTER_MASK 0x3 +#define BTRFS_BALANCE_FILTER_DEVID 0x4 +#define BTRFS_BALANCE_FILTER_MASK 0x7 /* All the possible options for a filter */ struct btrfs_ioctl_balance_start { @@ -155,7 +156,10 @@ struct btrfs_ioctl_balance_start { __u64 chunk_type; /* Flag bits required */ __u64 chunk_type_mask; /* Mask of bits to examine */ - __u64 spare[507]; /* Make up the size of the structure to 4088 + /* For FILTER_DEVID */ + __u64 devid; + + __u64 spare[506]; /* Make up the size of the structure to 4088 * bytes for future expansion */ }; diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 5ac0694..020260f 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -203,6 +203,13 @@ chunk types. \fBraid0\fR, \fBraid1\fR, \fBraid10\fR, \fBdup\fR for chunks of the given replication levels. +.TP +\fBdevid\fR=\fI<n>\fR + +Select chunks which have data on device ID \fI<n>\fR. This can be +used, for example, to reduplicate data in a mirrored configuration +where one drive has been lost due to hardware failure. + .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in case of failure. -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Implement the userspace side of the virtual address range filter. Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs_cmds.c | 22 ++++++++++++++++++++++ ioctl.h | 9 +++++++-- man/btrfs.8.in | 9 +++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/btrfs_cmds.c b/btrfs_cmds.c index 0f1434f..1f6149d 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -779,6 +779,12 @@ const struct filter_class_desc filter_class[] = { "devid=<n>\n" "\tBalance only chunks which have a stripe on device <n>.\n", BTRFS_BALANCE_FILTER_DEVID }, + { "vrange", + "vrange=<start>,<end>\n" + "\tBalances only chunks which have any bytes within the given\n" + "\trange of the filesystem''s virtual address space.\n" + "\t<start> is inclusive, <end> is exclusive.\n", + BTRFS_BALANCE_FILTER_VIRTUAL_ADDRESS_RANGE }, { NULL, NULL, 0 } }; @@ -883,6 +889,22 @@ int parse_filter(struct btrfs_ioctl_balance_start *args, char *filters_string) return 15; } break; + + case BTRFS_BALANCE_FILTER_VIRTUAL_ADDRESS_RANGE: + errno = 0; + args->vrange_start = strtoull(part, NULL, 10); + if (errno != 0) { + fprintf(stderr, "ERROR: ''%s'' is not a valid start address\n", part); + return 15; + } + part = strtok_r(NULL, "=,", &subsave); + errno = 0; + args->vrange_end = strtoull(part, NULL, 10); + if (errno != 0) { + fprintf(stderr, "ERROR: ''%s'' is not a valid end address\n", part); + return 15; + } + break; } this_filter_string = strtok_r(NULL, ":", &saveptr); diff --git a/ioctl.h b/ioctl.h index e30687c..85c5dcc 100644 --- a/ioctl.h +++ b/ioctl.h @@ -142,7 +142,8 @@ struct btrfs_ioctl_balance_progress { #define BTRFS_BALANCE_FILTER_CHUNK_TYPE 0x2 #define BTRFS_BALANCE_FILTER_DEVID 0x4 -#define BTRFS_BALANCE_FILTER_MASK 0x7 +#define BTRFS_BALANCE_FILTER_VIRTUAL_ADDRESS_RANGE 0x8 +#define BTRFS_BALANCE_FILTER_MASK 0xf /* All the possible options for a filter */ struct btrfs_ioctl_balance_start { @@ -159,7 +160,11 @@ struct btrfs_ioctl_balance_start { /* For FILTER_DEVID */ __u64 devid; - __u64 spare[506]; /* Make up the size of the structure to 4088 + /* For FILTER_VIRTUAL_ADDRESS_RANGE */ + __u64 vrange_start; + __u64 vrange_end; + + __u64 spare[504]; /* Make up the size of the structure to 4088 * bytes for future expansion */ }; diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 020260f..c49a82c 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -210,6 +210,15 @@ Select chunks which have data on device ID \fI<n>\fR. This can be used, for example, to reduplicate data in a mirrored configuration where one drive has been lost due to hardware failure. +.TP +\fBvrange\fR=\fI<start>\fB,\fI<end>\fR + +Select chunks which have btrfs-internal virtual addresses within the +range \fI<start>\fR (inclusive) to \fI<end>\fR (exclusive). Given the +address of the last chunk moved, this filter can be used to restart a +cancelled or interrupted balance operation, by supplying a range of +\fB0,\fI<chunkaddr+1>\fR. + .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in case of failure. -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Implement the userspace side of the balance filter for a range of bytes on any device. Note that this will match the same range on any device, so the use of the devid filter is recommended where this filter is used. Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs_cmds.c | 22 ++++++++++++++++++++++ ioctl.h | 9 +++++++-- man/btrfs.8.in | 8 ++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/btrfs_cmds.c b/btrfs_cmds.c index 1f6149d..f507626 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -785,6 +785,12 @@ const struct filter_class_desc filter_class[] = { "\trange of the filesystem''s virtual address space.\n" "\t<start> is inclusive, <end> is exclusive.\n", BTRFS_BALANCE_FILTER_VIRTUAL_ADDRESS_RANGE }, + { "drange", + "drange=<start>,<end>\n" + "\tBalances chunks which have any bytes within the given\n" + "\tbyte range on any of the filesystem''s underlying devices.\n" + "\t<start> is inclusive, <end> is exclusive.\n", + BTRFS_BALANCE_FILTER_DEVICE_ADDRESS_RANGE }, { NULL, NULL, 0 } }; @@ -905,6 +911,22 @@ int parse_filter(struct btrfs_ioctl_balance_start *args, char *filters_string) return 15; } break; + + case BTRFS_BALANCE_FILTER_DEVICE_ADDRESS_RANGE: + errno = 0; + args->drange_start = strtoull(part, NULL, 10); + if (errno != 0) { + fprintf(stderr, "ERROR: ''%s'' is not a valid start address\n", part); + return 15; + } + part = strtok_r(NULL, "=,", &subsave); + errno = 0; + args->drange_end = strtoull(part, NULL, 10); + if (errno != 0) { + fprintf(stderr, "ERROR: ''%s'' is not a valid end address\n", part); + return 15; + } + break; } this_filter_string = strtok_r(NULL, ":", &saveptr); diff --git a/ioctl.h b/ioctl.h index 85c5dcc..e6c676f 100644 --- a/ioctl.h +++ b/ioctl.h @@ -143,7 +143,8 @@ struct btrfs_ioctl_balance_progress { #define BTRFS_BALANCE_FILTER_CHUNK_TYPE 0x2 #define BTRFS_BALANCE_FILTER_DEVID 0x4 #define BTRFS_BALANCE_FILTER_VIRTUAL_ADDRESS_RANGE 0x8 -#define BTRFS_BALANCE_FILTER_MASK 0xf +#define BTRFS_BALANCE_FILTER_DEVICE_ADDRESS_RANGE 0x10 +#define BTRFS_BALANCE_FILTER_MASK 0x1f /* All the possible options for a filter */ struct btrfs_ioctl_balance_start { @@ -164,7 +165,11 @@ struct btrfs_ioctl_balance_start { __u64 vrange_start; __u64 vrange_end; - __u64 spare[504]; /* Make up the size of the structure to 4088 + /* For FILTER_DEVICE_ADDRESS_RANGE */ + __u64 drange_start; + __u64 drange_end; + + __u64 spare[502]; /* Make up the size of the structure to 4088 * bytes for future expansion */ }; diff --git a/man/btrfs.8.in b/man/btrfs.8.in index c49a82c..45b7abc 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -219,6 +219,14 @@ address of the last chunk moved, this filter can be used to restart a cancelled or interrupted balance operation, by supplying a range of \fB0,\fI<chunkaddr+1>\fR. +.TP +\fBdrange\fR=\fI<start>\fB,\fI<end>\fR + +Select chunks which contain data in the address range \fI<start>\fR +(inclusive) to \fI<end>\fR (exclusive) on \fIany\fR block device in +the filesystem. Can be mixed with the \fBdevid\fR filter to select +chunks in a given address range on a specific device. + .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in case of failure. -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Andreas Philipp
2011-Jun-30 22:18 UTC
Re: [PATCH v6 2/8] Add --monitor option to btrfs balance progress.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 01.05.2011 17:47, Hugo Mills wrote:> For the impatient, this patch introduces the pot-watching > --monitor option, which checks the balance progress at regular > intervals, and updates a single status line with the current > progress and an estimated completion time. > > Signed-off-by: Hugo Mills <hugo@carfax.org.uk> --- btrfs.c | > 4 +- btrfs_cmds.c | 109 > ++++++++++++++++++++++++++++++++++++++++++++++++++----- ioctl.h > | 2 +- man/btrfs.8.in | 7 ++-- 4 files changed, 106 > insertions(+), 16 deletions(-) > > diff --git a/btrfs.c b/btrfs.c index 3a24019..0b6186c 100644 --- > a/btrfs.c +++ b/btrfs.c @@ -99,8 +99,8 @@ static struct Command > commands[] = { "balance start", "<path>\n" "Synonym for \"btrfs > filesystem balance\"." }, - { do_balance_progress, 1, - "balance > progress", "<path>\n" + { do_balance_progress, -1, + "balance > progress", "[-m|--monitor] <path>\n" "Show progress of the balance > operation running on <path>." }, { do_scan, diff --git > a/btrfs_cmds.c b/btrfs_cmds.c index 00dda0a..ad2300d 100644 --- > a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -797,22 +797,108 @@ int > get_balance_progress(char *path, struct > btrfs_ioctl_balance_progress *bal) return err; } > > +const struct option progress_options[] = { + { "monitor", 0, NULL, > ''m'' }, + { NULL, 0, NULL, 0 } +}; + int do_balance_progress(int > argc, char **argv) { char *path; int ret = 0; int err = 0; struct > btrfs_ioctl_balance_progress bal; + __u64 last_completed = -1; + > __u64 initial_completed = -1; + struct timeval now; + struct > timeval started; + int monitor = 0; + + optind = 1; + while(1) { + > int c = getopt_long(argc, argv, "m", progress_options, NULL); + if > (c < 0) + break; + switch(c) { + case ''m'': + monitor = 1; + > break; + default: + fprintf(stderr, "Invalid arguments for > balance progress\n"); + free(argv); + return 1; + } + } + + > if(optind >= argc) { + fprintf(stderr, "No filesystem path given > for progress\n"); + return 1; + } + + path = argv[optind]; + do { > + int prs = 0; > > - path = argv[1]; + ret = get_balance_progress(path, &bal); + if > (ret) + break; > > - ret = get_balance_progress(path, &bal); - if (!ret) - > printf("\r%u/%u block groups moved, " - "%0.2f%% > complete.\n", - bal.completed, - bal.expected, - > (float)bal.completed/bal.expected*100.0); + if (last_completed !> bal.completed) { + printf("\r%u/%u block groups moved, " + > "%0.2f%% complete.", + bal.completed, + > bal.expected, + (float)bal.completed/bal.expected*100.0); > + } + + if (initial_completed != -1 + && initial_completed > != bal.completed) { + ret = gettimeofday(&now, NULL); + if > (ret) { + fprintf(stderr, "Can''t read current time\n"); + > return 22; + } + /* Seconds per block */ + float rate > (float)(now.tv_sec - started.tv_sec) + / (bal.completed - > initial_completed); + int secs_remaining = rate + * > (bal.expected - bal.completed); + printf(" Time remaining"); + > if (secs_remaining >= 60*60*24) { + printf(" %dd", > secs_remaining / (60*60*24)); + secs_remaining %= 60*60*24; + > prs = 1; + } + if (prs || secs_remaining >= 60*60) { + > printf(" %dh", secs_remaining / (60*60)); + secs_remaining %> 60*60; + prs = 1; + } + if (prs || secs_remaining > 60) { + > printf(" %dm", secs_remaining / 60); + secs_remaining %= 60; + > } + printf(" %ds\x1b[K", secs_remaining); + } + + if > (last_completed != -1 && last_completed != bal.completed) { + > initial_completed = bal.completed; + ret = gettimeofday(&started, > NULL); + if (ret) { + fprintf(stderr, "Can''t read current > time\n"); + return 22; + } + } + + last_completed > bal.completed; + + if (monitor) { + fflush(stdout); + > sleep(1); + } else { + printf("\n"); + } + } while(monitor); > > switch(ret) { case 0: @@ -821,10 +907,13 @@ int > do_balance_progress(int argc, char **argv) fprintf(stderr, "ERROR: > can''t access ''%s''\n", path); return 13; case EINVAL: - > fprintf(stderr, + if (!monitor) { + fprintf(stderr, "No > balance operation running on ''%s''.\n", path); - return 20; + > return 20; + } + break; default: fprintf(stderr, "ERROR: ioctl > returned error %d.", err);The output of fprintf should end with a newline. Cheers, Andreas> return 21; diff --git a/ioctl.h b/ioctl.h index f07d3a2..3eeaa33 > 100644 --- a/ioctl.h +++ b/ioctl.h @@ -174,6 +174,6 @@ struct > btrfs_ioctl_balance_progress { #define BTRFS_IOC_DEFAULT_SUBVOL > _IOW(BTRFS_IOCTL_MAGIC, 19, u64) #define BTRFS_IOC_SPACE_INFO > _IOWR(BTRFS_IOCTL_MAGIC, 20, \ struct btrfs_ioctl_space_args) > -#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 25, \ > +#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 27, \ > struct btrfs_ioctl_balance_progress) #endif diff --git > a/man/btrfs.8.in b/man/btrfs.8.in index 7b66fb7..5fcad89 100644 --- > a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -27,7 +27,7 @@ btrfs \- > control a btrfs filesystem .PP \fBbtrfs\fP \fBbalance start\fP\fI > <path> \fP .PP -\fBbtrfs\fP \fBbalance progress\fP\fI <path>\fP > +\fBbtrfs\fP \fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] > \fI<path>\fP .PP \fBbtrfs\fP \fBdevice show\fP\fI <dev>|<label> > [<dev>|<label>...]\fP .PP @@ -162,9 +162,10 @@ Add device(s) to the > filesystem identified by \fI<path>\fR. Remove device(s) from a > filesystem identified by \fI<path>\fR. .PP > > -\fBbalance progress\fP \fI<path>\fP +\fBbalance progress\fP > [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP Report progress on the > currently-running balance operation on the -filesystem mounted at > \fI<path>\fP. +filesystem mounted at \fI<path>\fP. Use --monitor to > report progress +continually, including an estimate of completion > time. > > .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it > succeeds. Non zero is returned in-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQIcBAEBAgAGBQJODPY2AAoJEJIcBJ3+XkgibsMP/Rl3UAdWks4qsTG5zHmhK2hd QgvveYc7eA5vbIFIXXLpWMmdgALvkogdsVae51PBdHe9Pc5KbVvH4n9VggGyMul7 cYJRmYLxXAwXnho8bqlCW6MBxZnYnUuEfG8BVmr7NbChwckr0+ffa5c76ZFb7B4n CyQF9JN8iwGHb808IlsHj2GOEUn9QZC/NzaUE62HuVK4s02FtUdWtvpzIt991IgG 4yWkH6te13WUGnfKTfmXBNUM+9K7Zf29TRHRCOOD7q4mWdZcc81/Up7sB590kjzg byWxZggc0sT9sL2WXkyiP+Wxsh4zeNo1sNzIPABMncdvkOToz1mGr53Ya15cqfgO 3yjrrScc/9XUweJnrz5aymUnYSyH/pBA9uNPlffYZEgTVCkC041nU/y1ly9Qxbji aObpFu8QWfIYw2igUOlPPr+bMdp3hpWmDrEaYsu+q6QpVSRj8M2fUqSNBaGtPXja lqgfgUSRmEcxgVPJwYUzNZht28qVKb26p+vi6F0DNBfAHuMXXZOOjsx79dX1eHw/ GRIqtYskyD9cGEvYHCsEmWfOJuyFjR+RgQwf1Qg21S8ZeZR9fP6Bwdht9dW5ngax c1LU5q2gB8ojPLG9QzO5/XAjSJpjRuu7T+CHdm5rndEZd8+qgp0+WQWDS84m5JEs zp0Jc8DBkq+RxmwNls9w =JR07 -----END PGP SIGNATURE----- -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Andreas Philipp
2011-Jun-30 22:22 UTC
Re: [PATCH v6 2/8] Add --monitor option to btrfs balance progress.
On 01.05.2011 17:47, Hugo Mills wrote:> For the impatient, this patch introduces the pot-watching --monitor > option, which checks the balance progress at regular intervals, and > updates a single status line with the current progress and an > estimated completion time. > > Signed-off-by: Hugo Mills <hugo@carfax.org.uk> > --- > btrfs.c | 4 +- > btrfs_cmds.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++----- > ioctl.h | 2 +- > man/btrfs.8.in | 7 ++-- > 4 files changed, 106 insertions(+), 16 deletions(-) > > diff --git a/btrfs.c b/btrfs.c > index 3a24019..0b6186c 100644 > --- a/btrfs.c > +++ b/btrfs.c > @@ -99,8 +99,8 @@ static struct Command commands[] = { > "balance start", "<path>\n" > "Synonym for \"btrfs filesystem balance\"." > }, > - { do_balance_progress, 1, > - "balance progress", "<path>\n" > + { do_balance_progress, -1, > + "balance progress", "[-m|--monitor] <path>\n" > "Show progress of the balance operation running on <path>." > }, > { do_scan, > diff --git a/btrfs_cmds.c b/btrfs_cmds.c > index 00dda0a..ad2300d 100644 > --- a/btrfs_cmds.c > +++ b/btrfs_cmds.c > @@ -797,22 +797,108 @@ int get_balance_progress(char *path, struct btrfs_ioctl_balance_progress *bal) > return err; > } > > +const struct option progress_options[] = { > + { "monitor", 0, NULL, ''m'' }, > + { NULL, 0, NULL, 0 } > +}; > + > int do_balance_progress(int argc, char **argv) > { > char *path; > int ret = 0; > int err = 0; > struct btrfs_ioctl_balance_progress bal; > + __u64 last_completed = -1; > + __u64 initial_completed = -1; > + struct timeval now; > + struct timeval started; > + int monitor = 0; > + > + optind = 1; > + while(1) { > + int c = getopt_long(argc, argv, "m", progress_options, NULL); > + if (c < 0) > + break; > + switch(c) { > + case ''m'': > + monitor = 1; > + break; > + default: > + fprintf(stderr, "Invalid arguments for balance progress\n"); > + free(argv); > + return 1; > + } > + } > + > + if(optind >= argc) { > + fprintf(stderr, "No filesystem path given for progress\n"); > + return 1; > + } > + > + path = argv[optind]; > + do { > + int prs = 0; > > - path = argv[1]; > + ret = get_balance_progress(path, &bal); > + if (ret) > + break; > > - ret = get_balance_progress(path, &bal); > - if (!ret) > - printf("\r%u/%u block groups moved, " > - "%0.2f%% complete.\n", > - bal.completed, > - bal.expected, > - (float)bal.completed/bal.expected*100.0); > + if (last_completed != bal.completed) { > + printf("\r%u/%u block groups moved, " > + "%0.2f%% complete.", > + bal.completed, > + bal.expected, > + (float)bal.completed/bal.expected*100.0); > + } > + > + if (initial_completed != -1 > + && initial_completed != bal.completed) { > + ret = gettimeofday(&now, NULL); > + if (ret) { > + fprintf(stderr, "Can''t read current time\n"); > + return 22; > + } > + /* Seconds per block */ > + float rate = (float)(now.tv_sec - started.tv_sec) > + / (bal.completed - initial_completed); > + int secs_remaining = rate > + * (bal.expected - bal.completed); > + printf(" Time remaining"); > + if (secs_remaining >= 60*60*24) { > + printf(" %dd", secs_remaining / (60*60*24)); > + secs_remaining %= 60*60*24; > + prs = 1; > + } > + if (prs || secs_remaining >= 60*60) { > + printf(" %dh", secs_remaining / (60*60)); > + secs_remaining %= 60*60; > + prs = 1; > + } > + if (prs || secs_remaining > 60) { > + printf(" %dm", secs_remaining / 60); > + secs_remaining %= 60; > + } > + printf(" %ds\x1b[K", secs_remaining); > + } > + > + if (last_completed != -1 && last_completed != bal.completed) { > + initial_completed = bal.completed; > + ret = gettimeofday(&started, NULL); > + if (ret) { > + fprintf(stderr, "Can''t read current time\n"); > + return 22; > + } > + } > + > + last_completed = bal.completed; > + > + if (monitor) { > + fflush(stdout); > + sleep(1); > + } else { > + printf("\n"); > + } > + } while(monitor); > > switch(ret) { > case 0: > @@ -821,10 +907,13 @@ int do_balance_progress(int argc, char **argv) > fprintf(stderr, "ERROR: can''t access ''%s''\n", path); > return 13; > case EINVAL: > - fprintf(stderr, > + if (!monitor) { > + fprintf(stderr, > "No balance operation running on ''%s''.\n", > path); > - return 20; > + return 20; > + } > + break; > default: > fprintf(stderr, "ERROR: ioctl returned error %d.", err);The output of fprintf should be terminated by a newline. Thanks, Andreas> return 21; > diff --git a/ioctl.h b/ioctl.h > index f07d3a2..3eeaa33 100644 > --- a/ioctl.h > +++ b/ioctl.h > @@ -174,6 +174,6 @@ struct btrfs_ioctl_balance_progress { > #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64) > #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ > struct btrfs_ioctl_space_args) > -#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 25, \ > +#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 27, \ > struct btrfs_ioctl_balance_progress) > #endif > diff --git a/man/btrfs.8.in b/man/btrfs.8.in > index 7b66fb7..5fcad89 100644 > --- a/man/btrfs.8.in > +++ b/man/btrfs.8.in > @@ -27,7 +27,7 @@ btrfs \- control a btrfs filesystem > .PP > \fBbtrfs\fP \fBbalance start\fP\fI <path> \fP > .PP > -\fBbtrfs\fP \fBbalance progress\fP\fI <path>\fP > +\fBbtrfs\fP \fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP > .PP > \fBbtrfs\fP \fBdevice show\fP\fI <dev>|<label> [<dev>|<label>...]\fP > .PP > @@ -162,9 +162,10 @@ Add device(s) to the filesystem identified by \fI<path>\fR. > Remove device(s) from a filesystem identified by \fI<path>\fR. > .PP > > -\fBbalance progress\fP \fI<path>\fP > +\fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP > Report progress on the currently-running balance operation on the > -filesystem mounted at \fI<path>\fP. > +filesystem mounted at \fI<path>\fP. Use --monitor to report progress > +continually, including an estimate of completion time. > > .SH EXIT STATUS > \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html