diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c index e1d5e8d614..24ee99cbc6 100644 --- a/tools/xenstored/domain.c +++ b/tools/xenstored/domain.c @@ -32,6 +32,7 @@ #include "transaction.h" #include "watch.h" #include "control.h" +#include "lu.h" #include #include @@ -42,6 +43,8 @@ #include #endif +#define XENSTORE_FEATURES XENSTORE_SERVER_FEATURE_ERROR + static xenmanage_handle *xm_handle; xengnttab_handle **xgt_handle; static evtchn_port_t virq_port; @@ -115,6 +118,9 @@ struct domain /* Event channel port */ evtchn_port_t port; + /* Server features supported for this domain. */ + unsigned int features; + /* Domain path in store. */ char *path; @@ -799,6 +805,7 @@ static struct domain *alloc_domain(const void *context, unsigned int domid, domain->unique_id = unique_id; domain->generation = generation; domain->introduced = false; + domain->features = XENSTORE_FEATURES; if (hashtable_add(domhash, &domain->domid, domain)) { talloc_free(domain); @@ -992,7 +999,8 @@ void ignore_connection(struct connection *conn, unsigned int err) { trace("CONN %p ignored, reason %u\n", conn, err); - if (conn->domain && conn->domain->interface) + if (conn->domain && conn->domain->interface && + (conn->domain->features & XENSTORE_SERVER_FEATURE_ERROR)) conn->domain->interface->error = err; conn->is_ignored = true; @@ -1032,6 +1040,8 @@ static struct domain *introduce_domain(const void *ctx, return NULL; } domain->interface = interface; + if (!restore) + interface->server_features = domain->features; if (is_master_domain) setup_structure(restore); @@ -1849,6 +1859,54 @@ void read_state_connection(const void *ctx, const void *state) } } +static int dump_state_domain(const void *k, void *v, void *arg) +{ + struct domain *domain = v; + FILE *fp = arg; + struct xs_state_domain sd; + struct xs_state_record_header head; + + head.type = XS_STATE_TYPE_DOMAIN; + head.length = sizeof(sd); + memset(&sd, 0, sizeof(sd)); + sd.domain_id = domain->domid; + + if (lu_status->version > 1) + sd.features = domain->features; + + if (fwrite(&head, sizeof(head), 1, fp) != 1) + return 1; + if (fwrite(&sd, sizeof(sd), 1, fp) != 1) + return 1; + if (dump_state_align(fp)) + return 1; + + return 0; +} + +const char *dump_state_domains(FILE *fp) +{ + const char *ret = NULL; + + if (hashtable_iterate(domhash, dump_state_domain, fp)) + ret = "Dump domain error"; + + return ret; +} + +void read_state_domain(const void *ctx, const void *state, unsigned int version) +{ + const struct xs_state_domain *sd = state; + struct domain *domain; + + domain = find_domain_struct(sd->domain_id); + if (!domain) + barf("referenced domain not found"); + + if (version > 1) + domain->features = sd->features; +} + struct domain_acc { unsigned int domid; int nodes; diff --git a/tools/xenstored/domain.h b/tools/xenstored/domain.h index 844ac11510..8bfaca8f90 100644 --- a/tools/xenstored/domain.h +++ b/tools/xenstored/domain.h @@ -162,8 +162,11 @@ void wrl_apply_debit_direct(struct connection *conn); void wrl_apply_debit_trans_commit(struct connection *conn); const char *dump_state_connections(FILE *fp); +const char *dump_state_domains(FILE *fp); void read_state_connection(const void *ctx, const void *state); +void read_state_domain(const void *ctx, const void *state, + unsigned int version); struct hashtable *domain_check_acc_init(void); void domain_check_acc_add(const struct node *node, struct hashtable *domains); diff --git a/tools/xenstored/lu.c b/tools/xenstored/lu.c index 2c6adecb56..77e0d377c5 100644 --- a/tools/xenstored/lu.c +++ b/tools/xenstored/lu.c @@ -21,6 +21,8 @@ #include "lu.h" #include "watch.h" +struct live_update *lu_status; + #ifndef NO_LIVE_UPDATE struct lu_dump_state { @@ -30,8 +32,6 @@ struct lu_dump_state { char *filename; }; -struct live_update *lu_status; - static int lu_destroy(void *data) { lu_status = NULL; @@ -128,6 +128,7 @@ void lu_read_state(void) struct xs_state_record_header *head; void *ctx = talloc_new(NULL); /* Work context for subfunctions. */ struct xs_state_preamble *pre; + unsigned int version; syslog(LOG_INFO, "live-update: read state\n"); lu_get_dump_state(&state); @@ -135,8 +136,9 @@ void lu_read_state(void) barf_perror("No state found after live-update"); pre = state.buf; + version = be32toh(pre->version); if (memcmp(pre->ident, XS_STATE_IDENT, sizeof(pre->ident)) || - !pre->version || be32toh(pre->version) > XS_STATE_VERSION || + !version || version > XS_STATE_VERSION || pre->flags != XS_STATE_FLAGS) barf("Unknown record identifier"); for (head = state.buf + sizeof(*pre); @@ -159,6 +161,9 @@ void lu_read_state(void) case XS_STATE_TYPE_NODE: read_state_node(ctx, head + 1); break; + case XS_STATE_TYPE_DOMAIN: + read_state_domain(ctx, head + 1, version); + break; default: xprintf("live-update: unknown state record %08x\n", head->type); @@ -297,6 +302,9 @@ static const char *lu_dump_state(const void *ctx, struct connection *conn) if (ret) goto out; ret = dump_state_nodes(fp, ctx); + if (ret) + goto out; + ret = dump_state_domains(fp); if (ret) goto out; diff --git a/tools/xenstored/lu.h b/tools/xenstored/lu.h index 512b8a6db2..aff7ab9011 100644 --- a/tools/xenstored/lu.h +++ b/tools/xenstored/lu.h @@ -5,7 +5,6 @@ * Copyright (C) 2022 Juergen Gross, SUSE LLC */ -#ifndef NO_LIVE_UPDATE struct live_update { /* For verification the correct connection is acting. */ struct connection *conn; @@ -32,6 +31,7 @@ struct live_update { extern struct live_update *lu_status; +#ifndef NO_LIVE_UPDATE struct connection *lu_get_connection(void); bool lu_is_pending(void); void lu_read_state(void);