X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=oslib%2Flinux-blkzoned.c;h=4e441d29b8de2b4173684f8f5d79744192dd0bff;hb=2c7dd23e5142e421723ede2557fe868ac32c8265;hp=61ea3a53d6d5ce1b029db3bef33a18ece1baa4ac;hpb=427a7e0950a49a6e350a8e63a31cd8b1f331d4cc;p=fio.git diff --git a/oslib/linux-blkzoned.c b/oslib/linux-blkzoned.c index 61ea3a53..4e441d29 100644 --- a/oslib/linux-blkzoned.c +++ b/oslib/linux-blkzoned.c @@ -23,6 +23,37 @@ #include +/* + * If the uapi headers installed on the system lacks zone capacity support, + * use our local versions. If the installed headers are recent enough to + * support zone capacity, do not redefine any structs. + */ +#ifndef CONFIG_HAVE_REP_CAPACITY +#define BLK_ZONE_REP_CAPACITY (1 << 0) + +struct blk_zone_v2 { + __u64 start; /* Zone start sector */ + __u64 len; /* Zone length in number of sectors */ + __u64 wp; /* Zone write pointer position */ + __u8 type; /* Zone type */ + __u8 cond; /* Zone condition */ + __u8 non_seq; /* Non-sequential write resources active */ + __u8 reset; /* Reset write pointer recommended */ + __u8 resv[4]; + __u64 capacity; /* Zone capacity in number of sectors */ + __u8 reserved[24]; +}; +#define blk_zone blk_zone_v2 + +struct blk_zone_report_v2 { + __u64 sector; + __u32 nr_zones; + __u32 flags; +struct blk_zone zones[0]; +}; +#define blk_zone_report blk_zone_report_v2 +#endif /* CONFIG_HAVE_REP_CAPACITY */ + /* * Read up to 255 characters from the first line of a file. Strip the trailing * newline. @@ -43,12 +74,16 @@ static char *read_file(const char *path) return strdup(line); } -int blkzoned_get_zoned_model(struct thread_data *td, struct fio_file *f, - enum zbd_zoned_model *model) +/* + * Get the value of a sysfs attribute for a block device. + * + * Returns NULL on failure. + * Returns a pointer to a string on success. + * The caller is responsible for freeing the memory. + */ +static char *blkzoned_get_sysfs_attr(const char *file_name, const char *attr) { - const char *file_name = f->file_name; - char *zoned_attr_path = NULL; - char *model_str = NULL; + char *attr_path = NULL; struct stat statbuf; char *sys_devno_path = NULL; char *part_attr_path = NULL; @@ -56,13 +91,7 @@ int blkzoned_get_zoned_model(struct thread_data *td, struct fio_file *f, char sys_path[PATH_MAX]; ssize_t sz; char *delim = NULL; - - if (f->filetype != FIO_TYPE_BLOCK) { - *model = ZBD_IGNORE; - return 0; - } - - *model = ZBD_NONE; + char *attr_str = NULL; if (stat(file_name, &statbuf) < 0) goto out; @@ -92,27 +121,74 @@ int blkzoned_get_zoned_model(struct thread_data *td, struct fio_file *f, *delim = '\0'; } - if (asprintf(&zoned_attr_path, - "/sys/dev/block/%s/queue/zoned", sys_path) < 0) + if (asprintf(&attr_path, + "/sys/dev/block/%s/%s", sys_path, attr) < 0) goto out; - model_str = read_file(zoned_attr_path); + attr_str = read_file(attr_path); +out: + free(attr_path); + free(part_str); + free(part_attr_path); + free(sys_devno_path); + + return attr_str; +} + +int blkzoned_get_zoned_model(struct thread_data *td, struct fio_file *f, + enum zbd_zoned_model *model) +{ + char *model_str = NULL; + + if (f->filetype != FIO_TYPE_BLOCK) + return -EINVAL; + + *model = ZBD_NONE; + + model_str = blkzoned_get_sysfs_attr(f->file_name, "queue/zoned"); if (!model_str) - goto out; - dprint(FD_ZBD, "%s: zbd model string: %s\n", file_name, model_str); + return 0; + + dprint(FD_ZBD, "%s: zbd model string: %s\n", f->file_name, model_str); if (strcmp(model_str, "host-aware") == 0) *model = ZBD_HOST_AWARE; else if (strcmp(model_str, "host-managed") == 0) *model = ZBD_HOST_MANAGED; -out: + free(model_str); - free(zoned_attr_path); - free(part_str); - free(part_attr_path); - free(sys_devno_path); + + return 0; +} + +int blkzoned_get_max_open_zones(struct thread_data *td, struct fio_file *f, + unsigned int *max_open_zones) +{ + char *max_open_str; + + if (f->filetype != FIO_TYPE_BLOCK) + return -EIO; + + max_open_str = blkzoned_get_sysfs_attr(f->file_name, "queue/max_open_zones"); + if (!max_open_str) + return 0; + + dprint(FD_ZBD, "%s: max open zones supported by device: %s\n", + f->file_name, max_open_str); + *max_open_zones = atoll(max_open_str); + + free(max_open_str); + return 0; } +static uint64_t zone_capacity(struct blk_zone_report *hdr, + struct blk_zone *blkz) +{ + if (hdr->flags & BLK_ZONE_REP_CAPACITY) + return blkz->capacity << 9; + return blkz->len << 9; +} + int blkzoned_report_zones(struct thread_data *td, struct fio_file *f, uint64_t offset, struct zbd_zone *zones, unsigned int nr_zones) @@ -143,12 +219,13 @@ int blkzoned_report_zones(struct thread_data *td, struct fio_file *f, } nr_zones = hdr->nr_zones; - blkz = &hdr->zones[0]; + blkz = (void *) hdr + sizeof(*hdr); z = &zones[0]; for (i = 0; i < nr_zones; i++, z++, blkz++) { z->start = blkz->start << 9; z->wp = blkz->wp << 9; z->len = blkz->len << 9; + z->capacity = zone_capacity(hdr, blkz); switch (blkz->type) { case BLK_ZONE_TYPE_CONVENTIONAL: @@ -192,7 +269,7 @@ int blkzoned_report_zones(struct thread_data *td, struct fio_file *f, default: /* Treat all these conditions as offline (don't use!) */ z->cond = ZBD_ZONE_COND_OFFLINE; - break; + z->wp = z->start; } } @@ -211,9 +288,21 @@ int blkzoned_reset_wp(struct thread_data *td, struct fio_file *f, .sector = offset >> 9, .nr_sectors = length >> 9, }; + int fd, ret = 0; - if (ioctl(f->fd, BLKRESETZONE, &zr) < 0) - return -errno; + /* If the file is not yet opened, open it for this function. */ + fd = f->fd; + if (fd < 0) { + fd = open(f->file_name, O_RDWR | O_LARGEFILE); + if (fd < 0) + return -errno; + } - return 0; + if (ioctl(fd, BLKRESETZONE, &zr) < 0) + ret = -errno; + + if (f->fd < 0) + close(fd); + + return ret; }