All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
@ 2017-01-23 13:32 Shaun Tancheff
  2017-02-09 12:36 ` Karel Zak
  2017-02-16 10:33 ` Karel Zak
  0 siblings, 2 replies; 13+ messages in thread
From: Shaun Tancheff @ 2017-01-23 13:32 UTC (permalink / raw)
  To: Karel Zak; +Cc: Shaun Tancheff, util-linux, Damien Le Moal, Bart Van Assche

This patch adds:
 - blkreset to issue Reset (Write Pointer) zone commands
 - blkreport to retrieve drive zone information

Signed-off-by: Shaun Tancheff <shaun@tancheff.com>
---
Changes for v3:
  - Renamed get_zone_size -> blkdev_chunk_sectors
  - Use blkdev_get_sectors instead of open coded BLKGETSIZE64 (fixes broken
    byte to sector shift).

Changes for v2:
  - Configure changes to require linux/blkzoned.h [Linux v4.10]
  - Cleanup of man pages
  - Removed redundant fall-back for missing linux/blkzoned.h
  - Removed unused report option (not yet implemented by Linux kernel.
  - Change report length to be (maximum) number of zones returned.
---
 .gitignore              |   2 +
 configure.ac            |  11 +++
 include/strutils.h      |   2 +
 lib/strutils.c          |   7 +-
 sys-utils/Makemodule.am |  17 ++++
 sys-utils/blkreport.8   |  68 ++++++++++++++
 sys-utils/blkreport.c   | 245 ++++++++++++++++++++++++++++++++++++++++++++++++
 sys-utils/blkreset.8    |  61 ++++++++++++
 sys-utils/blkreset.c    | 190 +++++++++++++++++++++++++++++++++++++
 9 files changed, 598 insertions(+), 5 deletions(-)
 create mode 100644 sys-utils/blkreport.8
 create mode 100644 sys-utils/blkreport.c
 create mode 100644 sys-utils/blkreset.8
 create mode 100644 sys-utils/blkreset.c

diff --git a/.gitignore b/.gitignore
index 2658dcd..c1e983b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,6 +62,8 @@ update.log
 /addpart
 /agetty
 /blkdiscard
+/blkreport
+/blkreset
 /blkid
 /blockdev
 /cal
diff --git a/configure.ac b/configure.ac
index fa3e6c8..da721e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -276,6 +276,8 @@ AC_CHECK_HEADERS([security/pam_misc.h],
 #endif
 ])
 
+AC_CHECK_HEADERS([linux/blkzoned.h])
+
 AC_CHECK_HEADERS([security/openpam.h], [], [], [
 #ifdef HAVE_SECURITY_PAM_APPL_H
 #include <security/pam_appl.h>
@@ -288,6 +290,7 @@ AC_CHECK_HEADERS([langinfo.h],
 
 dnl Convert some ac_cv_header_* variables to have_*
 dnl
+have_linux_blkzoned_h=$ac_cv_header_linux_blkzoned_h
 have_linux_btrfs_h=$ac_cv_header_linux_btrfs_h
 have_linux_raw_h=$ac_cv_header_linux_raw_h
 have_linux_securebits_h=$ac_cv_header_linux_securebits_h
@@ -1564,6 +1567,14 @@ UL_BUILD_INIT([blkdiscard], [check])
 UL_REQUIRES_LINUX([blkdiscard])
 AM_CONDITIONAL([BUILD_BLKDISCARD], [test "x$build_blkdiscard" = xyes])
 
+UL_BUILD_INIT([blkreport], [check])
+UL_REQUIRES_HAVE([blkreport], [linux_blkzoned_h], [linux/blkzoned.h header])
+AM_CONDITIONAL([BUILD_BLKREPORT], [test "x$build_blkreport" = xyes])
+
+UL_BUILD_INIT([blkreset], [check])
+UL_REQUIRES_HAVE([blkreset], [linux_blkzoned_h], [linux/blkzoned.h header])
+AM_CONDITIONAL([BUILD_BLKRESET], [test "x$build_blkreset" = xyes])
+
 UL_BUILD_INIT([ldattach], [check])
 UL_REQUIRES_LINUX([ldattach])
 AM_CONDITIONAL([BUILD_LDATTACH], [test "x$build_ldattach" = xyes])
diff --git a/include/strutils.h b/include/strutils.h
index aa31fc9..9e13b2b 100644
--- a/include/strutils.h
+++ b/include/strutils.h
@@ -26,10 +26,12 @@ extern uint16_t strtox16_or_err(const char *str, const char *errmesg);
 extern int32_t strtos32_or_err(const char *str, const char *errmesg);
 extern uint32_t strtou32_or_err(const char *str, const char *errmesg);
 extern uint32_t strtox32_or_err(const char *str, const char *errmesg);
+extern uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base);
 
 extern int64_t strtos64_or_err(const char *str, const char *errmesg);
 extern uint64_t strtou64_or_err(const char *str, const char *errmesg);
 extern uint64_t strtox64_or_err(const char *str, const char *errmesg);
+extern uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base);
 
 extern double strtod_or_err(const char *str, const char *errmesg);
 
diff --git a/lib/strutils.c b/lib/strutils.c
index d3daa36..2f6285d 100644
--- a/lib/strutils.c
+++ b/lib/strutils.c
@@ -264,9 +264,6 @@ char *strndup(const char *s, size_t n)
 }
 #endif
 
-static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base);
-static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base);
-
 int16_t strtos16_or_err(const char *str, const char *errmesg)
 {
 	int32_t num = strtos32_or_err(str, errmesg);
@@ -310,7 +307,7 @@ int32_t strtos32_or_err(const char *str, const char *errmesg)
 	return num;
 }
 
-static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base)
+uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base)
 {
 	uint64_t num = _strtou64_or_err(str, errmesg, base);
 
@@ -352,7 +349,7 @@ err:
 	errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
 }
 
