]> xenbits.xensource.com Git - xen.git/commitdiff
tools/xenstore: add read node state for live update
authorJuergen Gross <jgross@suse.com>
Wed, 13 Jan 2021 13:00:20 +0000 (14:00 +0100)
committerJuergen Gross <jgross@suse.com>
Thu, 21 Jan 2021 16:31:49 +0000 (17:31 +0100)
Add the needed functions for reading node state for live update.

This requires some refactoring of current node handling in Xenstore in
order to avoid repeating the same code patterns multiple times.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Paul Durrant <paul@xen.org>
Acked-by: Julien Grall <jgrall@amazon.com>
Acked-by: Wei Liu <wl@xen.org>
tools/xenstore/xenstored_control.c
tools/xenstore/xenstored_core.c
tools/xenstore/xenstored_core.h

index 7428b836a5f3b18dbcc8f2101f0a33e3ac072b25..287417de6bacd4f6ff880118fd1d3922f69e7885 100644 (file)
@@ -547,6 +547,7 @@ void lu_read_state(void)
                        xprintf("live-update: ignore transaction record\n");
                        break;
                case XS_STATE_TYPE_NODE:
+                       read_state_node(ctx, head + 1);
                        break;
                default:
                        xprintf("live-update: unknown state record %08x\n",
index b2c544b165a34ea06027cf6a7bfdab0c3bff0190..a5c1a56c6c02e92a690d187ef5b0765f2a655245 100644 (file)
@@ -979,13 +979,30 @@ static char *basename(const char *name)
        return strrchr(name, '/') + 1;
 }
 
-static struct node *construct_node(struct connection *conn, const void *ctx,
-                                  const char *name)
+static int add_child(const void *ctx, struct node *parent, const char *name)
 {
        const char *base;
        unsigned int baselen;
+       char *children;
+
+       base = basename(name);
+       baselen = strlen(base) + 1;
+       children = talloc_array(ctx, char, parent->childlen + baselen);
+       if (!children)
+               return ENOMEM;
+       memcpy(children, parent->children, parent->childlen);
+       memcpy(children + parent->childlen, base, baselen);
+       parent->children = children;
+       parent->childlen += baselen;
+
+       return 0;
+}
+
+static struct node *construct_node(struct connection *conn, const void *ctx,
+                                  const char *name)
+{
        struct node *parent, *node;
-       char *children, *parentname = get_parent(ctx, name);
+       char *parentname = get_parent(ctx, name);
 
        if (!parentname)
                return NULL;
@@ -998,15 +1015,8 @@ static struct node *construct_node(struct connection *conn, const void *ctx,
                return NULL;
 
        /* Add child to parent. */
-       base = basename(name);
-       baselen = strlen(base) + 1;
-       children = talloc_array(ctx, char, parent->childlen + baselen);
-       if (!children)
+       if (add_child(ctx, parent, name))
                goto nomem;
-       memcpy(children, parent->children, parent->childlen);
-       memcpy(children + parent->childlen, base, baselen);
-       parent->children = children;
-       parent->childlen += baselen;
 
        /* Allocate node */
        node = talloc(ctx, struct node);
@@ -2619,6 +2629,79 @@ void read_state_buffered_data(const void *ctx, struct connection *conn,
        }
 }
 
+void read_state_node(const void *ctx, const void *state)
+{
+       const struct xs_state_node *sn = state;
+       struct node *node, *parent;
+       TDB_DATA key;
+       char *name, *parentname;
+       unsigned int i;
+       struct connection conn = { .id = priv_domid };
+
+       name = (char *)(sn->perms + sn->perm_n);
+       node = talloc(ctx, struct node);
+       if (!node)
+               barf("allocation error restoring node");
+
+       node->name = name;
+       node->generation = ++generation;
+       node->datalen = sn->data_len;
+       node->data = name + sn->path_len;
+       node->childlen = 0;
+       node->children = NULL;
+       node->perms.num = sn->perm_n;
+       node->perms.p = talloc_array(node, struct xs_permissions,
+                                    node->perms.num);
+       if (!node->perms.p)
+               barf("allocation error restoring node");
+       for (i = 0; i < node->perms.num; i++) {
+               switch (sn->perms[i].access) {
+               case 'r':
+                       node->perms.p[i].perms = XS_PERM_READ;
+                       break;
+               case 'w':
+                       node->perms.p[i].perms = XS_PERM_WRITE;
+                       break;
+               case 'b':
+                       node->perms.p[i].perms = XS_PERM_READ | XS_PERM_WRITE;
+                       break;
+               default:
+                       node->perms.p[i].perms = XS_PERM_NONE;
+                       break;
+               }
+               if (sn->perms[i].flags & XS_STATE_NODE_PERM_IGNORE)
+                       node->perms.p[i].perms |= XS_PERM_IGNORE;
+               node->perms.p[i].id = sn->perms[i].domid;
+       }
+
+       if (strstarts(name, "@")) {
+               set_perms_special(&conn, name, &node->perms);
+               talloc_free(node);
+               return;
+       }
+
+       parentname = get_parent(node, name);
+       if (!parentname)
+               barf("allocation error restoring node");
+       parent = read_node(NULL, node, parentname);
+       if (!parent)
+               barf("read parent error restoring node");
+
+       if (add_child(node, parent, name))
+               barf("allocation error restoring node");
+
+       set_tdb_key(parentname, &key);
+       if (write_node_raw(NULL, &key, parent, true))
+               barf("write parent error restoring node");
+
+       set_tdb_key(name, &key);
+       if (write_node_raw(NULL, &key, node, true))
+               barf("write node error restoring node");
+       domain_entry_inc(&conn, node);
+
+       talloc_free(node);
+}
+
 /*
  * Local variables:
  *  mode: C
index dcb3ad3e4b0e04528a4c7d25b8a8a4f92560b5ff..6ac5a6fbfadbef82d74e42ad8fdeeff1ea2524a6 100644 (file)
@@ -276,6 +276,7 @@ const char *dump_state_node_perms(FILE *fp, struct xs_state_node *sn,
 void read_state_global(const void *ctx, const void *state);
 void read_state_buffered_data(const void *ctx, struct connection *conn,
                              const struct xs_state_connection *sc);
+void read_state_node(const void *ctx, const void *state);
 
 #endif /* _XENSTORED_CORE_H */