From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46505) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WnQnO-0003DH-IM for qemu-devel@nongnu.org; Thu, 22 May 2014 07:04:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WnQnE-00006F-6I for qemu-devel@nongnu.org; Thu, 22 May 2014 07:04:22 -0400 Received: from mail-pd0-f178.google.com ([209.85.192.178]:38672) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WnQnD-000061-UT for qemu-devel@nongnu.org; Thu, 22 May 2014 07:04:12 -0400 Received: by mail-pd0-f178.google.com with SMTP id v10so2372249pde.37 for ; Thu, 22 May 2014 04:04:11 -0700 (PDT) Message-ID: <537DD9A4.7080904@ozlabs.ru> Date: Thu, 22 May 2014 21:04:04 +1000 From: Alexey Kardashevskiy MIME-Version: 1.0 References: <1400756006-26297-1-git-send-email-aik@ozlabs.ru> <1400756006-26297-2-git-send-email-aik@ozlabs.ru> <537DD81B.4080007@suse.de> In-Reply-To: <537DD81B.4080007@suse.de> Content-Type: text/plain; charset=KOI8-R Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 1/2] vmstate: Add helper to enable GHashTable migration List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Alexander Graf , qemu-devel@nongnu.org Cc: qemu-ppc@nongnu.org On 05/22/2014 08:57 PM, Alexander Graf wrote: > > On 22.05.14 12:53, Alexey Kardashevskiy wrote: >> This adds a VMSTATE_HASH_V macro. This implements put/get callbacks for it. >> This implements a qemu_hash_init() wrapper to save key/value sizes. >> >> Signed-off-by: Alexey Kardashevskiy >> --- >> include/migration/vmstate.h | 10 +++++++++ >> include/qemu-common.h | 13 +++++++++++ >> vmstate.c | 54 >> +++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 77 insertions(+) >> >> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h >> index 7e45048..6af599d 100644 >> --- a/include/migration/vmstate.h >> +++ b/include/migration/vmstate.h >> @@ -166,6 +166,7 @@ extern const VMStateInfo vmstate_info_timer; >> extern const VMStateInfo vmstate_info_buffer; >> extern const VMStateInfo vmstate_info_unused_buffer; >> extern const VMStateInfo vmstate_info_bitmap; >> +static const VMStateInfo vmstate_info_hash; >> #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0) >> #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0) >> @@ -740,6 +741,15 @@ extern const VMStateInfo vmstate_info_bitmap; >> #define VMSTATE_BUFFER_UNSAFE(_field, _state, _version, _size) \ >> VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, >> vmstate_info_buffer, _size) >> +#define VMSTATE_HASH_V(_field, _state, _version) { \ >> + .name = (stringify(_field)), \ >> + .version_id = (_version), \ >> + .size = sizeof(qemu_hash), \ >> + .info = &vmstate_info_hash, \ >> + .flags = VMS_SINGLE, \ >> + .offset = vmstate_offset_value(_state, _field, qemu_hash), \ >> +} >> + >> #define VMSTATE_UNUSED_V(_v, _size) \ >> VMSTATE_UNUSED_BUFFER(NULL, _v, _size) >> diff --git a/include/qemu-common.h b/include/qemu-common.h >> index 3f3fd60..ee973e7 100644 >> --- a/include/qemu-common.h >> +++ b/include/qemu-common.h >> @@ -462,4 +462,17 @@ int parse_debug_env(const char *name, int max, int >> initial); >> const char *qemu_ether_ntoa(const MACAddr *mac); >> +typedef struct qemu_hash { >> + GHashTable *hash; >> + int key_size; >> + int value_size; >> +} qemu_hash; >> + >> +static inline void qemu_hash_init(qemu_hash *h, int key_size, int >> value_size) >> +{ >> + h->key_size = key_size; >> + h->value_size = value_size; >> + h->hash = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, >> g_free); >> +} >> + >> #endif >> diff --git a/vmstate.c b/vmstate.c >> index b5882fa..2148e73 100644 >> --- a/vmstate.c >> +++ b/vmstate.c >> @@ -667,3 +667,57 @@ const VMStateInfo vmstate_info_bitmap = { >> .get = get_bitmap, >> .put = put_bitmap, >> }; >> + >> +/* Save restore for qemu_hash which is a wrapper over GHashTable */ >> +static int get_hash(QEMUFile *f, void *pv, size_t size) >> +{ >> + qemu_hash *h = pv; >> + uint32_t num = g_hash_table_size(h->hash); >> + gpointer key, value; >> + >> + num = qemu_get_be32(f); >> + >> + for ( ; num; --num) { >> + int i; >> + >> + key = g_malloc0(h->key_size); >> + for (i = 0; i < h->key_size; ++i) { >> + ((uint8_t *)key)[i] = qemu_get_byte(f); >> + } >> + value = g_malloc0(h->value_size); >> + for (i = 0; i < h->value_size; ++i) { >> + ((uint8_t *)value)[i] = qemu_get_byte(f); >> + } >> + g_hash_table_insert(h->hash, key, value); >> + } >> + >> + return 0; >> +} >> + >> +static void put_hash(QEMUFile *f, void *pv, size_t size) >> +{ >> + qemu_hash *h = pv; >> + uint32_t num = g_hash_table_size(h->hash); >> + GHashTableIter iter; >> + gpointer key, value; >> + >> + qemu_put_be32(f, num); >> + >> + g_hash_table_iter_init(&iter, h->hash); >> + while (g_hash_table_iter_next (&iter, &key, &value)) { >> + int i; >> + >> + for (i = 0; i < h->key_size; ++i) { >> + qemu_put_byte(f, ((uint8_t *)key)[i]); >> + } >> + for (i = 0; i < h->value_size; ++i) { >> + qemu_put_byte(f, ((uint8_t *)value)[i]); > > I think the only way to do this safely would be to do a recursive > introspective walk through the hash table's key and value properties. Every > key and every property can be an object again, right? > > We would basically impose a limit onto ourselves that every member of the > hash table would have to be a GObject again. This is a bit too much for the task I am trying to solve :) @key here is uin32_t and there is no point in making it an object... -- Alexey