Skip to content

Commit

Permalink
tools/xenstore: add read connection state for live update
Browse files Browse the repository at this point in the history
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@suse.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>
Acked-by: Wei Liu <wl@xen.org>
  • Loading branch information
jgross1 committed Jan 21, 2021
1 parent e7217f0 commit 2ea411b
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 13 deletions.
1 change: 1 addition & 0 deletions tools/xenstore/xenstored_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
102 changes: 100 additions & 2 deletions tools/xenstore/xenstored_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1582,12 +1582,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;

Expand All @@ -1603,7 +1626,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;

Expand Down Expand Up @@ -2521,6 +2544,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
Expand Down
10 changes: 10 additions & 0 deletions tools/xenstore/xenstored_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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 */

Expand Down
60 changes: 49 additions & 11 deletions tools/xenstore/xenstored_domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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 {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tools/xenstore/xenstored_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

0 comments on commit 2ea411b

Please sign in to comment.