feat(block): add ephemeral wasm vvfat writes

This commit is contained in:
2026-07-21 15:36:39 -04:00
parent cbeba3fbe9
commit 962fc6e71d
+45 -3
View File
@@ -39,6 +39,7 @@
#include "qemu/ctype.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qemu/units.h"
#ifndef S_IWGRP
#define S_IWGRP 0
@@ -336,6 +337,9 @@ typedef struct BDRVVVFATState {
int downcase_short_names;
Error *migration_blocker;
#ifdef EMSCRIPTEN
GHashTable *write_overlay;
#endif
} BDRVVVFATState;
/* take the sector position spos and convert it to Cylinder/Head/Sector position
@@ -1246,10 +1250,13 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
s->bs = bs;
#ifdef EMSCRIPTEN
if (!floppy && s->fat_type == 32) {
if (!floppy && s->fat_type == 16) {
s->sectors_per_cluster = 0x10;
total_sectors = 32ULL * MiB / BDRV_SECTOR_SIZE;
} else if (!floppy && s->fat_type == 32) {
/* Browser SD Geometry - A larger cluster keeps the synthesized 32 GiB FAT near 4 MiB. */
s->sectors_per_cluster = 0x40;
total_sectors = 32ULL * 1024 * 1024 * 1024 / BDRV_SECTOR_SIZE;
total_sectors = 32ULL * GiB / BDRV_SECTOR_SIZE;
} else
#endif
{
@@ -1516,6 +1523,18 @@ vvfat_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sector
for(i=0;i<nb_sectors;i++,sector_num++) {
if (sector_num >= bs->total_sectors)
return -1;
#ifdef EMSCRIPTEN
if (s->write_overlay) {
int64_t key = sector_num;
const uint8_t *overlay = g_hash_table_lookup(s->write_overlay,
&key);
if (overlay) {
memcpy(buf + i * BDRV_SECTOR_SIZE, overlay,
BDRV_SECTOR_SIZE);
continue;
}
}
#endif
if (s->qcow) {
int64_t n;
int ret;
@@ -3027,6 +3046,19 @@ vvfat_write(BlockDriverState *bs, int64_t sector_num,
DLOG(checkpoint());
#ifdef EMSCRIPTEN
if (s->write_overlay) {
for (i = 0; i < nb_sectors; i++) {
int64_t *key = g_new(int64_t, 1);
uint8_t *sector = g_malloc(BDRV_SECTOR_SIZE);
*key = sector_num + i;
memcpy(sector, buf + i * BDRV_SECTOR_SIZE, BDRV_SECTOR_SIZE);
g_hash_table_replace(s->write_overlay, key, sector);
}
return 0;
}
#endif
/* Check if we're operating in read-only mode */
if (s->qcow == NULL) {
return -EACCES;
@@ -3129,7 +3161,8 @@ DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sec
ret = bdrv_co_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE, buf, 0);
if (ret < 0) {
fprintf(stderr, "Error writing to qcow backend\n");
fprintf(stderr, "Error writing to qcow backend: %s (%d)\n",
strerror(-ret), ret);
return ret;
}
@@ -3205,6 +3238,12 @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
int size = sector2cluster(s, s->sector_count);
QDict *options;
#ifdef EMSCRIPTEN
s->write_overlay = g_hash_table_new_full(g_int64_hash, g_int64_equal,
g_free, g_free);
return 0;
#endif
s->used_clusters = g_malloc0(size);
array_init(&(s->commits), sizeof(commit_t));
@@ -3280,6 +3319,9 @@ static void vvfat_close(BlockDriverState *bs)
if (s->qcow) {
migrate_del_blocker(&s->migration_blocker);
}
#ifdef EMSCRIPTEN
g_clear_pointer(&s->write_overlay, g_hash_table_destroy);
#endif
}
static const char *const vvfat_strong_runtime_opts[] = {