[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v11 23/27] tools/xenstore: add read connection state for live update
Add the needed functions for reading connection state for live update. As the connection is identified by a unique connection id in the state records we need to add this to struct connection. Add a new function to return the connection based on a connection id. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> Reviewed-by: Julien Grall <jgrall@xxxxxxxxxx> --- V2: - fixed condition in introduce_domain() (Julien Grall) V4: - set pending data msg type to XS_INVALID (Julien Grall) - add buffered read data (Julien Grall) V5: - really read buffered read data (Julien Grall) - drop conn parameter from introduce_domain() (Paul Durrant) - split pending write data into individual buffers V6: - rename "first" to "partial" (Paul Durrant) V7: - use local port from connection data V8: - remove dom0 special handling --- tools/xenstore/xenstored_control.c | 1 + tools/xenstore/xenstored_core.c | 102 ++++++++++++++++++++++++++++- tools/xenstore/xenstored_core.h | 10 +++ tools/xenstore/xenstored_domain.c | 60 +++++++++++++---- tools/xenstore/xenstored_domain.h | 2 + 5 files changed, 162 insertions(+), 13 deletions(-) diff --git a/tools/xenstore/xenstored_control.c b/tools/xenstore/xenstored_control.c index 497e1f2a63..d6454d4e77 100644 --- a/tools/xenstore/xenstored_control.c +++ b/tools/xenstore/xenstored_control.c @@ -539,6 +539,7 @@ void lu_read_state(void) read_state_global(ctx, head + 1); break; case XS_STATE_TYPE_CONN: + read_state_connection(ctx, head + 1); break; case XS_STATE_TYPE_WATCH: break; diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 71c0f8617b..4175b871ee 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -1575,12 +1575,35 @@ struct connection *new_connection(connwritefn_t *write, connreadfn_t *read) return new; } +struct connection *get_connection_by_id(unsigned int conn_id) +{ + struct connection *conn; + + list_for_each_entry(conn, &connections, list) + if (conn->conn_id == conn_id) + return conn; + + return NULL; +} + #ifdef NO_SOCKETS static void accept_connection(int sock) { } + +int writefd(struct connection *conn, const void *data, unsigned int len) +{ + errno = EBADF; + return -1; +} + +int readfd(struct connection *conn, void *data, unsigned int len) +{ + errno = EBADF; + return -1; +} #else -static int writefd(struct connection *conn, const void *data, unsigned int len) +int writefd(struct connection *conn, const void *data, unsigned int len) { int rc; @@ -1596,7 +1619,7 @@ static int writefd(struct connection *conn, const void *data, unsigned int len) return rc; } -static int readfd(struct connection *conn, void *data, unsigned int len) +int readfd(struct connection *conn, void *data, unsigned int len) { int rc; @@ -2514,6 +2537,81 @@ void read_state_global(const void *ctx, const void *state) domain_init(glb->evtchn_fd); } +static void add_buffered_data(struct buffered_data *bdata, + struct connection *conn, const uint8_t *data, + unsigned int len) +{ + bdata->hdr.msg.len = len; + if (len <= DEFAULT_BUFFER_SIZE) + bdata->buffer = bdata->default_buffer; + else + bdata->buffer = talloc_array(bdata, char, len); + if (!bdata->buffer) + barf("error restoring buffered data"); + + memcpy(bdata->buffer, data, len); + + /* Queue for later transmission. */ + list_add_tail(&bdata->list, &conn->out_list); +} + +void read_state_buffered_data(const void *ctx, struct connection *conn, + const struct xs_state_connection *sc) +{ + struct buffered_data *bdata; + const uint8_t *data; + unsigned int len; + bool partial = sc->data_resp_len; + + if (sc->data_in_len) { + bdata = new_buffer(conn); + if (!bdata) + barf("error restoring read data"); + if (sc->data_in_len < sizeof(bdata->hdr)) { + bdata->inhdr = true; + memcpy(&bdata->hdr, sc->data, sc->data_in_len); + bdata->used = sc->data_in_len; + } else { + bdata->inhdr = false; + memcpy(&bdata->hdr, sc->data, sizeof(bdata->hdr)); + if (bdata->hdr.msg.len <= DEFAULT_BUFFER_SIZE) + bdata->buffer = bdata->default_buffer; + else + bdata->buffer = talloc_array(bdata, char, + bdata->hdr.msg.len); + if (!bdata->buffer) + barf("Error allocating in buffer"); + bdata->used = sc->data_in_len - sizeof(bdata->hdr); + memcpy(bdata->buffer, sc->data + sizeof(bdata->hdr), + bdata->used); + } + + conn->in = bdata; + } + + for (data = sc->data + sc->data_in_len; + data < sc->data + sc->data_in_len + sc->data_out_len; + data += len) { + bdata = new_buffer(conn); + if (!bdata) + barf("error restoring buffered data"); + if (partial) { + bdata->inhdr = false; + /* Make trace look nice. */ + bdata->hdr.msg.type = XS_INVALID; + len = sc->data_resp_len; + add_buffered_data(bdata, conn, data, len); + partial = false; + continue; + } + + memcpy(&bdata->hdr, data, sizeof(bdata->hdr)); + data += sizeof(bdata->hdr); + len = bdata->hdr.msg.len; + add_buffered_data(bdata, conn, data, len); + } +} + /* * Local variables: * mode: C diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h index ac9fe1559e..dcb3ad3e4b 100644 --- a/tools/xenstore/xenstored_core.h +++ b/tools/xenstore/xenstored_core.h @@ -135,6 +135,9 @@ struct connection /* Methods for communicating over this connection: write can be NULL */ connwritefn_t *write; connreadfn_t *read; + + /* Support for live update: connection id. */ + unsigned int conn_id; }; extern struct list_head connections; @@ -195,6 +198,7 @@ struct node *read_node(struct connection *conn, const void *ctx, const char *name); struct connection *new_connection(connwritefn_t *write, connreadfn_t *read); +struct connection *get_connection_by_id(unsigned int conn_id); void check_store(void); void corrupt(struct connection *conn, const char *fmt, ...); enum xs_perm_type perm_for_conn(struct connection *conn, @@ -250,6 +254,10 @@ void finish_daemonize(void); /* Open a pipe for signal handling */ void init_pipe(int reopen_log_pipe[2]); +int writefd(struct connection *conn, const void *data, unsigned int len); +int readfd(struct connection *conn, void *data, unsigned int len); + +extern struct interface_funcs socket_funcs; extern xengnttab_handle **xgt_handle; int remember_string(struct hashtable *hash, const char *str); @@ -266,6 +274,8 @@ const char *dump_state_node_perms(FILE *fp, struct xs_state_node *sn, unsigned int n_perms); 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); #endif /* _XENSTORED_CORE_H */ diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c index 775546757b..6934f1bc89 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -355,7 +355,7 @@ static struct domain *find_or_alloc_domain(const void *ctx, unsigned int domid) return domain ? : alloc_domain(ctx, domid); } -static int new_domain(struct domain *domain, int port) +static int new_domain(struct domain *domain, int port, bool restore) { int rc; @@ -369,11 +369,16 @@ static int new_domain(struct domain *domain, int port) wrl_domain_new(domain); - /* Tell kernel we're interested in this event. */ - rc = xenevtchn_bind_interdomain(xce_handle, domain->domid, port); - if (rc == -1) - return errno; - domain->port = rc; + if (restore) + domain->port = port; + else { + /* Tell kernel we're interested in this event. */ + rc = xenevtchn_bind_interdomain(xce_handle, domain->domid, + port); + if (rc == -1) + return errno; + domain->port = rc; + } domain->introduced = true; @@ -423,7 +428,7 @@ static void domain_conn_reset(struct domain *domain) static struct domain *introduce_domain(const void *ctx, unsigned int domid, - evtchn_port_t port) + evtchn_port_t port, bool restore) { struct domain *domain; int rc; @@ -439,7 +444,7 @@ static struct domain *introduce_domain(const void *ctx, : map_interface(domid); if (!interface) return NULL; - if (new_domain(domain, port)) { + if (new_domain(domain, port, restore)) { rc = errno; if (is_master_domain) unmap_xenbus(interface); @@ -453,7 +458,7 @@ static struct domain *introduce_domain(const void *ctx, /* Now domain belongs to its connection. */ talloc_steal(domain->conn, domain); - if (!is_master_domain) + if (!is_master_domain && !restore) fire_watches(NULL, ctx, "@introduceDomain", NULL, false, NULL); } else { @@ -486,7 +491,7 @@ int do_introduce(struct connection *conn, struct buffered_data *in) if (port <= 0) return EINVAL; - domain = introduce_domain(in, domid, port); + domain = introduce_domain(in, domid, port, false); if (!domain) return errno; @@ -715,7 +720,7 @@ void dom0_init(void) if (port == -1) barf_perror("Failed to initialize dom0 port"); - dom0 = introduce_domain(NULL, xenbus_master_domid(), port); + dom0 = introduce_domain(NULL, xenbus_master_domid(), port, false); if (!dom0) barf_perror("Failed to initialize dom0"); @@ -1261,6 +1266,39 @@ const char *dump_state_special_nodes(FILE *fp) return ret; } +void read_state_connection(const void *ctx, const void *state) +{ + const struct xs_state_connection *sc = state; + struct connection *conn; + struct domain *domain, *tdomain; + + if (sc->conn_type == XS_STATE_CONN_TYPE_SOCKET) { + conn = new_connection(writefd, readfd); + if (!conn) + barf("error restoring connection"); + conn->fd = sc->spec.socket_fd; + } else { + domain = introduce_domain(ctx, sc->spec.ring.domid, + sc->spec.ring.evtchn, true); + if (!domain) + barf("domain allocation error"); + + if (sc->spec.ring.tdomid != DOMID_INVALID) { + tdomain = find_or_alloc_domain(ctx, + sc->spec.ring.tdomid); + if (!tdomain) + barf("target domain allocation error"); + talloc_reference(domain->conn, tdomain->conn); + domain->conn->target = tdomain->conn; + } + conn = domain->conn; + } + + conn->conn_id = sc->conn_id; + + read_state_buffered_data(ctx, conn, sc); +} + /* * Local variables: * mode: C diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h index b20269b038..8f3b4e0f8b 100644 --- a/tools/xenstore/xenstored_domain.h +++ b/tools/xenstore/xenstored_domain.h @@ -101,4 +101,6 @@ void wrl_apply_debit_trans_commit(struct connection *conn); const char *dump_state_connections(FILE *fp, struct connection *conn); const char *dump_state_special_nodes(FILE *fp); +void read_state_connection(const void *ctx, const void *state); + #endif /* _XENSTORED_DOMAIN_H */ -- 2.26.2
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |