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

[PATCH v3 21/25] tools/xenstore: introduce read_node_nocopy()



Introduce a read_node() variant returning a pointer to const struct
node, which doesn't do a copy of the node data after retrieval from
the data base.

Call this variant where appropriate.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
V3:
- new approach (Julien Grall)
---
 tools/xenstore/xenstored_core.c   | 104 ++++++++++++++++++++++--------
 tools/xenstore/xenstored_core.h   |   2 +
 tools/xenstore/xenstored_domain.c |   4 +-
 tools/xenstore/xenstored_watch.c  |  10 +--
 tools/xenstore/xenstored_watch.h  |   3 +-
 5 files changed, 89 insertions(+), 34 deletions(-)

diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index ea3d20a372..102be92a43 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -705,11 +705,11 @@ void db_delete(struct connection *conn, const char *name,
  * If it fails, returns NULL and sets errno.
  * Temporary memory allocations will be done with ctx.
  */
-struct node *read_node(struct connection *conn, const void *ctx,
-                      const char *name)
+static struct node *read_node_alloc(struct connection *conn, const void *ctx,
+                                   const char *name,
+                                   const struct node_hdr **hdr)
 {
        size_t size;
-       const struct node_hdr *hdr;
        struct node *node;
        const char *db_name;
        int err;
@@ -719,17 +719,16 @@ struct node *read_node(struct connection *conn, const 
void *ctx,
                errno = ENOMEM;
                return NULL;
        }
+
        node->name = talloc_strdup(node, name);
        if (!node->name) {
-               talloc_free(node);
                errno = ENOMEM;
-               return NULL;
+               goto error;
        }
 
        db_name = transaction_prepend(conn, name);
-       hdr = db_fetch(db_name, &size);
-
-       if (hdr == NULL) {
+       *hdr = db_fetch(db_name, &size);
+       if (*hdr == NULL) {
                node->hdr.generation = NO_GENERATION;
                err = access_node(conn, node, NODE_ACCESS_READ, NULL);
                errno = err ? : ENOENT;
@@ -739,31 +738,79 @@ struct node *read_node(struct connection *conn, const 
void *ctx,
        node->parent = NULL;
 
        /* Datalen, childlen, number of permissions */
-       node->hdr = *hdr;
-       node->acc.domid = perms_from_node_hdr(hdr)->id;
+       node->hdr = **hdr;
+       node->acc.domid = perms_from_node_hdr(*hdr)->id;
        node->acc.memory = size;
 
-       /* Copy node data to new memory area, starting with permissions. */
-       size -= sizeof(*hdr);
-       node->perms = talloc_memdup(node, perms_from_node_hdr(hdr), size);
-       if (node->perms == NULL) {
-               errno = ENOMEM;
-               goto error;
-       }
+       return node;
 
+ error:
+       talloc_free(node);
+       return NULL;
+}
+
+static int read_node_helper(struct connection *conn, struct node *node)
+{
        /* Data is binary blob (usually ascii, no nul). */
-       node->data = node->perms + hdr->num_perms;
+       node->data = node->perms + node->hdr.num_perms;
        /* Children is strings, nul separated. */
        node->children = node->data + node->hdr.datalen;
 
        if (domain_adjust_node_perms(node))
-               goto error;
+               return -1;
 
        /* If owner is gone reset currently accounted memory size. */
        if (node->acc.domid != get_node_owner(node))
                node->acc.memory = 0;
 
        if (access_node(conn, node, NODE_ACCESS_READ, NULL))
+               return -1;
+
+       return 0;
+}
+
+struct node *read_node(struct connection *conn, const void *ctx,
+                      const char *name)
+{
+       size_t size;
+       const struct node_hdr *hdr;
+       struct node *node;
+
+       node = read_node_alloc(conn, ctx, name, &hdr);
+       if (!node)
+               return NULL;
+
+       /* Copy node data to new memory area, starting with permissions. */
+       size = node->acc.memory - sizeof(*hdr);
+       node->perms = talloc_memdup(node, perms_from_node_hdr(hdr), size);
+       if (node->perms == NULL) {
+               errno = ENOMEM;
+               goto error;
+       }
+
+       if (read_node_helper(conn, node))
+               goto error;
+
+       return node;
+
+ error:
+       talloc_free(node);
+       return NULL;
+}
+
+const struct node *read_node_const(struct connection *conn, const void *ctx,
+                                  const char *name)
+{
+       const struct node_hdr *hdr;
+       struct node *node;
+
+       node = read_node_alloc(conn, ctx, name, &hdr);
+       if (!node)
+               return NULL;
+
+       node->perms = perms_from_node_hdr(hdr);
+
+       if (read_node_helper(conn, node))
                goto error;
 
        return node;
@@ -896,14 +943,14 @@ char *get_parent(const void *ctx, const char *node)
 static int ask_parents(struct connection *conn, const void *ctx,
                       const char *name, unsigned int *perm)
 {
-       struct node *node;
+       const struct node *node;
        struct node_perms perms;
 
        do {
                name = get_parent(ctx, name);
                if (!name)
                        return errno;
-               node = read_node(conn, ctx, name);
+               node = read_node_const(conn, ctx, name);
                if (node)
                        break;
                if (read_node_can_propagate_errno())
@@ -3194,9 +3241,8 @@ static int dump_state_node_err(struct dump_node_data 
*data, const char *err)
 }
 
 static int dump_state_node(const void *ctx, struct connection *conn,
-                          struct node *node, void *arg)
+                          const struct node *node, struct dump_node_data *data)
 {
-       struct dump_node_data *data = arg;
        FILE *fp = data->fp;
        unsigned int pathlen;
        struct xs_state_record_header head;
@@ -3241,14 +3287,20 @@ static int dump_state_node(const void *ctx, struct 
connection *conn,
        return WALK_TREE_OK;
 }
 
+static int dump_state_node_enter(const void *ctx, struct connection *conn,
+                                struct node *node, void *arg)
+{
+       return dump_state_node(ctx, conn, node, arg);
+}
+
 static int dump_state_special_node(FILE *fp, const void *ctx,
                                   struct dump_node_data *data,
                                   const char *name)
 {
-       struct node *node;
+       const struct node *node;
        int ret;
 
-       node = read_node(NULL, ctx, name);
+       node = read_node_const(NULL, ctx, name);
        if (!node)
                return dump_state_node_err(data, "Dump node read node error");
 
@@ -3264,7 +3316,7 @@ const char *dump_state_nodes(FILE *fp, const void *ctx)
                .fp = fp,
                .err = "Dump node walk error"
        };
-       struct walk_funcs walkfuncs = { .enter = dump_state_node };
+       struct walk_funcs walkfuncs = { .enter = dump_state_node_enter };
 
        if (walk_node_tree(ctx, NULL, "/", &walkfuncs, &data))
                return data.err;
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index adf8a785fc..65782c559d 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -282,6 +282,8 @@ int write_node_raw(struct connection *conn, const char 
*db_name,
 /* Get a node from the data base. */
 struct node *read_node(struct connection *conn, const void *ctx,
                       const char *name);
+const struct node *read_node_const(struct connection *conn, const void *ctx,
+                                  const char *name);
 
 /* Remove a node and its children. */
 int rm_node(struct connection *conn, const void *ctx, const char *name);
diff --git a/tools/xenstore/xenstored_domain.c 
b/tools/xenstore/xenstored_domain.c
index cdef6efef4..7290bbc848 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -563,12 +563,12 @@ static void domain_tree_remove(struct domain *domain)
 static void fire_special_watches(const char *name)
 {
        void *ctx = talloc_new(NULL);
-       struct node *node;
+       const struct node *node;
 
        if (!ctx)
                return;
 
-       node = read_node(NULL, ctx, name);
+       node = read_node_const(NULL, ctx, name);
 
        if (node)
                fire_watches(NULL, ctx, name, node, true, NULL);
diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c
index c161385f89..86cf8322b4 100644
--- a/tools/xenstore/xenstored_watch.c
+++ b/tools/xenstore/xenstored_watch.c
@@ -73,11 +73,11 @@ static const char *get_watch_path(const struct watch 
*watch, const char *name)
  * changed permissions we need to take the old permissions into account, too.
  */
 static bool watch_permitted(struct connection *conn, const void *ctx,
-                           const char *name, struct node *node,
+                           const char *name, const struct node *node,
                            struct node_perms *perms)
 {
        unsigned int perm;
-       struct node *parent;
+       const struct node *parent;
        char *parent_name;
        struct node_perms node_perms;
 
@@ -88,7 +88,7 @@ static bool watch_permitted(struct connection *conn, const 
void *ctx,
        }
 
        if (!node) {
-               node = read_node(conn, ctx, name);
+               node = read_node_const(conn, ctx, name);
                if (!node)
                        return false;
        }
@@ -103,7 +103,7 @@ static bool watch_permitted(struct connection *conn, const 
void *ctx,
                parent_name = get_parent(ctx, node->name);
                if (!parent_name)
                        return false;
-               parent = read_node(conn, ctx, parent_name);
+               parent = read_node_const(conn, ctx, parent_name);
                if (!parent)
                        return false;
        }
@@ -122,7 +122,7 @@ static bool watch_permitted(struct connection *conn, const 
void *ctx,
  * watch event, too.
  */
 void fire_watches(struct connection *conn, const void *ctx, const char *name,
-                 struct node *node, bool exact, struct node_perms *perms)
+                 const struct node *node, bool exact, struct node_perms *perms)
 {
        struct connection *i;
        struct buffered_data *req;
diff --git a/tools/xenstore/xenstored_watch.h b/tools/xenstore/xenstored_watch.h
index 091890edca..ea247997ad 100644
--- a/tools/xenstore/xenstored_watch.h
+++ b/tools/xenstore/xenstored_watch.h
@@ -28,7 +28,8 @@ int do_unwatch(const void *ctx, struct connection *conn,
 
 /* Fire all watches: !exact means all the children are affected (ie. rm). */
 void fire_watches(struct connection *conn, const void *tmp, const char *name,
-                 struct node *node, bool exact, struct node_perms *perms);
+                 const struct node *node, bool exact,
+                 struct node_perms *perms);
 
 void conn_delete_all_watches(struct connection *conn);
 
-- 
2.35.3




 


Rackspace

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