mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
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>
This commit is contained in:
1 parent
2d41c05017
commit
9e49dcf67f
4 files changed
+16
-5
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||