File xs-12-node-gen-count.patch of Package xen.23721
commit 9e49dcf67f4aa3e318e618e51eeb547a117c3805
Author: Juergen Gross <jgross@suse.com>
Date: Mon Dec 5 08:48:45 2016 +0100
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@suse.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Index: xen-4.7.2-testing/tools/xenstore/include/xenstore_lib.h
===================================================================
--- xen-4.7.2-testing.orig/tools/xenstore/include/xenstore_lib.h
+++ xen-4.7.2-testing/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;
Index: xen-4.7.2-testing/tools/xenstore/xenstored_core.c
===================================================================
--- xen-4.7.2-testing.orig/tools/xenstore/xenstored_core.c
+++ xen-4.7.2-testing/tools/xenstore/xenstored_core.c
@@ -447,6 +447,7 @@ static struct node *read_node(struct con
/* 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;
@@ -486,6 +487,7 @@ static bool write_node(struct connection
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;
Index: xen-4.7.2-testing/tools/xenstore/xenstored_core.h
===================================================================
--- xen-4.7.2-testing.orig/tools/xenstore/xenstored_core.h
+++ xen-4.7.2-testing/tools/xenstore/xenstored_core.h
@@ -115,6 +115,9 @@ struct node {
/* Parent (optional) */
struct node *parent;
+ /* Generation count. */
+ uint64_t generation;
+
/* Permissions. */
unsigned int num_perms;
struct xs_permissions *perms;
Index: xen-4.7.2-testing/tools/xenstore/xenstored_transaction.c
===================================================================
--- xen-4.7.2-testing.orig/tools/xenstore/xenstored_transaction.c
+++ xen-4.7.2-testing/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 *
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)
@@ -162,7 +167,7 @@ void do_transaction_start(struct connect
}
/* 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;
@@ -240,7 +245,7 @@ void do_transaction_end(struct connectio
/* 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);
}