-static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base)
+uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base)
 {
 	uintmax_t num;
 	char *end = NULL;
diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am
index 88be83e..2d3fdb0 100644
--- a/sys-utils/Makemodule.am
+++ b/sys-utils/Makemodule.am
@@ -126,6 +126,23 @@ blkdiscard_SOURCES = sys-utils/blkdiscard.c lib/monotonic.c
 blkdiscard_LDADD = $(LDADD) libcommon.la $(REALTIME_LIBS)
 endif
 
+if BUILD_BLKREPORT
+sbin_PROGRAMS += blkreport
+dist_man_MANS += sys-utils/blkreport.8
+blkreport_SOURCES = sys-utils/blkreport.c
+blkreport_LDADD = $(LDADD) libcommon.la $(REALTIME_LIBS)
+endif
+
+if BUILD_BLKRESET
+sbin_PROGRAMS += blkreset
+dist_man_MANS += sys-utils/blkreset.8
+blkreset_SOURCES = sys-utils/blkreset.c
+blkreset_LDADD = $(LDADD) libcommon.la $(REALTIME_LIBS)
+if HAVE_UDEV
+blkreset_LDADD += -ludev
+endif
+endif
+
 if BUILD_LDATTACH
 usrsbin_exec_PROGRAMS += ldattach
 dist_man_MANS += sys-utils/ldattach.8
diff --git a/sys-utils/blkreport.8 b/sys-utils/blkreport.8
new file mode 100644
index 0000000..2e65e39
--- /dev/null
+++ b/sys-utils/blkreport.8
@@ -0,0 +1,68 @@
+.TH BLKREPORT 5 "March 2016" "util-linux" "System Administration"
+.SH NAME
+blkreport \- report zones on a device
+.SH SYNOPSIS
+.B blkreport
+[options]
+.RB [ \-z
+.IR zone ]
+.RB [ \-c
+.IR count ]
+.I device
+.SH DESCRIPTION
+.B blkreport
+is used to report device zone information.  This is useful for
+zoned devices that support the ZAC or ZBC command set.
+.PP
+By default,
+.B blkreport
+will report on up to 4k zones from the start of the block device.
+Options may be used to modify this behavior based on the starting zone or
+size of the report, as explained below.
+.PP
+The
+.I device
+argument is the pathname of the block device.
+.PP
+.SH OPTIONS
+The
+.I zone
+and
+.I count
+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 common 0x prefix can be used to specify zone and length in hex.
+.TP
+.BR \-z , " \-\-zone \fIoffset", " \-\-offset \fIoffset"
+The starting zone of the report 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 \-c , " \-\-count \fIcount", " \-\-length \fIcount"
+The maximum number of zones to be returned by the report from the block device.
+Default is 4006, max is 65536
+.TP
+.BR \-v , " \-\-verbose"
+Display the number of zones returned in the report.
+.I offset
+and
+.IR length .
+.TP
+.BR \-V , " \-\-version"
+Display version information and exit.
+.TP
+.BR \-h , " \-\-help"
+Display help text and exit.
+.SH AUTHOR
+.MT shaun@tancheff.com
+Shaun Tancheff
+.ME
+.SH SEE ALSO
+.BR sg_rep_zones (8)
+.SH AVAILABILITY
+The blkreport command is part of the util-linux package and is available
+.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
+Linux Kernel Archive
+.UE .
diff --git a/sys-utils/blkreport.c b/sys-utils/blkreport.c
new file mode 100644
index 0000000..46c0377
--- /dev/null
+++ b/sys-utils/blkreport.c
@@ -0,0 +1,245 @@
+/*
+ * blkreport.c -- request a zone report on part (or all) of the block device.
+ *
+ * Copyright (C) 2015,2016 Seagate Technology PLC
+ * Written by Shaun Tancheff <shaun.tancheff@seagate.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This program uses BLKREPORT ioctl to query zone information about part of
+ * or a whole block device, if the device supports it.
+ * You can specify range (start and length) to be queried.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <getopt.h>
+#include <time.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <linux/fs.h>
+#include <linux/blkzoned.h>
+
+#include "nls.h"
+#include "strutils.h"
+#include "xalloc.h"
+#include "c.h"
+#include "closestream.h"
+#include "monotonic.h"
+
+static const char * type_text[] = {
+	"RESERVED",
+	"CONVENTIONAL",
+	"SEQ_WRITE_REQUIRED",
+	"SEQ_WRITE_PREFERRED",
+};
+
+#define ARRAY_COUNT(x) (sizeof((x))/sizeof((*x)))
+
+const char * condition_str[] = {
+	"cv", /* conventional zone */
+	"e0", /* empty */
+	"Oi", /* open implicit */
+	"Oe", /* open explicit */
+	"Cl", /* closed */
+	"x5", "x6", "x7", "x8", "x9", "xA", "xB", /* xN: reserved */
+	"ro", /* read only */
+	"fu", /* full */
+	"OL"  /* offline */
+	};
+
+static const char * zone_condition_str(uint8_t cond)
+{
+	return condition_str[cond & 0x0f];
+}
+
+static void print_zones(struct blk_zone *info, uint32_t count)
+{
+	uint32_t iter;
+
+	printf(_("Zones returned: %u\n"), count);
+
+	for (iter = 0; iter < count; iter++ ) {
+		struct blk_zone * entry = &info[iter];
+		unsigned int type  = entry->type;
+		uint64_t start = entry->start;
+		uint64_t wp = entry->wp;
+		uint8_t cond = entry->cond;
+		uint64_t len = entry->len;
+
+		if (!len)
+			break;
+
+		printf(_("  start: %9lx, len %6lx, wptr %6lx"
+			 " reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"),
+			start, len, wp - start,
+			entry->reset, entry->non_seq,
+			cond, zone_condition_str(cond),
+			type, type_text[type]);
+	}
+}
+
+static int do_report(int fd, uint64_t lba, uint32_t len, int verbose)
+{
+	int rc = -4;
+	struct blk_zone_report *zi;
+
+	zi = xmalloc(sizeof(struct blk_zone_report) + (len * sizeof(struct blk_zone)));
+	zi->nr_zones = len;
+	zi->sector = lba; /* maybe shift 4Kn -> 512e */
+	rc = ioctl(fd, BLKREPORTZONE, zi);
+	if (rc != -1) {
+		if (verbose)
+			printf(_("Found %d zones\n"), zi->nr_zones);
+		print_zones(zi->zones, zi->nr_zones);
+	} else {
+		warn(_("ERR: %d -> %s"), errno, strerror(errno));
+	}
+	free(zi);
+
+	return rc;
+}
+
+static void __attribute__((__noreturn__)) usage(FILE *out)
+{
+	fputs(USAGE_HEADER, out);
+	fprintf(out,
+	      _(" %s [options] <device>\n"), program_invocation_short_name);
+
+	fputs(USAGE_SEPARATOR, out);
+	fputs(_("Discard the content of sectors on a device.\n"), out);
+
+	fputs(USAGE_OPTIONS, out);
+	fputs(_(" -z, --zone <num>    zone lba in 512 byte sectors\n"
+		"     --offset <num>  zone lba in 512 byte sectors\n"
+		" -c, --count <num>   maximum number of zones in report\n"
+		"     --length <num>  maximum number of zones in report\n"
+		" -v, --verbose       print aligned length and offset"),
+		out);
+	fputs(USAGE_SEPARATOR, out);
+	fputs(USAGE_HELP, out);
+	fputs(USAGE_VERSION, out);
+	fprintf(out, USAGE_MAN_TAIL("blkreport(8)"));
+	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+#define DEF_REPORT_LEN		(1 << 12) /* 4k zones (256k kzalloc) */
+#define MAX_REPORT_LEN		(1 << 16) /* 64k zones */
+
+int main(int argc, char **argv)
+{
+	char *path;
+	int c;
+	int fd;
+	int secsize;
+	uint64_t blksize;
+	struct stat sb;
+	int verbose = 0;
+	uint64_t offset = 0ul;
+	uint32_t length = DEF_REPORT_LEN;
+	static const struct option longopts[] = {
+	    { "help",      0, 0, 'h' },
+	    { "version",   0, 0, 'V' },
+	    { "zone",      1, 0, 'z' }, /* starting LBA */
+	    { "offset",    1, 0, 'z' }, /* alias for zone */
+	    { "count",     1, 0, 'c' }, /* max #of zones (entries) for result */
+	    { "length",    1, 0, 'c' }, /* max #of zones (entries) for result */
+	    { "verbose",   0, 0, 'v' },
+	    { NULL,        0, 0, 0 }
+	};
+	const char *options = "hVc:z:v";
+
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+	atexit(close_stdout);
+
+	while ((c = getopt_long(argc, argv, options, longopts, NULL)) != -1) {
+		switch(c) {
+		case 'h':
+			usage(stdout);
+			break;
+		case 'V':
+			printf(UTIL_LINUX_VERSION);
+			return EXIT_SUCCESS;
+		case 'c':
+			length = _strtou32_or_err(optarg,
+					_("failed to parse report count"), 0);
+			break;
+		case 'z':
+			offset = _strtou64_or_err(optarg,
+					_("failed to parse zone offset"), 0);
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		default:
+			usage(stderr);
+			break;
+		}
+	}
+
+	if (optind == argc)
+		errx(EXIT_FAILURE, _("no device specified"));
+
+	path = argv[optind++];
+
+	if (optind != argc) {
+		warnx(_("unexpected number of arguments"));
+		usage(stderr);
+	}
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		err(EXIT_FAILURE, _("cannot open %s"), path);
+
+	if (fstat(fd, &sb) == -1)
+		err(EXIT_FAILURE, _("stat of %s failed"), path);
+	if (!S_ISBLK(sb.st_mode))
+		errx(EXIT_FAILURE, _("%s: not a block device"), path);
+
+	if (ioctl(fd, BLKGETSIZE64, &blksize))
+		err(EXIT_FAILURE, _("%s: BLKGETSIZE64 ioctl failed"), path);
+	if (ioctl(fd, BLKSSZGET, &secsize))
+		err(EXIT_FAILURE, _("%s: BLKSSZGET ioctl failed"), path);
+
+	/* check offset alignment to the sector size */
+	if (offset % secsize)
+		errx(EXIT_FAILURE, _("%s: offset %" PRIu64 " is not aligned "
+			 "to sector size %i"), path, offset, secsize);
+
+	/* is the range end behind the end of the device ?*/
+	if (offset > blksize)
+		errx(EXIT_FAILURE, _("%s: offset is greater than device size"), path);
+
+	if (length < 1)
+		length = 1;
+	if (length > MAX_REPORT_LEN) {
+		length = MAX_REPORT_LEN;
+		warnx(_("limiting report to %u entries"), length);
+	}
+
+	if (do_report(fd, offset, length, verbose))
+		 err(EXIT_FAILURE, _("%s: BLKREPORTZONE ioctl failed"), path);
+
+	close(fd);
+	return EXIT_SUCCESS;
+}
diff --git a/sys-utils/blkreset.8 b/sys-utils/blkreset.8
new file mode 100644
index 0000000..2c6c0a6
--- /dev/null
+++ b/sys-utils/blkreset.8
@@ -0,0 +1,61 @@
+.TH BLKRESET 5 "October 2016" "util-linux" "System Administration"
+.SH NAME
+blkreset \- Reset a range of zones
+.SH SYNOPSIS
+.B blkreset
+[options]
+.RB [ \-z
+.IR zone ]
+.RB [ \-c
+.IR count ]
+.SH DESCRIPTION
+.B blkreset
+is used to reset one or more zones.  This is useful for
+zoned devices that support the ZAC or ZBC command set.
+Unlike
+.BR sg_reset_wp (8) ,
+this command operates from the block layer and can reset a range of zones.
+.PP
+By default,
+.B blkreset
+will operate on the zone at device logical sector 0. 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
+.I device
+argument is the pathname of the block device.
+.PP
+.SH OPTIONS
+The
+.I zone
+argument 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 common 0x prefix can be used to specify zone and length in hex.
+.TP
+.BR \-z , " \-\-zone \fIoffset" , " \-\-offset \fIoffset"
+The starting zone to be operated upon 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 \-c , " \-\-count \fIcount" , " \-\-length \fIcount"
+The number of zones to be reset starting from offset. Default is 1 zone.
+.TP
+.BR \-V , " \-\-version"
+Display version information and exit.
+.TP
+.BR \-h , " \-\-help"
+Display help text and exit.
+.SH AUTHOR
+.MT shaun@tancheff.com
+Shaun Tancheff
+.ME
+.SH SEE ALSO
+.BR sg_reset_wp (8)
+.SH AVAILABILITY
+The blkreset command is part of the util-linux package and is available
+.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
+Linux Kernel Archive
+.UE .
diff --git a/sys-utils/blkreset.c b/sys-utils/blkreset.c
new file mode 100644
index 0000000..073d482
--- /dev/null
+++ b/sys-utils/blkreset.c
@@ -0,0 +1,190 @@
+/*
+ * blkreset.c -- Reset the WP on a range of zones.
+ *
+ * Copyright (C) 2015,2016 Seagate Technology PLC
+ * Written by Shaun Tancheff <shaun.tancheff@seagate.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This program uses BLKREPORT ioctl to query zone information about part of
+ * or a whole block device, if the device supports it.
+ * You can specify range (start and length) to be queried.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <getopt.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/blkzoned.h>
+
+#include "sysfs.h"
+#include "nls.h"
+#include "strutils.h"
+#include "c.h"
+#include "closestream.h"
+#include "monotonic.h"
+
+static unsigned long blkdev_chunk_sectors(const char *dname)
+{
+	struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
+	dev_t devno = sysfs_devname_to_devno(dname, NULL);
+	int major_no = major(devno);
+	int block_no = minor(devno) & ~0x0f;
+	uint64_t sz;
+
+	/*
+	 * Mapping /dev/sdXn -> /sys/block/sdX to read the chunk_size entry.
+	 * This method masks off the partition specified by the minor device
+	 * component.
+	 */
+	devno = makedev(major_no, block_no);
+	if (sysfs_init(&cxt, devno, NULL))
+		return 0;
+
+	if (sysfs_read_u64(&cxt, "queue/chunk_sectors", &sz) != 0)
+		warnx(_("%s: failed to read chunk size"), dname);
+
+	sysfs_deinit(&cxt);
+	return sz;
+}
+
+static void __attribute__((__noreturn__)) usage(FILE *out)
+{
+	fputs(USAGE_HEADER, out);
+	fprintf(out,
+	      _(" %s [options] <device>\n"), program_invocation_short_name);
+
+	fputs(USAGE_SEPARATOR, out);
+	fputs(_("Discard the content of sectors on a device.\n"), out);
+
+	fputs(USAGE_OPTIONS, out);
+	fputs(_(" -z, --zone <num>  lba of start of zone to act upon\n"
+		" -c, --count       number of zones to reset (default = 1)"),
+		out);
+	fputs(USAGE_SEPARATOR, out);
+	fputs(USAGE_HELP, out);
+	fputs(USAGE_VERSION, out);
+	fprintf(out, USAGE_MAN_TAIL("blkreset(8)"));
+	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+
+int main(int argc, char **argv)
+{
+	char *path;
+	int c, fd;
+	uint64_t blksize;
+	uint64_t blksectors;
+	struct stat sb;
+	struct blk_zone_range za;
+	uint64_t zsector = 0ul;
+	uint64_t zlen = 0;
+	uint64_t zcount = 1;
+	unsigned long zsize;
+	int rc = 0;
+
+	static const struct option longopts[] = {
+	    { "help",      0, 0, 'h' },
+	    { "version",   0, 0, 'V' },
+	    { "zone",      1, 0, 'z' },
+	    { "count",     1, 0, 'c' },
+	    { NULL,        0, 0, 0 }
+	};
+
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+	atexit(close_stdout);
+
+	while ((c = getopt_long(argc, argv, "hVz:c:", longopts, NULL)) != -1) {
+		switch(c) {
+		case 'h':
+			usage(stdout);
+			break;
+		case 'V':
+			printf(UTIL_LINUX_VERSION);
+			return EXIT_SUCCESS;
+		case 'z':
+			zsector = _strtou64_or_err(optarg,
+					_("failed to parse zone offset"), 0);
+			break;
+		case 'c':
+			zcount = _strtou64_or_err(optarg,
+					_("failed to parse number of zones"), 0);
+			break;
+		default:
+			usage(stderr);
+			break;
+		}
+	}
+
+	if (optind == argc)
+		errx(EXIT_FAILURE, _("no device specified"));
+
+	path = argv[optind++];
+
+	if (optind != argc) {
+		warnx(_("unexpected number of arguments"));
+		usage(stderr);
+	}
+
+	zsize = blkdev_chunk_sectors(path);
+	if (zsize == 0)
+		err(EXIT_FAILURE, _("%s: Unable to determine zone size"), path);
+
+	fd = open(path, O_WRONLY);
+	if (fd < 0)
+		err(EXIT_FAILURE, _("cannot open %s"), path);
+
+	if (fstat(fd, &sb) == -1)
+		err(EXIT_FAILURE, _("stat of %s failed"), path);
+	if (!S_ISBLK(sb.st_mode))
+		errx(EXIT_FAILURE, _("%s: not a block device"), path);
+
+	if (blkdev_get_sectors(fd, &blksize))
+		err(EXIT_FAILURE, _("%s: blkdev_get_sectors ioctl failed"), path);
+
+	/* check offset alignment to the chunk size */
+	if (zsector & (zsize - 1))
+		errx(EXIT_FAILURE, _("%s: zone %" PRIu64 " is not aligned "
+			 "to zone size %" PRIu64), path, zsector, zsize);
+	if (zsector > blksectors)
+		errx(EXIT_FAILURE, _("%s: zone %" PRIu64 " is too large "
+			 "for device %" PRIu64), path, zsector, blksectors);
+
+	zlen = zcount * zsize;
+	if (zsector + zlen > blksectors)
+		zlen = blksectors - zsector;
+
+	za.sector = zsector;
+	za.nr_sectors = zlen;
+	rc = ioctl(fd, BLKRESETZONE, &za);
+	if (rc == -1)
+		err(EXIT_FAILURE, _("%s: BLKRESETZONE ioctl failed"), path);
+
+	close(fd);
+	return EXIT_SUCCESS;
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-01-23 13:32 [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives Shaun Tancheff
@ 2017-02-09 12:36 ` Karel Zak
  2017-02-10  3:06   ` Damien Le Moal
  2017-02-16 10:33 ` Karel Zak
  1 sibling, 1 reply; 13+ messages in thread
From: Karel Zak @ 2017-02-09 12:36 UTC (permalink / raw)
  To: Shaun Tancheff; +Cc: util-linux, Damien Le Moal, Bart Van Assche

On Mon, Jan 23, 2017 at 08:32:42PM +0700, Shaun Tancheff wrote:
>  .gitignore              |   2 +
>  configure.ac            |  11 +++
>  include/strutils.h      |   2 +
>  lib/strutils.c          |   7 +-
>  sys-utils/Makemodule.am |  17 ++++
>  sys-utils/blkreport.8   |  68 ++++++++++++++
>  sys-utils/blkreport.c   | 245 ++++++++++++++++++++++++++++++++++++++++++++++++
>  sys-utils/blkreset.8    |  61 ++++++++++++
>  sys-utils/blkreset.c    | 190 +++++++++++++++++++++++++++++++++++++

Applied with some changes (see below), thanks.

Please, please "git pull" and test it!

I have no HW to do any tests (but I have free space for a new disk in
my workstation -- you know Seagate, right? :-)) Or is it possible to
test for example by scsi_debug?

> +blkreset_LDADD += -ludev

Fixed, unnecessary.

> +.BR \-z , " \-\-zone \fIoffset", " \-\-offset \fIoffset"
> +.BR \-c , " \-\-count \fIcount", " \-\-length \fIcount"

Fixed. I don't think we want to use aliases for the options (and one
of the utils had the aliases only in man page). I have modified man
pages and code to support

  --zone <offset>
  --count <length>

only.

> +#include "monotonic.h"

Copy & past I guess ;-) Unnecessary. Fixed.

> +	fputs(USAGE_OPTIONS, out);
> +	fputs(_(" -z, --zone <num>    zone lba in 512 byte sectors\n"
> +		"     --offset <num>  zone lba in 512 byte sectors\n"
> +		" -c, --count <num>   maximum number of zones in report\n"
> +		"     --length <num>  maximum number of zones in report\n"
> +		" -v, --verbose       print aligned length and offset"),
> +		out);

Fixed.

> +		case 'c':
> +			length = _strtou32_or_err(optarg,
> +					_("failed to parse report count"), 0);
> +			break;
> +		case 'z':
> +			offset = _strtou64_or_err(optarg,
> +					_("failed to parse zone offset"), 0);
> +			break;

The function strtou64_or_err() does not support size suffixes. Fixed
and replaced with strtosize_or_err().

> +
> +	if (ioctl(fd, BLKGETSIZE64, &blksize))
> +		err(EXIT_FAILURE, _("%s: BLKGETSIZE64 ioctl failed"), path);
> +	if (ioctl(fd, BLKSSZGET, &secsize))
> +		err(EXIT_FAILURE, _("%s: BLKSSZGET ioctl failed"), path);

replaced with blkdev.h functions (like you did in blkreset.c).

> +	/* check offset alignment to the chunk size */
> +	if (zsector & (zsize - 1))
> +		errx(EXIT_FAILURE, _("%s: zone %" PRIu64 " is not aligned "
> +			 "to zone size %" PRIu64), path, zsector, zsize);
> +	if (zsector > blksectors)
> +		errx(EXIT_FAILURE, _("%s: zone %" PRIu64 " is too large "
> +			 "for device %" PRIu64), path, zsector, blksectors);

It seems nowhere (blkreset and blkreport) we check if 
 
    offset + length <= blksectors

 it means we don't check the end of the area, I guess the end has to
 be within the block device.

 Maybe we can add this if() to the code, objections?

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-09 12:36 ` Karel Zak
@ 2017-02-10  3:06   ` Damien Le Moal
  2017-02-10  9:59     ` Karel Zak
  0 siblings, 1 reply; 13+ messages in thread
From: Damien Le Moal @ 2017-02-10  3:06 UTC (permalink / raw)
  To: Karel Zak, Shaun Tancheff; +Cc: util-linux, Bart Van Assche

Karel, Shaun,

Tested on SAS and SATA host-managed drive. No problems detected.
A few remarks though:

1) The term "lba" is being used throughout (command description and
error messages). This is confusing when using 4K drives. Since in fact
the unit used for the arguments and displayed results is the traditional
512B "sector", I think that "LBA" should be replaced by "sector" is all
messages, command argument descriptions and man pages.

2) In kernel, the offset passed to the zone reset ioctl is indeed
checked for alignment to the drive LBA size. So checking the offset
passed to blkreset makes sense. However, the same check for report is a
little too harsh since the kernel will accept an unaligned sector number
(it will be aligned down to the containing zone start sector before
issuing a report zones command to the drive). So we could get rid of
that check I think.

Otherwise, please feel free to add:
Tested-by: Damien Le Moal <damien.lemoal@wdc.com>

Best regards.

On 2/9/17 21:36, Karel Zak wrote:
> On Mon, Jan 23, 2017 at 08:32:42PM +0700, Shaun Tancheff wrote:
>>  .gitignore              |   2 +
>>  configure.ac            |  11 +++
>>  include/strutils.h      |   2 +
>>  lib/strutils.c          |   7 +-
>>  sys-utils/Makemodule.am |  17 ++++
>>  sys-utils/blkreport.8   |  68 ++++++++++++++
>>  sys-utils/blkreport.c   | 245 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  sys-utils/blkreset.8    |  61 ++++++++++++
>>  sys-utils/blkreset.c    | 190 +++++++++++++++++++++++++++++++++++++
> 
> Applied with some changes (see below), thanks.
> 
> Please, please "git pull" and test it!
> 
> I have no HW to do any tests (but I have free space for a new disk in
> my workstation -- you know Seagate, right? :-)) Or is it possible to
> test for example by scsi_debug?
> 
>> +blkreset_LDADD += -ludev
> 
> Fixed, unnecessary.
> 
>> +.BR \-z , " \-\-zone \fIoffset", " \-\-offset \fIoffset"
>> +.BR \-c , " \-\-count \fIcount", " \-\-length \fIcount"
> 
> Fixed. I don't think we want to use aliases for the options (and one
> of the utils had the aliases only in man page). I have modified man
> pages and code to support
> 
>   --zone <offset>
>   --count <length>
> 
> only.
> 
>> +#include "monotonic.h"
> 
> Copy & past I guess ;-) Unnecessary. Fixed.
> 
>> +	fputs(USAGE_OPTIONS, out);
>> +	fputs(_(" -z, --zone <num>    zone lba in 512 byte sectors\n"
>> +		"     --offset <num>  zone lba in 512 byte sectors\n"
>> +		" -c, --count <num>   maximum number of zones in report\n"
>> +		"     --length <num>  maximum number of zones in report\n"
>> +		" -v, --verbose       print aligned length and offset"),
>> +		out);
> 
> Fixed.
> 
>> +		case 'c':
>> +			length = _strtou32_or_err(optarg,
>> +					_("failed to parse report count"), 0);
>> +			break;
>> +		case 'z':
>> +			offset = _strtou64_or_err(optarg,
>> +					_("failed to parse zone offset"), 0);
>> +			break;
> 
> The function strtou64_or_err() does not support size suffixes. Fixed
> and replaced with strtosize_or_err().
> 
>> +
>> +	if (ioctl(fd, BLKGETSIZE64, &blksize))
>> +		err(EXIT_FAILURE, _("%s: BLKGETSIZE64 ioctl failed"), path);
>> +	if (ioctl(fd, BLKSSZGET, &secsize))
>> +		err(EXIT_FAILURE, _("%s: BLKSSZGET ioctl failed"), path);
> 
> replaced with blkdev.h functions (like you did in blkreset.c).
> 
>> +	/* check offset alignment to the chunk size */
>> +	if (zsector & (zsize - 1))
>> +		errx(EXIT_FAILURE, _("%s: zone %" PRIu64 " is not aligned "
>> +			 "to zone size %" PRIu64), path, zsector, zsize);
>> +	if (zsector > blksectors)
>> +		errx(EXIT_FAILURE, _("%s: zone %" PRIu64 " is too large "
>> +			 "for device %" PRIu64), path, zsector, blksectors);
> 
> It seems nowhere (blkreset and blkreport) we check if 
>  
>     offset + length <= blksectors
> 
>  it means we don't check the end of the area, I guess the end has to
>  be within the block device.
> 
>  Maybe we can add this if() to the code, objections?
> 
>     Karel
> 

-- 
Damien Le Moal, Ph.D.
Sr. Manager, System Software Research Group,
Western Digital Corporation
Damien.LeMoal@wdc.com
(+81) 0466-98-3593 (ext. 513593)
1 kirihara-cho, Fujisawa,
Kanagawa, 252-0888 Japan
www.wdc.com, www.hgst.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-10  3:06   ` Damien Le Moal
@ 2017-02-10  9:59     ` Karel Zak
  0 siblings, 0 replies; 13+ messages in thread
From: Karel Zak @ 2017-02-10  9:59 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: Shaun Tancheff, util-linux, Bart Van Assche

On Fri, Feb 10, 2017 at 12:06:58PM +0900, Damien Le Moal wrote:
> Karel, Shaun,
> 
> Tested on SAS and SATA host-managed drive. No problems detected.
> A few remarks though:
> 
> 1) The term "lba" is being used throughout (command description and
> error messages). This is confusing when using 4K drives. Since in fact
> the unit used for the arguments and displayed results is the traditional
> 512B "sector", I think that "LBA" should be replaced by "sector" is all
> messages, command argument descriptions and man pages.

 Fixed.

> 2) In kernel, the offset passed to the zone reset ioctl is indeed
> checked for alignment to the drive LBA size. So checking the offset
> passed to blkreset makes sense. However, the same check for report is a
> little too harsh since the kernel will accept an unaligned sector number
> (it will be aligned down to the containing zone start sector before
> issuing a report zones command to the drive). So we could get rid of
> that check I think.

