[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 40/62] block: Handle failure for potentially large al
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PULL 40/62] block: Handle failure for potentially large allocations |
Date: |
Fri, 8 Aug 2014 19:39:41 +0200 |
Some code in the block layer makes potentially huge allocations. Failure
is not completely unexpected there, so avoid aborting qemu and handle
out-of-memory situations gracefully.
This patch addresses bounce buffer allocations in block.c. While at it,
convert bdrv_commit() from plain g_malloc() to qemu_try_blockalign().
Signed-off-by: Kevin Wolf <address@hidden>
Reviewed-by: Eric Blake <address@hidden>
Reviewed-by: Stefan Hajnoczi <address@hidden>
---
block.c | 34 +++++++++++++++++++++++++++-------
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/block.c b/block.c
index 9cf8b5d..b3a06b8 100644
--- a/block.c
+++ b/block.c
@@ -2282,7 +2282,14 @@ int bdrv_commit(BlockDriverState *bs)
}
total_sectors = length >> BDRV_SECTOR_BITS;
- buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
+
+ /* qemu_try_blockalign() for bs will choose an alignment that works for
+ * bs->backing_hd as well, so no need to compare the alignment manually. */
+ buf = qemu_try_blockalign(bs, COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
+ if (buf == NULL) {
+ ret = -ENOMEM;
+ goto ro_cleanup;
+ }
for (sector = 0; sector < total_sectors; sector += n) {
ret = bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n);
@@ -2320,7 +2327,7 @@ int bdrv_commit(BlockDriverState *bs)
ret = 0;
ro_cleanup:
- g_free(buf);
+ qemu_vfree(buf);
if (ro) {
/* ignoring error return here */
@@ -2979,7 +2986,12 @@ static int coroutine_fn
bdrv_co_do_copy_on_readv(BlockDriverState *bs,
cluster_sector_num, cluster_nb_sectors);
iov.iov_len = cluster_nb_sectors * BDRV_SECTOR_SIZE;
- iov.iov_base = bounce_buffer = qemu_blockalign(bs, iov.iov_len);
+ iov.iov_base = bounce_buffer = qemu_try_blockalign(bs, iov.iov_len);
+ if (bounce_buffer == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
qemu_iovec_init_external(&bounce_qiov, &iov, 1);
ret = drv->bdrv_co_readv(bs, cluster_sector_num, cluster_nb_sectors,
@@ -3263,7 +3275,11 @@ static int coroutine_fn
bdrv_co_do_write_zeroes(BlockDriverState *bs,
/* Fall back to bounce buffer if write zeroes is unsupported */
iov.iov_len = num * BDRV_SECTOR_SIZE;
if (iov.iov_base == NULL) {
- iov.iov_base = qemu_blockalign(bs, num * BDRV_SECTOR_SIZE);
+ iov.iov_base = qemu_try_blockalign(bs, num * BDRV_SECTOR_SIZE);
+ if (iov.iov_base == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
memset(iov.iov_base, 0, num * BDRV_SECTOR_SIZE);
}
qemu_iovec_init_external(&qiov, &iov, 1);
@@ -3283,6 +3299,7 @@ static int coroutine_fn
bdrv_co_do_write_zeroes(BlockDriverState *bs,
nb_sectors -= num;
}
+fail:
qemu_vfree(iov.iov_base);
return ret;
}
@@ -4625,8 +4642,9 @@ static void bdrv_aio_bh_cb(void *opaque)
{
BlockDriverAIOCBSync *acb = opaque;
- if (!acb->is_write)
+ if (!acb->is_write && acb->ret >= 0) {
qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
+ }
qemu_vfree(acb->bounce);
acb->common.cb(acb->common.opaque, acb->ret);
qemu_bh_delete(acb->bh);
@@ -4648,10 +4666,12 @@ static BlockDriverAIOCB
*bdrv_aio_rw_vector(BlockDriverState *bs,
acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque);
acb->is_write = is_write;
acb->qiov = qiov;
- acb->bounce = qemu_blockalign(bs, qiov->size);
+ acb->bounce = qemu_try_blockalign(bs, qiov->size);
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_aio_bh_cb, acb);
- if (is_write) {
+ if (acb->bounce == NULL) {
+ acb->ret = -ENOMEM;
+ } else if (is_write) {
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
acb->ret = bs->drv->bdrv_write(bs, sector_num, acb->bounce,
nb_sectors);
} else {
--
1.8.3.1
- [Qemu-devel] [PULL 31/62] block: vhdx - add error check, (continued)
- [Qemu-devel] [PULL 31/62] block: vhdx - add error check, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 32/62] block: VHDX endian fixes, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 33/62] test-coroutine: add baseline test that times the cost of function calls, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 34/62] block: allow bdrv_unref() to be passed NULL pointers, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 36/62] block: use the standard 'ret' instead of 'result', Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 39/62] block: Introduce qemu_try_blockalign(), Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 37/62] block: vpc - use block layer ops in vpc_create, instead of posix calls, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 35/62] block: vdi - use block layer ops in vdi_create, instead of posix calls, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 41/62] bochs: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 38/62] block: iotest - update 084 to test static VDI image creation, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 40/62] block: Handle failure for potentially large allocations,
Kevin Wolf <=
- [Qemu-devel] [PULL 42/62] cloop: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 44/62] dmg: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 45/62] iscsi: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 46/62] nfs: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 43/62] curl: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 47/62] parallels: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 50/62] qed: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 48/62] qcow1: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 51/62] raw-posix: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 52/62] raw-win32: Handle failure for potentially large allocations, Kevin Wolf, 2014/08/08