aboutsummaryrefslogtreecommitdiff
path: root/monitor.c
diff options
context:
space:
mode:
authorCorey Bryant <coreyb@linux.vnet.ibm.com>2012-08-14 16:43:47 -0400
committerKevin Wolf <kwolf@redhat.com>2012-08-15 13:16:22 +0200
commitadb696f3d8535119fe0f5363de79a29e6bda83ed (patch)
tree7fe2a5557264b900f86caff04dc93d568ba1b4ab /monitor.c
parent2e1e79dae7a7e0a3d698fbd359d75e3a0239bdaa (diff)
block: Enable qemu_open/close to work with fd sets
When qemu_open is passed a filename of the "/dev/fdset/nnn" format (where nnn is the fdset ID), an fd with matching access mode flags will be searched for within the specified monitor fd set. If the fd is found, a dup of the fd will be returned from qemu_open. Signed-off-by: Corey Bryant <coreyb@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'monitor.c')
-rw-r--r--monitor.c86
1 files changed, 85 insertions, 1 deletions
diff --git a/monitor.c b/monitor.c
index 8d813d5121..a4a29b9cd7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -154,6 +154,7 @@ typedef struct MonFdset MonFdset;
struct MonFdset {
int64_t id;
QLIST_HEAD(, MonFdsetFd) fds;
+ QLIST_HEAD(, MonFdsetFd) dup_fds;
QLIST_ENTRY(MonFdset) next;
};
@@ -2398,7 +2399,7 @@ static void monitor_fdset_cleanup(MonFdset *mon_fdset)
}
}
- if (QLIST_EMPTY(&mon_fdset->fds)) {
+ if (QLIST_EMPTY(&mon_fdset->fds) && QLIST_EMPTY(&mon_fdset->dup_fds)) {
QLIST_REMOVE(mon_fdset, next);
g_free(mon_fdset);
}
@@ -2555,6 +2556,89 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
return fdset_list;
}
+int monitor_fdset_get_fd(int64_t fdset_id, int flags)
+{
+ MonFdset *mon_fdset;
+ MonFdsetFd *mon_fdset_fd;
+ int mon_fd_flags;
+
+#ifndef _WIN32
+ QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
+ if (mon_fdset->id != fdset_id) {
+ continue;
+ }
+ QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
+ mon_fd_flags = fcntl(mon_fdset_fd->fd, F_GETFL);
+ if (mon_fd_flags == -1) {
+ return -1;
+ }
+
+ if ((flags & O_ACCMODE) == (mon_fd_flags & O_ACCMODE)) {
+ return mon_fdset_fd->fd;
+ }
+ }
+ errno = EACCES;
+ return -1;
+ }
+#endif
+
+ errno = ENOENT;
+ return -1;
+}
+
+int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
+{
+ MonFdset *mon_fdset;
+ MonFdsetFd *mon_fdset_fd_dup;
+
+ QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
+ if (mon_fdset->id != fdset_id) {
+ continue;
+ }
+ QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
+ if (mon_fdset_fd_dup->fd == dup_fd) {
+ return -1;
+ }
+ }
+ mon_fdset_fd_dup = g_malloc0(sizeof(*mon_fdset_fd_dup));
+ mon_fdset_fd_dup->fd = dup_fd;
+ QLIST_INSERT_HEAD(&mon_fdset->dup_fds, mon_fdset_fd_dup, next);
+ return 0;
+ }
+ return -1;
+}
+
+static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
+{
+ MonFdset *mon_fdset;
+ MonFdsetFd *mon_fdset_fd_dup;
+
+ QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
+ QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
+ if (mon_fdset_fd_dup->fd == dup_fd) {
+ if (remove) {
+ QLIST_REMOVE(mon_fdset_fd_dup, next);
+ if (QLIST_EMPTY(&mon_fdset->dup_fds)) {
+ monitor_fdset_cleanup(mon_fdset);
+ }
+ }
+ return mon_fdset->id;
+ }
+ }
+ }
+ return -1;
+}
+
+int monitor_fdset_dup_fd_find(int dup_fd)
+{
+ return monitor_fdset_dup_fd_find_remove(dup_fd, false);
+}
+
+int monitor_fdset_dup_fd_remove(int dup_fd)
+{
+ return monitor_fdset_dup_fd_find_remove(dup_fd, true);
+}
+
/* mon_cmds and info_cmds would be sorted at runtime */
static mon_cmd_t mon_cmds[] = {
#include "hmp-commands.h"