tools/xenstored: add server feature support

Add per domain server features, which are initialized by the supported
features at domain introduction, or by live update from the migration
stream. This requires to add the DOMAIN_DATA record to the migration
stream, but for now it will only contain the feature word.

Advertise the Xenstore features to guests by setting the appropriate
bits in the ring page.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
This commit is contained in:
Juergen Gross authored and Jan Beulich committed 2025-07-28 13:07:08 +02:00
1 parent 1e675413cb
commit fdd31b3bed
4 files changed
+74 -5

No files matched your search

+59 -1
View File
@@ -32,6 +32,7 @@
#include "transaction.h"
#include "watch.h"
#include "control.h"
#include "lu.h"
#include <xenevtchn.h>
#include <xenmanage.h>
@@ -42,6 +43,8 @@
#include <mini-os/xenbus.h>
#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;
+3
View File
@@ -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);
+11 -3
View File
@@ -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;
+1 -1
View File
@@ -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);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.