From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50454) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XFoA8-0004nC-4Y for qemu-devel@nongnu.org; Fri, 08 Aug 2014 13:41:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XFoA1-0006r3-HM for qemu-devel@nongnu.org; Fri, 08 Aug 2014 13:41:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:32131) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XFoA1-0006q6-B1 for qemu-devel@nongnu.org; Fri, 08 Aug 2014 13:41:01 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s78Hf0oH020981 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 8 Aug 2014 13:41:00 -0400 From: Kevin Wolf Date: Fri, 8 Aug 2014 19:39:41 +0200 Message-Id: <1407519603-6635-41-git-send-email-kwolf@redhat.com> In-Reply-To: <1407519603-6635-1-git-send-email-kwolf@redhat.com> References: <1407519603-6635-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PULL 40/62] block: Handle failure for potentially large allocations List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com 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 Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi --- 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