Fixed.

> Otherwise, please feel free to add:
> Tested-by: Damien Le Moal <damien.lemoal@wdc.com>

Thanks.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-01-23 13:32 [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives Shaun Tancheff
  2017-02-09 12:36 ` Karel Zak
@ 2017-02-16 10:33 ` Karel Zak
  2017-02-16 10:41   ` Damien Le Moal
  2017-02-16 12:15   ` Benno Schulenberg
  1 sibling, 2 replies; 13+ messages in thread
From: Karel Zak @ 2017-02-16 10:33 UTC (permalink / raw)
  To: Shaun Tancheff; +Cc: util-linux, Damien Le Moal, Bart Van Assche


 Hi,

On Mon, Jan 23, 2017 at 08:32:42PM +0700, Shaun Tancheff wrote:
>  - blkreset to issue Reset (Write Pointer) zone commands
>  - blkreport to retrieve drive zone information

Shaun and Damien, what about to merge all to the 'blkzone'
command? Something like:

  blkzone report [--zone <offset>] [--count <length>]
  blkzone reset  [--zone <offset>] [--count <length>]

if there is no objection I'll do it today or tomorrow.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-16 10:33 ` Karel Zak
@ 2017-02-16 10:41   ` Damien Le Moal
  2017-02-16 12:15   ` Benno Schulenberg
  1 sibling, 0 replies; 13+ messages in thread
From: Damien Le Moal @ 2017-02-16 10:41 UTC (permalink / raw)
  To: Karel Zak; +Cc: Shaun Tancheff, util-linux, Bart Van Assche

Karel,

I am ok with merging.
One command to remember instead of two :)
And actually, we can in the future add open, close and finish this way too =
when/if the ioctls are added to the kernel (no use for now so not added in =
initial support).

Thanks !

Damien Le Moal

On Feb 16, 2017, at 19:33, Karel Zak <kzak@redhat.com> wrote:


Hi,

> On Mon, Jan 23, 2017 at 08:32:42PM +0700, Shaun Tancheff wrote:
> - blkreset to issue Reset (Write Pointer) zone commands
> - blkreport to retrieve drive zone information

Shaun and Damien, what about to merge all to the 'blkzone'
command? Something like:

 blkzone report [--zone <offset>] [--count <length>]
 blkzone reset  [--zone <offset>] [--count <length>]

if there is no objection I'll do it today or tomorrow.

   Karel

-- =

Karel Zak  <kzak@redhat.com>
http://karelzak.blogspot.com
Western Digital Corporation (and its subsidiaries) E-mail Confidentiality N=
otice & Disclaimer:

This e-mail and any files transmitted with it may contain confidential or l=
egally privileged information of WDC and/or its affiliates, and are intende=
d solely for the use of the individual or entity to which they are addresse=
d. If you are not the intended recipient, any disclosure, copying, distribu=
tion or any action taken or omitted to be taken in reliance on it, is prohi=
bited. If you have received this e-mail in error, please notify the sender =
immediately and delete the e-mail in its entirety from your system.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-16 10:33 ` Karel Zak
  2017-02-16 10:41   ` Damien Le Moal
@ 2017-02-16 12:15   ` Benno Schulenberg
  2017-02-17  0:12     ` Damien Le Moal
  1 sibling, 1 reply; 13+ messages in thread
From: Benno Schulenberg @ 2017-02-16 12:15 UTC (permalink / raw)
  To: Karel Zak; +Cc: Shaun Tancheff, Util-Linux, Damien Le Moal, Bart Van Assche


On Thu, Feb 16, 2017, at 11:33, Karel Zak wrote:
>   blkzone report [--zone <offset>] [--count <length>]
>   blkzone reset  [--zone <offset>] [--count <length>]

"blkzone --zone" feels a bit strange.  I would suggest:

  blkzone <command> [--offset <sector>] [--count <number>]

Benno

-- 
http://www.fastmail.com - Same, same, but different...


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-16 12:15   ` Benno Schulenberg
@ 2017-02-17  0:12     ` Damien Le Moal
  2017-02-23 16:33       ` Karel Zak
  0 siblings, 1 reply; 13+ messages in thread
From: Damien Le Moal @ 2017-02-17  0:12 UTC (permalink / raw)
  To: Benno Schulenberg, Karel Zak; +Cc: Shaun Tancheff, Util-Linux, Bart Van Assche

Benno,

On 2/16/17 21:15, Benno Schulenberg wrote:
> 
> On Thu, Feb 16, 2017, at 11:33, Karel Zak wrote:
>>   blkzone report [--zone <offset>] [--count <length>]
>>   blkzone reset  [--zone <offset>] [--count <length>]
> 
> "blkzone --zone" feels a bit strange.  I would suggest:
> 
>   blkzone <command> [--offset <sector>] [--count <number>]

Indeed, it is a little awkward. And to be consistent with other tools
such as blkdiscard, I would also suggest --length instead of --count.

So:

blkzone report [--offset <offset>] [--length <length>]
blkzone reset  [--offset <offset>] [--length <length>]

Best regards.

-- 
Damien Le Moal, Ph.D.
Sr. Manager, System Software Research Group,
Western Digital Corporation
Damien.LeMoal@wdc.com
(+81) 0466-98-3593 (ext. 513593)
1 kirihara-cho, Fujisawa,
Kanagawa, 252-0888 Japan
www.wdc.com, www.hgst.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-17  0:12     ` Damien Le Moal
@ 2017-02-23 16:33       ` Karel Zak
  2017-02-24  4:10         ` Damien Le Moal
  2017-02-24  6:55         ` Damien Le Moal
  0 siblings, 2 replies; 13+ messages in thread
From: Karel Zak @ 2017-02-23 16:33 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Benno Schulenberg, Shaun Tancheff, Util-Linux, Bart Van Assche

On Fri, Feb 17, 2017 at 09:12:29AM +0900, Damien Le Moal wrote:
> Benno,
> 
> On 2/16/17 21:15, Benno Schulenberg wrote:
> > 
> > On Thu, Feb 16, 2017, at 11:33, Karel Zak wrote:
> >>   blkzone report [--zone <offset>] [--count <length>]
> >>   blkzone reset  [--zone <offset>] [--count <length>]
> > 
> > "blkzone --zone" feels a bit strange.  I would suggest:
> > 
> >   blkzone <command> [--offset <sector>] [--count <number>]
> 
> Indeed, it is a little awkward. And to be consistent with other tools
> such as blkdiscard, I would also suggest --length instead of --count.
> 
> So:
> 
> blkzone report [--offset <offset>] [--length <length>]
> blkzone reset  [--offset <offset>] [--length <length>]

 blkzone(8) implemented, blkreset and blkreport removed. 

 Please, retest and review:
 https://github.com/karelzak/util-linux/blob/master/sys-utils/blkzone.c
 https://github.com/karelzak/util-linux/blob/master/sys-utils/blkzone.8

    Karel
-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-23 16:33       ` Karel Zak
@ 2017-02-24  4:10         ` Damien Le Moal
  2017-02-24  4:11           ` Damien Le Moal
  2017-02-24 11:03           ` Karel Zak
  2017-02-24  6:55         ` Damien Le Moal
  1 sibling, 2 replies; 13+ messages in thread
