Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12:Update
xen.10697
xs-18-default-buffer.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xs-18-default-buffer.patch of Package xen.10697
commit cc0612464896e7ecf93dd9a52c4c4348fcf33d0e Author: Juergen Gross <jgross@suse.com> Date: Mon Dec 5 08:48:52 2016 +0100 xenstore: add small default data buffer to internal struct Instead of always allocating a data buffer for incoming or outgoing xenstore wire data add a small buffer to the buffered_data structure of xenstored. This has the advantage that especially sending simple response messages like errors or "OK" will no longer need allocating a data buffer. This requires adding a memory context where the allocated buffer was used for that purpose. In order to avoid allocating a new buffered_data structure for each response reuse the structure of the original request. This in turn will avoid any new memory allocations for sending e.g. an ENOMEM response making it possible to send it at all. To do this the allocation of the buffered_data structure for the incoming request must be done when a new request is recognized instead of doing it when accepting a new connect. Signed-off-by: Juergen Gross <jgross@suse.com> Acked-by: Wei Liu <wei.liu2@citrix.com> --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -642,17 +642,20 @@ void send_reply(struct connection *conn, return; } - /* Message is a child of the connection context for auto-cleanup. */ - bdata = new_buffer(conn); - bdata->buffer = talloc_array(bdata, char, len); - - /* Echo request header in reply unless this is an async watch event. */ + /* Replies reuse the request buffer, events need a new one. */ if (type != XS_WATCH_EVENT) { - memcpy(&bdata->hdr.msg, &conn->in->hdr.msg, - sizeof(struct xsd_sockmsg)); + bdata = conn->in; + bdata->inhdr = true; + bdata->used = 0; + conn->in = NULL; } else { - memset(&bdata->hdr.msg, 0, sizeof(struct xsd_sockmsg)); + /* Message is a child of the connection for auto-cleanup. */ + bdata = new_buffer(conn); } + if (len <= DEFAULT_BUFFER_SIZE) + bdata->buffer = bdata->default_buffer; + else + bdata->buffer = talloc_array(bdata, char, len); /* Update relevant header fields and fill in the message body. */ bdata->hdr.msg.type = type; @@ -728,7 +731,7 @@ static char *perms_to_strings(const void return strings; } -char *canonicalize(struct connection *conn, const char *node) +char *canonicalize(struct connection *conn, const void *ctx, const char *node) { const char *prefix; @@ -736,7 +739,7 @@ char *canonicalize(struct connection *co return (char *)node; prefix = get_implicit_path(conn); if (prefix) - return talloc_asprintf(node, "%s/%s", prefix, node); + return talloc_asprintf(ctx, "%s/%s", prefix, node); return (char *)node; } @@ -750,7 +753,7 @@ static struct node *get_node_canonicaliz if (!canonical_name) canonical_name = &tmp_name; - *canonical_name = canonicalize(conn, name); + *canonical_name = canonicalize(conn, ctx, name); return get_node(conn, ctx, *canonical_name, perm); } @@ -860,17 +863,18 @@ static char *basename(const char *name) return strrchr(name, '/') + 1; } -static struct node *construct_node(struct connection *conn, const char *name) +static struct node *construct_node(struct connection *conn, const void *ctx, + const char *name) { const char *base; unsigned int baselen; struct node *parent, *node; - char *children, *parentname = get_parent(name, name); + char *children, *parentname = get_parent(ctx, name); /* If parent doesn't exist, create it. */ parent = read_node(conn, parentname, parentname); if (!parent) - parent = construct_node(conn, parentname); + parent = construct_node(conn, ctx, parentname); if (!parent) return NULL; @@ -880,7 +884,7 @@ static struct node *construct_node(struc /* Add child to parent. */ base = basename(name); baselen = strlen(base) + 1; - children = talloc_array(name, char, parent->childlen + baselen); + children = talloc_array(ctx, char, parent->childlen + baselen); if (!children) goto nomem; memcpy(children, parent->children, parent->childlen); @@ -889,7 +893,7 @@ static struct node *construct_node(struc parent->childlen += baselen; /* Allocate node */ - node = talloc(name, struct node); + node = talloc(ctx, struct node); if (!node) goto nomem; node->tdb = tdb_context(conn); @@ -933,13 +937,13 @@ static int destroy_node(void *_node) return 0; } -static struct node *create_node(struct connection *conn, +static struct node *create_node(struct connection *conn, const void *ctx, const char *name, void *data, unsigned int datalen) { struct node *node, *i; - node = construct_node(conn, name); + node = construct_node(conn, ctx, name); if (!node) return NULL; @@ -982,7 +986,8 @@ static int do_write(struct connection *c /* No permissions, invalid input? */ if (errno != ENOENT) return errno; - node = create_node(conn, name, in->buffer + offset, datalen); + node = create_node(conn, in, name, in->buffer + offset, + datalen); if (!node) return errno; } else { @@ -1012,7 +1017,7 @@ static int do_mkdir(struct connection *c /* No permissions? */ if (errno != ENOENT) return errno; - node = create_node(conn, name, NULL, 0); + node = create_node(conn, in, name, NULL, 0); if (!node) return errno; wrl_apply_debit_direct(conn); @@ -1084,12 +1089,13 @@ static bool delete_child(struct connecti } -static int _rm(struct connection *conn, struct node *node, const char *name) +static int _rm(struct connection *conn, const void *ctx, struct node *node, + const char *name) { /* Delete from parent first, then if we crash, the worst that can happen is the child will continue to take up space, but will otherwise be unreachable. */ - struct node *parent = read_node(conn, name, get_parent(name, name)); + struct node *parent = read_node(conn, ctx, get_parent(ctx, name)); if (!parent) return EINVAL; @@ -1106,7 +1112,7 @@ static void internal_rm(const char *name char *tname = talloc_strdup(NULL, name); struct node *node = read_node(NULL, tname, tname); if (node) - _rm(NULL, node, tname); + _rm(NULL, tname, node, tname); talloc_free(node); talloc_free(tname); } @@ -1137,7 +1143,7 @@ static int do_rm(struct connection *conn if (streq(name, "/")) return EINVAL; - ret = _rm(conn, node, name); + ret = _rm(conn, in, node, name); if (ret) return ret; @@ -1311,8 +1317,7 @@ static void consider_message(struct conn process_message(conn, conn->in); - talloc_free(conn->in); - conn->in = new_buffer(conn); + assert(conn->in == NULL); } /* Errors in reading or allocating here mean we get out of sync, so we @@ -1320,7 +1325,15 @@ static void consider_message(struct conn static void handle_input(struct connection *conn) { int bytes; - struct buffered_data *in = conn->in; + struct buffered_data *in; + + if (!conn->in) { + conn->in = new_buffer(conn); + /* In case of no memory just try it next time again. */ + if (!conn->in) + return; + } + in = conn->in; /* Not finished header yet? */ if (in->inhdr) { @@ -1338,7 +1351,10 @@ static void handle_input(struct connecti goto bad_client; } - in->buffer = talloc_array(in, char, in->hdr.msg.len); + if (in->hdr.msg.len <= DEFAULT_BUFFER_SIZE) + in->buffer = in->default_buffer; + else + in->buffer = talloc_array(in, char, in->hdr.msg.len); if (!in->buffer) goto bad_client; in->used = 0; @@ -1387,12 +1403,6 @@ struct connection *new_connection(connwr INIT_LIST_HEAD(&new->watches); INIT_LIST_HEAD(&new->transaction_list); - new->in = new_buffer(new); - if (new->in == NULL) { - talloc_free(new); - return NULL; - } - list_add_tail(&new->list, &connections); talloc_set_destructor(new, destroy_conn); trace_create(new, "connection"); @@ -1532,7 +1542,7 @@ static void setup_structure(void) if (remove_local) { internal_rm("/local"); - create_node(NULL, tlocal, NULL, 0); + create_node(NULL, NULL, tlocal, NULL, 0); check_store(); } --- a/tools/xenstore/xenstored_core.h +++ b/tools/xenstore/xenstored_core.h @@ -37,6 +37,9 @@ typedef int32_t wrl_creditt; #define WRL_CREDIT_MAX (1000*1000*1000) /* ^ satisfies non-overflow condition for wrl_xfer_credit */ +/* DEFAULT_BUFFER_SIZE should be large enough for each errno string. */ +#define DEFAULT_BUFFER_SIZE 16 + struct buffered_data { struct list_head list; @@ -54,6 +57,7 @@ struct buffered_data /* The actual data. */ char *buffer; + char default_buffer[DEFAULT_BUFFER_SIZE]; }; struct connection; @@ -143,7 +147,7 @@ void send_reply(struct connection *conn, void send_ack(struct connection *conn, enum xsd_sockmsg_type type); /* Canonicalize this path if possible. */ -char *canonicalize(struct connection *conn, const char *node); +char *canonicalize(struct connection *conn, const void *ctx, const char *node); /* Get this node, checking we have permissions. */ struct node *get_node(struct connection *conn, --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -349,9 +349,7 @@ static void domain_conn_reset(struct dom talloc_free(out); } - talloc_free(conn->in->buffer); - memset(conn->in, 0, sizeof(*conn->in)); - conn->in->inhdr = true; + talloc_free(conn->in); domain->interface->req_cons = domain->interface->req_prod = 0; domain->interface->rsp_cons = domain->interface->rsp_prod = 0; --- a/tools/xenstore/xenstored_transaction.c +++ b/tools/xenstore/xenstored_transaction.c @@ -212,8 +212,8 @@ int do_transaction_end(struct connection list_del(&trans->list); conn->transaction_started--; - /* Attach transaction to arg for auto-cleanup */ - talloc_steal(arg, trans); + /* Attach transaction to in for auto-cleanup */ + talloc_steal(in, trans); if (streq(arg, "T")) { wrl_apply_debit_trans_commit(conn); --- a/tools/xenstore/xenstored_watch.c +++ b/tools/xenstore/xenstored_watch.c @@ -165,7 +165,7 @@ int do_watch(struct connection *conn, st /* check if valid event */ } else { relative = !strstarts(vec[0], "/"); - vec[0] = canonicalize(conn, vec[0]); + vec[0] = canonicalize(conn, in, vec[0]); if (!is_valid_nodename(vec[0])) return EINVAL; } @@ -210,7 +210,7 @@ int do_unwatch(struct connection *conn, if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec)) return EINVAL; - node = canonicalize(conn, vec[0]); + node = canonicalize(conn, in, vec[0]); list_for_each_entry(watch, &conn->watches, list) { if (streq(watch->node, node) && streq(watch->token, vec[1])) { list_del(&watch->list);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor