From patchwork Wed Sep 13 18:19:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Reitz X-Patchwork-Id: 813573 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) 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 3xsr2j58kQz9rxl for ; Thu, 14 Sep 2017 04:35:56 +1000 (AEST) Received: from localhost ([::1]:44082 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dsCVr-0005Jw-04 for incoming@patchwork.ozlabs.org; Wed, 13 Sep 2017 14:35:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37949) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dsCId-0001JG-4v for qemu-devel@nongnu.org; Wed, 13 Sep 2017 14:22:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dsCIb-0006hg-UX for qemu-devel@nongnu.org; Wed, 13 Sep 2017 14:22:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:47404) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dsCIV-0006cd-7K; Wed, 13 Sep 2017 14:22:03 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 61CF7356D9; Wed, 13 Sep 2017 18:22:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 61CF7356D9 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=mreitz@redhat.com Received: from localhost (ovpn-204-23.brq.redhat.com [10.40.204.23]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D05265D6AE; Wed, 13 Sep 2017 18:22:01 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 13 Sep 2017 20:19:09 +0200 Message-Id: <20170913181910.29688-18-mreitz@redhat.com> In-Reply-To: <20170913181910.29688-1-mreitz@redhat.com> References: <20170913181910.29688-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 13 Sep 2017 18:22:02 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 17/18] qemu-io: Add background write X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , qemu-devel@nongnu.org, Max Reitz , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Add a new parameter -B to qemu-io's write command. When used, qemu-io will not wait for the result of the operation and instead execute it in the background. Signed-off-by: Max Reitz --- qemu-io-cmds.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 2811a89099..c635a248f5 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -481,6 +481,62 @@ static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset, typedef struct { BlockBackend *blk; int64_t offset; + int bytes; + char *buf; + int flags; +} CoBackgroundWrite; + +static void coroutine_fn co_background_pwrite_entry(void *opaque) +{ + CoBackgroundWrite *data = opaque; + QEMUIOVector qiov; + int ret; + + qemu_iovec_init(&qiov, 1); + qemu_iovec_add(&qiov, data->buf, data->bytes); + + ret = blk_co_pwritev(data->blk, data->offset, data->bytes, &qiov, + data->flags); + + qemu_iovec_destroy(&qiov); + g_free(data->buf); + + if (ret < 0) { + Error *err; + error_setg_errno(&err, -ret, "Background write failed"); + error_report_err(err); + } +} + +/* Takes ownership of @buf */ +static int do_background_pwrite(BlockBackend *blk, char *buf, int64_t offset, + int64_t bytes, int flags) +{ + Coroutine *co; + CoBackgroundWrite *data; + + if (bytes > INT_MAX) { + return -ERANGE; + } + + data = g_new(CoBackgroundWrite, 1); + *data = (CoBackgroundWrite){ + .blk = blk, + .offset = offset, + .bytes = bytes, + .buf = buf, + .flags = flags, + }; + + co = qemu_coroutine_create(co_background_pwrite_entry, data); + bdrv_coroutine_enter(blk_bs(blk), co); + + return bytes; +} + +typedef struct { + BlockBackend *blk; + int64_t offset; int64_t bytes; int64_t *total; int flags; @@ -931,6 +987,7 @@ static void write_help(void) " Writes into a segment of the currently open file, using a buffer\n" " filled with a set pattern (0xcdcdcdcd).\n" " -b, -- write to the VM state rather than the virtual disk\n" +" -B, -- just start a background write, do not wait for the result\n" " -c, -- write compressed data with blk_write_compressed\n" " -f, -- use Force Unit Access semantics\n" " -p, -- ignored for backwards compatibility\n" @@ -951,7 +1008,7 @@ static const cmdinfo_t write_cmd = { .perm = BLK_PERM_WRITE, .argmin = 2, .argmax = -1, - .args = "[-bcCfquz] [-P pattern] off len", + .args = "[-bBcCfquz] [-P pattern] off len", .oneline = "writes a number of bytes at a specified offset", .help = write_help, }; @@ -961,6 +1018,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) struct timeval t1, t2; bool Cflag = false, qflag = false, bflag = false; bool Pflag = false, zflag = false, cflag = false; + bool background = false; int flags = 0; int c, cnt; char *buf = NULL; @@ -970,11 +1028,14 @@ static int write_f(BlockBackend *blk, int argc, char **argv) int64_t total = 0; int pattern = 0xcd; - while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) { + while ((c = getopt(argc, argv, "bBcCfpP:quz")) != -1) { switch (c) { case 'b': bflag = true; break; + case 'B': + background = true; + break; case 'c': cflag = true; break; @@ -1032,6 +1093,11 @@ static int write_f(BlockBackend *blk, int argc, char **argv) return 0; } + if (background && (bflag || cflag || zflag)) { + printf("-B cannot be specified together with -b, -c, or -z\n"); + return 0; + } + offset = cvtnum(argv[optind]); if (offset < 0) { print_cvtnum_err(offset, argv[optind]); @@ -1074,6 +1140,8 @@ static int write_f(BlockBackend *blk, int argc, char **argv) cnt = do_co_pwrite_zeroes(blk, offset, count, flags, &total); } else if (cflag) { cnt = do_write_compressed(blk, buf, offset, count, &total); + } else if (background) { + cnt = do_background_pwrite(blk, buf, offset, count, flags); } else { cnt = do_pwrite(blk, buf, offset, count, flags, &total); } @@ -1088,12 +1156,15 @@ static int write_f(BlockBackend *blk, int argc, char **argv) goto out; } - /* Finally, report back -- -C gives a parsable format */ - t2 = tsub(t2, t1); - print_report("wrote", &t2, offset, count, total, cnt, Cflag); + if (!background) { + /* Finally, report back -- -C gives a parsable format */ + t2 = tsub(t2, t1); + print_report("wrote", &t2, offset, count, total, cnt, Cflag); + } out: - if (!zflag) { + /* do_background_pwrite() takes ownership of the buffer */ + if (!zflag && !background) { qemu_io_free(buf); }