diff options
author | Damien Le Moal | 2017-02-24 07:45:31 +0100 |
---|---|---|
committer | Karel Zak | 2017-02-24 11:53:45 +0100 |
commit | f1b8b84d3476ac910d922c63a50a4129adbaf584 (patch) | |
tree | fa23bbc3dface8fd942ca77acec72036be92fad9 | |
parent | blkzone: Improve zone information print (diff) | |
download | kernel-qcow2-util-linux-f1b8b84d3476ac910d922c63a50a4129adbaf584.tar.gz kernel-qcow2-util-linux-f1b8b84d3476ac910d922c63a50a4129adbaf584.tar.xz kernel-qcow2-util-linux-f1b8b84d3476ac910d922c63a50a4129adbaf584.zip |
blkzone: Add --count option
The length option is used to specify the number of zones to
operate on. To be more consistent with other tools, have this
option use a number of sectors and introduce the --count option
to allow users to specify a number of zones.
The --count and --length options cannot be used together on
the command line.
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
-rw-r--r-- | sys-utils/blkzone.8 | 39 | ||||
-rw-r--r-- | sys-utils/blkzone.c | 76 |
2 files changed, 76 insertions, 39 deletions
diff --git a/sys-utils/blkzone.8 b/sys-utils/blkzone.8 index 24b0cc7bd..983b04411 100644 --- a/sys-utils/blkzone.8 +++ b/sys-utils/blkzone.8 @@ -10,7 +10,7 @@ blkzone \- run zone command on a device .B blkzone is used to run zone command on device that support the Zoned Block Commands (ZBC) or Zoned-device ATA Commands (ZAC). The zones to operate on can be -specified using the offset and length options. +specified using the offset, count and length options. .PP The .I device @@ -19,8 +19,8 @@ argument is the pathname of the block device. .SS report The command \fBblkzone report\fP is used to report device zone information. .PP -By default, the command will report on up to 4k zones from the start of the -block device. Options may be used to modify this behavior, changing the +By default, the command will report all zones from the start of the +block device. Options may be used to modify this behavior, changing the starting zone or the size of the report, as explained below. .B Report output @@ -52,34 +52,43 @@ x?:Reserved conditions (should not be reported) .TE .SS reset -The command \fBblkzone reset\fP is used to reset one or more zones. Unlike -.BR sg_reset_wp (8) , +The command \fBblkzone reset\fP is used to reset one or more zones. Unlike +.BR sg_reset_wp (8), this command operates from the block layer and can reset a range of zones. .PP -By default, the command will operate from the zone at device logical +By default, the command will operate from the zone at device sector 0 and reset all zones. Options may be used to modify this behavior as well as specify the operation to be performed on the zone, as explained below. -.PP -The default number of zones (option \fB\-\-length\fP) is all zones. .SH OPTIONS The .I offset -option argument may be followed by the multiplicative suffixes KiB (=1024), +and +.I length +option arguments may be followed by the multiplicative suffixes KiB (=1024), MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB (the "iB" is optional, e.g., "K" has the same meaning as "KiB") or the suffixes KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB and YB. -Additionally, the 0x prefix can be used to specify \fIoffset\fR in hex. +Additionally, the 0x prefix can be used to specify \fIoffset\fR and +\fIlength\fR in hex. .TP .BR \-o , " \-\-offset "\fIsector\fP -The starting zone specified as a sector offset. The provided offset in sector -units (512 bytes) should match the start of a zone. The default value is zero. +The starting zone specified as a sector offset. The provided offset in sector +units (512 bytes) should match the start of a zone. The default value is zero. +.TP +.BR \-l , " \-\-length "\fIsectors\fP +The maximum number of sectors the command should operate on. The default value +is the number of sectors remaining after \fIoffset\fR. This option cannot be +used together with the option \fB\-\-count\fP. .TP -.BR \-l , " \-\-length "\fIcount\fP -The maximum number of zones to be used for the command. +.BR \-l , " \-\-count "\fIcount\fP +The maximum number of zones the command should operate on. The default value +is the nuber of zones starting from \fIoffset\fR. This option cannot be +used together with the option \fB\-\-length\fP. .TP .BR \-v , " \-\-verbose" -Display the number of zones returned in the report. +Display the number of zones returned in the report or the range of sectors +reset.. .TP .BR \-V , " \-\-version" Display version information and exit. diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c index 2d6a76015..b9f1ed752 100644 --- a/sys-utils/blkzone.c +++ b/sys-utils/blkzone.c @@ -63,6 +63,7 @@ struct blkzone_control { uint64_t offset; uint64_t length; + uint32_t count; unsigned int verbose : 1; }; @@ -137,7 +138,7 @@ static unsigned long blkdev_chunk_sectors(const char *dname) /* * blkzone report */ -#define DEF_REPORT_LEN (1 << 12) /* 4k zones per report (256k kzalloc) */ +#define DEF_REPORT_LEN (1U << 12) /* 4k zones per report (256k kzalloc) */ static const char *type_text[] = { "RESERVED", @@ -162,26 +163,31 @@ static int blkzone_report(struct blkzone_control *ctl) { struct blk_zone_report *zi; unsigned long zonesize; - uint32_t i; + uint32_t i, nr_zones; int fd; fd = init_device(ctl, O_RDONLY); if (ctl->offset > ctl->total_sectors) errx(EXIT_FAILURE, _("%s: offset is greater than device size"), ctl->devname); - if (ctl->length < 1) { - zonesize = blkdev_chunk_sectors(ctl->devname); - if (!zonesize) - errx(EXIT_FAILURE, _("%s: unable to determine zone size"), ctl->devname); - ctl->length = 1 + (ctl->total_sectors - ctl->offset) / zonesize; - } + + zonesize = blkdev_chunk_sectors(ctl->devname); + if (!zonesize) + errx(EXIT_FAILURE, _("%s: unable to determine zone size"), ctl->devname); + + if (ctl->count) + nr_zones = ctl->count; + else if (ctl->length) + nr_zones = (ctl->length + zonesize - 1) / zonesize; + else + nr_zones = 1 + (ctl->total_sectors - ctl->offset) / zonesize; zi = xmalloc(sizeof(struct blk_zone_report) + (DEF_REPORT_LEN * sizeof(struct blk_zone))); - while (ctl->length && ctl->offset < ctl->total_sectors) { + while (nr_zones && ctl->offset < ctl->total_sectors) { - zi->nr_zones = min(ctl->length, (uint64_t)DEF_REPORT_LEN); + zi->nr_zones = min(nr_zones, DEF_REPORT_LEN); zi->sector = ctl->offset; if (ioctl(fd, BLKREPORTZONE, zi) == -1) @@ -192,7 +198,7 @@ static int blkzone_report(struct blkzone_control *ctl) zi->nr_zones, ctl->offset); if (!zi->nr_zones) { - ctl->length = 0; + nr_zones = 0; break; } @@ -205,7 +211,7 @@ static int blkzone_report(struct blkzone_control *ctl) uint64_t len = entry->len; if (!len) { - ctl->length = 0; + nr_zones = 0; break; } @@ -216,7 +222,7 @@ static int blkzone_report(struct blkzone_control *ctl) cond, condition_str[cond & ARRAY_SIZE(condition_str)], type, type_text[type]); - ctl->length--; + nr_zones--; ctl->offset = start + len; } @@ -246,31 +252,39 @@ static int blkzone_reset(struct blkzone_control *ctl) fd = init_device(ctl, O_WRONLY); if (ctl->offset & (zonesize - 1)) - errx(EXIT_FAILURE, _("%s: zone %" PRIu64 " is not aligned " + errx(EXIT_FAILURE, _("%s: offset %" PRIu64 " is not aligned " "to zone size %" PRIu64), ctl->devname, ctl->offset, zonesize); if (ctl->offset > ctl->total_sectors) errx(EXIT_FAILURE, _("%s: offset is greater than device size"), ctl->devname); - if (!ctl->length) - zlen = ctl->total_sectors; + if (ctl->count) + zlen = ctl->count * zonesize; + else if (ctl->length) + zlen = ctl->length; else - zlen = ctl->length * zonesize; + zlen = ctl->total_sectors; if (ctl->offset + zlen > ctl->total_sectors) zlen = ctl->total_sectors - ctl->offset; + if (ctl->length && + (zlen & (zonesize - 1)) && + ctl->offset + zlen != ctl->total_sectors) + errx(EXIT_FAILURE, _("%s: number of sectors %" PRIu64 " is not aligned " + "to zone size %" PRIu64), + ctl->devname, ctl->length, zonesize); + za.sector = ctl->offset; za.nr_sectors = zlen; if (ioctl(fd, BLKRESETZONE, &za) == -1) err(EXIT_FAILURE, _("%s: BLKRESETZONE ioctl failed"), ctl->devname); - else if (ctl->verbose) printf(_("%s: successfully reset in range from %" PRIu64 ", to %" PRIu64), ctl->devname, ctl->offset, - zlen); + ctl->offset + zlen); close(fd); return 0; } @@ -291,7 +305,8 @@ static void __attribute__((__noreturn__)) usage(FILE *out) fputs(USAGE_OPTIONS, out); fputs(_(" -o, --offset <sector> start sector of zone to act (in 512-byte sectors)\n"), out); - fputs(_(" -l, --length <number> maximum number of zones\n"), out); + fputs(_(" -l, --length <sectors> maximum sectors to act (in 512-byte sectors)\n"), out); + fputs(_(" -c, --count <number> maximum number of zones\n"), out); fputs(_(" -v, --verbose display more details\n"), out); fputs(USAGE_SEPARATOR, out); fputs(USAGE_HELP, out); @@ -304,11 +319,17 @@ static void __attribute__((__noreturn__)) usage(FILE *out) int main(int argc, char **argv) { int c; - struct blkzone_control ctl = { .devname = NULL }; + struct blkzone_control ctl = { + .devname = NULL, + .offset = 0, + .count = 0, + .length = 0 + }; static const struct option longopts[] = { { "help", no_argument, NULL, 'h' }, - { "length", required_argument, NULL, 'l' }, /* max #of zones (entries) for result */ + { "count", required_argument, NULL, 'c' }, /* max #of zones to operate on */ + { "length", required_argument, NULL, 'l' }, /* max of sectors to operate on */ { "offset", required_argument, NULL, 'o' }, /* starting LBA */ { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, @@ -328,14 +349,18 @@ int main(int argc, char **argv) argc--; } - while ((c = getopt_long(argc, argv, "hl:o:vV", longopts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "hc:l:o:vV", longopts, NULL)) != -1) { switch (c) { case 'h': usage(stdout); break; + case 'c': + ctl.count = strtou32_or_err(optarg, + _("failed to parse number of zones")); + break; case 'l': ctl.length = strtosize_or_err(optarg, - _("failed to parse number of zones")); + _("failed to parse number of sectors")); break; case 'o': ctl.offset = strtosize_or_err(optarg, @@ -355,6 +380,9 @@ int main(int argc, char **argv) if (!ctl.command) errx(EXIT_FAILURE, _("no command specified")); + if (ctl.count && ctl.length) + errx(EXIT_FAILURE, _("zone count and number of sectors cannot be specified together")); + if (optind == argc) errx(EXIT_FAILURE, _("no device specified")); ctl.devname = argv[optind++]; |