From 7fd67eba0b961d94a5d6baa8e3c3de37b729f738 Mon Sep 17 00:00:00 2001 From: Ot ten Thije Date: Thu, 29 Jul 2010 10:26:01 +0100 Subject: Fixed rudimentary suspend/resume. This patch replaces the failing asynchronous I/O code in the qcow2 driver with a working synchronous implementation and fixes another minor bug in iteration over QField structs. As a result, the VM can now be suspended and resumed with the savevm and loadvm commands, albeit with the following (major) caveats: 1. The ADBd and other network services do not resume correctly. 2. Normal SD card usage is blocked, since snapshots are written to a qcow2 image that must (for now) be mounted on hda. 3. Resume only works after the emulator is fully booted. It is not (yet) possible to load an image immediately after the machine started. The synchronous I/O code is ported from commit ef845c3b in mainline QEMU, which addresses a similar issue. Further upstream mainline also introduces a fix for the async I/O, but that patch is quite involved, and for now this relatively simple fix works. Change-Id: I660c19c22316aecdd7dcae357e66da20e0ab6d80 --- block/qcow2-cluster.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'block/qcow2-cluster.c') diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index d349655..fdedf17 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -306,8 +306,8 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num, } -static int qcow_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +int qcow2_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, + int nb_sectors) { BDRVQcowState *s = bs->opaque; int ret, index_in_cluster, n, n1; @@ -358,7 +358,7 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect, n = n_end - n_start; if (n <= 0) return 0; - ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n); + ret = qcow2_read(bs, start_sect + n_start, s->cluster_data, n); if (ret < 0) return ret; if (s->crypt_method) { @@ -732,6 +732,12 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs, } nb_clusters = i; + if (!nb_clusters) { + abort(); + } + + QLIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight); + /* allocate a new cluster */ cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size); -- cgit v1.1