From nobody Wed Dec 17 05:37:10 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153078694357659.220376614192105; Thu, 5 Jul 2018 03:35:43 -0700 (PDT) Received: from localhost ([::1]:51694 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fb1by-0005a0-ON for importer@patchew.org; Thu, 05 Jul 2018 06:35:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58554) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fb1T3-00072F-PP for qemu-devel@nongnu.org; Thu, 05 Jul 2018 06:26:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fb1T2-00050d-7T for qemu-devel@nongnu.org; Thu, 05 Jul 2018 06:26:29 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:41152 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fb1Sv-0004gm-18; Thu, 05 Jul 2018 06:26:21 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9614C87928; Thu, 5 Jul 2018 10:26:20 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-44.ams2.redhat.com [10.36.117.44]) by smtp.corp.redhat.com (Postfix) with ESMTP id C63EF7C3E; Thu, 5 Jul 2018 10:26:19 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Thu, 5 Jul 2018 12:26:01 +0200 Message-Id: <20180705102604.4986-10-kwolf@redhat.com> In-Reply-To: <20180705102604.4986-1-kwolf@redhat.com> References: <20180705102604.4986-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Thu, 05 Jul 2018 10:26:20 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Thu, 05 Jul 2018 10:26:20 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL v2 09/12] block/blklogwrites: Add an option for appending to an old log 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: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Ari Sundholm Suggested by Kevin Wolf. May be useful when testing multiple batches of writes or doing long-term testing involving restarts of the VM. Signed-off-by: Ari Sundholm Signed-off-by: Kevin Wolf --- qapi/block-core.json | 3 +- block/blklogwrites.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++-= ---- 2 files changed, 135 insertions(+), 15 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index a9eab8cab8..d1753a2ae7 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3062,7 +3062,8 @@ { 'struct': 'BlockdevOptionsBlklogwrites', 'data': { 'file': 'BlockdevRef', 'log': 'BlockdevRef', - '*log-sector-size': 'uint32' } } + '*log-sector-size': 'uint32', + '*log-append': 'bool' } } =20 ## # @BlockdevOptionsBlkverify: diff --git a/block/blklogwrites.c b/block/blklogwrites.c index 272e11a021..56154e7325 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -24,6 +24,10 @@ #define LOG_FUA_FLAG (1 << 1) #define LOG_DISCARD_FLAG (1 << 2) #define LOG_MARK_FLAG (1 << 3) +#define LOG_FLAG_MASK (LOG_FLUSH_FLAG \ + | LOG_FUA_FLAG \ + | LOG_DISCARD_FLAG \ + | LOG_MARK_FLAG) =20 #define WRITE_LOG_VERSION 1ULL #define WRITE_LOG_MAGIC 0x6a736677736872ULL @@ -58,6 +62,11 @@ static QemuOptsList runtime_opts =3D { .head =3D QTAILQ_HEAD_INITIALIZER(runtime_opts.head), .desc =3D { { + .name =3D "log-append", + .type =3D QEMU_OPT_BOOL, + .help =3D "Append to an existing log", + }, + { .name =3D "log-sector-size", .type =3D QEMU_OPT_SIZE, .help =3D "Log sector size", @@ -72,6 +81,53 @@ static inline uint32_t blk_log_writes_log2(uint32_t valu= e) return 31 - clz32(value); } =20 +static inline bool blk_log_writes_sector_size_valid(uint32_t sector_size) +{ + return sector_size < (1ull << 24) && is_power_of_2(sector_size); +} + +static uint64_t blk_log_writes_find_cur_log_sector(BdrvChild *log, + uint32_t sector_size, + uint64_t nr_entries, + Error **errp) +{ + uint64_t cur_sector =3D 1; + uint64_t cur_idx =3D 0; + uint32_t sector_bits =3D blk_log_writes_log2(sector_size); + struct log_write_entry cur_entry; + + while (cur_idx < nr_entries) { + int read_ret =3D bdrv_pread(log, cur_sector << sector_bits, &cur_e= ntry, + sizeof(cur_entry)); + if (read_ret < 0) { + error_setg_errno(errp, -read_ret, + "Failed to read log entry %"PRIu64, cur_idx); + return (uint64_t)-1ull; + } + + if (cur_entry.flags & ~cpu_to_le64(LOG_FLAG_MASK)) { + error_setg(errp, "Invalid flags 0x%"PRIx64" in log entry %"PRI= u64, + le64_to_cpu(cur_entry.flags), cur_idx); + return (uint64_t)-1ull; + } + + /* Account for the sector of the entry itself */ + ++cur_sector; + + /* + * Account for the data of the write. + * For discards, this data is not present. + */ + if (!(cur_entry.flags & cpu_to_le64(LOG_DISCARD_FLAG))) { + cur_sector +=3D le64_to_cpu(cur_entry.nr_sectors); + } + + ++cur_idx; + } + + return cur_sector; +} + static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int f= lags, Error **errp) { @@ -80,6 +136,7 @@ static int blk_log_writes_open(BlockDriverState *bs, QDi= ct *options, int flags, Error *local_err =3D NULL; int ret; uint64_t log_sector_size; + bool log_append; =20 opts =3D qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); @@ -98,20 +155,6 @@ static int blk_log_writes_open(BlockDriverState *bs, QD= ict *options, int flags, goto fail; } =20 - log_sector_size =3D qemu_opt_get_size(opts, "log-sector-size", - BDRV_SECTOR_SIZE); - - if (log_sector_size > (1ull << 23) || !is_power_of_2(log_sector_size))= { - ret =3D -EINVAL; - error_setg(errp, "Invalid log sector size %"PRIu64, log_sector_siz= e); - goto fail; - } - - s->sectorsize =3D log_sector_size; - s->sectorbits =3D blk_log_writes_log2(log_sector_size); - s->cur_log_sector =3D 1; - s->nr_entries =3D 0; - /* Open the log file */ s->log_file =3D bdrv_open_child(NULL, options, "log", bs, &child_file,= false, &local_err); @@ -121,7 +164,83 @@ static int blk_log_writes_open(BlockDriverState *bs, Q= Dict *options, int flags, goto fail; } =20 + log_append =3D qemu_opt_get_bool(opts, "log-append", false); + + if (log_append) { + struct log_write_super log_sb =3D { 0, 0, 0, 0 }; + + if (qemu_opt_find(opts, "log-sector-size")) { + ret =3D -EINVAL; + error_setg(errp, "log-append and log-sector-size are mutually " + "exclusive"); + goto fail_log; + } + + /* Read log superblock or fake one for an empty log */ + if (!bdrv_getlength(s->log_file->bs)) { + log_sb.magic =3D cpu_to_le64(WRITE_LOG_MAGIC); + log_sb.version =3D cpu_to_le64(WRITE_LOG_VERSION); + log_sb.nr_entries =3D cpu_to_le64(0); + log_sb.sectorsize =3D cpu_to_le32(BDRV_SECTOR_SIZE); + } else { + ret =3D bdrv_pread(s->log_file, 0, &log_sb, sizeof(log_sb)); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not read log superbloc= k"); + goto fail_log; + } + } + + if (log_sb.magic !=3D cpu_to_le64(WRITE_LOG_MAGIC)) { + ret =3D -EINVAL; + error_setg(errp, "Invalid log superblock magic"); + goto fail_log; + } + + if (log_sb.version !=3D cpu_to_le64(WRITE_LOG_VERSION)) { + ret =3D -EINVAL; + error_setg(errp, "Unsupported log version %"PRIu64, + le64_to_cpu(log_sb.version)); + goto fail_log; + } + + log_sector_size =3D le32_to_cpu(log_sb.sectorsize); + s->cur_log_sector =3D 1; + s->nr_entries =3D 0; + + if (blk_log_writes_sector_size_valid(log_sector_size)) { + s->cur_log_sector =3D + blk_log_writes_find_cur_log_sector(s->log_file, log_sector= _size, + le64_to_cpu(log_sb.nr_entries), &local= _err); + if (local_err) { + ret =3D -EINVAL; + error_propagate(errp, local_err); + goto fail_log; + } + + s->nr_entries =3D le64_to_cpu(log_sb.nr_entries); + } + } else { + log_sector_size =3D qemu_opt_get_size(opts, "log-sector-size", + BDRV_SECTOR_SIZE); + s->cur_log_sector =3D 1; + s->nr_entries =3D 0; + } + + if (!blk_log_writes_sector_size_valid(log_sector_size)) { + ret =3D -EINVAL; + error_setg(errp, "Invalid log sector size %"PRIu64, log_sector_siz= e); + goto fail_log; + } + + s->sectorsize =3D log_sector_size; + s->sectorbits =3D blk_log_writes_log2(log_sector_size); + ret =3D 0; +fail_log: + if (ret < 0) { + bdrv_unref_child(bs, s->log_file); + s->log_file =3D NULL; + } fail: if (ret < 0) { bdrv_unref_child(bs, bs->file); --=20 2.13.6