From: Damien Le Moal @ 2017-02-24  4:10 UTC (permalink / raw)
  To: Karel Zak; +Cc: Benno Schulenberg, Shaun Tancheff, Util-Linux, Bart Van Assche

[-- Attachment #1: Type: text/plain, Size: 2706 bytes --]

Karel,

Please find attached 3 patches.
1) To be consistent with blkdiscard behavior, reset all zones of the device when length
is not specified.
2) Similarly, for report, report all zones of the device is length is unspecified on the command line.
3) Improve wording to match more closely the standards. ALos add "0x" to printed values to make it clear that these are hex.

Please review and let me know if you need more testing.

Best regards.

--
Damien Le Moal, Ph.D.
Sr. Manager, System Software Research Group,
Western Digital
Damien.LeMoal@wdc.com<mailto:Damien.LeMoal@wdc.com>
(+81) 0466-98-3593 (ext. 513593)
1 kirihara-cho, Fujisawa,
Kanagawa, 252-0888 Japan
www.wdc.com, www.hgst.com

From: Karel Zak <kzak@redhat.com>
Date: Friday, February 24, 2017 at 01:33
To: Damien Le Moal <Damien.LeMoal@wdc.com>
Cc: Benno Schulenberg <bensberg@justemail.net>, Shaun Tancheff <shaun@tancheff.com>, Util-Linux <util-linux@vger.kernel.org>, Van Assche Bart <Bart.VanAssche@sandisk.com>
Subject: Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives

On Fri, Feb 17, 2017 at 09:12:29AM +0900, Damien Le Moal wrote:
Benno,
On 2/16/17 21:15, Benno Schulenberg wrote:
>
> On Thu, Feb 16, 2017, at 11:33, Karel Zak wrote:
>>   blkzone report [--zone <offset>] [--count <length>]
>>   blkzone reset  [--zone <offset>] [--count <length>]
>
> "blkzone --zone" feels a bit strange.  I would suggest:
>
>   blkzone <command> [--offset <sector>] [--count <number>]
Indeed, it is a little awkward. And to be consistent with other tools
such as blkdiscard, I would also suggest --length instead of --count.
So:
blkzone report [--offset <offset>] [--length <length>]
blkzone reset  [--offset <offset>] [--length <length>]

blkzone(8) implemented, blkreset and blkreport removed.

Please, retest and review:
https://github.com/karelzak/util-linux/blob/master/sys-utils/blkzone.c
https://github.com/karelzak/util-linux/blob/master/sys-utils/blkzone.8

    Karel
--
Karel Zak  <kzak@redhat.com<mailto:kzak@redhat.com>>
http://karelzak.blogspot.com

Western Digital Corporation (and its subsidiaries) E-mail Confidentiality Notice & Disclaimer:

This e-mail and any files transmitted with it may contain confidential or legally privileged information of WDC and/or its affiliates, and are intended solely for the use of the individual or entity to which they are addressed. If you are not the intended recipient, any disclosure, copying, distribution or any action taken or omitted to be taken in reliance on it, is prohibited. If you have received this e-mail in error, please notify the sender immediately and delete the e-mail in its entirety from your system.

[-- Attachment #2: Type: text/html, Size: 8888 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-24  4:10         ` Damien Le Moal
@ 2017-02-24  4:11           ` Damien Le Moal
  2017-02-24 11:03           ` Karel Zak
  1 sibling, 0 replies; 13+ messages in thread
From: Damien Le Moal @ 2017-02-24  4:11 UTC (permalink / raw)
  To: Karel Zak; +Cc: Benno Schulenberg, Shaun Tancheff, Util-Linux, Bart Van Assche

[-- Attachment #1: Type: text/plain, Size: 2715 bytes --]

Forgot to attach the patches…

--
Damien Le Moal, Ph.D.
Sr. Manager, System Software Research Group,
Western Digital
Damien.LeMoal@wdc.com
(+81) 0466-98-3593 (ext. 513593)
1 kirihara-cho, Fujisawa,
Kanagawa, 252-0888 Japan
www.wdc.com, www.hgst.com

From: Damien Le Moal <Damien.LeMoal@wdc.com>
Date: Friday, February 24, 2017 at 13:10
To: Karel Zak <kzak@redhat.com>
Cc: Benno Schulenberg <bensberg@justemail.net>, Shaun Tancheff <shaun@tancheff.com>, Util-Linux <util-linux@vger.kernel.org>, Van Assche Bart <Bart.VanAssche@sandisk.com>
Subject: Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives

Karel,
 
Please find attached 3 patches.
1) To be consistent with blkdiscard behavior, reset all zones of the device when length
is not specified.
2) Similarly, for report, report all zones of the device is length is unspecified on the command line.
3) Improve wording to match more closely the standards. ALos add "0x" to printed values to make it clear that these are hex.
 
Please review and let me know if you need more testing.
 
Best regards.
 
--
Damien Le Moal, Ph.D.
Sr. Manager, System Software Research Group,
Western Digital
Damien.LeMoal@wdc.com
(+81) 0466-98-3593 (ext. 513593)
1 kirihara-cho, Fujisawa,
Kanagawa, 252-0888 Japan
www.wdc.com, www.hgst.com
 
From: Karel Zak <kzak@redhat.com>
Date: Friday, February 24, 2017 at 01:33
To: Damien Le Moal <Damien.LeMoal@wdc.com>
Cc: Benno Schulenberg <bensberg@justemail.net>, Shaun Tancheff <shaun@tancheff.com>, Util-Linux <util-linux@vger.kernel.org>, Van Assche Bart <Bart.VanAssche@sandisk.com>
Subject: Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
 
On Fri, Feb 17, 2017 at 09:12:29AM +0900, Damien Le Moal wrote:
Benno,
On 2/16/17 21:15, Benno Schulenberg wrote:
> 
> On Thu, Feb 16, 2017, at 11:33, Karel Zak wrote:
>>   blkzone report [--zone <offset>] [--count <length>]
>>   blkzone reset  [--zone <offset>] [--count <length>]
> 
> "blkzone --zone" feels a bit strange.  I would suggest:
> 
>   blkzone <command> [--offset <sector>] [--count <number>]
Indeed, it is a little awkward. And to be consistent with other tools
such as blkdiscard, I would also suggest --length instead of --count.
So:
blkzone report [--offset <offset>] [--length <length>]
blkzone reset  [--offset <offset>] [--length <length>]
 
blkzone(8) implemented, blkreset and blkreport removed. 
 
Please, retest and review:
https://github.com/karelzak/util-linux/blob/master/sys-utils/blkzone.c
https://github.com/karelzak/util-linux/blob/master/sys-utils/blkzone.8
 
    Karel
-- 
Karel Zak  <kzak@redhat.com>
http://karelzak.blogspot.com
 



