On Tue, May 03, 2022, Ben Gardon wrote: > diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c > index 1d75d41f92dc..12fa8cc88043 100644 > --- a/tools/testing/selftests/kvm/lib/kvm_util.c > +++ b/tools/testing/selftests/kvm/lib/kvm_util.c > @@ -2577,3 +2577,41 @@ void read_stats_header(int stats_fd, struct kvm_stats_header *header) > ret = read(stats_fd, header, sizeof(*header)); > TEST_ASSERT(ret == sizeof(*header), "Read stats header"); > } > + > +static ssize_t stats_descs_size(struct kvm_stats_header *header) Please spell out "descriptors", I find it difficult to visually differentiate desc vs. descs. I don't mind the short version for variable names, but for helpers provided by the library I think the added clarity is worth the verbosity. > +{ > + return header->num_desc * > + (sizeof(struct kvm_stats_desc) + header->name_size); > +} Aha! This is the right patch to deal with the "variable" name_size. Rather than open code the adjustment for header->name_size, add a helper for _that_. Then read_stats_descriptors() can do: desc_size = get_stats_descriptor_size(header); total_size = header->num_desc * get_stats_descriptor_size(header); stats_desc = calloc(header->num_desc, desc_size); TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); ret = pread(stats_fd, stats_desc, total_size, header->desc_offset); TEST_ASSERT(ret == total_size, "Read KVM stats descriptors"); Those helpers provide an even better place for the comments that my cleanup patch adds. > + > +/* > + * Read binary stats descriptors > + * > + * Input Args: > + * stats_fd - the file descriptor for the binary stats file from which to read > + * header - the binary stats metadata header corresponding to the given FD > + * > + * Output Args: None > + * > + * Return: > + * A pointer to a newly allocated series of stat descriptors. > + * Caller is responsible for freeing the returned kvm_stats_desc. > + * > + * Read the stats descriptors from the binary stats interface. > + */ > +struct kvm_stats_desc *read_stats_desc(int stats_fd, This be "read_stats_descriptors" (or read_stats_descs() if someone objects to the verbose name) to make it clear this reads multiple desriptors. E.g. this on top (compile tested only) --- .../selftests/kvm/include/kvm_util_base.h | 26 +++++++++++++++++-- .../selftests/kvm/kvm_binary_stats_test.c | 7 ++--- tools/testing/selftests/kvm/lib/kvm_util.c | 23 +++++++--------- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index fabe46ddc1b2..e31f7113a529 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -401,8 +401,30 @@ void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid); int vm_get_stats_fd(struct kvm_vm *vm); int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid); void read_stats_header(int stats_fd, struct kvm_stats_header *header); -struct kvm_stats_desc *read_stats_desc(int stats_fd, - struct kvm_stats_header *header); +struct kvm_stats_desc *read_stats_descriptors(int stats_fd, + struct kvm_stats_header *header); + +static inline ssize_t get_stats_descriptor_size(struct kvm_stats_header *header) +{ + /* + * The base size of the descriptor is defined by KVM's ABI, but the + * size of the name field is variable as far as KVM's ABI is concerned. + * But, the size of name is constant for a given instance of KVM and + * is provided by KVM in the overall stats header. + */ + return sizeof(struct kvm_stats_desc) + header->name_size; +} + +static inline struct kvm_stats_desc *get_stats_descriptor(struct kvm_stats_desc *stats, + int index, + struct kvm_stats_header *header) +{ + /* + * Note, size_desc includes the of the name field, which is + * variable, i.e. this is NOT equivalent to &stats_desc[i]. + */ + return (void *)stats + index * get_stats_descriptor_size(header); +} uint32_t guest_get_vcpuid(void); diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c index b49fae45db1e..6252e3d6e964 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -35,7 +35,7 @@ static void stats_test(int stats_fd) /* Read kvm stats header */ read_stats_header(stats_fd, &header); - size_desc = sizeof(*stats_desc) + header.name_size; + size_desc = get_stats_descriptor_size(&header); /* Read kvm stats id string */ id = malloc(header.name_size); @@ -63,11 +63,12 @@ static void stats_test(int stats_fd) "Descriptor block is overlapped with data block"); /* Read kvm stats descriptors */ - stats_desc = read_stats_desc(stats_fd, &header); + stats_desc = read_stats_descriptors(stats_fd, &header); /* Sanity check for fields in descriptors */ for (i = 0; i < header.num_desc; ++i) { - pdesc = (void *)stats_desc + i * size_desc; + pdesc = get_stats_descriptor(stats_desc, i, &header); + /* Check type,unit,base boundaries */ TEST_ASSERT((pdesc->flags & KVM_STATS_TYPE_MASK) <= KVM_STATS_TYPE_MAX, "Unknown KVM stats type"); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 12fa8cc88043..4374c553de1f 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2578,12 +2578,6 @@ void read_stats_header(int stats_fd, struct kvm_stats_header *header) TEST_ASSERT(ret == sizeof(*header), "Read stats header"); } -static ssize_t stats_descs_size(struct kvm_stats_header *header) -{ - return header->num_desc * - (sizeof(struct kvm_stats_desc) + header->name_size); -} - /* * Read binary stats descriptors * @@ -2599,19 +2593,20 @@ static ssize_t stats_descs_size(struct kvm_stats_header *header) * * Read the stats descriptors from the binary stats interface. */ -struct kvm_stats_desc *read_stats_desc(int stats_fd, - struct kvm_stats_header *header) +struct kvm_stats_desc *read_stats_descriptors(int stats_fd, + struct kvm_stats_header *header) { + ssize_t ret, desc_size, total_size; struct kvm_stats_desc *stats_desc; - ssize_t ret; - stats_desc = malloc(stats_descs_size(header)); + desc_size = get_stats_descriptor_size(header); + total_size = header->num_desc * get_stats_descriptor_size(header); + + stats_desc = calloc(header->num_desc, desc_size); TEST_ASSERT(stats_desc, "Allocate memory for stats descriptors"); - ret = pread(stats_fd, stats_desc, stats_descs_size(header), - header->desc_offset); - TEST_ASSERT(ret == stats_descs_size(header), - "Read KVM stats descriptors"); + ret = pread(stats_fd, stats_desc, total_size, header->desc_offset); + TEST_ASSERT(ret == total_size, "Read KVM stats descriptors"); return stats_desc; } base-commit: 6d8fd8c4f5fa1da6fa63da1d127b2804e79b1092 --