qemu: fill capabilities for virtiofsd

Run the daemon with --print-capabilities first, to see what it supports.

Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Ján Tomko 2024-07-04 15:54:28 +02:00
parent 132bf6d89b
commit 730eaafaac
7 changed files with 81 additions and 3 deletions

View File

@ -2600,6 +2600,7 @@ void virDomainFSDefFree(virDomainFSDef *def)
g_free(def->sock);
g_free(def->idmap.uidmap);
g_free(def->idmap.gidmap);
virBitmapFree(def->caps);
g_free(def);
}

View File

@ -899,6 +899,7 @@ struct _virDomainFSDef {
virDomainIdMapDef idmap;
virDomainVirtioOptions *virtio;
virObject *privateData;
virBitmap *caps;
};

View File

@ -22,6 +22,7 @@
#include "qemu_vhost_user.h"
#include "qemu_interop_config.h"
#include "virbitmap.h"
#include "virjson.h"
#include "virlog.h"
#include "viralloc.h"
@ -90,6 +91,12 @@ VIR_ENUM_IMPL(qemuVhostUserGPUFeature,
"render-node",
);
VIR_ENUM_IMPL(qemuVhostUserFSFeature,
QEMU_VHOST_USER_FS_FEATURE_LAST,
"migrate-precopy",
"separate-options",
);
typedef struct _qemuVhostUserGPU qemuVhostUserGPU;
struct _qemuVhostUserGPU {
size_t nfeatures;
@ -414,6 +421,52 @@ qemuVhostUserFillDomainGPU(virQEMUDriver *driver,
return ret;
}
int
qemuVhostUserFillFSCapabilities(virBitmap **caps,
const char *binary)
{
g_autoptr(virJSONValue) doc = NULL;
g_autofree char *output = NULL;
g_autoptr(virCommand) cmd = NULL;
virJSONValue *featuresJSON;
size_t nfeatures;
size_t i;
g_autoptr(virBitmap) features = NULL;
cmd = virCommandNewArgList(binary, "--print-capabilities", NULL);
virCommandSetOutputBuffer(cmd, &output);
if (virCommandRun(cmd, NULL) < 0)
return -2;
if (!(doc = virJSONValueFromString(output))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unable to parse json capabilities '%1$s'"),
binary);
return -1;
}
/* Older virtiofsd did not print any features */
if (!(featuresJSON = virJSONValueObjectGetArray(doc, "features")))
return 0;
features = virBitmapNew(0);
nfeatures = virJSONValueArraySize(featuresJSON);
for (i = 0; i < nfeatures; i++) {
virJSONValue *item = virJSONValueArrayGet(featuresJSON, i);
const char *tmpStr = virJSONValueGetString(item);
int tmp;
if ((tmp = qemuVhostUserFSFeatureTypeFromString(tmpStr)) < 0) {
VIR_DEBUG("ignoring unknown virtiofs feature '%s'", tmpStr);
continue;
}
virBitmapSetBitExpand(features, tmp);
}
*caps = g_steal_pointer(&features);
return 0;
}
int
qemuVhostUserFillDomainFS(virQEMUDriver *driver,
@ -435,6 +488,11 @@ qemuVhostUserFillDomainFS(virQEMUDriver *driver,
continue;
fs->binary = g_strdup(vu->binary);
/* skip binaries that can't report their capabilities */
if (qemuVhostUserFillFSCapabilities(&fs->caps,
vu->binary) == -1)
continue;
break;
}

View File

@ -46,3 +46,14 @@ qemuVhostUserFillDomainGPU(virQEMUDriver *driver,
int
qemuVhostUserFillDomainFS(virQEMUDriver *driver,
virDomainFSDef *fs);
int
qemuVhostUserFillFSCapabilities(virBitmap **caps,
const char *binary);
typedef enum {
QEMU_VHOST_USER_FS_FEATURE_MIGRATE_PRECOPY = 0,
QEMU_VHOST_USER_FS_FEATURE_SEPARATE_OPTIONS,
QEMU_VHOST_USER_FS_FEATURE_LAST
} qemuVhostUserFSFeature;
VIR_ENUM_DECL(qemuVhostUserFSFeature);

View File

@ -446,8 +446,13 @@ qemuVirtioFSPrepareDomain(virQEMUDriver *driver,
if (fs->sock)
return 0;
if (!fs->binary && qemuVhostUserFillDomainFS(driver, fs) < 0)
return -1;
if (fs->binary) {
if (qemuVhostUserFillFSCapabilities(&fs->caps, fs->binary) < 0)
return -1;
} else {
if (qemuVhostUserFillDomainFS(driver, fs) < 0)
return -1;
}
if (!driver->privileged && !fs->idmap.uidmap) {
if (qemuVirtioFSPrepareIdMap(fs) < 0)

View File

@ -1,5 +1,5 @@
{
"description": "virtiofsd vhost-user-fs",
"type": "fs",
"binary": "/usr/libexec/qemu/vhost-user/test-vhost-user-gpu"
"binary": "/usr/libexec/qemu/vhost-user/test-virtiofsd"
}

View File

@ -1076,6 +1076,8 @@ mymain(void)
virFileWrapperAddPrefix("/usr/libexec/qemu/vhost-user",
abs_srcdir "/qemuvhostuserdata/usr/libexec/qemu/vhost-user");
virFileWrapperAddPrefix("/usr/libexec/virtiofsd",
abs_srcdir "/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-virtiofsd");
if (!(conn = virGetConnect()))
return EXIT_FAILURE;