From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990561000742.8865964392231; Tue, 13 Mar 2018 18:22:41 -0700 (PDT) Received: from localhost ([::1]:43898 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv7e-0001ZP-0N for importer@patchew.org; Tue, 13 Mar 2018 21:22:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36269) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5g-0000Ll-UK for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5c-0006KH-GI for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:28 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5c-0006Hx-45 for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:24 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:23 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:21 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632785" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:09 +0800 Message-Id: <1520990418-28258-2-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 01/10] RFC: Add save and support snapshot dependency function to block driver. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He We want to support incremental snapshot saving, this needs the file system support dependency saving. Later snapshots may ref the dependent snapshot's content, and most time should be cluster aligned. Add a query function to check whether the file system support this, and use the save_dependency function to do the real work. Signed-off-by: Junyan He --- include/block/block_int.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/block/block_int.h b/include/block/block_int.h index 64a5700..be1eca3 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -274,6 +274,15 @@ struct BlockDriver { const char *snapshot_id, const char *name, Error **errp); + int (*bdrv_snapshot_save_dependency)(BlockDriverState *bs, + const char *depend_snapshot_id, + int64_t depend_offset, + int64_t depend_size, + int64_t offset, + Error **errp); + int (*bdrv_snapshot_support_dependency)(BlockDriverState *bs, + int32_t *alignment); + int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs); =20 --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990561031754.8541142054174; Tue, 13 Mar 2018 18:22:41 -0700 (PDT) Received: from localhost ([::1]:43900 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv7i-0001bS-Io for importer@patchew.org; Tue, 13 Mar 2018 21:22:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36274) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5g-0000Lo-WA for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5e-0006LN-Km for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:28 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5e-0006Hx-9F for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:26 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:26 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:24 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632802" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:10 +0800 Message-Id: <1520990418-28258-3-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 02/10] RFC: Implement qcow2's snapshot dependent saving function. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He For qcow2 format, we can increase the cluster's reference count of dependent snapshot content and link the offset to the L2 table of the new snapshot point. This way can avoid obvious snapshot's dependent relationship, so when we delete some snapshot point, just decrease the cluster count and no need to check further. Signed-off-by: Junyan He --- block/qcow2-snapshot.c | 154 +++++++++++++++++++++++++++++++++++++++++++++= ++++ block/qcow2.c | 2 + block/qcow2.h | 7 +++ 3 files changed, 163 insertions(+) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index cee25f5..8e83084 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -736,3 +736,157 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, =20 return 0; } + +int qcow2_snapshot_save_dependency(BlockDriverState *bs, + const char *depend_snapshot_id, + int64_t depend_offset, + int64_t depend_size, + int64_t offset, + Error **errp) +{ + int snapshot_index; + BDRVQcow2State *s =3D bs->opaque; + QCowSnapshot *sn; + int ret; + int64_t i; + int64_t total_bytes =3D depend_size; + int64_t depend_offset1, offset1; + uint64_t *depend_l1_table =3D NULL; + uint64_t depend_l1_bytes; + uint64_t *depend_l2_table =3D NULL; + uint64_t depend_l2_offset; + uint64_t depend_entry; + QCowL2Meta l2meta; + + assert(bs->read_only =3D=3D false); + + if (depend_snapshot_id =3D=3D NULL) { + return 0; + } + + if (!QEMU_IS_ALIGNED(depend_offset, s->cluster_size)) { + error_setg(errp, "Specified snapshot offset is not multiple of %u", + s->cluster_size); + return -EINVAL; + } + + if (!QEMU_IS_ALIGNED(offset, s->cluster_size)) { + error_setg(errp, "Offset is not multiple of %u", s->cluster_size); + return -EINVAL; + } + + if (!QEMU_IS_ALIGNED(depend_size, s->cluster_size)) { + error_setg(errp, "depend_size is not multiple of %u", s->cluster_s= ize); + return -EINVAL; + } + + snapshot_index =3D find_snapshot_by_id_and_name(bs, NULL, depend_snaps= hot_id); + /* Search the snapshot */ + if (snapshot_index < 0) { + error_setg(errp, "Can't find snapshot"); + return -ENOENT; + } + + sn =3D &s->snapshots[snapshot_index]; + if (sn->disk_size !=3D bs->total_sectors * BDRV_SECTOR_SIZE) { + error_report("qcow2: depend on the snapshots with different disk " + "size is not implemented"); + return -ENOTSUP; + } + + /* Only can save dependency of snapshot's vmstate data */ + depend_offset1 =3D depend_offset + qcow2_vm_state_offset(s); + offset1 =3D offset + qcow2_vm_state_offset(s); + + depend_l1_bytes =3D s->l1_size * sizeof(uint64_t); + depend_l1_table =3D g_try_malloc0(depend_l1_bytes); + if (depend_l1_table =3D=3D NULL) { + return -ENOMEM; + } + + ret =3D bdrv_pread(bs->file, sn->l1_table_offset, depend_l1_table, + depend_l1_bytes); + if (ret < 0) { + g_free(depend_l1_table); + goto out; + } + for (i =3D 0; i < depend_l1_bytes / sizeof(uint64_t); i++) { + be64_to_cpus(&depend_l1_table[i]); + } + + while (total_bytes) { + assert(total_bytes > 0); + /* Find the cluster of depend */ + depend_l2_offset =3D + depend_l1_table[depend_offset1 >> (s->l2_bits + s->cluster_bit= s)]; + depend_l2_offset &=3D L1E_OFFSET_MASK; + if (depend_l2_offset =3D=3D 0) { + ret =3D -EINVAL; + goto out; + } + + if (offset_into_cluster(s, depend_l2_offset)) { + qcow2_signal_corruption(bs, true, -1, -1, "L2 table offset %#" + PRIx64 " unaligned (L1 index: %#" + PRIx64 ")", + depend_l2_offset, + depend_offset1 >> + (s->l2_bits + s->cluster_bits)); + return -EIO; + } + + ret =3D qcow2_cache_get(bs, s->l2_table_cache, depend_l2_offset, + (void **)(&depend_l2_table)); + if (ret < 0) { + goto out; + } + + depend_entry =3D + be64_to_cpu( + depend_l2_table[offset_to_l2_index(s, depend_offset1)]); + if (depend_entry =3D=3D 0) { + ret =3D -EINVAL; + qcow2_cache_put(s->l2_table_cache, (void **)(&depend_l2_table)= ); + goto out; + } + + memset(&l2meta, 0, sizeof(l2meta)); + l2meta.offset =3D offset1; + l2meta.alloc_offset =3D (depend_entry & L2E_OFFSET_MASK); + l2meta.nb_clusters =3D 1; + /* Add a ref to this cluster */ + ret =3D qcow2_update_cluster_refcount( + bs, l2meta.alloc_offset >> s->cluster_bits, + 1, false, QCOW2_DISCARD_SNAPSHOT); + if (ret < 0) { + qcow2_cache_put(s->l2_table_cache, (void **)(&depend_l2_table)= ); + goto out; + } + + ret =3D qcow2_alloc_cluster_link_l2(bs, &l2meta); + if (ret < 0) { + qcow2_cache_put(s->l2_table_cache, (void **)(&depend_l2_table)= ); + goto out; + } + + total_bytes -=3D s->cluster_size; + offset1 +=3D s->cluster_size; + depend_offset1 +=3D s->cluster_size; + + qcow2_cache_put(s->l2_table_cache, (void **)(&depend_l2_table)); + } + +out: + g_free(depend_l1_table); + return ret; +} + +int qcow2_snapshot_support_dependency(BlockDriverState *bs, int32_t *align= ment) +{ + BDRVQcow2State *s =3D bs->opaque; + if (alignment) { + *alignment =3D s->cluster_size; + } + + return 1; +} diff --git a/block/qcow2.c b/block/qcow2.c index 071dc4d..9786ba4 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -4371,6 +4371,8 @@ BlockDriver bdrv_qcow2 =3D { .bdrv_snapshot_delete =3D qcow2_snapshot_delete, .bdrv_snapshot_list =3D qcow2_snapshot_list, .bdrv_snapshot_load_tmp =3D qcow2_snapshot_load_tmp, + .bdrv_snapshot_support_dependency =3D qcow2_snapshot_support_dependenc= y, + .bdrv_snapshot_save_dependency =3D qcow2_snapshot_save_dependency, .bdrv_measure =3D qcow2_measure, .bdrv_get_info =3D qcow2_get_info, .bdrv_get_specific_info =3D qcow2_get_specific_info, diff --git a/block/qcow2.h b/block/qcow2.h index 1a84cc7..dc7ef45 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -640,6 +640,13 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, =20 void qcow2_free_snapshots(BlockDriverState *bs); int qcow2_read_snapshots(BlockDriverState *bs); +int qcow2_snapshot_save_dependency(BlockDriverState *bs, + const char *depend_snapshot_id, + int64_t depend_offset, + int64_t depend_size, + int64_t offset, + Error **errp); +int qcow2_snapshot_support_dependency(BlockDriverState *bs, int32_t *align= ment); =20 /* qcow2-cache.c functions */ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables, --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990719525647.2007072355287; Tue, 13 Mar 2018 18:25:19 -0700 (PDT) Received: from localhost ([::1]:43914 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evvAM-0003yt-LJ for importer@patchew.org; Tue, 13 Mar 2018 21:25:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36300) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5i-0000M2-65 for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5g-0006NR-PQ for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:30 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5g-0006Hx-F6 for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:28 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:28 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:26 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632822" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:11 +0800 Message-Id: <1520990418-28258-4-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 03/10] RFC: Implement save and support snapshot dependency in block driver layer. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He Signed-off-by: Junyan He --- block/snapshot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/block/snapshot.h | 7 +++++++ 2 files changed, 52 insertions(+) diff --git a/block/snapshot.c b/block/snapshot.c index eacc1f1..8cc40ac 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -401,6 +401,51 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverSt= ate *bs, return ret; } =20 +int bdrv_snapshot_save_dependency(BlockDriverState *bs, + const char *depend_snapshot_id, + int64_t depend_offset, + int64_t depend_size, + int64_t offset, + Error **errp) +{ + BlockDriver *drv =3D bs->drv; + + if (!drv) { + return -ENOMEDIUM; + } + + if (drv->bdrv_snapshot_save_dependency) { + return drv->bdrv_snapshot_save_dependency(bs, depend_snapshot_id, + depend_offset, depend_si= ze, + offset, errp); + } + + if (bs->file) { + return bdrv_snapshot_save_dependency(bs->file->bs, depend_snapshot= _id, + depend_offset, depend_size, + offset, errp); + } + + return -ENOTSUP; +} + +int bdrv_snapshot_support_dependency(BlockDriverState *bs, int32_t *alignm= ent) +{ + BlockDriver *drv =3D bs->drv; + if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { + return 0; + } + + if (drv->bdrv_snapshot_support_dependency) { + return drv->bdrv_snapshot_support_dependency(bs, alignment); + } + + if (bs->file !=3D NULL) { + return bdrv_snapshot_support_dependency(bs->file->bs, alignment); + } + + return -ENOTSUP; +} =20 /* Group operations. All block drivers are involved. * These functions will properly handle dataplane (take aio_context_acquire diff --git a/include/block/snapshot.h b/include/block/snapshot.h index f73d109..e5bf06f 100644 --- a/include/block/snapshot.h +++ b/include/block/snapshot.h @@ -73,6 +73,13 @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs, int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs, const char *id_or_name, Error **errp); +int bdrv_snapshot_save_dependency(BlockDriverState *bs, + const char *depend_snapshot_id, + int64_t depend_offset, + int64_t depend_size, + int64_t offset, + Error **errp); +int bdrv_snapshot_support_dependency(BlockDriverState *bs, int32_t *alignm= ent); =20 =20 /* Group operations. All block drivers are involved. --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990717338617.7470605986623; Tue, 13 Mar 2018 18:25:17 -0700 (PDT) Received: from localhost ([::1]:43913 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evvAK-0003wT-FD for importer@patchew.org; Tue, 13 Mar 2018 21:25:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36344) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5j-0000Mw-TH for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5j-0006Pb-0G for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:31 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5i-0006Hx-Jt for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:30 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:30 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:28 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632831" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:12 +0800 Message-Id: <1520990418-28258-5-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 04/10] RFC: Set memory_region_set_log available for more client. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He We need to collect dirty log for nvdimm kind memory, need to enable memory_region_set_log for more clients rather than just VGA. Signed-off-by: Junyan He --- memory.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/memory.c b/memory.c index e70b64b..4a8a2fe 100644 --- a/memory.c +++ b/memory.c @@ -1921,11 +1921,12 @@ void memory_region_set_log(MemoryRegion *mr, bool l= og, unsigned client) uint8_t mask =3D 1 << client; uint8_t old_logging; =20 - assert(client =3D=3D DIRTY_MEMORY_VGA); - old_logging =3D mr->vga_logging_count; - mr->vga_logging_count +=3D log ? 1 : -1; - if (!!old_logging =3D=3D !!mr->vga_logging_count) { - return; + if (client =3D=3D DIRTY_MEMORY_VGA) { + old_logging =3D mr->vga_logging_count; + mr->vga_logging_count +=3D log ? 1 : -1; + if (!!old_logging =3D=3D !!mr->vga_logging_count) { + return; + } } =20 memory_region_transaction_begin(); --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990873982410.9928796048432; Tue, 13 Mar 2018 18:27:53 -0700 (PDT) Received: from localhost ([::1]:43929 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evvCi-0006Ay-9j for importer@patchew.org; Tue, 13 Mar 2018 21:27:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36365) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5m-0000PL-0D for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5l-0006R5-2O for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:33 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5k-0006Hx-QT for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:33 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:32 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:30 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632845" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:13 +0800 Message-Id: <1520990418-28258-6-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 05/10] RFC: Add memory region snapshot bitmap get function. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He We need to get the bitmap content of the snapshot when enable dirty log trace for nvdimm. Signed-off-by: Junyan He --- exec.c | 7 +++++++ include/exec/memory.h | 9 +++++++++ include/exec/ram_addr.h | 2 ++ memory.c | 7 +++++++ 4 files changed, 25 insertions(+) diff --git a/exec.c b/exec.c index a9181e6..3d2bf0d 100644 --- a/exec.c +++ b/exec.c @@ -1235,6 +1235,13 @@ bool cpu_physical_memory_snapshot_get_dirty(DirtyBit= mapSnapshot *snap, return false; } =20 +unsigned long *cpu_physical_memory_snapshot_get_dirty_bitmap + (DirtyBitmapSnapshot *snap) +{ + assert(snap); + return snap->dirty; +} + /* Called from RCU critical section */ hwaddr memory_region_section_get_iotlb(CPUState *cpu, MemoryRegionSection *section, diff --git a/include/exec/memory.h b/include/exec/memory.h index 31eae0a..f742995 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1179,6 +1179,15 @@ bool memory_region_snapshot_get_dirty(MemoryRegion *= mr, hwaddr addr, hwaddr size); =20 /** + * memory_region_snapshot_get_dirty_bitmap: Get the dirty bitmap data of + * snapshot. + * + * @snap: the dirty bitmap snapshot + */ +unsigned long *memory_region_snapshot_get_dirty_bitmap + (DirtyBitmapSnapshot *snap); + +/** * memory_region_reset_dirty: Mark a range of pages as clean, for a specif= ied * client. * diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index cf2446a..ce366c1 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -371,6 +371,8 @@ DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_c= lear_dirty bool cpu_physical_memory_snapshot_get_dirty(DirtyBitmapSnapshot *snap, ram_addr_t start, ram_addr_t length); +unsigned long *cpu_physical_memory_snapshot_get_dirty_bitmap + (DirtyBitmapSnapshot *snap); =20 static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, ram_addr_t length) diff --git a/memory.c b/memory.c index 4a8a2fe..68f17f0 100644 --- a/memory.c +++ b/memory.c @@ -1991,6 +1991,13 @@ DirtyBitmapSnapshot *memory_region_snapshot_and_clea= r_dirty(MemoryRegion *mr, memory_region_get_ram_addr(mr) + addr, size, client); } =20 +unsigned long *memory_region_snapshot_get_dirty_bitmap + (DirtyBitmapSnapshot *snap) +{ + assert(snap); + return cpu_physical_memory_snapshot_get_dirty_bitmap(snap); +} + bool memory_region_snapshot_get_dirty(MemoryRegion *mr, DirtyBitmapSnapsho= t *snap, hwaddr addr, hwaddr size) { --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990567844104.31119727295868; Tue, 13 Mar 2018 18:22:47 -0700 (PDT) Received: from localhost ([::1]:43901 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv7v-0001oL-09 for importer@patchew.org; Tue, 13 Mar 2018 21:22:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36405) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5r-0000Tz-03 for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5n-0006Sa-9n for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:38 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5n-0006Hx-1G for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:35 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:34 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:32 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632854" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:14 +0800 Message-Id: <1520990418-28258-7-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 06/10] RFC: Add save dependency functions to qemu_file 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He When we save snapshot, we need qemu_file to support save dependency operations. It should call brv_driver's save dependency functions to implement these operations. Signed-off-by: Junyan He --- migration/qemu-file.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ migration/qemu-file.h | 14 ++++++++++++ migration/savevm.c | 33 +++++++++++++++++++++++++--- 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 2ab2bf3..9d2a39a 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -46,10 +46,13 @@ struct QEMUFile { int buf_index; int buf_size; /* 0 when writing */ uint8_t buf[IO_BUF_SIZE]; + char ref_name_str[128]; /* maybe snapshot id */ =20 DECLARE_BITMAP(may_free, MAX_IOV_SIZE); struct iovec iov[MAX_IOV_SIZE]; unsigned int iovcnt; + bool support_dependency; + int32_t dependency_aligment; =20 int last_error; }; @@ -745,3 +748,61 @@ void qemu_file_set_blocking(QEMUFile *f, bool block) f->ops->set_blocking(f->opaque, block); } } + +void qemu_file_set_support_dependency(QEMUFile *f, int32_t alignment) +{ + f->dependency_aligment =3D alignment; + f->support_dependency =3D true; +} + +bool qemu_file_is_support_dependency(QEMUFile *f, int32_t *alignment) +{ + if (f->support_dependency && alignment) { + *alignment =3D f->dependency_aligment; + } + + return f->support_dependency; +} + +/* This function set the reference name for snapshot usage. Sometimes it n= eeds + * to depend on other snapshot's data to avoid redundance. + */ +bool qemu_file_set_ref_name(QEMUFile *f, const char *name) +{ + if (strlen(name) + 1 > sizeof(f->ref_name_str)) { + return false; + } + + memcpy(f->ref_name_str, name, strlen(name) + 1); + return true; +} + +ssize_t qemu_file_save_dependency(QEMUFile *f, int64_t depend_offset, + int64_t size) +{ + ssize_t ret; + + if (f->support_dependency =3D=3D false) { + return -1; + } + + assert(f->ops->save_dependency); + + if (!QEMU_IS_ALIGNED(depend_offset, f->dependency_aligment)) { + return -1; + } + + qemu_fflush(f); + + if (!QEMU_IS_ALIGNED(f->pos, f->dependency_aligment)) { + return -1; + } + + ret =3D f->ops->save_dependency(f->opaque, f->ref_name_str, + depend_offset, size, f->pos); + if (ret > 0) { + f->pos +=3D size; + } + + return ret; +} diff --git a/migration/qemu-file.h b/migration/qemu-file.h index aae4e5e..137b917 100644 --- a/migration/qemu-file.h +++ b/migration/qemu-file.h @@ -57,6 +57,14 @@ typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque,= struct iovec *iov, int iovcnt, int64_t pos); =20 /* + * This function add reference to the dependency data in snapshot specifie= d by + * ref_name_str to this file's offset + */ +typedef ssize_t (QEMUFileSaveDependencyFunc)(void *opaque, const char *nam= e, + int64_t depend_offset, + int64_t offset, int64_t size); + +/* * This function provides hooks around different * stages of RAM migration. * 'opaque' is the backend specific data in QEMUFile @@ -104,6 +112,7 @@ typedef struct QEMUFileOps { QEMUFileWritevBufferFunc *writev_buffer; QEMURetPathFunc *get_return_path; QEMUFileShutdownFunc *shut_down; + QEMUFileSaveDependencyFunc *save_dependency; } QEMUFileOps; =20 typedef struct QEMUFileHooks { @@ -153,6 +162,11 @@ int qemu_file_shutdown(QEMUFile *f); QEMUFile *qemu_file_get_return_path(QEMUFile *f); void qemu_fflush(QEMUFile *f); void qemu_file_set_blocking(QEMUFile *f, bool block); +bool qemu_file_set_ref_name(QEMUFile *f, const char *name); +void qemu_file_set_support_dependency(QEMUFile *f, int32_t alignment); +bool qemu_file_is_support_dependency(QEMUFile *f, int32_t *alignment); +ssize_t qemu_file_save_dependency(QEMUFile *f, int64_t depend_offset, + int64_t size); =20 size_t qemu_get_counted_string(QEMUFile *f, char buf[256]); =20 diff --git a/migration/savevm.c b/migration/savevm.c index 358c5b5..1bbd6aa 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -196,6 +196,20 @@ static ssize_t block_writev_buffer(void *opaque, struc= t iovec *iov, int iovcnt, return qiov.size; } =20 +static ssize_t block_save_dependency(void *opaque, const char *id_name, + int64_t depend_offset, + int64_t offset, int64_t size) +{ + int ret =3D bdrv_snapshot_save_dependency(opaque, id_name, + depend_offset, offset, + size, NULL); + if (ret < 0) { + return ret; + } + + return size; +} + static ssize_t block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, size_t size) { @@ -213,15 +227,28 @@ static const QEMUFileOps bdrv_read_ops =3D { }; =20 static const QEMUFileOps bdrv_write_ops =3D { - .writev_buffer =3D block_writev_buffer, - .close =3D bdrv_fclose + .writev_buffer =3D block_writev_buffer, + .close =3D bdrv_fclose, + .save_dependency =3D block_save_dependency }; =20 static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable) { + int ret =3D 0; + int32_t alignment =3D 0; + QEMUFile *f =3D NULL; + if (is_writable) { - return qemu_fopen_ops(bs, &bdrv_write_ops); + f =3D qemu_fopen_ops(bs, &bdrv_write_ops); + + ret =3D bdrv_snapshot_support_dependency(bs, &alignment); + if (ret > 0) { + qemu_file_set_support_dependency(f, alignment); + } + + return f; } + return qemu_fopen_ops(bs, &bdrv_read_ops); } =20 --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990987733264.9714749171035; Tue, 13 Mar 2018 18:29:47 -0700 (PDT) Received: from localhost ([::1]:43937 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evvEg-0007sQ-SN for importer@patchew.org; Tue, 13 Mar 2018 21:29:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36404) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5q-0000Tx-Vp for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5p-0006UC-ED for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:38 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5p-0006Hx-5u for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:37 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:36 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:34 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632863" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:15 +0800 Message-Id: <1520990418-28258-8-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 07/10] RFC: Add get_current_snapshot_info to get the snapshot state. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He We need to know the snapshot saving information when we do dependent snapshot saving, e.g the name of previous snapshot. Add this global function to query the snapshot status is usable. Signed-off-by: Junyan He --- include/migration/snapshot.h | 3 +++ migration/savevm.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/migration/snapshot.h b/include/migration/snapshot.h index c85b6ec..0b950ce 100644 --- a/include/migration/snapshot.h +++ b/include/migration/snapshot.h @@ -15,7 +15,10 @@ #ifndef QEMU_MIGRATION_SNAPSHOT_H #define QEMU_MIGRATION_SNAPSHOT_H =20 +#include "block/snapshot.h" + int save_snapshot(const char *name, Error **errp); int load_snapshot(const char *name, Error **errp); +int get_current_snapshot_info(QEMUSnapshotInfo *sn); =20 #endif diff --git a/migration/savevm.c b/migration/savevm.c index 1bbd6aa..3a9b904 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2212,6 +2212,29 @@ int qemu_loadvm_state(QEMUFile *f) return ret; } =20 +static int in_snap_saving; +static QEMUSnapshotInfo in_snap_saving_sn; + +int get_current_snapshot_info(QEMUSnapshotInfo *sn) +{ + if (in_snap_saving && sn) { + memcpy(sn, &in_snap_saving_sn, sizeof(QEMUSnapshotInfo)); + } + + return in_snap_saving; +} + +static void set_current_snapshot_info(QEMUSnapshotInfo *sn) +{ + if (sn) { + memcpy(&in_snap_saving_sn, sn, sizeof(QEMUSnapshotInfo)); + in_snap_saving =3D 1; + } else { + memset(&in_snap_saving_sn, 0, sizeof(QEMUSnapshotInfo)); + in_snap_saving =3D 0; + } +} + int save_snapshot(const char *name, Error **errp) { BlockDriverState *bs, *bs1; @@ -2282,6 +2305,8 @@ int save_snapshot(const char *name, Error **errp) strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm); } =20 + set_current_snapshot_info(sn); + /* save the VM state */ f =3D qemu_fopen_bdrv(bs, 1); if (!f) { @@ -2313,6 +2338,8 @@ int save_snapshot(const char *name, Error **errp) ret =3D 0; =20 the_end: + set_current_snapshot_info(NULL); + if (aio_context) { aio_context_release(aio_context); } --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990797725189.2039452604016; Tue, 13 Mar 2018 18:26:37 -0700 (PDT) Received: from localhost ([::1]:43925 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evvBc-0005Ga-Qx for importer@patchew.org; Tue, 13 Mar 2018 21:26:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36425) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5t-0000WK-4y for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5r-0006VX-RP for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:41 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5r-0006Hx-F2 for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:39 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:39 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:37 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632868" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:16 +0800 Message-Id: <1520990418-28258-9-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 08/10] RFC: Add a section_id parameter to save_live_iterate call. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He We need to know the section_id when we do snapshot saving. Add a parameter to save_live_iterate function call. Signed-off-by: Junyan He --- hw/ppc/spapr.c | 2 +- hw/s390x/s390-stattrib.c | 2 +- include/migration/register.h | 2 +- migration/block.c | 2 +- migration/ram.c | 2 +- migration/savevm.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 7e1c858..4cde4f4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1974,7 +1974,7 @@ static int htab_save_later_pass(QEMUFile *f, sPAPRMac= hineState *spapr, #define MAX_ITERATION_NS 5000000 /* 5 ms */ #define MAX_KVM_BUF_SIZE 2048 =20 -static int htab_save_iterate(QEMUFile *f, void *opaque) +static int htab_save_iterate(QEMUFile *f, void *opaque, int section_id) { sPAPRMachineState *spapr =3D opaque; int fd; diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c index adf07ef..18ece84 100644 --- a/hw/s390x/s390-stattrib.c +++ b/hw/s390x/s390-stattrib.c @@ -246,7 +246,7 @@ static int cmma_save(QEMUFile *f, void *opaque, int fin= al) return ret; } =20 -static int cmma_save_iterate(QEMUFile *f, void *opaque) +static int cmma_save_iterate(QEMUFile *f, void *opaque, int section_id) { return cmma_save(f, opaque, 0); } diff --git a/include/migration/register.h b/include/migration/register.h index f4f7bdc..7f7df2c 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -31,7 +31,7 @@ typedef struct SaveVMHandlers { * use data that is local to the migration thread or protected * by other locks. */ - int (*save_live_iterate)(QEMUFile *f, void *opaque); + int (*save_live_iterate)(QEMUFile *f, void *opaque, int section_id); =20 /* This runs outside the iothread lock! */ int (*save_setup)(QEMUFile *f, void *opaque); diff --git a/migration/block.c b/migration/block.c index 1f03946..6d4c8a3 100644 --- a/migration/block.c +++ b/migration/block.c @@ -755,7 +755,7 @@ static int block_save_setup(QEMUFile *f, void *opaque) return ret; } =20 -static int block_save_iterate(QEMUFile *f, void *opaque) +static int block_save_iterate(QEMUFile *f, void *opaque, int section_id) { int ret; int64_t last_ftell =3D qemu_ftell(f); diff --git a/migration/ram.c b/migration/ram.c index 3b6c077..d1db422 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2249,7 +2249,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) * @f: QEMUFile where to send the data * @opaque: RAMState pointer */ -static int ram_save_iterate(QEMUFile *f, void *opaque) +static int ram_save_iterate(QEMUFile *f, void *opaque, int section_id) { RAMState **temp =3D opaque; RAMState *rs =3D *temp; diff --git a/migration/savevm.c b/migration/savevm.c index 3a9b904..ce4133a 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1072,7 +1072,7 @@ int qemu_savevm_state_iterate(QEMUFile *f, bool postc= opy) =20 save_section_header(f, se, QEMU_VM_SECTION_PART); =20 - ret =3D se->ops->save_live_iterate(f, se->opaque); + ret =3D se->ops->save_live_iterate(f, se->opaque, se->section_id); trace_savevm_section_end(se->idstr, se->section_id, ret); save_section_footer(f, se); =20 --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990931665432.6399523061393; Tue, 13 Mar 2018 18:28:51 -0700 (PDT) Received: from localhost ([::1]:43935 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evvDm-00070i-IU for importer@patchew.org; Tue, 13 Mar 2018 21:28:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36449) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv5x-0000aq-Fc for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5u-0006XB-De for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:45 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5t-0006Hx-Ra for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:42 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:41 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:39 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632881" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:17 +0800 Message-Id: <1520990418-28258-10-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 09/10] RFC: Add nvdimm snapshot saving to migration. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He The nvdimm size is huge, sometimes is more than 256G or even more. This is a huge burden for snapshot saving. One snapshot point with nvdimm may occupy more than 50G disk space even with compression enabled. We need to introduce dependent snapshot manner to solve this problem. The first snapshot point should always be saved completely, and enable dirty log trace after saving for nvdimm memory region. The later snapshot point should add the reference to previous snapshot's nvdimm data and just saving dirty pages. This can save a lot of disk and time if the snapshot operations are triggered frequently. Signed-off-by: Junyan He --- Makefile.target | 1 + include/migration/misc.h | 4 + migration/nvdimm.c | 1033 ++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 1038 insertions(+) create mode 100644 migration/nvdimm.c diff --git a/Makefile.target b/Makefile.target index 6549481..0259e70 100644 --- a/Makefile.target +++ b/Makefile.target @@ -139,6 +139,7 @@ obj-y +=3D memory.o obj-y +=3D memory_mapping.o obj-y +=3D dump.o obj-y +=3D migration/ram.o +obj-y +=3D migration/nvdimm.o LIBS :=3D $(libs_softmmu) $(LIBS) =20 # Hardware support diff --git a/include/migration/misc.h b/include/migration/misc.h index 77fd4f5..0c23da8 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -20,6 +20,10 @@ =20 void ram_mig_init(void); =20 +/* migration/nvdimm.c */ +void nvdimm_snapshot_init(void); +bool ram_block_is_nvdimm_active(RAMBlock *block); + /* migration/block.c */ =20 #ifdef CONFIG_LIVE_BLOCK_MIGRATION diff --git a/migration/nvdimm.c b/migration/nvdimm.c new file mode 100644 index 0000000..8516bb0 --- /dev/null +++ b/migration/nvdimm.c @@ -0,0 +1,1033 @@ +/* + * QEMU System Emulator + * + * Authors: + * He Junyan + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/mem/nvdimm.h" +#include "cpu.h" +#include "qemu/cutils.h" +#include "exec/ram_addr.h" +#include "exec/target_page.h" +#include "qemu/rcu_queue.h" +#include "qemu/error-report.h" +#include "migration.h" +#include "qapi/error.h" +#include "migration/register.h" +#include "migration/ram.h" +#include "migration/qemu-file.h" +#include "migration.h" +#include "migration/misc.h" +#include "migration/savevm.h" +#include "block/snapshot.h" +#include "migration/snapshot.h" + +#define NVDIMM_MIG_VERSION 0x01 + +/* PADDING data, useless */ +#define NVDIMM_PADDING_BYTE 0xce +/* PAGE id, is all zero */ +#define NVDIMM_ZERO_PAGE_ID 0xaabc250f +#define NVDIMM_NONZERO_PAGE_ID 0xacbc250e +/* No usage date, for alignment only */ +#define NVDIMM_SECTION_PADDING_ID 0xaaceccea +/* Section for dirty log kind */ +#define NVDIMM_SECTION_DIRTY_LOG_ID 0xbbcd0c1e +/* Section for raw data, no bitmap, dump the whole mem */ +#define NVDIMM_SECTION_DATA_ID 0x76bbcae3 +/* Section for setup */ +#define NVDIMM_SECTION_SETUP 0x7ace0cfa +/* Section for setup */ +#define NVDIMM_SECTION_COMPLETE 0x8ace0cfa +/* Section end symbol */ +#define NVDIMM_SECTION_END_ID 0xccbe8752 +/************************ Sections** *********************** +Padding section +---------------------------------------------------- +| PADDING_ID | size | PADDING_BYTE ...... | END_ID | +---------------------------------------------------- +Dirty log section +--------------------------------------------------------------------------= ---------- +| DIRTY_BITMAP_ID | total size | ram name size | ram name | ram size | bit= map size | +--------------------------------------------------------------------------= ---------- + ----------------------------------------------------------------- + bitmap data... | dirty page size | dirty page data... | END_ID | + ----------------------------------------------------------------- +Raw data section +--------------------------------------------------------------------------= ------------- +| DATA_ID | size | ram name size | ram name | ram size | data size | data.= .. | END_ID | +--------------------------------------------------------------------------= ------------- +*************************************************************/ + +/* State of NVDimm for migration */ +struct NVDimmState { + /* Whether the block driver support dependency + between snapshots */ + char *depend_snapshot_id; + int64_t depend_offset; + int64_t depend_size; + char *cur_snapshot_id; + int64_t cur_offset; + int64_t cur_size; + RAMBlock **blocks; + int block_num; + bool dirty_logging; +}; +typedef struct NVDimmState NVDimmState; + +static NVDimmState *nvdimm_state_p; + +static int nvdimm_device_list_append(Object *obj, void *opaque) +{ + GSList **list =3D opaque; + + if (object_dynamic_cast(obj, TYPE_NVDIMM)) { + *list =3D g_slist_append(*list, DEVICE(obj)); + } + + object_child_foreach(obj, nvdimm_device_list_append, opaque); + return 0; +} + +static bool ram_block_is_nvdimm(RAMBlock *block) +{ + GSList *list =3D NULL; + GSList *device_list =3D NULL; + bool ret =3D false; + + object_child_foreach(qdev_get_machine(), + nvdimm_device_list_append, &device_list); + + if (device_list =3D=3D NULL) { + return false; + } + + for (list =3D device_list; list; list =3D list->next) { + NVDIMMDevice *nvd =3D list->data; + MemoryRegion *mr =3D &nvd->nvdimm_mr; + int fd =3D memory_region_get_fd(mr); + + if (fd >=3D 0 && fd =3D=3D block->fd) { + ret =3D true; + break; + } + } + + g_slist_free(device_list); + return ret; +} + +bool ram_block_is_nvdimm_active(RAMBlock *block) +{ + if (block =3D=3D NULL) { + return false; + } + + if (get_current_snapshot_info(NULL) =3D=3D false) { + return false; + } + + return ram_block_is_nvdimm(block); +} + +/* Just support snapshot, live migration use ram's handlers */ +static bool nvdimm_is_active(void *opaque) +{ + RAMBlock *block; + int ret =3D get_current_snapshot_info(NULL); + if (ret) { + return true; + } + + if (!ram_bytes_total()) { + return false; + } + + rcu_read_lock(); + RAMBLOCK_FOREACH(block) + { + if (ram_block_is_nvdimm_active(block)) { + rcu_read_unlock(); + return true; + } + } + rcu_read_unlock(); + + return false; +} + +static int nvdimm_padding_to_alignment(QEMUFile *f, int section_id, + int32_t alignment, bool add_footer) +{ + int64_t cur_pos; + int32_t padding_sz; + int ret =3D 0; + + cur_pos =3D qemu_ftell(f); + /* We need to insert some padding section here. */ + padding_sz =3D (int32_t)(QEMU_ALIGN_UP(cur_pos, alignment) - cur_pos); + ret =3D padding_sz; + + padding_sz -=3D sizeof(int32_t); // NVDIMM_SECTION_PADDING_ID + padding_sz -=3D sizeof(int32_t); // NVDIMM_PADDING_BYTE size + padding_sz -=3D sizeof(int32_t); // NVDIMM_SECTION_END_ID + if (migrate_get_current()->send_section_footer) { + padding_sz -=3D sizeof(int8_t); + padding_sz -=3D sizeof(int32_t); + } + + if (padding_sz <=3D 0) { + padding_sz +=3D alignment; + ret +=3D alignment; + } + + qemu_put_be32(f, NVDIMM_SECTION_PADDING_ID); + qemu_put_be32(f, padding_sz); + while (padding_sz) { + qemu_put_byte(f, NVDIMM_PADDING_BYTE); + padding_sz--; + } + qemu_put_be32(f, NVDIMM_SECTION_END_ID); + if (add_footer && migrate_get_current()->send_section_footer) { + qemu_put_byte(f, QEMU_VM_SECTION_FOOTER); + qemu_put_be32(f, section_id); + } + + cur_pos =3D qemu_ftell(f); + assert(QEMU_IS_ALIGNED(cur_pos, alignment) || add_footer =3D=3D false); + return ret; +} + +static int nvdimm_state_save_dependency(QEMUFile *f, NVDimmState *nvdimm_s= tate) +{ + int64_t cur_pos; + int ret; + int32_t alignment =3D 0; + + if (qemu_file_is_support_dependency(f, &alignment) =3D=3D false) { + error_report("Enable nvdimm dependent snapshot without" + "file dependency support"); + return -ENOTSUP; + } + + cur_pos =3D qemu_ftell(f); + assert(QEMU_IS_ALIGNED(cur_pos, alignment)); + assert(QEMU_IS_ALIGNED(nvdimm_state->depend_offset, alignment)); + assert(QEMU_IS_ALIGNED(nvdimm_state->depend_size, alignment)); + + ret =3D qemu_file_set_ref_name(f, nvdimm_state->depend_snapshot_id); + assert(ret); + + ret =3D qemu_file_save_dependency(f, nvdimm_state->depend_offset, + nvdimm_state->depend_size); + if (ret < 0) { + error_report("save file dependency failed, depend_offset =3D %lx " + "depend_size is %ld, ret is %d", + nvdimm_state->depend_offset, + nvdimm_state->depend_size, ret); + return ret; + } + + cur_pos =3D qemu_ftell(f); + assert(QEMU_IS_ALIGNED(cur_pos, alignment)); + + return ret; +} + +static inline void *nvdimm_host_from_ram_block_offset(RAMBlock *block, + ram_addr_t offset) +{ + if (!offset_in_ramblock(block, offset)) { + return NULL; + } + + return block->host + offset; +} + +static int nvdimm_state_save_all_pages(QEMUFile *f, + NVDimmState *nvdimm_state, int i) +{ + hwaddr addr; + uint64_t total_sz; + int name_sz; + uint64_t data_sz; + void *host_ptr; + + if (memory_region_size(nvdimm_state->blocks[i]->mr) =3D=3D 0) { + return 0; + } + + data_sz =3D 0; + for (addr =3D 0; addr < memory_region_size(nvdimm_state->blocks[i]->mr= ); + addr +=3D 1 << TARGET_PAGE_BITS) { + assert(QEMU_IS_ALIGNED(addr, 1 << TARGET_PAGE_BITS)); + host_ptr =3D + nvdimm_host_from_ram_block_offset(nvdimm_state->blocks[i], add= r); + if (!host_ptr) { + error_report("Illegal RAM offset " RAM_ADDR_FMT, addr); + return -EINVAL; + } + + if (buffer_is_zero(host_ptr, 1 << TARGET_PAGE_BITS)) { + data_sz +=3D sizeof(int); // Zero page, just a ID + } else { + data_sz +=3D ((1 << TARGET_PAGE_BITS) + sizeof(int)); // ID + = page + } + } + + total_sz =3D sizeof(unsigned int); // NVDIMM_SECTION_DIRTY_BITMAP_ID + total_sz +=3D sizeof(uint64_t); // the total size itself + total_sz +=3D sizeof(int); // ram name size + name_sz =3D strlen(nvdimm_state->blocks[i]->idstr) + 1; + total_sz +=3D name_sz; + total_sz +=3D sizeof(uint64_t); // ram size + total_sz +=3D sizeof(uint64_t); // data size + total_sz +=3D data_sz; + total_sz +=3D sizeof(unsigned int); // NVDIMM_SECTION_END_ID + + qemu_put_be32(f, NVDIMM_SECTION_DATA_ID); + qemu_put_be64(f, total_sz); + qemu_put_be32(f, name_sz); + qemu_put_buffer(f, (uint8_t *)nvdimm_state->blocks[i]->idstr, name_sz); + qemu_put_be64(f, memory_region_size(nvdimm_state->blocks[i]->mr)); + qemu_put_be64(f, data_sz); + + for (addr =3D 0; addr < memory_region_size(nvdimm_state->blocks[i]->mr= ); + addr +=3D 1 << TARGET_PAGE_BITS) { + host_ptr =3D + nvdimm_host_from_ram_block_offset(nvdimm_state->blocks[i], add= r); + + if (buffer_is_zero(host_ptr, 1 << TARGET_PAGE_BITS)) { + qemu_put_be32(f, NVDIMM_ZERO_PAGE_ID); + data_sz -=3D sizeof(int); + } else { + qemu_put_be32(f, NVDIMM_NONZERO_PAGE_ID); + data_sz -=3D sizeof(int); + qemu_put_buffer(f, host_ptr, 1 << TARGET_PAGE_BITS); + data_sz -=3D 1 << TARGET_PAGE_BITS; + } + } + assert(data_sz =3D=3D 0); + qemu_put_be32(f, NVDIMM_SECTION_END_ID); + + return 1; +} + +static int nvdimm_state_save_dirty_pages(QEMUFile *f, + NVDimmState *nvdimm_state, int i) +{ + DirtyBitmapSnapshot *snap; + uint64_t bit_sz; + uint64_t total_sz; + int name_sz; + uint64_t data_sz; + hwaddr addr; + + if (memory_region_size(nvdimm_state->blocks[i]->mr) =3D=3D 0) { + return 0; + } + + snap =3D memory_region_snapshot_and_clear_dirty( + nvdimm_state->blocks[i]->mr, + 0, + memory_region_size(nvdimm_state->blocks[i]->mr), + DIRTY_MEMORY_MIGRATION); + if (snap =3D=3D NULL) { + error_report("Can not create snapshot bitmap for block %s", + nvdimm_state->blocks[i]->idstr); + return -1; + } + + bit_sz =3D + memory_region_size(nvdimm_state->blocks[i]->mr) >> (TARGET_PAGE_BI= TS + 3); + + data_sz =3D 0; + for (addr =3D 0; addr < memory_region_size(nvdimm_state->blocks[i]->mr= ); + addr +=3D 1 << TARGET_PAGE_BITS) { + assert(QEMU_IS_ALIGNED(addr, 1 << TARGET_PAGE_BITS)); + if (memory_region_snapshot_get_dirty(nvdimm_state->blocks[i]->mr, + snap, addr, 1 << TARGET_PAGE_= BITS)) { + data_sz +=3D 1 << TARGET_PAGE_BITS; + } + } + + total_sz =3D sizeof(unsigned int); // NVDIMM_SECTION_DIRTY_BITMAP_ID + total_sz +=3D sizeof(uint64_t); // the total size itself + total_sz +=3D sizeof(int); // ram name size + name_sz =3D strlen(nvdimm_state->blocks[i]->idstr) + 1; + total_sz +=3D name_sz; + total_sz +=3D sizeof(uint64_t); // ram size + total_sz +=3D sizeof(uint64_t); // bitmap size + total_sz +=3D bit_sz; + total_sz +=3D sizeof(uint64_t); // data size + total_sz +=3D data_sz; + total_sz +=3D sizeof(unsigned int); // NVDIMM_SECTION_END_ID + + qemu_put_be32(f, NVDIMM_SECTION_DIRTY_LOG_ID); + qemu_put_be64(f, total_sz); + qemu_put_be32(f, name_sz); + qemu_put_buffer(f, (uint8_t *)nvdimm_state->blocks[i]->idstr, name_sz); + qemu_put_be64(f, memory_region_size(nvdimm_state->blocks[i]->mr)); + qemu_put_be64(f, bit_sz); + qemu_put_buffer(f, (uint8_t *)memory_region_snapshot_get_dirty_bitmap(= snap), + bit_sz); + + qemu_put_be64(f, data_sz); + if (data_sz !=3D 0) { + for (addr =3D 0; addr < memory_region_size(nvdimm_state->blocks[i]= ->mr); + addr +=3D 1 << TARGET_PAGE_BITS) { + assert(QEMU_IS_ALIGNED(addr, 1 << TARGET_PAGE_BITS)); + if (memory_region_snapshot_get_dirty(nvdimm_state->blocks[i]->= mr, + snap, addr, 1 << TARGET_P= AGE_BITS)) { + qemu_put_buffer(f, nvdimm_state->blocks[i]->host + addr, + 1 << TARGET_PAGE_BITS); + data_sz -=3D 1 << TARGET_PAGE_BITS; + } + } + assert(data_sz =3D=3D 0); + } + + qemu_put_be32(f, NVDIMM_SECTION_END_ID); + g_free(snap); + + return 1; +} + +/** + * nvdimm_save_iterate: iterative stage for migration + * + * Returns zero to indicate success and negative for error + * + * @f: QEMUFile where to send the data + * @opaque: NVDimmState pointer + */ +static int nvdimm_save_iterate(QEMUFile *f, void *opaque, int section_id) +{ + NVDimmState *nvdimm_state =3D *(void **)opaque; + int ret =3D 0; + int i; + int32_t alignment; + int64_t begin_pos, cur_pos; + bool padded =3D false; + + /* Must support dependency */ + ret =3D qemu_file_is_support_dependency(f, &alignment); + assert(ret =3D=3D true); + + cur_pos =3D qemu_ftell(f); + if (!QEMU_IS_ALIGNED(cur_pos, alignment)) { + ret =3D nvdimm_padding_to_alignment(f, section_id, alignment, true= ); + if (ret < 0) { + error_report("NVDIMM saving, failed to padding to aligment"); + return ret; + } + padded =3D true; + } + + begin_pos =3D qemu_ftell(f); + assert(QEMU_IS_ALIGNED(begin_pos, alignment)); + nvdimm_state->cur_offset =3D begin_pos; + + if (nvdimm_state->dirty_logging) { + ret =3D nvdimm_state_save_dependency(f, nvdimm_state); + if (ret < 0) { + error_report("NVDIMM saving, failed to save dependency"); + return ret; + } + + for (i =3D 0; i < nvdimm_state->block_num; i++) { + cpu_physical_memory_test_and_clear_dirty( + memory_region_get_ram_addr(nvdimm_state->blocks[i]->mr), + memory_region_size(nvdimm_state->blocks[i]->mr), + DIRTY_MEMORY_MIGRATION); + } + + if (padded) { + qemu_put_byte(f, QEMU_VM_SECTION_PART); + qemu_put_be32(f, section_id); + } + + for (i =3D 0; i < nvdimm_state->block_num; i++) { + ret =3D nvdimm_state_save_dirty_pages(f, nvdimm_state, i); + if (ret < 0) { + error_report("NVDIMM saving, failed to save dirty pages"); + return ret; + } + } + } else { + if (padded) { + qemu_put_byte(f, QEMU_VM_SECTION_PART); + qemu_put_be32(f, section_id); + } + + /* Save the whole content of nvdimm, no dependency needed */ + for (i =3D 0; i < nvdimm_state->block_num; i++) { + ret =3D nvdimm_state_save_all_pages(f, nvdimm_state, i); + if (ret < 0) { + error_report("NVDIMM saving, failed to save all pages"); + return ret; + } + } + } + + /* Need to add padding to make the whole data aligned, include + QEMU_VM_SECTION_FOOTER and section_id */ + cur_pos =3D qemu_ftell(f); + if (migrate_get_current()->send_section_footer) { + cur_pos +=3D (1 + sizeof(int)); + } + + if (QEMU_IS_ALIGNED(cur_pos, alignment)) { // Already aligned + nvdimm_state->cur_size =3D cur_pos - begin_pos; + assert(QEMU_IS_ALIGNED(nvdimm_state->cur_size, alignment)); + return ret; + } + + /* Appending the footer if needed */ + if (migrate_get_current()->send_section_footer) { + qemu_put_byte(f, QEMU_VM_SECTION_FOOTER); + qemu_put_be32(f, section_id); + qemu_put_byte(f, QEMU_VM_SECTION_PART); + qemu_put_be32(f, section_id); + } + ret =3D nvdimm_padding_to_alignment(f, section_id, alignment, false); + if (ret < 0) { + error_report("NVDIMM saving, failed to save all pages"); + return ret; + } + + cur_pos =3D qemu_ftell(f); + nvdimm_state->cur_size =3D cur_pos - begin_pos; + if (migrate_get_current()->send_section_footer) { + nvdimm_state->cur_size +=3D (1 + sizeof(int)); + } + assert(QEMU_IS_ALIGNED(nvdimm_state->cur_size, alignment)); + + return ret; +} + +static void nvdimm_destroy_nvdimm_state(NVDimmState *nvdimm_state) +{ + if (nvdimm_state) { + /* disable all dirty log trace */ + if (nvdimm_state->depend_snapshot_id) { + int i; + for (i =3D 0; i < nvdimm_state->block_num; i++) { + memory_region_set_log(nvdimm_state->blocks[i]->mr, false, + DIRTY_MEMORY_MIGRATION); + } + } + + if (nvdimm_state->cur_snapshot_id) { + g_free(nvdimm_state->cur_snapshot_id); + } + if (nvdimm_state->blocks) { + g_free(nvdimm_state->blocks); + } + g_free(nvdimm_state); + } +} + +static NVDimmState *nvdimm_alloc_nvdimm_state(void) +{ + NVDimmState *nvdimm_state =3D g_try_new0(NVDimmState, 1); + RAMBlock *block; + + if (nvdimm_state =3D=3D NULL) { + return NULL; + } + + rcu_read_lock(); + RAMBLOCK_FOREACH(block) + { + if (ram_block_is_nvdimm(block)) { + nvdimm_state->block_num++; + nvdimm_state->blocks =3D + g_try_renew(RAMBlock *, + nvdimm_state->blocks, + nvdimm_state->block_num); + if (nvdimm_state->blocks =3D=3D NULL) { + rcu_read_unlock(); + nvdimm_destroy_nvdimm_state(nvdimm_state); + return NULL; + } + + nvdimm_state->blocks[nvdimm_state->block_num - 1] =3D block; + } + } + rcu_read_unlock(); + + return nvdimm_state; +} + +/** + * nvdimm_save_setup: Setup nvdimm for migration + * + * Returns zero to indicate success and negative for error + * + * @f: QEMUFile where to send the data + * @opaque: NVDimmState pointer + */ +static int nvdimm_save_setup(QEMUFile *f, void *opaque) +{ + NVDimmState *nvdimm_state =3D *(void **)opaque; + int ret =3D 0; + QEMUSnapshotInfo sn; + RAMBlock *block; + int i; + + ret =3D get_current_snapshot_info(&sn); + if (ret =3D=3D 0) { /* Just enable in snapshot mode */ + info_report("Not in snapshot saving, no nvdimm snapshot optimizati= on"); + return -1; + } + + /* No dependency support, just let the ram common logic do its job */ + if (qemu_file_is_support_dependency(f, NULL) =3D=3D false) { + assert(nvdimm_state =3D=3D NULL); + info_report("The drive file does not support dependent snapshot"); + return -1; + } + + if (nvdimm_state =3D=3D NULL) { /* First time */ + nvdimm_state =3D nvdimm_alloc_nvdimm_state(); + if (nvdimm_state =3D=3D NULL) { + error_report("Alloc the nvdimm state for snapshot saving faile= d"); + goto failed; + } + + nvdimm_state->cur_snapshot_id =3D g_strdup(sn.name); + *(void **)opaque =3D nvdimm_state; + } else { + assert(nvdimm_state->cur_snapshot_id); + if (nvdimm_state->depend_snapshot_id) { + g_free(nvdimm_state->depend_snapshot_id); + } + nvdimm_state->depend_snapshot_id =3D nvdimm_state->cur_snapshot_id; + nvdimm_state->depend_offset =3D nvdimm_state->cur_offset; + nvdimm_state->depend_size =3D nvdimm_state->cur_size; + nvdimm_state->cur_snapshot_id =3D g_strdup(sn.name); + nvdimm_state->cur_offset =3D 0; + nvdimm_state->cur_size =3D 0; + + rcu_read_lock(); + RAMBLOCK_FOREACH(block) + { + if (ram_block_is_nvdimm_active(block)) { + for (i =3D 0; i < nvdimm_state->block_num; i++) { + if (block =3D=3D nvdimm_state->blocks[i]) { + break; + } + } + + // Can not find the same block? + if (i =3D=3D nvdimm_state->block_num) { + rcu_read_unlock(); + error_report("Can not find the block %s", block->idstr= ); + goto failed; + } + } + } + rcu_read_unlock(); + } + + qemu_put_be32(f, NVDIMM_SECTION_SETUP); + qemu_put_be32(f, NVDIMM_SECTION_END_ID); + + return ret; + +failed: + nvdimm_destroy_nvdimm_state(nvdimm_state); + *(void **)opaque =3D NULL; + return -1; +} + +/** + * nvdimm_save_complete: function called to send the remaining amount of r= am + * + * Returns zero to indicate success + * + * Called with iothread lock + * + * @f: QEMUFile where to send the data + * @opaque: NVDimmState pointer + */ +static int nvdimm_save_complete(QEMUFile *f, void *opaque) +{ + NVDimmState *nvdimm_state =3D *(void **)opaque; + int i; + + for (i =3D 0; i < nvdimm_state->block_num; i++) { + memory_region_set_log(nvdimm_state->blocks[i]->mr, true, + DIRTY_MEMORY_MIGRATION); + } + + /* Enable the dirty logging for next time usage */ + nvdimm_state->dirty_logging =3D true; + + qemu_put_be32(f, NVDIMM_SECTION_COMPLETE); + qemu_put_be32(f, NVDIMM_SECTION_END_ID); + + return 0; +} + +static bool nvdimm_has_postcopy(void *opaque) +{ + return false; +} + +static void nvdimm_save_pending(QEMUFile *f, void *opaque, uint64_t max_si= ze, + uint64_t *non_postcopiable_pending, + uint64_t *postcopiable_pending) +{ +} + +static void nvdimm_save_cleanup(void *opaque) +{ + return; +} + +/** + * nvdimm_load_setup: Setup NVDimm for migration incoming side + * + * Returns zero to indicate success and negative for error + * + * @f: QEMUFile where to receive the data + * @opaque: NVDimmState pointer + */ +static int nvdimm_load_setup(QEMUFile *f, void *opaque) +{ + NVDimmState *nvdimm_state =3D *(void **)opaque; + + if (nvdimm_state) { + nvdimm_destroy_nvdimm_state(nvdimm_state); + *(void **)opaque =3D NULL; + } + + nvdimm_state =3D nvdimm_alloc_nvdimm_state(); + if (nvdimm_state =3D=3D NULL) { + return -1; + } + + *(void **)opaque =3D nvdimm_state; + return 1; +} + +static int nvdimm_load_cleanup(void *opaque) +{ + NVDimmState *nvdimm_state =3D *(void **)opaque; + nvdimm_destroy_nvdimm_state(nvdimm_state); + *(void **)opaque =3D NULL; + + return 0; +} + +static int nvdimm_load_dirty_pages(QEMUFile *f, NVDimmState *nvdimm_state) +{ + int64_t total_sz =3D qemu_get_be64(f); + int ret =3D 0; + int name_sz; + int64_t sz; + uint8_t *name_buf =3D NULL; + uint8_t *bitmap_buf =3D NULL; + RAMBlock *block; + int64_t ram_sz =3D 0; + int64_t bitmap_sz =3D 0; + int64_t data_sz =3D 0; + hwaddr addr; + void *host_ptr; + + if (total_sz <=3D 0) { + ret =3D -EINVAL; + return ret; + } + + name_sz =3D qemu_get_be32(f); + if (name_sz <=3D 0) { + ret =3D -EINVAL; + return ret; + } + + name_buf =3D g_malloc(name_sz); + if (name_buf =3D=3D NULL) { + ret =3D -ENOMEM; + return ret; + } + + sz =3D qemu_get_buffer(f, name_buf, name_sz); + if (sz !=3D name_sz) { + ret =3D -EINVAL; + return ret; + } + + block =3D qemu_ram_block_by_name((char *)name_buf); + if (block =3D=3D NULL || block->host =3D=3D NULL) { + ret =3D -EINVAL; + return ret; + } + g_free(name_buf); + name_buf =3D NULL; + + ram_sz =3D qemu_get_be64(f); + if (ram_sz !=3D memory_region_size(block->mr)) { + ret =3D -EINVAL; + return ret; + } + + bitmap_sz =3D qemu_get_be64(f); + if (bitmap_sz <=3D 0) { + ret =3D -EINVAL; + return ret; + } + + bitmap_buf =3D g_malloc(bitmap_sz); + if (bitmap_buf =3D=3D NULL) { + ret =3D -ENOMEM; + return ret; + } + + sz =3D qemu_get_buffer(f, bitmap_buf, bitmap_sz); + if (sz !=3D bitmap_sz) { + ret =3D -EINVAL; + goto out; + } + + data_sz =3D qemu_get_be64(f); + if (data_sz < 0) { + ret =3D -EINVAL; + goto out; + } + + assert(QEMU_IS_ALIGNED(data_sz, TARGET_PAGE_SIZE)); + addr =3D 0; + while (data_sz) { + addr =3D find_next_bit((unsigned long *)bitmap_buf, + ram_sz >> TARGET_PAGE_BITS, addr); + host_ptr =3D nvdimm_host_from_ram_block_offset(block, addr); + if (!host_ptr) { + error_report("Illegal RAM offset " RAM_ADDR_FMT, addr); + ret =3D -EINVAL; + goto out; + } + + qemu_get_buffer(f, host_ptr, TARGET_PAGE_SIZE); + data_sz -=3D TARGET_PAGE_SIZE; + } + + if (qemu_get_be32(f) !=3D NVDIMM_SECTION_END_ID) { + ret =3D -EINVAL; + goto out; + } + +out: + if (bitmap_buf) { + g_free(bitmap_buf); + } + return ret; +} + +static int nvdimm_load_all_pages(QEMUFile *f, NVDimmState *nvdimm_state) +{ + int64_t total_sz =3D qemu_get_be64(f); + int64_t sz; + int64_t data_sz; + int name_sz; + int ret =3D 0; + uint8_t *buf =3D NULL; + RAMBlock *block; + hwaddr addr; + void *host_ptr; + int64_t ram_sz =3D 0; + int tag; + + if (total_sz <=3D 0) { + ret =3D -EINVAL; + return ret; + } + + name_sz =3D qemu_get_be32(f); + if (name_sz <=3D 0) { + ret =3D -EINVAL; + return ret; + } + + buf =3D g_malloc(name_sz); + if (buf =3D=3D NULL) { + ret =3D -ENOMEM; + return ret; + } + + sz =3D qemu_get_buffer(f, buf, name_sz); + if (sz !=3D name_sz) { + ret =3D -EINVAL; + goto out; + } + + block =3D qemu_ram_block_by_name((char *)buf); + if (block =3D=3D NULL || block->host =3D=3D NULL) { + ret =3D -EINVAL; + goto out; + } + + ram_sz =3D qemu_get_be64(f); + if (ram_sz !=3D memory_region_size(block->mr)) { + ret =3D -EINVAL; + goto out; + } + + data_sz =3D qemu_get_be64(f); + if (data_sz <=3D 0) { + ret =3D -EINVAL; + goto out; + } + + for (addr =3D 0; addr < ram_sz; addr +=3D 1 << TARGET_PAGE_BITS) { + assert(QEMU_IS_ALIGNED(addr, 1 << TARGET_PAGE_BITS)); + host_ptr =3D nvdimm_host_from_ram_block_offset(block, addr); + if (!host_ptr) { + error_report("Illegal RAM offset " RAM_ADDR_FMT, addr); + ret =3D -EINVAL; + goto out; + } + + tag =3D qemu_get_be32(f); + if (tag =3D=3D NVDIMM_ZERO_PAGE_ID) { + memset(host_ptr, 0, 1 << TARGET_PAGE_BITS); + } else { + assert(tag =3D=3D NVDIMM_NONZERO_PAGE_ID); + qemu_get_buffer(f, host_ptr, TARGET_PAGE_SIZE); + } + host_ptr +=3D TARGET_PAGE_SIZE; + } + + tag =3D qemu_get_be32(f); + if (tag !=3D NVDIMM_SECTION_END_ID) { + ret =3D -EINVAL; + goto out; + } + +out: + if (buf) { + g_free(buf); + } + + return ret; +} + +static int nvdimm_load(QEMUFile *f, void *opaque, int version_id) +{ + int ret =3D 0; + unsigned int sec_id; + uint8_t *buf =3D NULL; + size_t sz; + NVDimmState *nvdimm_state =3D *(void **)opaque; + + if (version_id !=3D NVDIMM_MIG_VERSION) { + ret =3D -EINVAL; + goto failed; + } + + sec_id =3D qemu_get_be32(f); + if (sec_id =3D=3D NVDIMM_SECTION_PADDING_ID) { + /* Just skip all this padding section. */ + int padding_sz =3D qemu_get_be32(f); + unsigned int end_id; + buf =3D g_malloc(padding_sz); + if (buf =3D=3D NULL) { + ret =3D -ENOMEM; + goto failed; + } + + sz =3D qemu_get_buffer(f, buf, padding_sz); + if (sz !=3D padding_sz) { + ret =3D -EINVAL; + goto failed; + } + padding_sz--; + while (padding_sz >=3D 0) { + if (buf[padding_sz] !=3D NVDIMM_PADDING_BYTE) { + ret =3D -EINVAL; + goto failed; + } + padding_sz--; + } + + end_id =3D qemu_get_be32(f); + if (end_id !=3D NVDIMM_SECTION_END_ID) { + ret =3D -EINVAL; + goto failed; + } + + g_free(buf); + buf =3D NULL; + } else if (sec_id =3D=3D NVDIMM_SECTION_DIRTY_LOG_ID) { + ret =3D nvdimm_load_dirty_pages(f, nvdimm_state); + if (ret < 0) { + goto failed; + } + } else if (sec_id =3D=3D NVDIMM_SECTION_DATA_ID) { + ret =3D nvdimm_load_all_pages(f, nvdimm_state); + if (ret < 0) { + goto failed; + } + } else if (sec_id =3D=3D NVDIMM_SECTION_SETUP || + sec_id =3D=3D NVDIMM_SECTION_COMPLETE) { + unsigned int d =3D qemu_get_be32(f); + if (d !=3D NVDIMM_SECTION_END_ID) { + ret =3D -EINVAL; + goto failed; + } + } else { + error_report("NVDIMM load, can not recognize SEC id %d", sec_id); + ret =3D -EINVAL; + goto failed; + } + + return ret; + +failed: + if (buf) { + g_free(buf); + } + + return ret; +} + +static SaveVMHandlers savevm_nvdimm_handlers =3D { + .is_active =3D nvdimm_is_active, + .save_setup =3D nvdimm_save_setup, + .save_live_iterate =3D nvdimm_save_iterate, + .save_live_complete_precopy =3D nvdimm_save_complete, + .has_postcopy =3D nvdimm_has_postcopy, + .save_live_pending =3D nvdimm_save_pending, + .load_state =3D nvdimm_load, + .save_cleanup =3D nvdimm_save_cleanup, + .load_setup =3D nvdimm_load_setup, + .load_cleanup =3D nvdimm_load_cleanup, +}; + +void nvdimm_snapshot_init(void) +{ + register_savevm_live(NULL, "nvdimm", 0, NVDIMM_MIG_VERSION, + &savevm_nvdimm_handlers, &nvdimm_state_p); +} --=20 2.7.4 From nobody Fri Apr 19 05:08:29 2024 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=hotmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520990716956657.1923842451711; Tue, 13 Mar 2018 18:25:16 -0700 (PDT) Received: from localhost ([::1]:43912 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evvAK-0003w4-5D for importer@patchew.org; Tue, 13 Mar 2018 21:25:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36458) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evv61-0000e4-33 for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evv5w-0006YA-7J for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:49 -0400 Received: from mga18.intel.com ([134.134.136.126]:28906) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evv5v-0006Hx-UK for qemu-devel@nongnu.org; Tue, 13 Mar 2018 21:20:44 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Mar 2018 18:20:43 -0700 Received: from natrouter.sh.intel.com (HELO robinhe-hp.domain) ([10.239.13.3]) by orsmga001.jf.intel.com with ESMTP; 13 Mar 2018 18:20:41 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,466,1515484800"; d="scan'208";a="38632892" From: junyan.he@hotmail.com To: qemu-devel@nongnu.org Date: Wed, 14 Mar 2018 09:20:18 +0800 Message-Id: <1520990418-28258-11-git-send-email-junyan.he@hotmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> References: <1520990418-28258-1-git-send-email-junyan.he@hotmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH 10/10] RFC: Enable nvdimm snapshot functions. 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, famz@redhat.com, crosthwaite.peter@gmail.com, quintela@redhat.com, dgilbert@redhat.com, mreitz@redhat.com, Junyan He , pbonzini@redhat.com, rth@twiddle.net 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: Junyan He In snapshot saving, all nvdimm kind memory will be saved in different way and we exclude all nvdimm kind memory region in ram.c Signed-off-by: Junyan He --- migration/ram.c | 17 +++++++++++++++++ vl.c | 1 + 2 files changed, 18 insertions(+) diff --git a/migration/ram.c b/migration/ram.c index d1db422..ad32469 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1219,9 +1219,15 @@ static bool find_dirty_block(RAMState *rs, PageSearc= hStatus *pss, bool *again) /* Didn't find anything in this RAM Block */ pss->page =3D 0; pss->block =3D QLIST_NEXT_RCU(pss->block, next); + while (ram_block_is_nvdimm_active(pss->block)) { + pss->block =3D QLIST_NEXT_RCU(pss->block, next); + } if (!pss->block) { /* Hit the end of the list */ pss->block =3D QLIST_FIRST_RCU(&ram_list.blocks); + while (ram_block_is_nvdimm_active(pss->block)) { + pss->block =3D QLIST_NEXT_RCU(pss->block, next); + } /* Flag that we've looped */ pss->complete_round =3D true; rs->ram_bulk_stage =3D false; @@ -1541,6 +1547,9 @@ static int ram_find_and_save_block(RAMState *rs, bool= last_stage) =20 if (!pss.block) { pss.block =3D QLIST_FIRST_RCU(&ram_list.blocks); + while (ram_block_is_nvdimm_active(pss.block)) { + pss.block =3D QLIST_NEXT_RCU(pss.block, next); + } } =20 do { @@ -1583,6 +1592,10 @@ uint64_t ram_bytes_total(void) =20 rcu_read_lock(); RAMBLOCK_FOREACH(block) { + if (ram_block_is_nvdimm_active(block)) { + // If snapshot and the block is nvdimm, let nvdimm do the job + continue; + } total +=3D block->used_length; } rcu_read_unlock(); @@ -2222,6 +2235,10 @@ static int ram_save_setup(QEMUFile *f, void *opaque) qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE); =20 RAMBLOCK_FOREACH(block) { + if (ram_block_is_nvdimm_active(block)) { + // If snapshot and the block is nvdimm, let nvdimm do the job + continue; + } qemu_put_byte(f, strlen(block->idstr)); qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr)); qemu_put_be64(f, block->used_length); diff --git a/vl.c b/vl.c index 3ef04ce..1bd5711 100644 --- a/vl.c +++ b/vl.c @@ -4502,6 +4502,7 @@ int main(int argc, char **argv, char **envp) =20 blk_mig_init(); ram_mig_init(); + nvdimm_snapshot_init(); =20 /* If the currently selected machine wishes to override the units-per-= bus * property of its default HBA interface type, do so now. */ --=20 2.7.4