qcow2: cache L1 table (speed up ~10% on my system)

This commit is contained in:
Ivan Baravy 2023-01-18 19:46:44 +00:00
parent 76c7819882
commit dd34949209
2 changed files with 29 additions and 12 deletions

6
io.c
View File

@ -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;

View File

@ -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;
}