qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Corey Bryant <coreyb@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, aliguori@us.ibm.com,
	stefanb@linux.vnet.ibm.com,
	Corey Bryant <coreyb@linux.vnet.ibm.com>,
	mdroth@linux.vnet.ibm.com, lcapitulino@redhat.com,
	jschopp@linux.vnet.ibm.com, stefanha@redhat.com
Subject: [Qemu-devel] [PATCH 2/7] vnvram: VNVRAM in-memory support
Date: Thu, 23 May 2013 13:44:42 -0400	[thread overview]
Message-ID: <1369331087-22345-3-git-send-email-coreyb@linux.vnet.ibm.com> (raw)
In-Reply-To: <1369331087-22345-1-git-send-email-coreyb@linux.vnet.ibm.com>

Provides support for in-memory VNVRAM entries.  The in-memory
entries are used for fast access to entry data such as the
current or max size of an entry and the disk offset where an
entry's binary blob data is stored.

Signed-off-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
---
 vnvram.c |  196 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 195 insertions(+), 1 deletions(-)

diff --git a/vnvram.c b/vnvram.c
index e467198..37b7070 100644
--- a/vnvram.c
+++ b/vnvram.c
@@ -13,6 +13,7 @@
 
 #include "vnvram.h"
 #include "block/block.h"
+#include "monitor/monitor.h"
 
 /*
 #define VNVRAM_DEBUG
@@ -69,6 +70,14 @@ typedef struct VNVRAMDrvEntry {
 
 static int vnvram_drv_entry_create(VNVRAM *, VNVRAMEntry *, uint64_t, uint32_t);
 static int vnvram_drv_entry_update(VNVRAM *, VNVRAMEntry *, uint64_t, uint32_t);
+static int vnvram_register_entry_internal(VNVRAM *, const VNVRAMEntryName *,
+                                          uint64_t, uint32_t, uint32_t);
+static VNVRAMEntry *vnvram_find_entry(VNVRAM *, const VNVRAMEntryName *);
+static uint64_t vnvram_get_size_kb(VNVRAM *);
+
+/* Round a value up to the next SIZE */
+#define ROUNDUP(VAL, SIZE) \
+    (((VAL)+(SIZE)-1) & ~((SIZE)-1))
 
 /*
  * Macros for finding entries and their drive offsets
@@ -154,7 +163,8 @@ static int vnvram_drv_adjust_size(VNVRAM *vnvram)
     int rc = 0;
     int64_t needed_size;
 
-    needed_size = 0;
+    /* qcow2 size needs to be multiple of 512 */
+    needed_size = vnvram_get_size_kb(vnvram) * 1024;
 
     if (bdrv_getlength(vnvram->bds) < needed_size) {
         rc = bdrv_truncate(vnvram->bds, needed_size);
@@ -485,3 +495,187 @@ static bool vnvram_drv_hdr_is_valid(VNVRAM *vnvram, VNVRAMDrvHdr *hdr)
 
     return true;
 }