[-- Attachment #2: 0001-blkzone-Reset-all-zones-when-length-is-not-specified.patch --]
[-- Type: application/octet-stream, Size: 1152 bytes --]

From 481f3a45f6cb4817f4196eee1844dcaf25baca91 Mon Sep 17 00:00:00 2001
From: Damien Le Moal <damien.lemoal@wdc.com>
Date: Fri, 24 Feb 2017 11:48:45 +0900
Subject: [PATCH 1/3] blkzone: Reset all zones when length is not specified

If length is 0, operate on all zones starting from offset.
This also fix the maximum length calculation from offset.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 sys-utils/blkzone.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c
index ddb13fc..1c3a7ef 100644
--- a/sys-utils/blkzone.c
+++ b/sys-utils/blkzone.c
@@ -235,10 +235,12 @@ static int blkzone_reset(struct blkzone_control *ctl)
 	if (ctl->offset > ctl->total_sectors)
 		errx(EXIT_FAILURE, _("%s: offset is greater than device size"), ctl->devname);
 
-	zlen = ctl->length * zonesize;
-
+	if (!ctl->length)
+		zlen = ctl->total_sectors;
+	else
+		zlen = ctl->length * zonesize;
 	if (ctl->offset + zlen > ctl->total_sectors)
-		zlen = ctl->total_sectors - ctl->length;
+		zlen = ctl->total_sectors - ctl->offset;
 
 	za.sector = ctl->offset;
 	za.nr_sectors = zlen;
-- 
2.9.3


[-- Attachment #3: 0002-blkzone-Report-all-zones-if-length-is-not-specified.patch --]
[-- Type: application/octet-stream, Size: 5628 bytes --]

From 8549334fb5c62b95d97c73e08a4327bf23331b9b Mon Sep 17 00:00:00 2001
From: Damien Le Moal <damien.lemoal@wdc.com>
Date: Fri, 24 Feb 2017 12:36:08 +0900
Subject: [PATCH 2/3] blkzone: Report all zones if length is not specified

Report all zones of the block device when length is not specified
on the command line. To do this, introduce an inner loop in
blkzone_report to repeatedly issue report zone ioctl to the
device.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 sys-utils/blkzone.c | 126 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 72 insertions(+), 54 deletions(-)

diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c
index 1c3a7ef..c9d65dc 100644
--- a/sys-utils/blkzone.c
+++ b/sys-utils/blkzone.c
@@ -108,10 +108,36 @@ static int init_device(struct blkzone_control *ctl, int mode)
 }
 
 /*
+ * Get the device zone size indicated by chunk sectors).
+ */
+static unsigned long blkdev_chunk_sectors(const char *dname)
+{
+	struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
+	dev_t devno = sysfs_devname_to_devno(dname, NULL);
+	int major_no = major(devno);
+	int block_no = minor(devno) & ~0x0f;
+	uint64_t sz;
+	int rc;
+
+	/*
+	 * Mapping /dev/sdXn -> /sys/block/sdX to read the chunk_size entry.
+	 * This method masks off the partition specified by the minor device
+	 * component.
+	 */
+	devno = makedev(major_no, block_no);
+	if (sysfs_init(&cxt, devno, NULL))
+		return 0;
+
+	rc = sysfs_read_u64(&cxt, "queue/chunk_sectors", &sz);
+
+	sysfs_deinit(&cxt);
+	return rc == 0 ? sz : 0;
+}
+
+/*
  * blkzone report
  */
-#define DEF_REPORT_LEN		(1 << 12) /* 4k zones (256k kzalloc) */
-#define MAX_REPORT_LEN		(1 << 16) /* 64k zones */
+#define DEF_REPORT_LEN		(1 << 12) /* 4k zones per report (256k kzalloc) */
 
 static const char *type_text[] = {
 	"RESERVED",
@@ -135,6 +161,7 @@ static const char *condition_str[] = {
 static int blkzone_report(struct blkzone_control *ctl)
 {
 	struct blk_zone_report *zi;
+	unsigned long zonesize;
 	uint32_t i;
 	int fd;
 
@@ -142,43 +169,58 @@ static int blkzone_report(struct blkzone_control *ctl)
 
 	if (ctl->offset > ctl->total_sectors)
 		errx(EXIT_FAILURE, _("%s: offset is greater than device size"), ctl->devname);
-	if (ctl->length < 1)
-		ctl->length = 1;
-	if (ctl->length > MAX_REPORT_LEN) {
-		ctl->length = MAX_REPORT_LEN;
-		warnx(_("limiting report to %" PRIu64 " entries"), ctl->length);
+	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;
 	}
 
-	zi = xmalloc(sizeof(struct blk_zone_report)
-		     + (ctl->length * sizeof(struct blk_zone)));
-	zi->nr_zones = ctl->length;
-	zi->sector = ctl->offset;		/* maybe shift 4Kn -> 512e */
+	zi = xmalloc(sizeof(struct blk_zone_report) +
+		     (DEF_REPORT_LEN * sizeof(struct blk_zone)));
 
-	if (ioctl(fd, BLKREPORTZONE, zi) == -1)
-		err(EXIT_FAILURE, _("%s: BLKREPORTZONE ioctl failed"), ctl->devname);
+	while (ctl->length && ctl->offset < ctl->total_sectors) {
 
-	if (ctl->verbose)
-		printf(_("Found %d zones\n"), zi->nr_zones);
+		zi->nr_zones = min(ctl->length, (uint64_t)DEF_REPORT_LEN);
+		zi->sector = ctl->offset;
 
-	printf(_("Zones returned: %u\n"), zi->nr_zones);
+		if (ioctl(fd, BLKREPORTZONE, zi) == -1)
+			err(EXIT_FAILURE, _("%s: BLKREPORTZONE ioctl failed"), ctl->devname);
 
-	for (i = 0; i < zi->nr_zones; i++) {
-		const struct blk_zone *entry = &zi->zones[i];
-		unsigned int type = entry->type;
-		uint64_t start = entry->start;
-		uint64_t wp = entry->wp;
-		uint8_t cond = entry->cond;
-		uint64_t len = entry->len;
+		if (ctl->verbose)
+			printf(_("Found %d zones from %lx\n"),
+				zi->nr_zones, ctl->offset);
 
-		if (!len)
+		if (!zi->nr_zones) {
+			ctl->length = 0;
 			break;
+		}
+
+		for (i = 0; i < zi->nr_zones; i++) {
+			const struct blk_zone *entry = &zi->zones[i];
+			unsigned int type = entry->type;
+			uint64_t start = entry->start;
+			uint64_t wp = entry->wp;
+			uint8_t cond = entry->cond;
+			uint64_t len = entry->len;
+
+			if (!len) {
+				ctl->length = 0;
+				break;
+			}
+
+			printf(_("  start: %9lx, len %6lx, wptr %6lx"
+			 	" reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"),
+				start, len, wp - start,
+				entry->reset, entry->non_seq,
+				cond, condition_str[cond & ARRAY_SIZE(condition_str)],
+				type, type_text[type]);
+
+			ctl->length--;
+			ctl->offset = start + len;
+
+		}
 
-		printf(_("  start: %9lx, len %6lx, wptr %6lx"
-			 " reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"),
-			start, len, wp - start,
-			entry->reset, entry->non_seq,
-			cond, condition_str[cond & ARRAY_SIZE(condition_str)],
-			type, type_text[type]);
 	}
 
 	free(zi);
@@ -190,30 +232,6 @@ static int blkzone_report(struct blkzone_control *ctl)
 /*
  * blkzone reset
  */
-static unsigned long blkdev_chunk_sectors(const char *dname)
-{
-	struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
-	dev_t devno = sysfs_devname_to_devno(dname, NULL);
-	int major_no = major(devno);
-	int block_no = minor(devno) & ~0x0f;
-	uint64_t sz;
-	int rc;
-
-	/*
-	 * Mapping /dev/sdXn -> /sys/block/sdX to read the chunk_size entry.
-	 * This method masks off the partition specified by the minor device
-	 * component.
-	 */
-	devno = makedev(major_no, block_no);
-	if (sysfs_init(&cxt, devno, NULL))
-		return 0;
-
-	rc = sysfs_read_u64(&cxt, "queue/chunk_sectors", &sz);
-
-	sysfs_deinit(&cxt);
-	return rc == 0 ? sz : 0;
-}
-
 static int blkzone_reset(struct blkzone_control *ctl)
 {
 	struct blk_zone_range za = { .sector = 0 };
-- 
2.9.3


[-- Attachment #4: 0003-blkzone-Improve-zone-information-print.patch --]
[-- Type: application/octet-stream, Size: 4761 bytes --]

From ac3f2b3a0a7e772b7883659023bf87b529afec65 Mon Sep 17 00:00:00 2001
From: Damien Le Moal <damien.lemoal@wdc.com>
Date: Fri, 24 Feb 2017 12:47:29 +0900
Subject: [PATCH 3/3] blkzone: Improve zone information print

Add "0x" to the zone start, length and write pointer print
to make it always clear that the values are Hexadecimal.

Also update the zone condition string and associated comments
to match more closely the wording in the standard document.
The man page is also updated to match the new wording.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 sys-utils/blkzone.8 | 39 ++++++++++++++++++---------------------
 sys-utils/blkzone.c | 22 +++++++++++-----------
 2 files changed, 29 insertions(+), 32 deletions(-)

diff --git a/sys-utils/blkzone.8 b/sys-utils/blkzone.8
index 6394ed2..24b0cc7 100644
--- a/sys-utils/blkzone.8
+++ b/sys-utils/blkzone.8
@@ -9,8 +9,8 @@ blkzone \- run zone command on a device
 .SH DESCRIPTION
 .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 are addresses by the offset
-and length options.
+(ZBC) or Zoned-device ATA Commands (ZAC). The zones to operate on can be
+specified using the offset and length options.
 .PP
 The
 .I device
@@ -40,15 +40,15 @@ type:Zone type
 .TS
 tab(:);
 left l l.
-Cl:closed
-cv:conventional zone
-e0:empty
-fu:full
-Oe:open explicit
-Oi:open implicit
-OL:offline
-ro:read only
-x?:reserved conditions (should not be reported)
+cl:Closed
+nw:Not write pointer
+em:Empty
+fu:Full
+oe:Explicitly opened
+oi:Implicitly opened
+ol:Offline
+ro:Read only
+x?:Reserved conditions (should not be reported)
 .TE
 
 .SS reset
@@ -56,23 +56,20 @@ 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 on the zone at device logical
-sector 0.  Options may be used to modify this behavior as well as specify the
-operation to be performed on the zone, as explained below.
+By default, the command will operate from the zone at device logical
+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 (options \fB\-\-length\fP) is 4096, the maximum 65536.
+The default number of zones (option \fB\-\-length\fP) is all zones.
 
 .SH OPTIONS
 The
-.I sector
-and
-.I count
-option arguments may be followed by the multiplicative suffixes KiB (=1024),
+.I offset
+option argument 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 \fIsector\fR and
-\fIcount\fR in hex.
+Additionally, the 0x prefix can be used to specify \fIoffset\fR in hex.
 .TP
 .BR \-o , " \-\-offset "\fIsector\fP
 The starting zone specified as a sector offset.  The provided offset in sector
diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c
index c9d65dc..2d6a760 100644
--- a/sys-utils/blkzone.c
+++ b/sys-utils/blkzone.c
@@ -147,15 +147,15 @@ static const char *type_text[] = {
 };
 
 static const char *condition_str[] = {
-	"cv", /* conventional zone */
-	"e0", /* empty */
-	"Oi", /* open implicit */
-	"Oe", /* open explicit */
-	"Cl", /* closed */
+	"nw", /* Not write pointer */
+	"em", /* Empty */
+	"io", /* Implicitly opened */
+	"eo", /* Explicitly opened */
+	"cl", /* Closed */
 	"x5", "x6", "x7", "x8", "x9", "xA", "xB", /* xN: reserved */
-	"ro", /* read only */
-	"fu", /* full */
-	"OL"  /* offline */
+	"ro", /* Read only */
+	"fu", /* Full */
+	"of"  /* Offline */
 };
 
 static int blkzone_report(struct blkzone_control *ctl)
@@ -188,7 +188,7 @@ static int blkzone_report(struct blkzone_control *ctl)
 			err(EXIT_FAILURE, _("%s: BLKREPORTZONE ioctl failed"), ctl->devname);
 
 		if (ctl->verbose)
-			printf(_("Found %d zones from %lx\n"),
+			printf(_("Found %d zones from 0x%lx\n"),
 				zi->nr_zones, ctl->offset);
 
 		if (!zi->nr_zones) {
@@ -209,9 +209,9 @@ static int blkzone_report(struct blkzone_control *ctl)
 				break;
 			}
 
-			printf(_("  start: %9lx, len %6lx, wptr %6lx"
+			printf(_("  start: 0x%09lx, len 0x%06lx, wptr 0x%06lx"
 			 	" reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"),
-				start, len, wp - start,
+				start, len, (type == 0x1) ? 0 : wp - start,
 				entry->reset, entry->non_seq,
 				cond, condition_str[cond & ARRAY_SIZE(condition_str)],
 				type, type_text[type]);
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-23 16:33       ` Karel Zak
  2017-02-24  4:10         ` Damien Le Moal
@ 2017-02-24  6:55         ` Damien Le Moal
  1 sibling, 0 replies; 13+ messages in thread
From: Damien Le Moal @ 2017-02-24  6:55 UTC (permalink / raw)
  To: Karel Zak; +Cc: Benno Schulenberg, Shaun Tancheff, Util-Linux, Bart Van Assche

[-- Attachment #1: Type: text/plain, Size: 2649 bytes --]

Karel,

Added one more patch to the series.
The fourth patch changes the --length option to use a sector count (as expected from the name)
and adds the --count option which can be used in place of --length (it is --length OR --count,
both are not allowed on the command line).

All tested on several different host-managed drives with kernel 4.10. No problems detected.

Let me know what you think.

Best regards.

--
Damien Le Moal, Ph.D.
Sr. Manager, System Software Research Group,
Western Digital
Damien.LeMoal@wdc.com
(+81) 0466-98-3593 (ext. 513593)
1 kirihara-cho, Fujisawa,
Kanagawa, 252-0888 Japan
www.wdc.com, www.hgst.com

From: Karel Zak <kzak@redhat.com>
Date: Friday, February 24, 2017 at 01:33
To: Damien Le Moal <Damien.LeMoal@wdc.com>
Cc: Benno Schulenberg <bensberg@justemail.net>, Shaun Tancheff <shaun@tancheff.com>, Util-Linux <util-linux@vger.kernel.org>, Van Assche Bart <Bart.VanAssche@sandisk.com>
Subject: Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives

On Fri, Feb 17, 2017 at 09:12:29AM +0900, Damien Le Moal wrote:
Benno,
On 2/16/17 21:15, Benno Schulenberg wrote:
> 
> On Thu, Feb 16, 2017, at 11:33, Karel Zak wrote:
>>   blkzone report [--zone <offset>] [--count <length>]
>>   blkzone reset  [--zone <offset>] [--count <length>]
> 
> "blkzone --zone" feels a bit strange.  I would suggest:
> 
>   blkzone <command> [--offset <sector>] [--count <number>]
Indeed, it is a little awkward. And to be consistent with other tools
such as blkdiscard, I would also suggest --length instead of --count.
So:
blkzone report [--offset <offset>] [--length <length>]
blkzone reset  [--offset <offset>] [--length <length>]

blkzone(8) implemented, blkreset and blkreport removed. 

Please, retest and review:
https://github.com/karelzak/util-linux/blob/master/sys-utils/blkzone.c
https://github.com/karelzak/util-linux/blob/master/sys-utils/blkzone.8

    Karel
-- 
Karel Zak  <kzak@redhat.com>
http://karelzak.blogspot.com



Western Digital Corporation (and its subsidiaries) E-mail Confidentiality Notice & Disclaimer:

This e-mail and any files transmitted with it may contain confidential or legally privileged information of WDC and/or its affiliates, and are intended solely for the use of the individual or entity to which they are addressed. If you are not the intended recipient, any disclosure, copying, distribution or any action taken or omitted to be taken in reliance on it, is prohibited. If you have received this e-mail in error, please notify the sender immediately and delete the e-mail in its entirety from your system.

[-- Attachment #2: 0001-blkzone-Reset-all-zones-when-length-is-not-specified.patch --]
[-- Type: application/octet-stream, Size: 1155 bytes --]

From 481f3a45f6cb4817f4196eee1844dcaf25baca91 Mon Sep 17 00:00:00 2001
From: Damien Le Moal <damien.lemoal@wdc.com>
Date: Fri, 24 Feb 2017 11:48:45 +0900
Subject: [PATCH v2 1/4] blkzone: Reset all zones when length is not specified

If length is 0, operate on all zones starting from offset.
This also fix the maximum length calculation from offset.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 sys-utils/blkzone.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c
index ddb13fc..1c3a7ef 100644
--- a/sys-utils/blkzone.c
+++ b/sys-utils/blkzone.c
@@ -235,10 +235,12 @@ static int blkzone_reset(struct blkzone_control *ctl)
 	if (ctl->offset > ctl->total_sectors)
 		errx(EXIT_FAILURE, _("%s: offset is greater than device size"), ctl->devname);
 
-	zlen = ctl->length * zonesize;
-
+	if (!ctl->length)
+		zlen = ctl->total_sectors;
+	else
+		zlen = ctl->length * zonesize;
 	if (ctl->offset + zlen > ctl->total_sectors)
-		zlen = ctl->total_sectors - ctl->length;
+		zlen = ctl->total_sectors - ctl->offset;
 
 	za.sector = ctl->offset;
 	za.nr_sectors = zlen;
-- 
2.9.3


[-- Attachment #3: 0002-blkzone-Report-all-zones-if-length-is-not-specified.patch --]
[-- Type: application/octet-stream, Size: 5631 bytes --]

From 8549334fb5c62b95d97c73e08a4327bf23331b9b Mon Sep 17 00:00:00 2001
From: Damien Le Moal <damien.lemoal@wdc.com>
Date: Fri, 24 Feb 2017 12:36:08 +0900
Subject: [PATCH v2 2/4] blkzone: Report all zones if length is not specified

Report all zones of the block device when length is not specified
on the command line. To do this, introduce an inner loop in
blkzone_report to repeatedly issue report zone ioctl to the
device.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 sys-utils/blkzone.c | 126 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 72 insertions(+), 54 deletions(-)

diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c
index 1c3a7ef..c9d65dc 100644
--- a/sys-utils/blkzone.c
+++ b/sys-utils/blkzone.c
@@ -108,10 +108,36 @@ static int init_device(struct blkzone_control *ctl, int mode)
 }
 
 /*
+ * Get the device zone size indicated by chunk sectors).
+ */
+static unsigned long blkdev_chunk_sectors(const char *dname)
+{
+	struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
+	dev_t devno = sysfs_devname_to_devno(dname, NULL);
+	int major_no = major(devno);
+	int block_no = minor(devno) & ~0x0f;
+	uint64_t sz;
+	int rc;
+
+	/*
+	 * Mapping /dev/sdXn -> /sys/block/sdX to read the chunk_size entry.
+	 * This method masks off the partition specified by the minor device
+	 * component.
+	 */
+	devno = makedev(major_no, block_no);
+	if (sysfs_init(&cxt, devno, NULL))
+		return 0;
+
+	rc = sysfs_read_u64(&cxt, "queue/chunk_sectors", &sz);
+
+	sysfs_deinit(&cxt);
+	return rc == 0 ? sz : 0;
+}
+
+/*
  * blkzone report
  */
-#define DEF_REPORT_LEN		(1 << 12) /* 4k zones (256k kzalloc) */
-#define MAX_REPORT_LEN		(1 << 16) /* 64k zones */
+#define DEF_REPORT_LEN		(1 << 12) /* 4k zones per report (256k kzalloc) */
 
 static const char *type_text[] = {
 	"RESERVED",
@@ -135,6 +161,7 @@ static const char *condition_str[] = {
 static int blkzone_report(struct blkzone_control *ctl)
 {
 	struct blk_zone_report *zi;
+	unsigned long zonesize;
 	uint32_t i;
 	int fd;
 
@@ -142,43 +169,58 @@ static int blkzone_report(struct blkzone_control *ctl)
 
 	if (ctl->offset > ctl->total_sectors)
 		errx(EXIT_FAILURE, _("%s: offset is greater than device size"), ctl->devname);
-	if (ctl->length < 1)
-		ctl->length = 1;
-	if (ctl->length > MAX_REPORT_LEN) {
-		ctl->length = MAX_REPORT_LEN;
-		warnx(_("limiting report to %" PRIu64 " entries"), ctl->length);
+	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;
 	}
 
-	zi = xmalloc(sizeof(struct blk_zone_report)
-		     + (ctl->length * sizeof(struct blk_zone)));
-	zi->nr_zones = ctl->length;
-	zi->sector = ctl->offset;		/* maybe shift 4Kn -> 512e */
+	zi = xmalloc(sizeof(struct blk_zone_report) +
+		     (DEF_REPORT_LEN * sizeof(struct blk_zone)));
 
-	if (ioctl(fd, BLKREPORTZONE, zi) == -1)
-		err(EXIT_FAILURE, _("%s: BLKREPORTZONE ioctl failed"), ctl->devname);
+	while (ctl->length && ctl->offset < ctl->total_sectors) {
 
-	if (ctl->verbose)
-		printf(_("Found %d zones\n"), zi->nr_zones);
+		zi->nr_zones = min(ctl->length, (uint64_t)DEF_REPORT_LEN);
+		zi->sector = ctl->offset;
 
-	printf(_("Zones returned: %u\n"), zi->nr_zones);
+		if (ioctl(fd, BLKREPORTZONE, zi) == -1)
+			err(EXIT_FAILURE, _("%s: BLKREPORTZONE ioctl failed"), ctl->devname);
 
-	for (i = 0; i < zi->nr_zones; i++) {
-		const struct blk_zone *entry = &zi->zones[i];
-		unsigned int type = entry->type;
-		uint64_t start = entry->start;
-		uint64_t wp = entry->wp;
-		uint8_t cond = entry->cond;
-		uint64_t len = entry->len;
+		if (ctl->verbose)
+			printf(_("Found %d zones from %lx\n"),
+				zi->nr_zones, ctl->offset);
 
-		if (!len)
+		if (!zi->nr_zones) {
+			ctl->length = 0;
 			break;
+		}
+
+		for (i = 0; i < zi->nr_zones; i++) {
+			const struct blk_zone *entry = &zi->zones[i];
+			unsigned int type = entry->type;
+			uint64_t start = entry->start;
+			uint64_t wp = entry->wp;
+			uint8_t cond = entry->cond;
+			uint64_t len = entry->len;
+
+			if (!len) {
+				ctl->length = 0;
+				break;
+			}
+
+			printf(_("  start: %9lx, len %6lx, wptr %6lx"
+			 	" reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"),
+				start, len, wp - start,
+				entry->reset, entry->non_seq,
+				cond, condition_str[cond & ARRAY_SIZE(condition_str)],
+				type, type_text[type]);
+
+			ctl->length--;
+			ctl->offset = start + len;
+
+		}
 
-		printf(_("  start: %9lx, len %6lx, wptr %6lx"
-			 " reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"),
-			start, len, wp - start,
-			entry->reset, entry->non_seq,
-			cond, condition_str[cond & ARRAY_SIZE(condition_str)],
-			type, type_text[type]);
 	}
 
 	free(zi);
@@ -190,30 +232,6 @@ static int blkzone_report(struct blkzone_control *ctl)
 /*
  * blkzone reset
  */
-static unsigned long blkdev_chunk_sectors(const char *dname)
-{
-	struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
-	dev_t devno = sysfs_devname_to_devno(dname, NULL);
-	int major_no = major(devno);
-	int block_no = minor(devno) & ~0x0f;
-	uint64_t sz;
-	int rc;
-
-	/*
-	 * Mapping /dev/sdXn -> /sys/block/sdX to read the chunk_size entry.
-	 * This method masks off the partition specified by the minor device
-	 * component.
-	 */
-	devno = makedev(major_no, block_no);
-	if (sysfs_init(&cxt, devno, NULL))
-		return 0;
-
-	rc = sysfs_read_u64(&cxt, "queue/chunk_sectors", &sz);
-
-	sysfs_deinit(&cxt);
-	return rc == 0 ? sz : 0;
-}
-
 static int blkzone_reset(struct blkzone_control *ctl)
 {
 	struct blk_zone_range za = { .sector = 0 };
-- 
2.9.3


[-- Attachment #4: 0003-blkzone-Improve-zone-information-print.patch --]
[-- Type: application/octet-stream, Size: 4764 bytes --]

From ac3f2b3a0a7e772b7883659023bf87b529afec65 Mon Sep 17 00:00:00 2001
From: Damien Le Moal <damien.lemoal@wdc.com>
Date: Fri, 24 Feb 2017 12:47:29 +0900
Subject: [PATCH v2 3/4] blkzone: Improve zone information print

Add "0x" to the zone start, length and write pointer print
to make it always clear that the values are Hexadecimal.

Also update the zone condition string and associated comments
to match more closely the wording in the standard document.
The man page is also updated to match the new wording.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 sys-utils/blkzone.8 | 39 ++++++++++++++++++---------------------
 sys-utils/blkzone.c | 22 +++++++++++-----------
 2 files changed, 29 insertions(+), 32 deletions(-)

diff --git a/sys-utils/blkzone.8 b/sys-utils/blkzone.8
index 6394ed2..24b0cc7 100644
--- a/sys-utils/blkzone.8
+++ b/sys-utils/blkzone.8
@@ -9,8 +9,8 @@ blkzone \- run zone command on a device
 .SH DESCRIPTION
 .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 are addresses by the offset
-and length options.
+(ZBC) or Zoned-device ATA Commands (ZAC). The zones to operate on can be
+specified using the offset and length options.
 .PP
 The
 .I device
@@ -40,15 +40,15 @@ type:Zone type
 .TS
 tab(:);
 left l l.
-Cl:closed
-cv:conventional zone
-e0:empty
-fu:full
-Oe:open explicit
-Oi:open implicit
-OL:offline
-ro:read only
-x?:reserved conditions (should not be reported)
+cl:Closed
+nw:Not write pointer
+em:Empty
+fu:Full
+oe:Explicitly opened
+oi:Implicitly opened
+ol:Offline
+ro:Read only
+x?:Reserved conditions (should not be reported)
 .TE
 
 .SS reset
@@ -56,23 +56,20 @@ 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 on the zone at device logical
-sector 0.  Options may be used to modify this behavior as well as specify the
-operation to be performed on the zone, as explained below.
+By default, the command will operate from the zone at device logical
+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 (options \fB\-\-length\fP) is 4096, the maximum 65536.
+The default number of zones (option \fB\-\-length\fP) is all zones.
 
 .SH OPTIONS
 The
-.I sector
-and
-.I count
-option arguments may be followed by the multiplicative suffixes KiB (=1024),
+.I offset
+option argument 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 \fIsector\fR and
-\fIcount\fR in hex.
+Additionally, the 0x prefix can be used to specify \fIoffset\fR in hex.
 .TP
 .BR \-o , " \-\-offset "\fIsector\fP
 The starting zone specified as a sector offset.  The provided offset in sector
diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c
index c9d65dc..2d6a760 100644
--- a/sys-utils/blkzone.c
+++ b/sys-utils/blkzone.c
@@ -147,15 +147,15 @@ static const char *type_text[] = {
 };
 
 static const char *condition_str[] = {
-	"cv", /* conventional zone */
-	"e0", /* empty */
-	"Oi", /* open implicit */
-	"Oe", /* open explicit */
-	"Cl", /* closed */
+	"nw", /* Not write pointer */
+	"em", /* Empty */
+	"io", /* Implicitly opened */
+	"eo", /* Explicitly opened */
+	"cl", /* Closed */
 	"x5", "x6", "x7", "x8", "x9", "xA", "xB", /* xN: reserved */
-	"ro", /* read only */
-	"fu", /* full */
-	"OL"  /* offline */
+	"ro", /* Read only */
+	"fu", /* Full */
+	"of"  /* Offline */
 };
 
 static int blkzone_report(struct blkzone_control *ctl)
@@ -188,7 +188,7 @@ static int blkzone_report(struct blkzone_control *ctl)
 			err(EXIT_FAILURE, _("%s: BLKREPORTZONE ioctl failed"), ctl->devname);
 
 		if (ctl->verbose)
-			printf(_("Found %d zones from %lx\n"),
+			printf(_("Found %d zones from 0x%lx\n"),
 				zi->nr_zones, ctl->offset);
 
 		if (!zi->nr_zones) {
@@ -209,9 +209,9 @@ static int blkzone_report(struct blkzone_control *ctl)
 				break;
 			}
 
-			printf(_("  start: %9lx, len %6lx, wptr %6lx"
+			printf(_("  start: 0x%09lx, len 0x%06lx, wptr 0x%06lx"
 			 	" reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"),
-				start, len, wp - start,
+				start, len, (type == 0x1) ? 0 : wp - start,
 				entry->reset, entry->non_seq,
 				cond, condition_str[cond & ARRAY_SIZE(condition_str)],
 				type, type_text[type]);
-- 
2.9.3


[-- Attachment #5: 0004-blkzone-Add-count-option.patch --]
[-- Type: application/octet-stream, Size: 10567 bytes --]

From 5623702061479ca0d37137ddbc369b6d848d1c75 Mon Sep 17 00:00:00 2001
From: Damien Le Moal <damien.lemoal@wdc.com>
Date: Fri, 24 Feb 2017 15:45:31 +0900
Subject: [PATCH v2 4/4] 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>
---
 sys-utils/blkzone.8 | 39 ++++++++++++++++-----------
 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 24b0cc7..983b044 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 2d6a760..b9f1ed7 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++];
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives
  2017-02-24  4:10         ` Damien Le Moal
  2017-02-24  4:11           ` Damien Le Moal
@ 2017-02-24 11:03           ` Karel Zak
  1 sibling, 0 replies; 13+ messages in thread
From: Karel Zak @ 2017-02-24 11:03 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Benno Schulenberg, Shaun Tancheff, Util-Linux, Bart Van Assche

On Fri, Feb 24, 2017 at 04:10:09AM +0000, Damien Le Moal wrote:
> Please find attached 3 patches.

All 4 patches applied, Thanks!

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-02-24 11:09 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-23 13:32 [PATCH v3] Add blkzonecmd and blkreport ZAC/ZBC drives Shaun Tancheff
2017-02-09 12:36 ` Karel Zak
2017-02-10  3:06   ` Damien Le Moal
2017-02-10  9:59     ` Karel Zak
2017-02-16 10:33 ` Karel Zak
2017-02-16 10:41   ` Damien Le Moal
2017-02-16 12:15   ` Benno Schulenberg
2017-02-17  0:12     ` Damien Le Moal
2017-02-23 16:33       ` Karel Zak
2017-02-24  4:10         ` Damien Le Moal
2017-02-24  4:11           ` Damien Le Moal
2017-02-24 11:03           ` Karel Zak
2017-02-24  6:55         ` Damien Le Moal

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.