summaryrefslogtreecommitdiffstats
path: root/sys-utils/blkzone.c
diff options
context:
space:
mode:
authorDamien Le Moal2017-02-24 04:36:08 +0100
committerKarel Zak2017-02-24 11:53:45 +0100
commit6e1958d8dd58ddc7c613466531df968d8eba27eb (patch)
tree06b4d122a164ae35a873b74a982f807af0b53ad4 /sys-utils/blkzone.c
parentblkzone: Reset all zones when length is not specified (diff)
downloadkernel-qcow2-util-linux-6e1958d8dd58ddc7c613466531df968d8eba27eb.tar.gz
kernel-qcow2-util-linux-6e1958d8dd58ddc7c613466531df968d8eba27eb.tar.xz
kernel-qcow2-util-linux-6e1958d8dd58ddc7c613466531df968d8eba27eb.zip
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>
Diffstat (limited to 'sys-utils/blkzone.c')
-rw-r--r--sys-utils/blkzone.c126
1 files changed, 72 insertions, 54 deletions
diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c
index 1c3a7ef7d..c9d65dc23 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 };