diff options
Diffstat (limited to 'sys-utils/blkzone.c')
-rw-r--r-- | sys-utils/blkzone.c | 126 |
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 }; |