Files
xen/tools/libs/light/libxl_9pfs.c
T
Juergen Gross e21d9dbf44 tools: add 9pfs device to xenstore-stubdom
Add a 9pfs device to Xenstore stubdom in order to allow it to do e.g.
logging into a dom0 file.

Use the following parameters for the new device:

- tag = "Xen"
- type = "xen_9pfsd"
- path = "/var/lib/xen/xenstore"
- security-model = "none"

For now don't limit allowed file space or number of files.

Add a new libxl function for adding it similar to the function for
adding the console device.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
2024-02-23 17:43:06 +00:00

238 lines
7.3 KiB
C

/*
* Copyright (C) 2017 Aporeto
* Author Stefano Stabellini <stefano@aporeto.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
#include "libxl_osdeps.h"
#include "libxl_internal.h"
static int libxl__device_p9_setdefault(libxl__gc *gc, uint32_t domid,
libxl_device_p9 *p9, bool hotplug)
{
if (p9->type == LIBXL_P9_TYPE_UNKNOWN) {
p9->type = LIBXL_P9_TYPE_QEMU;
}
if (p9->type == LIBXL_P9_TYPE_QEMU &&
(p9->max_files || p9->max_open_files || p9->max_space ||
p9->auto_delete)) {
LOGD(ERROR, domid, "Illegal 9pfs parameter combination");
return ERROR_INVAL;
}
if (p9->type == LIBXL_P9_TYPE_XEN_9PFSD && !p9->tag) {
p9->tag = libxl__strdup(NOGC, "Xen");
}
if (!p9->path || !p9->security_model || !p9->tag) {
LOGD(ERROR, domid, "9pfs spec missing required field!");
return ERROR_INVAL;
}
return libxl__resolve_domid(gc, p9->backend_domname, &p9->backend_domid);
}
static int libxl__set_xenstore_p9(libxl__gc *gc, uint32_t domid,
libxl_device_p9 *p9,
flexarray_t *back, flexarray_t *front,
flexarray_t *ro_front)
{
flexarray_append_pair(back, "path", p9->path);
flexarray_append_pair(back, "security_model", p9->security_model);
flexarray_append_pair(front, "tag", p9->tag);
if (p9->type == LIBXL_P9_TYPE_XEN_9PFSD) {
flexarray_append_pair(back, "max-space",
GCSPRINTF("%u", p9->max_space));
flexarray_append_pair(back, "max-files",
GCSPRINTF("%u", p9->max_files));
flexarray_append_pair(back, "max-open-files",
GCSPRINTF("%u", p9->max_open_files));
flexarray_append_pair(back, "auto-delete",
p9->auto_delete ? "1" : "0");
}
return 0;
}
static int libxl__device_from_p9(libxl__gc *gc, uint32_t domid,
libxl_device_p9 *type, libxl__device *device)
{
device->backend_devid = type->devid;
device->backend_domid = type->backend_domid;
device->backend_kind = type->type == LIBXL_P9_TYPE_QEMU
? LIBXL__DEVICE_KIND_9PFS
: LIBXL__DEVICE_KIND_XEN_9PFS;
device->devid = type->devid;
device->domid = domid;
device->kind = LIBXL__DEVICE_KIND_9PFS;
return 0;
}
static int libxl__device_p9_dm_needed(void *e, unsigned domid)
{
libxl_device_p9 *elem = e;
return elem->type == LIBXL_P9_TYPE_QEMU && elem->backend_domid == domid;
}
typedef struct libxl__aop9_state libxl__aop9_state;
struct libxl__aop9_state {
libxl__spawn_state spawn;
libxl__ao_device *aodev;
libxl_device_p9 p9;
uint32_t domid;
};
static void xen9pfsd_confirm(libxl__egc *egc, libxl__spawn_state *spawn,
const char *xsdata);
static void xen9pfsd_failed(libxl__egc *egc, libxl__spawn_state *spawn, int rc);
static void xen9pfsd_detached(libxl__egc *egc, libxl__spawn_state *spawn);
static void xen9pfsd_spawn_outcome(libxl__egc *egc, libxl__aop9_state *aop9,
int rc);
/*
* Spawn the xen-9pfsd daemon if needed.
* returns:
* < 0 if error
* 0 if no daemon needs to be spawned
* 1 if daemon was spawned
*/
static int xen9pfsd_spawn(libxl__egc *egc, uint32_t domid, libxl_device_p9 *p9,
libxl__ao_device *aodev)
{
STATE_AO_GC(aodev->ao);
struct libxl__aop9_state *aop9;
int rc;
char *args[] = { "xen-9pfsd", NULL };
char *path = GCSPRINTF("/local/domain/%u/libxl/xen-9pfs",
p9->backend_domid);
if (p9->type != LIBXL_P9_TYPE_XEN_9PFSD ||
libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", path)))
return 0;
GCNEW(aop9);
aop9->aodev = aodev;
libxl_device_p9_copy(CTX, &aop9->p9, p9);
aop9->domid = domid;
aop9->spawn.ao = aodev->ao;
aop9->spawn.what = "xen-9pfs daemon";
aop9->spawn.xspath = GCSPRINTF("%s/state", path);
aop9->spawn.timeout_ms = LIBXL_DEVICE_MODEL_START_TIMEOUT * 1000;
aop9->spawn.pidpath = GCSPRINTF("%s/pid", path);
aop9->spawn.midproc_cb = libxl__spawn_record_pid;
aop9->spawn.confirm_cb = xen9pfsd_confirm;
aop9->spawn.failure_cb = xen9pfsd_failed;
aop9->spawn.detached_cb = xen9pfsd_detached;
rc = libxl__spawn_spawn(egc, &aop9->spawn);
if (rc < 0)
return rc;
if (!rc) {
setsid();
libxl__exec(gc, -1, -1, -1, LIBEXEC_BIN "/xen-9pfsd", args, NULL);
}
return 1;
}
static void xen9pfsd_confirm(libxl__egc *egc, libxl__spawn_state *spawn,
const char *xsdata)
{
STATE_AO_GC(spawn->ao);
if (!xsdata)
return;
if (strcmp(xsdata, "running"))
return;
libxl__spawn_initiate_detach(gc, spawn);
}
static void xen9pfsd_failed(libxl__egc *egc, libxl__spawn_state *spawn, int rc)
{
libxl__aop9_state *aop9 = CONTAINER_OF(spawn, *aop9, spawn);
xen9pfsd_spawn_outcome(egc, aop9, rc);
}
static void xen9pfsd_detached(libxl__egc *egc, libxl__spawn_state *spawn)
{
libxl__aop9_state *aop9 = CONTAINER_OF(spawn, *aop9, spawn);
xen9pfsd_spawn_outcome(egc, aop9, 0);
}
static void xen9pfsd_spawn_outcome(libxl__egc *egc, libxl__aop9_state *aop9,
int rc)
{
aop9->aodev->rc = rc;
if (rc)
aop9->aodev->callback(egc, aop9->aodev);
else
libxl__device_add_async(egc, aop9->domid, &libxl__p9_devtype,
&aop9->p9, aop9->aodev);
}
static void libxl__device_p9_add(libxl__egc *egc, uint32_t domid,
libxl_device_p9 *p9,
libxl__ao_device *aodev)
{
int rc;
rc = xen9pfsd_spawn(egc, domid, p9, aodev);
if (rc == 1)
return;
if (rc == 0)
libxl__device_add_async(egc, domid, &libxl__p9_devtype, p9, aodev);
aodev->rc = rc;
if (rc)
aodev->callback(egc, aodev);
}
int libxl_device_9pfs_add(libxl_ctx *ctx, uint32_t domid, libxl_device_p9 *p9,
const libxl_asyncop_how *ao_how)
{
AO_CREATE(ctx, domid, ao_how);
libxl__ao_device *aodev;
GCNEW(aodev);
libxl__prepare_ao_device(ao, aodev);
aodev->action = LIBXL__DEVICE_ACTION_ADD;
aodev->callback = device_addrm_aocomplete;
libxl__device_p9_add(egc, domid, p9, aodev);
return AO_INPROGRESS;
}
#define libxl_device_p9_list NULL
#define libxl_device_p9_compare NULL
static LIBXL_DEFINE_UPDATE_DEVID(p9)
static LIBXL_DEFINE_DEVICES_ADD(p9)
LIBXL_DEFINE_DEVICE_REMOVE(p9)
DEFINE_DEVICE_TYPE_STRUCT(p9, 9PFS, p9s,
.set_xenstore_config = (device_set_xenstore_config_fn_t)
libxl__set_xenstore_p9,
.dm_needed = libxl__device_p9_dm_needed,
);