mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 17:35:17 +00:00
qemu: add monitor functions for handling file descriptors
add-fd, remove-fd, and query-fdsets provide functionality that can be used for passing fds to qemu and closing fdsets that are no longer necessary. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Laine Stump <laine@redhat.com>
This commit is contained in:
parent
0b1a05ffb5
commit
b8998cc670
@ -2649,6 +2649,99 @@ qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* qemuMonitorAddFileHandleToSet:
|
||||
* @mon: monitor object
|
||||
* @fd: file descriptor to pass to qemu
|
||||
* @fdset: the fdset to register this fd with, -1 to create a new fdset
|
||||
* @opaque: opaque data to associated with this fd
|
||||
* @info: structure that will be updated with the fd and fdset returned by qemu
|
||||
*
|
||||
* Attempts to register a file descriptor with qemu that can then be referenced
|
||||
* via the file path /dev/fdset/$FDSETID
|
||||
* Returns 0 if ok, and -1 on failure */
|
||||
int
|
||||
qemuMonitorAddFileHandleToSet(qemuMonitorPtr mon,
|
||||
int fd,
|
||||
int fdset,
|
||||
const char *opaque,
|
||||
qemuMonitorAddFdInfoPtr info)
|
||||
{
|
||||
VIR_DEBUG("fd=%d,fdset=%i,opaque=%s", fd, fdset, opaque);
|
||||
|
||||
QEMU_CHECK_MONITOR(mon);
|
||||
|
||||
if (fd < 0) {
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
_("fd must be valid"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return qemuMonitorJSONAddFileHandleToSet(mon, fd, fdset, opaque, info);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* qemuMonitorRemoveFdset:
|
||||
* @mon: monitor object
|
||||
* @fdset: the fdset to remove
|
||||
*
|
||||
* Attempts to remove a fdset from qemu and close associated file descriptors
|
||||
* Returns 0 if ok, and -1 on failure */
|
||||
int
|
||||
qemuMonitorRemoveFdset(qemuMonitorPtr mon,
|
||||
int fdset)
|
||||
{
|
||||
VIR_DEBUG("fdset=%d", fdset);
|
||||
|
||||
QEMU_CHECK_MONITOR(mon);
|
||||
|
||||
if (fdset < 0) {
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
_("fdset must be valid"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return qemuMonitorJSONRemoveFdset(mon, fdset);
|
||||
}
|
||||
|
||||
|
||||
void qemuMonitorFdsetsFree(qemuMonitorFdsetsPtr fdsets)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < fdsets->nfdsets; i++) {
|
||||
size_t j;
|
||||
qemuMonitorFdsetInfoPtr set = &fdsets->fdsets[i];
|
||||
|
||||
for (j = 0; j < set->nfds; j++)
|
||||
g_free(set->fds[j].opaque);
|
||||
}
|
||||
g_free(fdsets->fdsets);
|
||||
g_free(fdsets);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* qemuMonitorQueryFdsets:
|
||||
* @mon: monitor object
|
||||
* @fdsets: a pointer that is filled with a new qemuMonitorFdsets struct
|
||||
*
|
||||
* Queries qemu for the fdsets that are registered with that instance, and
|
||||
* returns a structure describing those fdsets. The returned struct should be
|
||||
* freed with qemuMonitorFdsetsFree();
|
||||
*
|
||||
* Returns 0 if ok, and -1 on failure */
|
||||
int
|
||||
qemuMonitorQueryFdsets(qemuMonitorPtr mon,
|
||||
qemuMonitorFdsetsPtr *fdsets)
|
||||
{
|
||||
QEMU_CHECK_MONITOR(mon);
|
||||
|
||||
return qemuMonitorJSONQueryFdsets(mon, fdsets);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorSendFileHandle(qemuMonitorPtr mon,
|
||||
const char *fdname,
|
||||
|
@ -880,6 +880,47 @@ int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
|
||||
int tlsPort,
|
||||
const char *tlsSubject);
|
||||
|
||||
typedef struct _qemuMonitorAddFdInfo qemuMonitorAddFdInfo;
|
||||
typedef qemuMonitorAddFdInfo *qemuMonitorAddFdInfoPtr;
|
||||
struct _qemuMonitorAddFdInfo {
|
||||
int fd;
|
||||
int fdset;
|
||||
};
|
||||
int
|
||||
qemuMonitorAddFileHandleToSet(qemuMonitorPtr mon,
|
||||
int fd,
|
||||
int fdset,
|
||||
const char *opaque,
|
||||
qemuMonitorAddFdInfoPtr info);
|
||||
|
||||
int
|
||||
qemuMonitorRemoveFdset(qemuMonitorPtr mon,
|
||||
int fdset);
|
||||
|
||||
typedef struct _qemuMonitorFdsetFdInfo qemuMonitorFdsetFdInfo;
|
||||
typedef qemuMonitorFdsetFdInfo *qemuMonitorFdsetFdInfoPtr;
|
||||
struct _qemuMonitorFdsetFdInfo {
|
||||
int fd;
|
||||
char *opaque;
|
||||
};
|
||||
typedef struct _qemuMonitorFdsetInfo qemuMonitorFdsetInfo;
|
||||
typedef qemuMonitorFdsetInfo *qemuMonitorFdsetInfoPtr;
|
||||
struct _qemuMonitorFdsetInfo {
|
||||
int id;
|
||||
qemuMonitorFdsetFdInfoPtr fds;
|
||||
int nfds;
|
||||
};
|
||||
typedef struct _qemuMonitorFdsets qemuMonitorFdsets;
|
||||
typedef qemuMonitorFdsets *qemuMonitorFdsetsPtr;
|
||||
struct _qemuMonitorFdsets {
|
||||
qemuMonitorFdsetInfoPtr fdsets;
|
||||
int nfdsets;
|
||||
};
|
||||
void qemuMonitorFdsetsFree(qemuMonitorFdsetsPtr fdsets);
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuMonitorFdsets, qemuMonitorFdsetsFree);
|
||||
int qemuMonitorQueryFdsets(qemuMonitorPtr mon,
|
||||
qemuMonitorFdsetsPtr *fdsets);
|
||||
|
||||
int qemuMonitorSendFileHandle(qemuMonitorPtr mon,
|
||||
const char *fdname,
|
||||
int fd);
|
||||
|
@ -3929,6 +3929,179 @@ int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuAddfdInfoParse(virJSONValuePtr msg,
|
||||
qemuMonitorAddFdInfoPtr fdinfo)
|
||||
{
|
||||
virJSONValuePtr returnObj;
|
||||
|
||||
if (!(returnObj = virJSONValueObjectGetObject(msg, "return"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid return data in add-fd response"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virJSONValueObjectGetNumberInt(returnObj, "fd", &fdinfo->fd) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid fd in add-fd response"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virJSONValueObjectGetNumberInt(returnObj, "fdset-id", &fdinfo->fdset) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing or invalid fdset-id in add-fd response"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* if fdset is negative, qemu will create a new fdset and add the fd to that */
|
||||
int qemuMonitorJSONAddFileHandleToSet(qemuMonitorPtr mon,
|
||||
int fd,
|
||||
int fdset,
|
||||
const char *opaque,
|
||||
qemuMonitorAddFdInfoPtr fdinfo)
|
||||
{
|
||||
virJSONValuePtr args = NULL;
|
||||
g_autoptr(virJSONValue) reply = NULL;
|
||||
g_autoptr(virJSONValue) cmd = NULL;
|
||||
|
||||
if (virJSONValueObjectCreate(&args, "S:opaque", opaque, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
if (fdset >= 0)
|
||||
if (virJSONValueObjectAdd(args, "j:fdset-id", fdset, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
if (!(cmd = qemuMonitorJSONMakeCommandInternal("add-fd", args)))
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuAddfdInfoParse(reply, fdinfo) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qemuMonitorJSONQueryFdsetsParse(virJSONValuePtr msg,
|
||||
qemuMonitorFdsetsPtr *fdsets)
|
||||
{
|
||||
virJSONValuePtr returnArray, entry;
|
||||
size_t i;
|
||||
g_autoptr(qemuMonitorFdsets) sets = g_new0(qemuMonitorFdsets, 1);
|
||||
int ninfo;
|
||||
|
||||
returnArray = virJSONValueObjectGetArray(msg, "return");
|
||||
|
||||
ninfo = virJSONValueArraySize(returnArray);
|
||||
if (ninfo > 0)
|
||||
sets->fdsets = g_new0(qemuMonitorFdsetInfo, ninfo);
|
||||
sets->nfdsets = ninfo;
|
||||
|
||||
for (i = 0; i < ninfo; i++) {
|
||||
size_t j;
|
||||
const char *tmp;
|
||||
virJSONValuePtr fdarray;
|
||||
qemuMonitorFdsetInfoPtr fdsetinfo = &sets->fdsets[i];
|
||||
|
||||
if (!(entry = virJSONValueArrayGet(returnArray, i))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-fdsets return data missing fdset array element"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virJSONValueObjectGetNumberInt(entry, "fdset-id", &fdsetinfo->id) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-fdsets reply was missing 'fdset-id'"));
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
fdarray = virJSONValueObjectGetArray(entry, "fds");
|
||||
fdsetinfo->nfds = virJSONValueArraySize(fdarray);
|
||||
if (fdsetinfo->nfds > 0)
|
||||
fdsetinfo->fds = g_new0(qemuMonitorFdsetFdInfo, fdsetinfo->nfds);
|
||||
|
||||
for (j = 0; j < fdsetinfo->nfds; j++) {
|
||||
qemuMonitorFdsetFdInfoPtr fdinfo = &fdsetinfo->fds[j];
|
||||
virJSONValuePtr fdentry;
|
||||
|
||||
if (!(fdentry = virJSONValueArrayGet(fdarray, j))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-fdsets return data missing fd array element"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virJSONValueObjectGetNumberInt(fdentry, "fd", &fdinfo->fd) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-fdsets return data missing 'fd'"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* opaque is optional and may be missing */
|
||||
tmp = virJSONValueObjectGetString(fdentry, "opaque");
|
||||
if (tmp)
|
||||
fdinfo->opaque = g_strdup(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
*fdsets = g_steal_pointer(&sets);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorJSONQueryFdsets(qemuMonitorPtr mon,
|
||||
qemuMonitorFdsetsPtr *fdsets)
|
||||
{
|
||||
g_autoptr(virJSONValue) reply = NULL;
|
||||
g_autoptr(virJSONValue) cmd = qemuMonitorJSONMakeCommand("query-fdsets",
|
||||
NULL);
|
||||
|
||||
if (!cmd)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONQueryFdsetsParse(reply, fdsets) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorJSONRemoveFdset(qemuMonitorPtr mon,
|
||||
int fdset)
|
||||
{
|
||||
g_autoptr(virJSONValue) reply = NULL;
|
||||
g_autoptr(virJSONValue) cmd = qemuMonitorJSONMakeCommand("remove-fd",
|
||||
"i:fdset-id", fdset,
|
||||
NULL);
|
||||
|
||||
if (!cmd)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon,
|
||||
const char *fdname,
|
||||
int fd)
|
||||
|
@ -202,6 +202,18 @@ int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon,
|
||||
int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon,
|
||||
virPCIDeviceAddress *guestAddr);
|
||||
|
||||
int qemuMonitorJSONAddFileHandleToSet(qemuMonitorPtr mon,
|
||||
int fd,
|
||||
int fdset,
|
||||
const char *opaque,
|
||||
qemuMonitorAddFdInfoPtr info);
|
||||
|
||||
int qemuMonitorJSONRemoveFdset(qemuMonitorPtr mon,
|
||||
int fdset);
|
||||
|
||||
int qemuMonitorJSONQueryFdsets(qemuMonitorPtr mon,
|
||||
qemuMonitorFdsetsPtr *fdsets);
|
||||
|
||||
int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon,
|
||||
const char *fdname,
|
||||
int fd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user