From patchwork Tue Jun 24 15:36:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 363497 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 56898140081 for ; Wed, 25 Jun 2014 01:40:20 +1000 (EST) Received: from localhost ([::1]:60362 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzSpW-00032g-If for incoming@patchwork.ozlabs.org; Tue, 24 Jun 2014 11:40:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40877) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzSmf-0006ml-Tk for qemu-devel@nongnu.org; Tue, 24 Jun 2014 11:37:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WzSmY-0008PP-DZ for qemu-devel@nongnu.org; Tue, 24 Jun 2014 11:37:21 -0400 Received: from mx1.redhat.com ([209.132.183.28]:17089) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzSmY-0008PK-5N for qemu-devel@nongnu.org; Tue, 24 Jun 2014 11:37:14 -0400 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s5OFbB1p023387 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 24 Jun 2014 11:37:11 -0400 Received: from noname.redhat.com (ovpn-116-75.ams2.redhat.com [10.36.116.75]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s5OFb5Gg000684; Tue, 24 Jun 2014 11:37:09 -0400 From: Kevin Wolf To: qemu-devel@nongnu.org Date: Tue, 24 Jun 2014 17:36:44 +0200 Message-Id: <1403624224-2084-3-git-send-email-kwolf@redhat.com> In-Reply-To: <1403624224-2084-1-git-send-email-kwolf@redhat.com> References: <1403624224-2084-1-git-send-email-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, benoit.canet@irqsave.net, maxa@catit.be, stefanha@redhat.com Subject: [Qemu-devel] [PATCH v4 02/21] block: Handle failure for potentially large allocations X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 cebbaf7..db90eae 100644 --- a/block.c +++ b/block.c @@ -2299,7 +2299,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); @@ -2337,7 +2344,7 @@ int bdrv_commit(BlockDriverState *bs) ret = 0; ro_cleanup: - g_free(buf); + qemu_vfree(buf); if (ro) { /* ignoring error return here */ @@ -3003,7 +3010,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, @@ -3275,7 +3287,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); @@ -3295,6 +3311,7 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, nb_sectors -= num; } +fail: qemu_vfree(iov.iov_base); return ret; } @@ -4611,8 +4628,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); @@ -4634,10 +4652,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 {