From patchwork Mon Mar 7 20:10:41 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 85806 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C4911B6EE9 for ; Tue, 8 Mar 2011 07:25:23 +1100 (EST) Received: from localhost ([127.0.0.1]:41180 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pwgx8-0007jQ-Sl for incoming@patchwork.ozlabs.org; Mon, 07 Mar 2011 15:22:51 -0500 Received: from [140.186.70.92] (port=41496 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pwgm1-0001hF-M6 for qemu-devel@nongnu.org; Mon, 07 Mar 2011 15:11:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Pwgm0-0006ba-3r for qemu-devel@nongnu.org; Mon, 07 Mar 2011 15:11:21 -0500 Received: from e9.ny.us.ibm.com ([32.97.182.139]:48133) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Pwgm0-0006bO-0M for qemu-devel@nongnu.org; Mon, 07 Mar 2011 15:11:20 -0500 Received: from d01dlp02.pok.ibm.com (d01dlp02.pok.ibm.com [9.56.224.85]) by e9.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p27Jj0kZ015284 for ; Mon, 7 Mar 2011 14:45:01 -0500 Received: from d01relay05.pok.ibm.com (d01relay05.pok.ibm.com [9.56.227.237]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id 6CECD6E8044 for ; Mon, 7 Mar 2011 15:11:19 -0500 (EST) Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by d01relay05.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p27KBJDO230090 for ; Mon, 7 Mar 2011 15:11:19 -0500 Received: from d01av01.pok.ibm.com (loopback [127.0.0.1]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p27KBIdJ013011 for ; Mon, 7 Mar 2011 15:11:19 -0500 Received: from localhost.localdomain (sig-9-76-30-5.mts.ibm.com [9.76.30.5]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p27KAi8P010005; Mon, 7 Mar 2011 15:11:17 -0500 From: Michael Roth To: qemu-devel@nongnu.org Date: Mon, 7 Mar 2011 14:10:41 -0600 Message-Id: <1299528642-23631-16-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1299528642-23631-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1299528642-23631-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Content-Scanned: Fidelis XPS MAILER X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 32.97.182.139 Cc: agl@linux.vnet.ibm.com, stefanha@linux.vnet.ibm.com, Jes.Sorensen@redhat.com, mdroth@linux.vnet.ibm.com, markus_mueller@de.ibm.com, aliguori@linux.vnet.ibm.com, abeekhof@redhat.com Subject: [Qemu-devel] [RFC][PATCH v7 15/16] virtagent: qemu-va, system-level virtagent guest agent X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Michael Roth --- qemu-va.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 247 insertions(+), 0 deletions(-) create mode 100644 qemu-va.c diff --git a/qemu-va.c b/qemu-va.c new file mode 100644 index 0000000..a9ff56f --- /dev/null +++ b/qemu-va.c @@ -0,0 +1,247 @@ +/* + * virtagent - QEMU guest agent + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Michael Roth + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include "qemu-ioh.h" +#include "qemu-tool.h" +#include "virtagent-common.h" + +static bool verbose_enabled; +#define DEBUG_ENABLED + +#ifdef DEBUG_ENABLED +#define DEBUG(msg, ...) do { \ + fprintf(stderr, "%s:%s():L%d: " msg "\n", \ + __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \ +} while(0) +#else +#define DEBUG(msg, ...) do {} while (0) +#endif + +#define INFO(msg, ...) do { \ + if (!verbose_enabled) { \ + break; \ + } \ + warnx(msg, ## __VA_ARGS__); \ +} while(0) + +/* mirror qemu I/O loop for standalone daemon */ +static void main_loop_wait(int nonblocking) +{ + fd_set rfds, wfds, xfds; + int ret, nfds; + struct timeval tv; + int timeout = 100000; + + if (nonblocking) { + timeout = 0; + } + + /* poll any events */ + nfds = -1; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&xfds); + qemu_get_fdset(&nfds, &rfds, &wfds, &xfds); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); + + if (ret > 0) { + qemu_process_fd_handlers(&rfds, &wfds, &xfds); + } + + DEBUG("running timers..."); + qemu_run_all_timers(); +} + +static void usage(const char *cmd) +{ + printf( +"Usage: %s -c \n" +"QEMU virtagent guest agent %s\n" +"\n" +" -c, --channel channel method: one of unix-connect, virtio-serial, or\n" +" isa-serial\n" +" -p, --path channel path\n" +" -v, --verbose display extra debugging information\n" +" -d, --daemonize become a daemon\n" +" -h, --help display this help and exit\n" +"\n" +"Report bugs to \n" + , cmd, VA_VERSION); +} + +static int init_virtagent(const char *method, const char *path) { + VAContext ctx; + int ret; + + INFO("initializing agent..."); + + if (method == NULL) { + /* try virtio-serial as our default */ + method = "virtio-serial"; + } + + if (path == NULL) { + if (strcmp(method, "virtio-serial")) { + errx(EXIT_FAILURE, "must specify a path for this channel"); + } + /* try the default name for the virtio-serial port */ + path = VA_GUEST_PATH_VIRTIO_DEFAULT; + } + + /* initialize virtagent */ + ctx.is_host = false; + ctx.channel_method = method; + ctx.channel_path = path; + ret = va_init(ctx); + if (ret) { + errx(EXIT_FAILURE, "unable to initialize virtagent"); + } + + return 0; +} + +static void become_daemon(void) +{ + pid_t pid, sid; + int pidfd; + char *pidstr; + + pid = fork(); + if (pid < 0) + exit(EXIT_FAILURE); + if (pid > 0) { + exit(EXIT_SUCCESS); + } + + pidfd = open(VA_PIDFILE, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); + if (!pidfd || lockf(pidfd, F_TLOCK, 0)) + errx(EXIT_FAILURE, "Cannot lock pid file"); + + if (ftruncate(pidfd, 0) || lseek(pidfd, 0, SEEK_SET)) + errx(EXIT_FAILURE, "Cannot truncate pid file"); + if (asprintf(&pidstr, "%d", getpid()) == -1) + errx(EXIT_FAILURE, "Cannot allocate memory"); + if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) + errx(EXIT_FAILURE, "Failed to write pid file"); + free(pidstr); + + umask(0); + sid = setsid(); + if (sid < 0) + goto fail; + if ((chdir("/")) < 0) + goto fail; + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + return; + +fail: + unlink(VA_PIDFILE); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + const char *sopt = "hVvdc:p:", *channel_method = NULL, *channel_path = NULL; + struct option lopt[] = { + { "help", 0, NULL, 'h' }, + { "version", 0, NULL, 'V' }, + { "verbose", 0, NULL, 'v' }, + { "channel", 0, NULL, 'c' }, + { "path", 0, NULL, 'p' }, + { "daemonize", 0, NULL, 'd' }, + { NULL, 0, NULL, 0 } + }; + int opt_ind = 0, ch, ret, daemonize = 0; + + while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { + switch (ch) { + case 'c': + channel_method = optarg; + break; + case 'p': + channel_path = optarg; + break; + case 'v': + verbose_enabled = 1; + break; + case 'V': + printf("QEMU Virtagent %s\n", VA_VERSION); + return 0; + case 'd': + daemonize = 1; + break; + case 'h': + usage(argv[0]); + return 0; + case '?': + errx(EXIT_FAILURE, "Try '%s --help' for more information.", + argv[0]); + } + } + + if (daemonize) { + become_daemon(); + } + + init_clocks(); + configure_alarms("dynticks"); + if (init_timer_alarm() < 0) { + errx(EXIT_FAILURE, "could not initialize alarm timer"); + } + + /* initialize virtagent */ + ret = init_virtagent(channel_method, channel_path); + if (ret) { + errx(EXIT_FAILURE, "error initializing communication channel"); + } + + /* main i/o loop */ + for (;;) { + DEBUG("entering main_loop_wait()"); + main_loop_wait(0); + DEBUG("left main_loop_wait()"); + } + + unlink(VA_PIDFILE); + return 0; +}