|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 18/18] tools/xenstore: add nocopy flag to node read functions
Today when reading a node from the data base through read_node(), the
node data is copied in order to avoid modifying the data base when
preparing a node update, as otherwise an error might result in an
inconsistent state.
There are, however, many cases where such a copy operation isn't
needed, as the node isn't modified.
Add a "nocopy" flag to read_node() and get_node*() functions for making
those cases less memory consuming and more performant.
Note that there is one modification of the node data left, which is not
problematic: domain_adjust_node_perms() might set the "ignore" flag of
a permission. This does no harm, as such an update of the permissions
doesn't need to be undone in case of a later processing error.
Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
V2:
- new patch
---
tools/xenstore/xenstored_core.c | 68 +++++++++++++++++--------------
tools/xenstore/xenstored_core.h | 2 +-
tools/xenstore/xenstored_domain.c | 2 +-
tools/xenstore/xenstored_watch.c | 4 +-
4 files changed, 41 insertions(+), 35 deletions(-)
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 7495747d76..8041a6a1c6 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -706,7 +706,7 @@ void db_delete(struct connection *conn, const char *name,
* Temporary memory allocations will be done with ctx.
*/
struct node *read_node(struct connection *conn, const void *ctx,
- const char *name)
+ const char *name, bool nocopy)
{
size_t size;
struct node_hdr *hdr;
@@ -743,14 +743,18 @@ struct node *read_node(struct connection *conn, const
void *ctx,
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_size(node, size);
- if (node->perms == NULL) {
- errno = ENOMEM;
- goto error;
+ if (nocopy) {
+ node->perms = (struct xs_permissions *)(hdr + 1);
+ } else {
+ /* Copy node data to new area, starting with permissions. */
+ size -= sizeof(*hdr);
+ node->perms = talloc_size(node, size);
+ if (node->perms == NULL) {
+ errno = ENOMEM;
+ goto error;
+ }
+ memcpy(node->perms, perms_from_node_hdr(hdr), size);
}
- memcpy(node->perms, perms_from_node_hdr(hdr), size);
/* Permissions are struct xs_permissions. */
if (domain_adjust_node_perms(node))
@@ -905,7 +909,7 @@ static int ask_parents(struct connection *conn, const void
*ctx,
name = get_parent(ctx, name);
if (!name)
return errno;
- node = read_node(conn, ctx, name);
+ node = read_node(conn, ctx, name, true);
if (node)
break;
if (read_node_can_propagate_errno())
@@ -954,12 +958,12 @@ static int errno_from_parents(struct connection *conn,
const void *ctx,
static struct node *get_node(struct connection *conn,
const void *ctx,
const char *name,
- unsigned int perm)
+ unsigned int perm, bool nocopy)
{
struct node *node;
struct node_perms perms;
- node = read_node(conn, ctx, name);
+ node = read_node(conn, ctx, name, nocopy);
/* If we don't have permission, we don't have node. */
if (node) {
node_to_node_perms(node, &perms);
@@ -1248,7 +1252,7 @@ static struct node *get_node_canonicalized(struct
connection *conn,
const void *ctx,
const char *name,
char **canonical_name,
- unsigned int perm)
+ unsigned int perm, bool nocopy)
{
char *tmp_name;
@@ -1261,17 +1265,18 @@ static struct node *get_node_canonicalized(struct
connection *conn,
errno = EINVAL;
return NULL;
}
- return get_node(conn, ctx, *canonical_name, perm);
+ return get_node(conn, ctx, *canonical_name, perm, nocopy);
}
static struct node *get_spec_node(struct connection *conn, const void *ctx,
const char *name, char **canonical_name,
- unsigned int perm)
+ unsigned int perm, bool nocopy)
{
if (name[0] == '@')
- return get_node(conn, ctx, name, perm);
+ return get_node(conn, ctx, name, perm, nocopy);
- return get_node_canonicalized(conn, ctx, name, canonical_name, perm);
+ return get_node_canonicalized(conn, ctx, name, canonical_name, perm,
+ nocopy);
}
static int send_directory(const void *ctx, struct connection *conn,
@@ -1280,7 +1285,7 @@ static int send_directory(const void *ctx, struct
connection *conn,
struct node *node;
node = get_node_canonicalized(conn, ctx, onearg(in), NULL,
- XS_PERM_READ);
+ XS_PERM_READ, true);
if (!node)
return errno;
@@ -1302,7 +1307,7 @@ static int send_directory_part(const void *ctx, struct
connection *conn,
/* First arg is node name. */
node = get_node_canonicalized(conn, ctx, in->buffer, NULL,
- XS_PERM_READ);
+ XS_PERM_READ, true);
if (!node)
return errno;
@@ -1352,7 +1357,7 @@ static int do_read(const void *ctx, struct connection
*conn,
struct node *node;
node = get_node_canonicalized(conn, ctx, onearg(in), NULL,
- XS_PERM_READ);
+ XS_PERM_READ, true);
if (!node)
return errno;
@@ -1414,7 +1419,7 @@ static struct node *construct_node(struct connection
*conn, const void *ctx,
return NULL;
/* Try to read parent node until we found an existing one. */
- parent = read_node(conn, ctx, parentname);
+ parent = read_node(conn, ctx, parentname, false);
if (!parent && (errno != ENOENT || !strcmp(parentname, "/")))
return NULL;
@@ -1566,7 +1571,8 @@ static int do_write(const void *ctx, struct connection
*conn,
offset = strlen(vec[0]) + 1;
datalen = in->used - offset;
- node = get_node_canonicalized(conn, ctx, vec[0], &name, XS_PERM_WRITE);
+ node = get_node_canonicalized(conn, ctx, vec[0], &name, XS_PERM_WRITE,
+ false);
if (!node) {
/* No permissions, invalid input? */
if (errno != ENOENT)
@@ -1595,7 +1601,7 @@ static int do_mkdir(const void *ctx, struct connection
*conn,
char *name;
node = get_node_canonicalized(conn, ctx, onearg(in), &name,
- XS_PERM_WRITE);
+ XS_PERM_WRITE, false);
/* If it already exists, fine. */
if (!node) {
@@ -1689,7 +1695,7 @@ int rm_node(struct connection *conn, const void *ctx,
const char *name)
if (!parentname)
return errno;
- parent = read_node(conn, ctx, parentname);
+ parent = read_node(conn, ctx, parentname, false);
if (!parent)
return read_node_can_propagate_errno() ? errno : EINVAL;
@@ -1725,7 +1731,7 @@ static int do_rm(const void *ctx, struct connection *conn,
char *parentname;
node = get_node_canonicalized(conn, ctx, onearg(in), &name,
- XS_PERM_WRITE);
+ XS_PERM_WRITE, false);
if (!node) {
/* Didn't exist already? Fine, if parent exists. */
if (errno == ENOENT) {
@@ -1734,7 +1740,7 @@ static int do_rm(const void *ctx, struct connection *conn,
parentname = get_parent(ctx, name);
if (!parentname)
return errno;
- node = read_node(conn, ctx, parentname);
+ node = read_node(conn, ctx, parentname, false);
if (node) {
send_ack(conn, XS_RM);
return 0;
@@ -1767,7 +1773,7 @@ static int do_get_perms(const void *ctx, struct
connection *conn,
unsigned int len;
struct node_perms perms;
- node = get_spec_node(conn, ctx, onearg(in), NULL, XS_PERM_READ);
+ node = get_spec_node(conn, ctx, onearg(in), NULL, XS_PERM_READ, true);
if (!node)
return errno;
@@ -1811,7 +1817,7 @@ static int do_set_perms(const void *ctx, struct
connection *conn,
/* We must own node to do this (tools can do this too). */
node = get_spec_node(conn, ctx, in->buffer, &name,
- XS_PERM_WRITE | XS_PERM_OWNER);
+ XS_PERM_WRITE | XS_PERM_OWNER, false);
if (!node)
return errno;
@@ -1933,7 +1939,7 @@ int walk_node_tree(const void *ctx, struct connection
*conn, const char *root,
parent = node;
}
/* Read next node (root node or next child). */
- node = read_node(conn, tmpctx, name);
+ node = read_node(conn, tmpctx, name, false);
if (!node) {
/* Child not found - should not happen! */
/* ENOENT case can be handled by supplied function. */
@@ -2483,7 +2489,7 @@ int check_store_path(const char *name, struct
check_store_data *data)
{
struct node *node;
- node = read_node(NULL, NULL, name);
+ node = read_node(NULL, NULL, name, false);
if (!node) {
log("check_store: error %d reading special node '%s'", errno,
name);
@@ -3245,7 +3251,7 @@ static int dump_state_special_node(FILE *fp, const void
*ctx,
struct node *node;
int ret;
- node = read_node(NULL, ctx, name);
+ node = read_node(NULL, ctx, name, true);
if (!node)
return dump_state_node_err(data, "Dump node read node error");
@@ -3447,7 +3453,7 @@ void read_state_node(const void *ctx, const void *state)
parentname = get_parent(node, name);
if (!parentname)
barf("allocation error restoring node");
- parent = read_node(NULL, node, parentname);
+ parent = read_node(NULL, node, parentname, false);
if (!parent)
barf("read parent error restoring node");
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index 79b2a699fd..a4cd3e503a 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -280,7 +280,7 @@ 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 char *name, bool nocopy);
/* 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 4d66dc91ce..b8fd7469d0 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -568,7 +568,7 @@ static void fire_special_watches(const char *name)
if (!ctx)
return;
- node = read_node(NULL, ctx, name);
+ node = read_node(NULL, ctx, name, true);
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 10645f762d..54a9468090 100644
--- a/tools/xenstore/xenstored_watch.c
+++ b/tools/xenstore/xenstored_watch.c
@@ -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(conn, ctx, name, true);
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(conn, ctx, parent_name, true);
if (!parent)
return false;
}
--
2.35.3
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |