From 0c0f53e25cded4b3b1909391f9bf22d334ed8155 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 13 Jul 2010 21:13:12 +0200 Subject: qemu-options: add documentation for stdio signal=on|off Commit 5989020bc11f8ba448d6fb79f4562f882a693d89 introduced a chardev option to disable signals on stdio. Add the corresponding documentation. Signed-off-by: Aurelien Jarno --- qemu-options.hx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 8de71d6ba..76e0fd791 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1114,7 +1114,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, "-chardev serial,id=id,path=path\n" #else "-chardev pty,id=id\n" - "-chardev stdio,id=id\n" + "-chardev stdio,id=id,[,signal=on|off]\n" #endif #ifdef CONFIG_BRLAPI "-chardev braille,id=id\n" @@ -1290,10 +1290,14 @@ not take any options. @option{pty} is not available on Windows hosts. -@item -chardev stdio ,id=@var{id} +@item -chardev stdio ,id=@var{id} [,signal=on|off] Connect to standard input and standard output of the qemu process. -@option{stdio} does not take any options. @option{stdio} is not available on -Windows hosts. + +@option{signal} controls if signals are enabled on the terminal, that includes +exiting QEMU with the key sequence @key{Control-c}. This option is enabled by +default, use @option{signal=off} to disable it. + +@option{stdio} is not available on Windows hosts. @item -chardev braille ,id=@var{id} -- cgit v1.2.3 From 2020dd5535affec319c03bf8ecd92818dee8d30b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 14 Jul 2010 10:30:31 +0200 Subject: vmdk: fix double free fail_gd error case would also free rgd_buf that was already freed Signed-off-by: Juan Quintela Signed-off-by: Anthony Liguori (cherry picked from commit a161329b61106ab093aab6d3227ac85e0b8251a9) Conflicts: block/vmdk.c Signed-off-by: Kevin Wolf --- block/vmdk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/vmdk.c b/block/vmdk.c index 4e486225b..765e95a28 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -285,7 +285,6 @@ static int vmdk_snapshot_create(const char *filename, const char *backing_file) goto fail_rgd; if (write(snp_fd, rgd_buf, gd_size) == -1) goto fail_rgd; - qemu_free(rgd_buf); /* write GD */ gd_buf = qemu_malloc(gd_size); @@ -298,6 +297,7 @@ static int vmdk_snapshot_create(const char *filename, const char *backing_file) if (write(snp_fd, gd_buf, gd_size) == -1) goto fail_gd; qemu_free(gd_buf); + qemu_free(rgd_buf); close(p_fd); close(snp_fd); -- cgit v1.2.3 From 82e9cbeb0d369a896e898fee6ab6527e416ee631 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 14 Jul 2010 10:33:49 +0200 Subject: qcow2: Fix creation of large images qcow_create2 assumes that the new image will only need one cluster for its refcount table initially. Obviously that's not true any more when the image is big enough (exact value depends on the cluster size). This patch calculates the refcount table size dynamically. Signed-off-by: Kevin Wolf (cherry picked from commit 4768fa902c3860f2fe34403e6e1c83bfca6da034) Conflicts: block/qcow2.c Signed-off-by: Kevin Wolf --- block/qcow2.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 5d33d6c79..35c05e0b2 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -747,10 +747,11 @@ static int qcow_create2(const char *filename, int64_t total_size, { int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; - int ref_clusters, backing_format_len = 0; + int ref_clusters, reftable_clusters, backing_format_len = 0; int rounded_ext_bf_len = 0; QCowHeader header; uint64_t tmp, offset; + uint64_t old_ref_clusters; QCowCreateState s1, *s = &s1; QCowExtension ext_bf = {0, 0}; @@ -809,17 +810,37 @@ static int qcow_create2(const char *filename, int64_t total_size, header.l1_size = cpu_to_be32(l1_size); offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size); - s->refcount_table = qemu_mallocz(s->cluster_size); + /* count how many refcount blocks needed */ + +#define NUM_CLUSTERS(bytes) \ + (((bytes) + (s->cluster_size) - 1) / (s->cluster_size)) + + ref_clusters = NUM_CLUSTERS(NUM_CLUSTERS(offset) * sizeof(uint16_t)); + + do { + uint64_t image_clusters; + old_ref_clusters = ref_clusters; + + /* Number of clusters used for the refcount table */ + reftable_clusters = NUM_CLUSTERS(ref_clusters * sizeof(uint64_t)); + + /* Number of clusters that the whole image will have */ + image_clusters = NUM_CLUSTERS(offset) + ref_clusters + + reftable_clusters; + + /* Number of refcount blocks needed for the image */ + ref_clusters = NUM_CLUSTERS(image_clusters * sizeof(uint16_t)); + + } while (ref_clusters != old_ref_clusters); + + s->refcount_table = qemu_mallocz(reftable_clusters * s->cluster_size); s->refcount_table_offset = offset; header.refcount_table_offset = cpu_to_be64(offset); - header.refcount_table_clusters = cpu_to_be32(1); - offset += s->cluster_size; + header.refcount_table_clusters = cpu_to_be32(reftable_clusters); + offset += (reftable_clusters * s->cluster_size); s->refcount_block_offset = offset; - /* count how many refcount blocks needed */ - tmp = offset >> s->cluster_bits; - ref_clusters = (tmp >> (s->cluster_bits - REFCOUNT_SHIFT)) + 1; for (i=0; i < ref_clusters; i++) { s->refcount_table[i] = cpu_to_be64(offset); offset += s->cluster_size; @@ -831,7 +852,8 @@ static int qcow_create2(const char *filename, int64_t total_size, qcow2_create_refcount_update(s, 0, header_size); qcow2_create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t)); - qcow2_create_refcount_update(s, s->refcount_table_offset, s->cluster_size); + qcow2_create_refcount_update(s, s->refcount_table_offset, + reftable_clusters * s->cluster_size); qcow2_create_refcount_update(s, s->refcount_block_offset, ref_clusters * s->cluster_size); @@ -859,7 +881,8 @@ static int qcow_create2(const char *filename, int64_t total_size, write(fd, &tmp, sizeof(tmp)); } lseek(fd, s->refcount_table_offset, SEEK_SET); - write(fd, s->refcount_table, s->cluster_size); + write(fd, s->refcount_table, + reftable_clusters * s->cluster_size); lseek(fd, s->refcount_block_offset, SEEK_SET); write(fd, s->refcount_block, ref_clusters * s->cluster_size); -- cgit v1.2.3 From 34d0d68bdf295fe834b7c49d3f610fe86f587c6e Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 16 Apr 2010 19:28:14 +0200 Subject: vmdk: Fix COW When trying to do COW, VMDK wrote the data back to the backing file. This problem was revealed by the patch that made backing files read-only. This patch does not only fix the problem, but also simplifies the VMDK code a bit. This fixes the backing file qemu-iotests cases for VMDK. Signed-off-by: Kevin Wolf (cherry picked from commit c336500df5bf08492f4e7796b2193cd4976f3548) --- block/vmdk.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 765e95a28..d52904a0e 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -87,14 +87,6 @@ typedef struct VmdkMetaData { int valid; } VmdkMetaData; -typedef struct ActiveBDRVState{ - BlockDriverState *hd; // active image handler - uint64_t cluster_offset; // current write offset -}ActiveBDRVState; - -static ActiveBDRVState activeBDRV; - - static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename) { uint32_t magic; @@ -458,30 +450,28 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data, static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset, uint64_t offset, int allocate) { - uint64_t parent_cluster_offset; BDRVVmdkState *s = bs->opaque; uint8_t whole_grain[s->cluster_sectors*512]; // 128 sectors * 512 bytes each = grain size 64KB // we will be here if it's first write on non-exist grain(cluster). // try to read from parent image, if exist if (bs->backing_hd) { - BDRVVmdkState *ps = bs->backing_hd->opaque; + int ret; if (!vmdk_is_cid_valid(bs)) return -1; - parent_cluster_offset = get_cluster_offset(bs->backing_hd, NULL, - offset, allocate); - - if (parent_cluster_offset) { - BDRVVmdkState *act_s = activeBDRV.hd->opaque; - - if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != ps->cluster_sectors*512) - return -1; + ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain, + s->cluster_sectors); + if (ret < 0) { + return -1; + } - //Write grain only into the active image - if (bdrv_pwrite(act_s->hd, activeBDRV.cluster_offset << 9, whole_grain, sizeof(whole_grain)) != sizeof(whole_grain)) - return -1; + //Write grain only into the active image + ret = bdrv_write(s->hd, cluster_offset, whole_grain, + s->cluster_sectors); + if (ret < 0) { + return -1; } } return 0; @@ -567,9 +557,6 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data, cluster_offset >>= 9; tmp = cpu_to_le32(cluster_offset); l2_table[l2_index] = tmp; - // Save the active image state - activeBDRV.cluster_offset = cluster_offset; - activeBDRV.hd = bs; } /* First of all we write grain itself, to avoid race condition * that may to corrupt the image. -- cgit v1.2.3 From 729862401ddbf2554807f085e234e26625ba542c Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 21 Apr 2010 11:37:52 +0200 Subject: qcow2: Remove abort on free_clusters failure While it's true that during regular operation free_clusters failure would be a bug, an I/O error can always happen. There's no need to kill the VM, the worst thing that can happen (and it will) is that we leak some clusters. Signed-off-by: Kevin Wolf (cherry picked from commit 003fad6e2cae5311d3aea996388c90e3ab17de90) --- block/qcow2-refcount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 465d5d36e..ff2cf6db2 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -631,7 +631,7 @@ void qcow2_free_clusters(BlockDriverState *bs, ret = update_refcount(bs, offset, size, -1); if (ret < 0) { fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret)); - abort(); + /* TODO Remember the clusters to free them later and avoid leaking */ } } -- cgit v1.2.3 From 39187b5192bf16a6bbd3f272bef88f92e61b4c02 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 10 May 2010 21:46:26 +0200 Subject: block/vpc: Fix conversion from size to disk geometry The VHD algorithm calculates a disk geometry which is usually smaller than the requested size. QEMU tried to round up but failed for certain sizes: qemu-img create -f vpc disk.vpc 9437184 would create an image with 9435136 bytes (which is too small for qemu-img convert). Instead of hacking the geometry algorithm, the patch increases the number of sectors until we get enough sectors. Cc: Kevin Wolf Signed-off-by: Stefan Weil Signed-off-by: Kevin Wolf (cherry picked from commit dede4188cc817a039154ed2ecd7f3285f6b94056) --- block/vpc.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index 950ad58b3..afe6f1a9a 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -470,9 +470,7 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls, } } - // Note: Rounding up deviates from the Virtual PC behaviour - // However, we need this to avoid truncating images in qemu-img convert - *cyls = (cyls_times_heads + *heads - 1) / *heads; + *cyls = cyls_times_heads / *heads; return 0; } @@ -484,9 +482,9 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options) struct vhd_dyndisk_header* dyndisk_header = (struct vhd_dyndisk_header*) buf; int fd, i; - uint16_t cyls; - uint8_t heads; - uint8_t secs_per_cyl; + uint16_t cyls = 0; + uint8_t heads = 0; + uint8_t secs_per_cyl = 0; size_t block_size, num_bat_entries; int64_t total_sectors = 0; @@ -503,9 +501,14 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options) if (fd < 0) return -EIO; - // Calculate matching total_size and geometry - if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl)) - return -EFBIG; + /* Calculate matching total_size and geometry. Increase the number of + sectors requested until we get enough (or fail). */ + for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) { + if (calculate_geometry(total_sectors + i, + &cyls, &heads, &secs_per_cyl)) { + return -EFBIG; + } + } total_sectors = (int64_t) cyls * heads * secs_per_cyl; // Prepare the Hard Disk Footer -- cgit v1.2.3 From 6fd82592cec15256a6dcfe516a7ce6c99f1912b7 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 14 Jul 2010 11:50:47 +0200 Subject: block/vdi: Fix image opening and creation for odd disk sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fix is based on a patch from Kevin Wolf. Here his comment: "The number of blocks needs to be rounded up to cover all of the virtual hard disk. Without this fix, we can't even open our own images if their size is not a multiple of the block size." While Kevin's patch addressed vdi_create, my modification also fixes vdi_open which now accepts images with odd disk sizes. v3: Don't allow reading of disk images with too large disk sizes. Neither VBoxManage nor old versions of qemu-img read such images. This change requires rounding of odd disk sizes before we do the checks. Cc: Kevin Wolf Cc: François Revol Signed-off-by: Stefan Weil Signed-off-by: Kevin Wolf (cherry picked from commit f21dc3a4652eeb82117d7d55d975278fe1444b26) Conflicts: block/vdi.c Signed-off-by: Kevin Wolf --- block/vdi.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index 45aa81c70..64bf66f0b 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -399,6 +399,15 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags) vdi_header_print(&header); #endif + if (header.disk_size % SECTOR_SIZE != 0) { + /* 'VBoxManage convertfromraw' can create images with odd disk sizes. + We accept them but round the disk size to the next multiple of + SECTOR_SIZE. */ + logout("odd disk size %" PRIu64 " B, round up\n", header.disk_size); + header.disk_size += SECTOR_SIZE - 1; + header.disk_size &= ~(SECTOR_SIZE - 1); + } + if (header.version != VDI_VERSION_1_1) { logout("unsupported version %u.%u\n", header.version >> 16, header.version & 0xffff); @@ -417,9 +426,9 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags) } else if (header.block_size != 1 * MiB) { logout("unsupported block size %u B\n", header.block_size); goto fail; - } else if (header.disk_size != + } else if (header.disk_size > (uint64_t)header.blocks_in_image * header.block_size) { - logout("unexpected block number %u B\n", header.blocks_in_image); + logout("unsupported disk size %" PRIu64 " B\n", header.disk_size); goto fail; } else if (!uuid_is_null(header.uuid_link)) { logout("link uuid != 0, unsupported\n"); @@ -831,7 +840,10 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) return -errno; } - blocks = bytes / block_size; + /* We need enough blocks to store the given disk size, + so always round up. */ + blocks = (bytes + block_size - 1) / block_size; + bmap_size = blocks * sizeof(uint32_t); bmap_size = ((bmap_size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE -1)); -- cgit v1.2.3 From dfe0bb55eea9efabc98d074407e01c9a85b7497b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 7 Jun 2010 16:43:22 +0200 Subject: qcow2: Restore L1 entry on l2_allocate failure If writing the L1 table to disk failed, we need to restore its old content in memory to avoid inconsistencies. Reported-by: Juan Quintela Signed-off-by: Kevin Wolf (cherry picked from commit 68dba0bf455e60061bb3c9c40ef0d82916372664) --- block/qcow2-cluster.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index b7a5b35f4..8c67e3c07 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -266,6 +266,7 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index) return l2_table; fail: + s->l1_table[l1_index] = old_l2_offset; qcow2_l2_cache_reset(bs); return NULL; } -- cgit v1.2.3 From ceef722d01482f111df24f5005e71a615d87f3fd Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 16 Jun 2010 16:38:15 +0200 Subject: block: Add bdrv_(p)write_sync Add new functions that write and flush the written data to disk immediately. This is what needs to be used for image format metadata to maintain integrity for cache=... modes that don't use O_DSYNC. (Actually, we only need barriers, and therefore the functions are defined as such, but flushes is what is implemented in this patch - we can try to change that later) Signed-off-by: Kevin Wolf (cherry picked from commit f08145fe16470aca09304099888f68cfbc5d1de7) --- block.c | 39 +++++++++++++++++++++++++++++++++++++++ block.h | 4 ++++ block_int.h | 1 + 3 files changed, 44 insertions(+) diff --git a/block.c b/block.c index 298414c92..e3b3a5504 100644 --- a/block.c +++ b/block.c @@ -452,6 +452,8 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, (flags & (BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO)); else open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT); + + bs->open_flags = open_flags; if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) ret = -ENOTSUP; else @@ -779,6 +781,43 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset, return count1; } +/* + * Writes to the file and ensures that no writes are reordered across this + * request (acts as a barrier) + * + * Returns 0 on success, -errno in error cases. + */ +int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, + const void *buf, int count) +{ + int ret; + + ret = bdrv_pwrite(bs, offset, buf, count); + if (ret < 0) { + return ret; + } + + /* No flush needed for cache=writethrough, it uses O_DSYNC */ + if ((bs->open_flags & BDRV_O_CACHE_MASK) != 0) { + bdrv_flush(bs); + } + + return 0; +} + +/* + * Writes to the file and ensures that no writes are reordered across this + * request (acts as a barrier) + * + * Returns 0 on success, -errno in error cases. + */ +int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + return bdrv_pwrite_sync(bs, BDRV_SECTOR_SIZE * sector_num, + buf, BDRV_SECTOR_SIZE * nb_sectors); +} + /** * Truncate file to 'offset' bytes (needed only for file protocols) */ diff --git a/block.h b/block.h index fa51ddf15..762d88a5c 100644 --- a/block.h +++ b/block.h @@ -77,6 +77,10 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset, void *buf, int count); int bdrv_pwrite(BlockDriverState *bs, int64_t offset, const void *buf, int count); +int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, + const void *buf, int count); +int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors); int bdrv_truncate(BlockDriverState *bs, int64_t offset); int64_t bdrv_getlength(BlockDriverState *bs); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); diff --git a/block_int.h b/block_int.h index 9a3b2e09d..631e8c56d 100644 --- a/block_int.h +++ b/block_int.h @@ -127,6 +127,7 @@ struct BlockDriverState { int64_t total_sectors; /* if we are reading a disk image, give its size in sectors */ int read_only; /* if true, the media is read only */ + int open_flags; /* flags used to open the file, re-used for re-open */ int removable; /* if true, the media can be removed */ int locked; /* if true, the media cannot temporarily be ejected */ int encrypted; /* if true, the media is encrypted */ -- cgit v1.2.3 From 7205c21e76dec9be51a3b044bc045df75b6d7893 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 14 Jul 2010 12:02:53 +0200 Subject: qcow: Use bdrv_(p)write_sync for metadata writes Use bdrv_(p)write_sync to ensure metadata integrity in case of a crash. Signed-off-by: Kevin Wolf (cherry picked from commit 5e5557d97026d1d3325e0e7b0ba593366da2f3dc) Conflicts: block/qcow.c Signed-off-by: Kevin Wolf --- block/qcow.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/block/qcow.c b/block/qcow.c index 7fc85ae58..6a4c30f61 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -277,8 +277,9 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, /* update the L1 entry */ s->l1_table[l1_index] = l2_offset; tmp = cpu_to_be64(l2_offset); - if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp), - &tmp, sizeof(tmp)) != sizeof(tmp)) + if (bdrv_pwrite_sync(s->hd, + s->l1_table_offset + l1_index * sizeof(tmp), + &tmp, sizeof(tmp)) < 0) return 0; new_l2_table = 1; } @@ -306,8 +307,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, l2_table = s->l2_cache + (min_index << s->l2_bits); if (new_l2_table) { memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); - if (bdrv_pwrite(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) != - s->l2_size * sizeof(uint64_t)) + if (bdrv_pwrite_sync(s->hd, l2_offset, l2_table, + s->l2_size * sizeof(uint64_t)) < 0) return 0; } else { if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) != @@ -372,8 +373,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, /* update L2 table */ tmp = cpu_to_be64(cluster_offset); l2_table[l2_index] = tmp; - if (bdrv_pwrite(s->hd, - l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp)) + if (bdrv_pwrite_sync(s->hd, l2_offset + l2_index * sizeof(tmp), + &tmp, sizeof(tmp)) < 0) return 0; } return cluster_offset; @@ -821,8 +822,9 @@ static int qcow_make_empty(BlockDriverState *bs) int ret; memset(s->l1_table, 0, l1_length); - if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0) - return -1; + if (bdrv_pwrite_sync(s->hd, s->l1_table_offset, s->l1_table, + l1_length) < 0) + return -1; ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length); if (ret < 0) return ret; -- cgit v1.2.3 From 37060c28e522843fbf6f7e59af745dfcb05b132c Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 14 Jul 2010 12:11:51 +0200 Subject: qcow2: Use bdrv_(p)write_sync for metadata writes Use bdrv_(p)write_sync to ensure metadata integrity in case of a crash. Signed-off-by: Kevin Wolf (cherry picked from commit 8b3b720620a1137a1b794fc3ed64734236f94e06) Conflicts: block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2-snapshot.c block/qcow2.c Signed-off-by: Kevin Wolf --- block/qcow2-cluster.c | 45 ++++++++++++++++++++++++--------------------- block/qcow2-refcount.c | 31 ++++++++++++++++--------------- block/qcow2-snapshot.c | 23 +++++++++++------------ 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 8c67e3c07..0a555dc67 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -62,8 +62,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size) for(i = 0; i < s->l1_size; i++) new_l1_table[i] = cpu_to_be64(new_l1_table[i]); - ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2); - if (ret != new_l1_size2) + ret = bdrv_pwrite_sync(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2); + if (ret < 0) goto fail; for(i = 0; i < s->l1_size; i++) new_l1_table[i] = be64_to_cpu(new_l1_table[i]); @@ -71,8 +71,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size) /* set new table */ cpu_to_be32w((uint32_t*)data, new_l1_size); cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset); - ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data)); - if (ret != sizeof(data)) { + ret = bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data)); + if (ret < 0) { goto fail; } qemu_free(s->l1_table); @@ -84,7 +84,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size) fail: qemu_free(new_l1_table); qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2); - return ret < 0 ? ret : -EIO; + return ret; } void qcow2_l2_cache_reset(BlockDriverState *bs) @@ -188,17 +188,17 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index) { uint64_t buf[L1_ENTRIES_PER_SECTOR]; int l1_start_index; - int i; + int i, ret; l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1); for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) { buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]); } - if (bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index, - buf, sizeof(buf)) != sizeof(buf)) - { - return -1; + ret = bdrv_pwrite_sync(s->hd, s->l1_table_offset + 8 * l1_start_index, + buf, sizeof(buf)); + if (ret < 0) { + return ret; } return 0; @@ -221,6 +221,7 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index) uint64_t old_l2_offset; uint64_t *l2_table; int64_t l2_offset; + int ret; old_l2_offset = s->l1_table[l1_index]; @@ -247,10 +248,11 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index) goto fail; } /* write the l2 table to the file */ - if (bdrv_pwrite(s->hd, l2_offset, - l2_table, s->l2_size * sizeof(uint64_t)) != - s->l2_size * sizeof(uint64_t)) + ret = bdrv_pwrite_sync(s->hd, l2_offset, l2_table, + s->l2_size * sizeof(uint64_t)); + if (ret < 0) { goto fail; + } /* update the L1 entry */ s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED; @@ -384,8 +386,8 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect, s->cluster_data, n, 1, &s->aes_encrypt_key); } - ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start, - s->cluster_data, n); + ret = bdrv_write_sync(s->hd, (cluster_offset >> 9) + n_start, + s->cluster_data, n); if (ret < 0) return ret; return 0; @@ -597,10 +599,10 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, /* compressed clusters never have the copied flag */ l2_table[l2_index] = cpu_to_be64(cluster_offset); - if (bdrv_pwrite(s->hd, + if (bdrv_pwrite_sync(s->hd, l2_offset + l2_index * sizeof(uint64_t), l2_table + l2_index, - sizeof(uint64_t)) != sizeof(uint64_t)) + sizeof(uint64_t)) < 0) return 0; return cluster_offset; @@ -618,11 +620,12 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table, int start_offset = (8 * l2_index) & ~511; int end_offset = (8 * (l2_index + num) + 511) & ~511; size_t len = end_offset - start_offset; + int ret; - if (bdrv_pwrite(s->hd, l2_offset + start_offset, &l2_table[l2_start_index], - len) != len) - { - return -1; + ret = bdrv_pwrite_sync(s->hd, l2_offset + start_offset, + &l2_table[l2_start_index], len); + if (ret < 0) { + return ret; } return 0; diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index ff2cf6db2..06998dab0 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -42,8 +42,8 @@ static int write_refcount_block(BDRVQcowState *s) return 0; } - if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset, - s->refcount_block_cache, size) != size) + if (bdrv_pwrite_sync(s->hd, s->refcount_block_cache_offset, + s->refcount_block_cache, size) < 0) { return -EIO; } @@ -246,7 +246,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) } /* Now the new refcount block needs to be written to disk */ - ret = bdrv_pwrite(s->hd, new_block, s->refcount_block_cache, + ret = bdrv_pwrite_sync(s->hd, new_block, s->refcount_block_cache, s->cluster_size); if (ret < 0) { goto fail_block; @@ -255,7 +255,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) /* If the refcount table is big enough, just hook the block up there */ if (refcount_table_index < s->refcount_table_size) { uint64_t data64 = cpu_to_be64(new_block); - ret = bdrv_pwrite(s->hd, + ret = bdrv_pwrite_sync(s->hd, s->refcount_table_offset + refcount_table_index * sizeof(uint64_t), &data64, sizeof(data64)); if (ret < 0) { @@ -332,7 +332,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) } /* Write refcount blocks to disk */ - ret = bdrv_pwrite(s->hd, meta_offset, new_blocks, + ret = bdrv_pwrite_sync(s->hd, meta_offset, new_blocks, blocks_clusters * s->cluster_size); qemu_free(new_blocks); if (ret < 0) { @@ -344,7 +344,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) cpu_to_be64s(&new_table[i]); } - ret = bdrv_pwrite(s->hd, table_offset, new_table, + ret = bdrv_pwrite_sync(s->hd, table_offset, new_table, table_size * sizeof(uint64_t)); if (ret < 0) { goto fail_table; @@ -358,7 +358,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) uint8_t data[12]; cpu_to_be64w((uint64_t*)data, table_offset); cpu_to_be32w((uint32_t*)(data + 8), table_clusters); - ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset), + ret = bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, refcount_table_offset), data, sizeof(data)); if (ret < 0) { goto fail_table; @@ -397,6 +397,7 @@ static int write_refcount_block_entries(BDRVQcowState *s, int64_t refcount_block_offset, int first_index, int last_index) { size_t size; + int ret; if (cache_refcount_updates) { return 0; @@ -411,11 +412,11 @@ static int write_refcount_block_entries(BDRVQcowState *s, & ~(REFCOUNTS_PER_SECTOR - 1); size = (last_index - first_index) << REFCOUNT_SHIFT; - if (bdrv_pwrite(s->hd, + ret = bdrv_pwrite_sync(s->hd, refcount_block_offset + (first_index << REFCOUNT_SHIFT), - &s->refcount_block_cache[first_index], size) != size) - { - return -EIO; + &s->refcount_block_cache[first_index], size); + if (ret < 0) { + return ret; } return 0; @@ -771,8 +772,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } } if (l2_modified) { - if (bdrv_pwrite(s->hd, - l2_offset, l2_table, l2_size) != l2_size) + if (bdrv_pwrite_sync(s->hd, + l2_offset, l2_table, l2_size) < 0) goto fail; } @@ -793,8 +794,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, if (l1_modified) { for(i = 0; i < l1_size; i++) cpu_to_be64s(&l1_table[i]); - if (bdrv_pwrite(s->hd, l1_table_offset, l1_table, - l1_size2) != l1_size2) + if (bdrv_pwrite_sync(s->hd, l1_table_offset, l1_table, + l1_size2) < 0) goto fail; for(i = 0; i < l1_size; i++) be64_to_cpus(&l1_table[i]); diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 8ddaea23b..64af36181 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -158,25 +158,25 @@ static int qcow_write_snapshots(BlockDriverState *bs) h.id_str_size = cpu_to_be16(id_str_size); h.name_size = cpu_to_be16(name_size); offset = align_offset(offset, 8); - if (bdrv_pwrite(s->hd, offset, &h, sizeof(h)) != sizeof(h)) + if (bdrv_pwrite_sync(s->hd, offset, &h, sizeof(h)) < 0) goto fail; offset += sizeof(h); - if (bdrv_pwrite(s->hd, offset, sn->id_str, id_str_size) != id_str_size) + if (bdrv_pwrite_sync(s->hd, offset, sn->id_str, id_str_size) < 0) goto fail; offset += id_str_size; - if (bdrv_pwrite(s->hd, offset, sn->name, name_size) != name_size) + if (bdrv_pwrite_sync(s->hd, offset, sn->name, name_size) < 0) goto fail; offset += name_size; } /* update the various header fields */ data64 = cpu_to_be64(snapshots_offset); - if (bdrv_pwrite(s->hd, offsetof(QCowHeader, snapshots_offset), - &data64, sizeof(data64)) != sizeof(data64)) + if (bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, snapshots_offset), + &data64, sizeof(data64)) < 0) goto fail; data32 = cpu_to_be32(s->nb_snapshots); - if (bdrv_pwrite(s->hd, offsetof(QCowHeader, nb_snapshots), - &data32, sizeof(data32)) != sizeof(data32)) + if (bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, nb_snapshots), + &data32, sizeof(data32)) < 0) goto fail; /* free the old snapshot table */ @@ -284,9 +284,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) for(i = 0; i < s->l1_size; i++) { l1_table[i] = cpu_to_be64(s->l1_table[i]); } - if (bdrv_pwrite(s->hd, sn->l1_table_offset, - l1_table, s->l1_size * sizeof(uint64_t)) != - (s->l1_size * sizeof(uint64_t))) + if (bdrv_pwrite_sync(s->hd, sn->l1_table_offset, + l1_table, s->l1_size * sizeof(uint64_t)) < 0) goto fail; qemu_free(l1_table); l1_table = NULL; @@ -335,8 +334,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) if (bdrv_pread(s->hd, sn->l1_table_offset, s->l1_table, l1_size2) != l1_size2) goto fail; - if (bdrv_pwrite(s->hd, s->l1_table_offset, - s->l1_table, l1_size2) != l1_size2) + if (bdrv_pwrite_sync(s->hd, s->l1_table_offset, + s->l1_table, l1_size2) < 0) goto fail; for(i = 0;i < s->l1_size; i++) { be64_to_cpus(&s->l1_table[i]); -- cgit v1.2.3 From a9d9a66f13775cdcf502f7dc19bcfc01b63b7544 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 14 Jul 2010 13:08:04 +0200 Subject: vmdk: Use bdrv_(p)write_sync for metadata writes Use bdrv_(p)write_sync to ensure metadata integrity in case of a crash. Signed-off-by: Kevin Wolf (cherry picked from commit b8852e87d9d113096342c3e0977266cda0fe9ee5) Conflicts: block/vmdk.c Signed-off-by: Kevin Wolf --- block/vmdk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index d52904a0e..cd8727924 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -153,7 +153,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) pstrcat(desc, sizeof(desc), tmp_desc); } - if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE) + if (bdrv_pwrite_sync(s->hd, 0x200, desc, DESC_SIZE) < 0) return -1; return 0; } @@ -482,14 +482,14 @@ static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data) BDRVVmdkState *s = bs->opaque; /* update L2 table */ - if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)), - &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset)) + if (bdrv_pwrite_sync(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)), + &(m_data->offset), sizeof(m_data->offset)) < 0) return -1; /* update backup L2 table */ if (s->l1_backup_table_offset != 0) { m_data->l2_offset = s->l1_backup_table[m_data->l1_index]; - if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)), - &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset)) + if (bdrv_pwrite_sync(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)), + &(m_data->offset), sizeof(m_data->offset)) < 0) return -1; } -- cgit v1.2.3 From a2f0cbaa5808e4071fbde6903bdfa0971e918f7e Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 14 Jul 2010 13:08:45 +0200 Subject: vpc: Use bdrv_(p)write_sync for metadata writes Use bdrv_(p)write_sync to ensure metadata integrity in case of a crash. Signed-off-by: Kevin Wolf (cherry picked from commit 078a458e077d6b0db262c4b05fee51d01de2d1d2) Conflicts: block/vpc.c Signed-off-by: Kevin Wolf --- block/vpc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index afe6f1a9a..9e0acf4b1 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -266,7 +266,7 @@ static inline int64_t get_sector_offset(BlockDriverState *bs, s->last_bitmap_offset = bitmap_offset; memset(bitmap, 0xff, s->bitmap_size); - bdrv_pwrite(s->hd, bitmap_offset, bitmap, s->bitmap_size); + bdrv_pwrite_sync(s->hd, bitmap_offset, bitmap, s->bitmap_size); } // printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n", @@ -316,7 +316,7 @@ static int rewrite_footer(BlockDriverState* bs) BDRVVPCState *s = bs->opaque; int64_t offset = s->free_data_block_offset; - ret = bdrv_pwrite(s->hd, offset, s->footer_buf, HEADER_SIZE); + ret = bdrv_pwrite_sync(s->hd, offset, s->footer_buf, HEADER_SIZE); if (ret < 0) return ret; @@ -351,7 +351,8 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num) // Initialize the block's bitmap memset(bitmap, 0xff, s->bitmap_size); - bdrv_pwrite(s->hd, s->free_data_block_offset, bitmap, s->bitmap_size); + bdrv_pwrite_sync(s->hd, s->free_data_block_offset, bitmap, + s->bitmap_size); // Write new footer (the old one will be overwritten) s->free_data_block_offset += s->block_size + s->bitmap_size; @@ -362,7 +363,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num) // Write BAT entry to disk bat_offset = s->bat_offset + (4 * index); bat_value = be32_to_cpu(s->pagetable[index]); - ret = bdrv_pwrite(s->hd, bat_offset, &bat_value, 4); + ret = bdrv_pwrite_sync(s->hd, bat_offset, &bat_value, 4); if (ret < 0) goto fail; -- cgit v1.2.3 From 191d44fc4361932c3ae647eee343e150fb8b6e34 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 14 Jul 2010 12:42:02 +0200 Subject: block: Fix early failure in multiwrite bdrv_aio_writev may call the callback immediately (and it will commonly do so in error cases). Current code doesn't consider this. For details see the comment added by this patch. Signed-off-by: Kevin Wolf (cherry picked from commit 453f9a1652629e5805995b165be2e634c8487139) Conflicts: block.c Signed-off-by: Kevin Wolf --- block.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/block.c b/block.c index e3b3a5504..80f2faecd 100644 --- a/block.c +++ b/block.c @@ -1802,8 +1802,29 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) // Check for mergable requests num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb); - // Run the aio requests + /* + * Run the aio requests. As soon as one request can't be submitted + * successfully, fail all requests that are not yet submitted (we must + * return failure for all requests anyway) + * + * num_requests cannot be set to the right value immediately: If + * bdrv_aio_writev fails for some request, num_requests would be too high + * and therefore multiwrite_cb() would never recognize the multiwrite + * request as completed. We also cannot use the loop variable i to set it + * when the first request fails because the callback may already have been + * called for previously submitted requests. Thus, num_requests must be + * incremented for each request that is submitted. + * + * The problem that callbacks may be called early also means that we need + * to take care that num_requests doesn't become 0 before all requests are + * submitted - multiwrite_cb() would consider the multiwrite request + * completed. A dummy request that is "completed" by a manual call to + * multiwrite_cb() takes care of this. + */ + mcb->num_requests = 1; + for (i = 0; i < num_reqs; i++) { + mcb->num_requests++; acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov, reqs[i].nb_sectors, multiwrite_cb, mcb); @@ -1811,23 +1832,25 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) // We can only fail the whole thing if no request has been // submitted yet. Otherwise we'll wait for the submitted AIOs to // complete and report the error in the callback. - if (mcb->num_requests == 0) { - reqs[i].error = -EIO; + if (i == 0) { goto fail; } else { - mcb->num_requests++; multiwrite_cb(mcb, -EIO); break; } - } else { - mcb->num_requests++; } } + /* Complete the dummy request */ + multiwrite_cb(mcb, 0); + return 0; fail: - free(mcb); + for (i = 0; i < mcb->num_callbacks; i++) { + reqs[i].error = -EIO; + } + qemu_free(mcb); return -1; } -- cgit v1.2.3 From bb44e0bbcea21e50aaed1bd54d0aa53c46cecbf1 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 1 Jul 2010 16:08:51 +0200 Subject: block: Handle multiwrite errors only when all requests have completed Don't try to be clever by freeing all temporary data and calling all callbacks when the return value (an error) is certain. Doing so has at least two important problems: * The temporary data that is freed (qiov, possibly zero buffer) is still used by the requests that have not yet completed. * Calling the callbacks for all requests in the multiwrite means for the caller that it may free buffers etc. which are still in use. Just remember the error value and do the cleanup when all requests have completed. Signed-off-by: Kevin Wolf (cherry picked from commit de189a1b4a471d37a2909e97646654fc9751b52f) --- block.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/block.c b/block.c index 80f2faecd..169478046 100644 --- a/block.c +++ b/block.c @@ -1661,14 +1661,11 @@ static void multiwrite_cb(void *opaque, int ret) if (ret < 0 && !mcb->error) { mcb->error = ret; - multiwrite_user_cb(mcb); } mcb->num_requests--; if (mcb->num_requests == 0) { - if (mcb->error == 0) { - multiwrite_user_cb(mcb); - } + multiwrite_user_cb(mcb); qemu_free(mcb); } } -- cgit v1.2.3 From e91644894048ff6640a8e462da936e7ff0e28d38 Mon Sep 17 00:00:00 2001 From: malc Date: Sun, 28 Feb 2010 18:34:21 +0300 Subject: audio/alsa: Handle SND_PCM_STATE_SETUP in alsa_poll_handler Signed-off-by: malc (cherry picked from commit d9812b033a17c82f9e933757c1c3ef364e3ba62d) --- audio/alsaaudio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 6a9b87aa7..88344ff03 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -213,6 +213,10 @@ static void alsa_poll_handler (void *opaque) state = snd_pcm_state (hlp->handle); switch (state) { + case SND_PCM_STATE_SETUP: + alsa_recover (hlp->handle); + break; + case SND_PCM_STATE_XRUN: alsa_recover (hlp->handle); break; -- cgit v1.2.3 From 174f225e9d62e8f3002e274e4f718bd2a967fbf4 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 22 Jul 2010 14:39:04 +0200 Subject: Update for 0.12.5 release Signed-off-by: Aurelien Jarno --- Changelog | 47 +++++++++++++++++++++++++++++++++++++++++++++++ VERSION | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 4feb1867e..5030c9b7d 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,50 @@ +version 0.12.5 + - audio/alsa: Handle SND_PCM_STATE_SETUP in alsa_poll_handler + - block: Handle multiwrite errors only when all requests have completed + - block: Fix early failure in multiwrite + - vpc: Use bdrv_(p)write_sync for metadata writes + - vmdk: Use bdrv_(p)write_sync for metadata writes + - qcow2: Use bdrv_(p)write_sync for metadata writes + - qcow: Use bdrv_(p)write_sync for metadata writes + - block: Add bdrv_(p)write_sync + - qcow2: Restore L1 entry on l2_allocate failure + - block/vdi: Fix image opening and creation for odd disk sizes + - block/vpc: Fix conversion from size to disk geometry + - qcow2: Remove abort on free_clusters failure + - vmdk: Fix COW + - qcow2: Fix creation of large images + - vmdk: fix double free + - qemu-options: add documentation for stdio signal=on|off + - target-arm : fix parallel saturated subtraction implementation + - target-arm : fix thumb2 parallel add/sub opcode decoding + - target-arm: fix addsub/subadd implementation + - target-i386: fix xchg rax,r8 + - block/vvfat.c: fix warnings with _FORTIFY_SOURCE + - audio/alsa: Spelling typo (paramters) + - target-mips: fix DINSU instruction + - Correct definitions for FD_CMD_SAVE and FD_CMD_RESTORE + - qcow2: Fix corruption after error in update_refcount + - qcow2: Fix corruption after refblock allocation + - block: Fix multiwrite with overlapping requests + - qcow2: Fix error handling in l2_allocate + - qcow2: Clear L2 table cache after write error + - ide: Fix ide_dma_cancel + - usb-bus: fix no params + - Avoid crash on '-usbdevice ' without parameters + - Fix -usbdevice crash + - Fix multiboot compilation + - Fix missing symbols in .rel/.rela.plt sections + - target-ppc: fix RFI by clearing some bits of MSR + - Fix typo in balloon help + - arm_timer: fix oneshot mode + - arm_timer: reload timer when enabled + - qemu-sockets: avoid strlen of NULL pointer + - block: fix aio_flush segfaults for read-only protocols (e.g. curl) + - virtio-blk: fix barrier support + - block: fix sector comparism in multiwrite_req_compare + - pci: irq_state vmstate breakage + - qemu-img: use the heap instead of the huge stack array for win32 + version 0.12.4 - Workaround for broken OSS_GETVERSION on FreeBSD, part two (Juergen Lock) - oss: fix fragment setting (malc) diff --git a/VERSION b/VERSION index e01e0ddd8..43c2417ca 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.12.4 +0.12.5 -- cgit v1.2.3