mirror of https://github.com/xqemu/xqemu.git
qemu-config: Add new -add-fd command line option
This option can be used for passing file descriptors on the command line. It mirrors the existing add-fd QMP command which allows an fd to be passed to QEMU via SCM_RIGHTS and added to an fd set. This can be combined with commands such as -drive to link file descriptors in an fd set to a drive: qemu-kvm -add-fd fd=3,set=2,opaque="rdwr:/path/to/file" -add-fd fd=4,set=2,opaque="rdonly:/path/to/file" -drive file=/dev/fdset/2,index=0,media=disk This example adds dups of fds 3 and 4, and the accompanying opaque strings to the fd set with ID=2. qemu_open() already knows how to handle a filename of this format. qemu_open() searches the corresponding fd set for an fd and when it finds a match, QEMU goes on to use a dup of that fd just like it would have used an fd that it opened itself. Signed-off-by: Corey Bryant <coreyb@linux.vnet.ibm.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
ebe52b592d
commit
587ed6be0b
|
@ -653,6 +653,27 @@ QemuOptsList qemu_boot_opts = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static QemuOptsList qemu_add_fd_opts = {
|
||||||
|
.name = "add-fd",
|
||||||
|
.head = QTAILQ_HEAD_INITIALIZER(qemu_add_fd_opts.head),
|
||||||
|
.desc = {
|
||||||
|
{
|
||||||
|
.name = "fd",
|
||||||
|
.type = QEMU_OPT_NUMBER,
|
||||||
|
.help = "file descriptor of which a duplicate is added to fd set",
|
||||||
|
},{
|
||||||
|
.name = "set",
|
||||||
|
.type = QEMU_OPT_NUMBER,
|
||||||
|
.help = "ID of the fd set to add fd to",
|
||||||
|
},{
|
||||||
|
.name = "opaque",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "free-form string used to describe fd",
|
||||||
|
},
|
||||||
|
{ /* end of list */ }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static QemuOptsList *vm_config_groups[32] = {
|
static QemuOptsList *vm_config_groups[32] = {
|
||||||
&qemu_drive_opts,
|
&qemu_drive_opts,
|
||||||
&qemu_chardev_opts,
|
&qemu_chardev_opts,
|
||||||
|
@ -669,6 +690,7 @@ static QemuOptsList *vm_config_groups[32] = {
|
||||||
&qemu_boot_opts,
|
&qemu_boot_opts,
|
||||||
&qemu_iscsi_opts,
|
&qemu_iscsi_opts,
|
||||||
&qemu_sandbox_opts,
|
&qemu_sandbox_opts,
|
||||||
|
&qemu_add_fd_opts,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,14 @@ qemu-system-i386 -drive file=file,index=2,media=disk
|
||||||
qemu-system-i386 -drive file=file,index=3,media=disk
|
qemu-system-i386 -drive file=file,index=3,media=disk
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
You can open an image using pre-opened file descriptors from an fd set:
|
||||||
|
@example
|
||||||
|
qemu-system-i386
|
||||||
|
-add-fd fd=3,set=2,opaque="rdwr:/path/to/file"
|
||||||
|
-add-fd fd=4,set=2,opaque="rdonly:/path/to/file"
|
||||||
|
-drive file=/dev/fdset/2,index=0,media=disk
|
||||||
|
@end example
|
||||||
|
|
||||||
You can connect a CDROM to the slave of ide0:
|
You can connect a CDROM to the slave of ide0:
|
||||||
@example
|
@example
|
||||||
qemu-system-i386 -drive file=file,if=ide,index=1,media=cdrom
|
qemu-system-i386 -drive file=file,if=ide,index=1,media=cdrom
|
||||||
|
@ -285,6 +293,34 @@ qemu-system-i386 -hda a -hdb b
|
||||||
@end example
|
@end example
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
|
DEF("add-fd", HAS_ARG, QEMU_OPTION_add_fd,
|
||||||
|
"-add-fd fd=fd,set=set[,opaque=opaque]\n"
|
||||||
|
" Add 'fd' to fd 'set'\n", QEMU_ARCH_ALL)
|
||||||
|
STEXI
|
||||||
|
@item -add-fd fd=@var{fd},set=@var{set}[,opaque=@var{opaque}]
|
||||||
|
@findex -add-fd
|
||||||
|
|
||||||
|
Add a file descriptor to an fd set. Valid options are:
|
||||||
|
|
||||||
|
@table @option
|
||||||
|
@item fd=@var{fd}
|
||||||
|
This option defines the file descriptor of which a duplicate is added to fd set.
|
||||||
|
The file descriptor cannot be stdin, stdout, or stderr.
|
||||||
|
@item set=@var{set}
|
||||||
|
This option defines the ID of the fd set to add the file descriptor to.
|
||||||
|
@item opaque=@var{opaque}
|
||||||
|
This option defines a free-form string that can be used to describe @var{fd}.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
You can open an image using pre-opened file descriptors from an fd set:
|
||||||
|
@example
|
||||||
|
qemu-system-i386
|
||||||
|
-add-fd fd=3,set=2,opaque="rdwr:/path/to/file"
|
||||||
|
-add-fd fd=4,set=2,opaque="rdonly:/path/to/file"
|
||||||
|
-drive file=/dev/fdset/2,index=0,media=disk
|
||||||
|
@end example
|
||||||
|
ETEXI
|
||||||
|
|
||||||
DEF("set", HAS_ARG, QEMU_OPTION_set,
|
DEF("set", HAS_ARG, QEMU_OPTION_set,
|
||||||
"-set group.id.arg=value\n"
|
"-set group.id.arg=value\n"
|
||||||
" set <arg> parameter for item <id> of type <group>\n"
|
" set <arg> parameter for item <id> of type <group>\n"
|
||||||
|
|
94
vl.c
94
vl.c
|
@ -790,6 +790,78 @@ static int parse_sandbox(QemuOpts *opts, void *opaque)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
static int parse_add_fd(QemuOpts *opts, void *opaque)
|
||||||
|
{
|
||||||
|
int fd, dupfd, flags;
|
||||||
|
int64_t fdset_id;
|
||||||
|
const char *fd_opaque = NULL;
|
||||||
|
|
||||||
|
fd = qemu_opt_get_number(opts, "fd", -1);
|
||||||
|
fdset_id = qemu_opt_get_number(opts, "set", -1);
|
||||||
|
fd_opaque = qemu_opt_get(opts, "opaque");
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
|
"fd option is required and must be non-negative");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd <= STDERR_FILENO) {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
|
"fd cannot be a standard I/O stream");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All fds inherited across exec() necessarily have FD_CLOEXEC
|
||||||
|
* clear, while qemu sets FD_CLOEXEC on all other fds used internally.
|
||||||
|
*/
|
||||||
|
flags = fcntl(fd, F_GETFD);
|
||||||
|
if (flags == -1 || (flags & FD_CLOEXEC)) {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
|
"fd is not valid or already in use");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fdset_id < 0) {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
|
"set option is required and must be non-negative");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef F_DUPFD_CLOEXEC
|
||||||
|
dupfd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
|
||||||
|
#else
|
||||||
|
dupfd = dup(fd);
|
||||||
|
if (dupfd != -1) {
|
||||||
|
qemu_set_cloexec(dupfd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (dupfd == -1) {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
|
"Error duplicating fd: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the duplicate fd, and optionally the opaque string, to the fd set */
|
||||||
|
monitor_fdset_add_fd(dupfd, true, fdset_id, fd_opaque ? true : false,
|
||||||
|
fd_opaque, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cleanup_add_fd(QemuOpts *opts, void *opaque)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = qemu_opt_get_number(opts, "fd", -1);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
/* QEMU Block devices */
|
/* QEMU Block devices */
|
||||||
|
|
||||||
|
@ -3309,6 +3381,18 @@ int main(int argc, char **argv, char **envp)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QEMU_OPTION_add_fd:
|
||||||
|
#ifndef _WIN32
|
||||||
|
opts = qemu_opts_parse(qemu_find_opts("add-fd"), optarg, 0);
|
||||||
|
if (!opts) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
error_report("File descriptor passing is disabled on this "
|
||||||
|
"platform");
|
||||||
|
exit(1);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
os_parse_cmd_args(popt->index, optarg);
|
os_parse_cmd_args(popt->index, optarg);
|
||||||
}
|
}
|
||||||
|
@ -3320,6 +3404,16 @@ int main(int argc, char **argv, char **envp)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (qemu_opts_foreach(qemu_find_opts("add-fd"), parse_add_fd, NULL, 1)) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemu_opts_foreach(qemu_find_opts("add-fd"), cleanup_add_fd, NULL, 1)) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (machine == NULL) {
|
if (machine == NULL) {
|
||||||
fprintf(stderr, "No machine found.\n");
|
fprintf(stderr, "No machine found.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
Loading…
Reference in New Issue