+
+/************************ VNVRAM in-memory ***************************/
+/* High-level VNVRAM functions that work with in-memory entries.     */
+/*********************************************************************/
+
+/*
+ * Check if the specified vnvram has been created
+ */
+static bool vnvram_exists(VNVRAM *vnvram_target)
+{
+    VNVRAM *vnvram;
+
+    QLIST_FOREACH(vnvram, &vnvrams, list) {
+        if (vnvram == vnvram_target) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/*
+ * Get total size of the VNVRAM
+ */
+static uint64_t vnvram_get_size(VNVRAM *vnvram)
+{
+    const VNVRAMEntry *entry;
+    uint64_t totsize = sizeof(VNVRAMDrvHdr);
+
+    for (entry = VNVRAM_FIRST_ENTRY(vnvram); entry != NULL;
+         entry = VNVRAM_NEXT_ENTRY(entry)) {
+        totsize += sizeof(VNVRAMDrvEntry) + entry->max_size;
+    }
+
+    return totsize;
+}
+
+/*
+ * Get the total size of the VNVRAM in kilobytes (rounded up to the next kb)
+ */
+static uint64_t vnvram_get_size_kb(VNVRAM *vnvram)
+{
+    return ROUNDUP(vnvram_get_size(vnvram), 1024) / 1024;
+}
+
+/*
+ * Check if the VNVRAM entries are valid
+ */
+static bool vnvram_entries_are_valid(VNVRAM *vnvram, uint64_t drv_size)
+{
+    const VNVRAMEntry *i_entry, *j_entry;
+
+    /* Entries must not overlap or point beyond end of drive size */
+    for (i_entry = VNVRAM_FIRST_ENTRY(vnvram); i_entry != NULL;
+         i_entry = VNVRAM_NEXT_ENTRY(i_entry)) {
+
+        uint64_t i_blob_start = i_entry->blob_offset;
+        uint64_t i_blob_end = i_blob_start + i_entry->max_size-1;
+
+        if (i_entry->max_size == 0) {
+            DPRINTF("%s: VNVRAM entry max size shouldn't be 0\n", __func__);
+            return false;
+        }
+
+        if (i_blob_end > drv_size) {
+            DPRINTF("%s: VNVRAM entry blob too large for drive\n", __func__);
+            return false;
+        }
+
+        for (j_entry = VNVRAM_NEXT_ENTRY(i_entry); j_entry != NULL;
+             j_entry = VNVRAM_NEXT_ENTRY(j_entry)) {
+
+            uint64_t j_blob_start = j_entry->blob_offset;
+            uint64_t j_blob_end = j_blob_start + j_entry->max_size-1;
+
+            if (j_entry->max_size == 0) {
+                DPRINTF("%s: VNVRAM entry max size shouldn't be 0\n", __func__);
+                return false;
+            }
+
+            if (j_blob_end > drv_size) {
+                DPRINTF("%s: VNVRAM entry blob too large for drive\n",
+                        __func__);
+                return false;
+            }
+
+            if ((i_blob_start >= j_blob_start && i_blob_start <= j_blob_end) ||
+                (i_blob_end   >= j_blob_start && i_blob_end   <= j_blob_end)) {
+                DPRINTF("%s: VNVRAM entries overlap\n", __func__);
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+/*
+ * Synchronize the in-memory VNVRAM entries with those found on the drive.
+ */
+static int vnvram_sync_from_drv(VNVRAM *vnvram, VNVRAMDrvHdr *hdr)
+{
+    int rc = 0, num_entries = 0, i;
+    VNVRAMDrvEntry *drv_entries = NULL;
+
+    rc = vnvram_drv_entries_get(vnvram, hdr, &drv_entries, &num_entries);
+    if (rc != 0) {
+        return rc;
+    }
+
+    for (i = 0; i < num_entries; i++) {
+        rc = vnvram_register_entry_internal(vnvram,
+                                (const VNVRAMEntryName *)&drv_entries[i].name,
+                                drv_entries[i].blob_offset,
+                                drv_entries[i].cur_size,
+                                drv_entries[i].max_size);
+        if (rc != 0) {
+            goto err_exit;
+        }
+    }
+
+    vnvram->end_offset = vnvram_get_size(vnvram);
+
+err_exit:
+    g_free(drv_entries);
+
+    return rc;
+}
+
+/*
+ * Register an entry with the in-memory entry list
+ */
+static int vnvram_register_entry_internal(VNVRAM *vnvram,
+                                          const VNVRAMEntryName *entry_name,
+                                          uint64_t blob_offset,
+                                          uint32_t cur_size,
+                                          uint32_t max_size)
+{
+    VNVRAMEntry *new_entry;
+    const VNVRAMEntry *existing_entry;
+    int rc = 0;
+
+    existing_entry = vnvram_find_entry(vnvram, entry_name);
+    if (existing_entry) {
+        if (existing_entry->max_size != max_size) {
+            qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                         "VNVRAM entry already registered with different size");
+            return -EINVAL;
+        }
+        /* Entry already exists with same max size - success */
+        return 0;
+    }
+
+    new_entry = g_new0(VNVRAMEntry, 1);
+
+    pstrcpy(new_entry->name, sizeof(new_entry->name), (char *)entry_name);
+    new_entry->blob_offset = blob_offset;
+    new_entry->cur_size = cur_size;
+    new_entry->max_size = max_size;
+
+    QLIST_INSERT_HEAD(&vnvram->entries_head, new_entry, next);
+
+    DPRINTF("%s: VNVRAM entry '%s' registered with max_size=%"PRIu32"\n",
+            __func__, new_entry->name, new_entry->max_size);
+
+    return rc;
+}
+
+/*
+ * Find the in-memory VNVRAM entry with the specified name
+ */
+static VNVRAMEntry *vnvram_find_entry(VNVRAM *vnvram,
+                                      const VNVRAMEntryName *entry_name)
+{
+    VNVRAMEntry *entry;
+
+    QLIST_FOREACH(entry, &vnvram->entries_head, next) {
+        if (!strncmp(entry->name, (char *)entry_name, sizeof(*entry_name))) {
+            return entry;
+        }
+    }
+
+    return NULL;
+}
-- 
1.7.1

  parent reply	other threads:[~2013-05-23 17:45 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-23 17:44 [Qemu-devel] [PATCH 0/7] VNVRAM persistent storage Corey Bryant
2013-05-23 17:44 ` [Qemu-devel] [PATCH 1/7] vnvram: VNVRAM bdrv support Corey Bryant
2013-05-24 13:06   ` Kevin Wolf
2013-05-24 15:33     ` Corey Bryant
2013-05-24 15:37       ` Kevin Wolf
2013-05-24 15:47         ` Corey Bryant
2013-05-23 17:44 ` Corey Bryant [this message]
2013-05-23 17:44 ` [Qemu-devel] [PATCH 3/7] vnvram: VNVRAM bottom-half r/w scheduling support Corey Bryant
2013-05-23 17:44 ` [Qemu-devel] [PATCH 4/7] vnvram: VNVRAM internal APIs Corey Bryant
2013-05-23 17:44 ` [Qemu-devel] [PATCH 5/7] vnvram: VNVRAM additional debug support Corey Bryant
2013-05-23 17:44 ` [Qemu-devel] [PATCH 6/7] main: Initialize VNVRAM Corey Bryant
2013-05-23 17:44 ` [Qemu-devel] [PATCH 7/7] monitor: QMP/HMP support for retrieving VNVRAM details Corey Bryant
2013-05-23 17:59   ` Eric Blake
2013-05-23 18:43     ` Corey Bryant
2013-05-29 17:15   ` Luiz Capitulino
2013-05-29 17:34     ` Corey Bryant
2013-05-23 18:03 ` [Qemu-devel] [PATCH 0/7] VNVRAM persistent storage Anthony Liguori
2013-05-23 18:41   ` Corey Bryant
2013-05-23 19:15     ` Anthony Liguori
2013-05-24 15:27       ` Corey Bryant
2013-05-29 13:34         ` Anthony Liguori
2013-05-24  9:59 ` Stefan Hajnoczi
2013-05-24 12:13   ` Stefan Berger
2013-05-24 12:36     ` Stefan Hajnoczi
2013-05-24 15:39       ` Corey Bryant
2013-05-27  8:40         ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1369331087-22345-3-git-send-email-coreyb@linux.vnet.ibm.com \
    --to=coreyb@linux.vnet.ibm.com \
    --cc=aliguori@us.ibm.com \
    --cc=jschopp@linux.vnet.ibm.com \
    --cc=kwolf@redhat.com \
    --cc=lcapitulino@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanb@linux.vnet.ibm.com \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).