[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 04/12] xenstore: add per-node generation counter



In order to be able to support reading the list of a node's children in
multiple chunks (needed for list sizes > 4096 bytes) without having to
allocate a temporary buffer we need some kind of generation counter for
each node. This will help to recognize a node has changed between
reading two chunks.

As removing a node and reintroducing it must result in different
generation counts each generation value has to be globally unique. This
can be ensured only by using a global 64 bit counter.

For handling of transactions there is already such a counter available,
it just has to be expanded to 64 bits and must be stored in each
modified node.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
 tools/xenstore/include/xenstore_lib.h  |  1 +
 tools/xenstore/xenstored_core.c        |  2 ++
 tools/xenstore/xenstored_core.h        |  3 +++
 tools/xenstore/xenstored_transaction.c | 15 ++++++++++-----
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/tools/xenstore/include/xenstore_lib.h 
b/tools/xenstore/include/xenstore_lib.h
index efdf935..0ffbae9 100644
--- a/tools/xenstore/include/xenstore_lib.h
+++ b/tools/xenstore/include/xenstore_lib.h
@@ -44,6 +44,7 @@ struct xs_permissions
 
 /* Header of the node record in tdb. */
 struct xs_tdb_record_hdr {
+       uint64_t generation;
        uint32_t num_perms;
        uint32_t datalen;
        uint32_t childlen;
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index dfad0d5..95d6d7d 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -442,6 +442,7 @@ static struct node *read_node(struct connection *conn, 
const void *ctx,
 
        /* Datalen, childlen, number of permissions */
        hdr = (void *)data.dptr;
+       node->generation = hdr->generation;
        node->num_perms = hdr->num_perms;
        node->datalen = hdr->datalen;
        node->childlen = hdr->childlen;
@@ -481,6 +482,7 @@ static bool write_node(struct connection *conn, struct node 
*node)
 
        data.dptr = talloc_size(node, data.dsize);
        hdr = (void *)data.dptr;
+       hdr->generation = node->generation;
        hdr->num_perms = node->num_perms;
        hdr->datalen = node->datalen;
        hdr->childlen = node->childlen;
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index ecc614f..089625f 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -109,6 +109,9 @@ struct node {
        /* Parent (optional) */
        struct node *parent;
 
+       /* Generation count. */
+       uint64_t generation;
+
        /* Permissions. */
        unsigned int num_perms;
        struct xs_permissions *perms;
diff --git a/tools/xenstore/xenstored_transaction.c 
b/tools/xenstore/xenstored_transaction.c
index b08b2eb..6c65dc5 100644
--- a/tools/xenstore/xenstored_transaction.c
+++ b/tools/xenstore/xenstored_transaction.c
@@ -68,7 +68,10 @@ struct transaction
        uint32_t id;
 
        /* Generation when transaction started. */
-       unsigned int generation;
+       uint64_t generation;
+
+       /* Transaction internal generation. */
+       uint64_t trans_gen;
 
        /* TDB to work on, and filename */
        TDB_CONTEXT *tdb;
@@ -82,7 +85,7 @@ struct transaction
 };
 
 extern int quota_max_transaction;
-static unsigned int generation;
+static uint64_t generation;
 
 /* Return tdb context to use for this connection. */
 TDB_CONTEXT *tdb_transaction_context(struct transaction *trans)
@@ -99,12 +102,14 @@ void add_change_node(struct connection *conn, struct node 
*node, bool recurse)
 
        if (!conn || !conn->transaction) {
                /* They're changing the global database. */
-               generation++;
+               node->generation = generation++;
                return;
        }
 
        trans = conn->transaction;
 
+       node->generation = generation + trans->trans_gen++;
+
        list_for_each_entry(i, &trans->changes, list) {
                if (streq(i->node, node->name)) {
                        if (recurse)
@@ -161,7 +166,7 @@ void do_transaction_start(struct connection *conn, struct 
buffered_data *in)
        }
 
        /* Attach transaction to input for autofree until it's complete */
-       trans = talloc(in, struct transaction);
+       trans = talloc_zero(in, struct transaction);
        INIT_LIST_HEAD(&trans->changes);
        INIT_LIST_HEAD(&trans->changed_domains);
        trans->generation = generation;
@@ -235,7 +240,7 @@ void do_transaction_end(struct connection *conn, struct 
buffered_data *in)
                /* Fire off the watches for everything that changed. */
                list_for_each_entry(i, &trans->changes, list)
                        fire_watches(conn, in, i->node, i->recurse);
-               generation++;
+               generation += trans->trans_gen;
        }
        send_ack(conn, XS_TRANSACTION_END);
 }
-- 
2.6.6


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.