From dd34949209e15ba00aff08071d2421d4079e8331 Mon Sep 17 00:00:00 2001 From: Ivan Baravy Date: Wed, 18 Jan 2023 19:46:44 +0000 Subject: [PATCH] qcow2: cache L1 table (speed up ~10% on my system) --- io.c | 6 +++--- vdisk/qcow2.c | 35 ++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/io.c b/io.c index 4fac7e5..07edf64 100644 --- a/io.c +++ b/io.c @@ -25,7 +25,7 @@ io_init(int *running) { void io_close(struct umka_io *io) { - io_async_close(io->async); + io_async_close(io->async); free(io); } @@ -44,8 +44,8 @@ ssize_t io_write(int fd, const void *buf, size_t count, struct umka_io *io) { ssize_t res; if (!*io->running) { - res = write(fd, buf, count); - } else { + res = write(fd, buf, count); + } else { res = io_async_write(fd, buf, count, io->async); } return res; diff --git a/vdisk/qcow2.c b/vdisk/qcow2.c index 0387822..d38f39d 100644 --- a/vdisk/qcow2.c +++ b/vdisk/qcow2.c @@ -16,6 +16,9 @@ #include "miniz/miniz.h" #include "io.h" +#define L1_MAX_LEN (32u*1024u*1024u) +#define L1_MAX_ENTRIES (L1_MAX_LEN / sizeof(uint64_t)) + struct vdisk_qcow2 { struct vdisk vdisk; int fd; @@ -33,6 +36,7 @@ struct vdisk_qcow2 { off_t refcount_table_offset; size_t l1_size; uint64_t sector_idx_mask; + uint64_t *l1; }; #define QCOW2_MAGIC "QFI\xfb" @@ -93,16 +97,8 @@ qcow2_read_guest_sector(struct vdisk_qcow2 *d, uint64_t sector, uint8_t *buf) { uint64_t cluster_index = offset / d->cluster_size; uint64_t l1_index = (cluster_index) / l2_entries; uint64_t l2_index = (cluster_index) % l2_entries; - uint64_t l1_entry; + uint64_t l1_entry = d->l1[l1_index]; uint64_t l2_entry; - uint64_t l1_entry_offset = d->l1_table_offset + l1_index*sizeof(l1_entry); - lseek(d->fd, l1_entry_offset, SEEK_SET); - if (!io_read(d->fd, &l1_entry, sizeof(l1_entry), d->vdisk.io)) { - fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n", - strerror(errno)); - return; - } - l1_entry = be64(&l1_entry); uint64_t l2_table_offset = l1_entry & L1_ENTRY_OFFSET_MASK; if (!l2_table_offset) { @@ -162,6 +158,7 @@ vdisk_qcow2_close(void *userdata) { } free(d->cluster); free(d->cmp_cluster); + free(d->l1); free(d); COVERAGE_ON(); } @@ -306,5 +303,25 @@ vdisk_init_qcow2(const char *fname, struct umka_io *io) { return NULL; } + d->l1 = (uint64_t*)malloc(d->l1_size * sizeof(uint64_t)); + if (!d->l1) { + fprintf(stderr, "[vdisk.qcow2] can't allocate memory: %s\n", + strerror(errno)); + vdisk_qcow2_close(d); + return NULL; + } + + lseek(d->fd, d->l1_table_offset, SEEK_SET); + if (!io_read(d->fd, d->l1, d->l1_size * sizeof(uint64_t), d->vdisk.io)) { + fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n", + strerror(errno)); + vdisk_qcow2_close(d); + return NULL; + } + + for (uint64_t *x = d->l1; x < d->l1 + d->l1_size; x++) { + *x = be64(x); + } + return (struct vdisk*)d; }