diff options
-rw-r--r-- | cmds-scrub.c | 40 | ||||
-rw-r--r-- | man/btrfs.8.in | 22 |
2 files changed, 55 insertions, 7 deletions
diff --git a/cmds-scrub.c b/cmds-scrub.c index f06eb20d..59223615 100644 --- a/cmds-scrub.c +++ b/cmds-scrub.c @@ -24,6 +24,7 @@ #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> +#include <sys/syscall.h> #include <poll.h> #include <sys/file.h> #include <uuid/uuid.h> @@ -60,6 +61,15 @@ struct scrub_stats { u64 canceled; }; +/* TBD: replace with #include "linux/ioprio.h" in some years */ +#if !defined (IOPRIO_H) +#define IOPRIO_WHO_PROCESS 1 +#define IOPRIO_CLASS_SHIFT 13 +#define IOPRIO_PRIO_VALUE(class, data) \ + (((class) << IOPRIO_CLASS_SHIFT) | (data)) +#define IOPRIO_CLASS_IDLE 3 +#endif + struct scrub_progress { struct btrfs_ioctl_scrub_args scrub_args; int fd; @@ -69,6 +79,8 @@ struct scrub_progress { struct scrub_file_record *resumed; int ioctl_errno; pthread_mutex_t progress_mutex; + int ioprio_class; + int ioprio_classdata; }; struct scrub_file_record { @@ -813,6 +825,14 @@ static void *scrub_one_dev(void *ctx) sp->stats.duration = 0; sp->stats.finished = 0; + ret = syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0, + IOPRIO_PRIO_VALUE(sp->ioprio_class, + sp->ioprio_classdata)); + if (ret) + fprintf(stderr, + "WARNING: setting ioprio failed: %s (ignored).\n", + strerror(errno)); + ret = ioctl(sp->fd, BTRFS_IOC_SCRUB, &sp->scrub_args); gettimeofday(&tv, NULL); sp->ret = ret; @@ -1029,6 +1049,8 @@ static int scrub_start(int argc, char **argv, int resume) int do_record = 1; int readonly = 0; int do_stats_per_dev = 0; + int ioprio_class = IOPRIO_CLASS_IDLE; + int ioprio_classdata = 0; int n_start = 0; int n_skip = 0; int n_resume = 0; @@ -1054,7 +1076,7 @@ static int scrub_start(int argc, char **argv, int resume) u64 devid; optind = 1; - while ((c = getopt(argc, argv, "BdqrR")) != -1) { + while ((c = getopt(argc, argv, "BdqrRc:n:")) != -1) { switch (c) { case 'B': do_background = 0; @@ -1073,6 +1095,12 @@ static int scrub_start(int argc, char **argv, int resume) case 'R': print_raw = 1; break; + case 'c': + ioprio_class = (int)strtol(optarg, NULL, 10); + break; + case 'n': + ioprio_classdata = (int)strtol(optarg, NULL, 10); + break; case '?': default: usage(resume ? cmd_scrub_resume_usage : @@ -1182,6 +1210,8 @@ static int scrub_start(int argc, char **argv, int resume) sp[i].skip = 0; sp[i].scrub_args.end = (u64)-1ll; sp[i].scrub_args.flags = readonly ? BTRFS_SCRUB_READONLY : 0; + sp[i].ioprio_class = ioprio_class; + sp[i].ioprio_classdata = ioprio_classdata; } if (!n_start && !n_resume) { @@ -1435,13 +1465,15 @@ out: } static const char * const cmd_scrub_start_usage[] = { - "btrfs scrub start [-Bdqr] <path>|<device>", + "btrfs scrub start Bdqr] [-c ioprio_class -n ioprio_classdata] <path>|<device>\n", "Start a new scrub", "", "-B do not background", "-d stats per device (-B only)", "-q be quiet", "-r read only mode", + "-c set ioprio class (see ionice(1) manpage)", + "-n set ioprio classdata (see ionice(1) manpage)", NULL }; @@ -1494,13 +1526,15 @@ out: } static const char * const cmd_scrub_resume_usage[] = { - "btrfs scrub resume [-Bdqr] <path>|<device>", + "btrfs scrub resume [-Bdqr] [-c ioprio_class -n ioprio_classdata] <path>|<device>\n", "Resume previously canceled or interrupted scrub", "", "-B do not background", "-d stats per device (-B only)", "-q be quiet", "-r read only mode", + "-c set ioprio class (see ionice(1) manpage)", + "-n set ioprio classdata (see ionice(1) manpage)", NULL }; diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 94f4ffea..08e5fd79 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -47,11 +47,11 @@ btrfs \- control a btrfs filesystem .PP \fBbtrfs\fP \fBreplace cancel\fP \fI<path>\fP .PP -\fBbtrfs\fP \fBscrub start\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP} +\fBbtrfs\fP \fBscrub start\fP [-Bdqru] [-c ioprio_class -n ioprio_classdata] {\fI<path>\fP|\fI<device>\fP} .PP \fBbtrfs\fP \fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP} .PP -\fBbtrfs\fP \fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP} +\fBbtrfs\fP \fBscrub resume\fP [-Bdqru] [-c ioprio_class -n ioprio_classdata] {\fI<path>\fP|\fI<device>\fP} .PP \fBbtrfs\fP \fBscrub status\fP [-d] {\fI<path>\fP|\fI<device>\fP} .PP @@ -355,11 +355,16 @@ Cancel a running device replace operation. .TP \fBscrub start\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP} +\fBscrub start\fP [-Bdqru] [-c ioprio_class -n ioprio_classdata] {\fI<path>\fP|\fI<device>\fP} Start a scrub on all devices of the filesystem identified by \fI<path>\fR or on a single \fI<device>\fR. Without options, scrub is started as a background process. Progress can be obtained with the \fBscrub status\fR command. Scrubbing involves reading all data from all disks and verifying checksums. Errors are corrected along the way if possible. +.IP +The default IO priority of scrub is the idle class. The priority can be configured similar to the +.BR ionice (1) +syntax. .RS \fIOptions\fR @@ -373,6 +378,14 @@ Quiet. Omit error messages and statistics. Read only mode. Do not attempt to correct anything. .IP -u 5 Scrub unused space as well. (NOT IMPLEMENTED) +.IP -c 5 +Set IO priority class (see +.BR ionice (1) +manpage). +.IP -n 5 +Set IO priority classdata (see +.BR ionice (1) +manpage). .RE .TP @@ -384,7 +397,7 @@ If a \fI<device>\fR is given, the corresponding filesystem is found and \fBscrub cancel\fP behaves as if it was called on that filesystem. .TP -\fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP} +\fBscrub resume\fP [-Bdqru] [-c ioprio_class -n ioprio_classdata] {\fI<path>\fP|\fI<device>\fP} Resume a canceled or interrupted scrub cycle on the filesystem identified by \fI<path>\fR or on a given \fI<device>\fR. Does not start a new scrub if the last scrub finished successfully. @@ -446,4 +459,5 @@ and not suitable for any uses other than benchmarking and review. Please refer to the btrfs wiki http://btrfs.wiki.kernel.org for further details. .SH SEE ALSO -.BR mkfs.btrfs (8) +.BR mkfs.btrfs (8), +.BR ionice (1) |