summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 };