From nobody Sun Apr 28 18:56:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1502640060704685.2585289112674; Sun, 13 Aug 2017 09:01:00 -0700 (PDT) Received: from localhost ([::1]:35474 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dgvJz-0001jg-GA for importer@patchew.org; Sun, 13 Aug 2017 12:00:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40056) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dgvIA-0000QP-HA for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dgvI5-0003kT-ME for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:06 -0400 Received: from mail-wm0-x243.google.com ([2a00:1450:400c:c09::243]:33792) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dgvI5-0003jV-Cb for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:01 -0400 Received: by mail-wm0-x243.google.com with SMTP id x64so11895426wmg.1 for ; Sun, 13 Aug 2017 08:58:59 -0700 (PDT) Received: from bark.daynix ([141.226.163.173]) by smtp.gmail.com with ESMTPSA id c68sm3909025wmh.21.2017.08.13.08.58.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 13 Aug 2017 08:58:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=O0Fj3aiivOBle73BtR39uw9jlWrsUkYg2MaEV1T+dWc=; b=cbgsw4HNfhcLASBOXAa+d1spFBvW2QizTxFm1sHoG8sTFtjv8ksnOLQ9cIZ3XQF2fp TO+8tWSv650iaaYfQycACeeEH341dYxzaoKfdwoQbUcEth66YEbrcsjsUlT8+2Ikz/KV nW6dvQXlO+tRKpp8E/kCyyqgbb5NFosKeyVGc/Y6KRnHPyn9wO8C2nkQ5eyDJALvqZhB OAuSzq028HdgHZAnqLcWkM+1Ztr77hlNm4Hm444B95HnjWAig1T5F6QOSQoqvEe/IijU LjI3sJ2lQvCPLjriEEZeVp9eA4aTNUXpcq/1ze4BQxbT1wtVrcAvZOCqmJw3/iAnVWkq KMSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=O0Fj3aiivOBle73BtR39uw9jlWrsUkYg2MaEV1T+dWc=; b=DpMksT12ktv7duuGq6Ps6RfI6QiRzhNbJEil6BoHLehl3XbGQ0tlPyzic4uHNu8cbC A1iLlcweZSRgkA/CXr3NXVhFzdnzZWiSByxNU3iK14IVvM2UP2B67oPuEZwwA5bsKQKx Z5CuaH8ODuMd3yVWrn5GkFZgLkiYfIPon9jT4hZ4wsn8es7WbxWJu9dcxDqmCNvfhHPl m2kKlOvX8x1lyZV8LRn8KL6HgMM7jSLqUWA1RK1L2iaflVOjpUUIDr4nuH3BMs+tnYPJ eg8fOo93XjIyeaNk1Y7O0eH0YElnatCoALC7lcAAAGt3Wsf3N+cNHS91usc87zeGLaG1 Xw0w== X-Gm-Message-State: AHYfb5iVU80qvd/qA1b459Wl9ys5YbupmB5E/ZfjYSZb4wbs2Atzut4U fjo6crKBw+e+bbKIRgo= X-Received: by 10.28.56.130 with SMTP id f124mr3303512wma.88.1502639938509; Sun, 13 Aug 2017 08:58:58 -0700 (PDT) From: Sameeh Jubran To: qemu-devel@nongnu.org, mdroth@linux.vnet.ibm.com Date: Sun, 13 Aug 2017 18:58:47 +0300 Message-Id: <20170813155849.11368-2-sameeh@daynix.com> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170813155849.11368-1-sameeh@daynix.com> References: <20170813155849.11368-1-sameeh@daynix.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::243 Subject: [Qemu-devel] [PATCH 1/3] qga: Channel: Add functions for checking serial status X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yan@daynix.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Sameeh Jubran This commit adds functions to check if the serial is connected/disconnected or else if it has been attached or detached. Signed-off-by: Sameeh Jubran --- qga/channel-posix.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ qga/channel-win32.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++ qga/channel.h | 9 ++++++++ 3 files changed, 123 insertions(+) diff --git a/qga/channel-posix.c b/qga/channel-posix.c index 3f34465..d307cf4 100644 --- a/qga/channel-posix.c +++ b/qga/channel-posix.c @@ -295,3 +295,57 @@ void ga_channel_free(GAChannel *c) } g_free(c); } + +static bool is_serial_present(GAChannelMethod method, const gchar *path, + int *error_code) +{ + int fd =3D -1; + bool ret =3D true; + + assert(error_code); + *error_code =3D 0; + + switch (method) { + case GA_CHANNEL_VIRTIO_SERIAL: + fd =3D qemu_open(path, O_RDWR | O_NONBLOCK +#ifndef CONFIG_SOLARIS + | O_ASYNC +#endif + ); + break; + case GA_CHANNEL_ISA_SERIAL: + fd =3D qemu_open(path, O_RDWR | O_NOCTTY | O_NONBLOCK); + break; + default: + ret =3D false; + } + if (fd < 0) { + *error_code =3D errno; + ret =3D false; + } else { + close(fd); + } + return ret; +} + +bool ga_channel_serial_is_present(GAChannelMethod method, const gchar *pat= h) +{ + int error_code =3D 0; + return is_serial_present(method, path, &error_code) || + error_code =3D=3D EBUSY; +} + +bool ga_channel_was_serial_attached(GAChannelMethod method, const gchar *p= ath, + bool is_serial_attached) +{ + int error_code =3D 0; + return !is_serial_attached && + is_serial_present(method, path, &error_code); +} +bool ga_channel_was_serial_detached(GAChannelMethod method, const gchar *p= ath, + bool is_serial_attached) +{ + int error_code =3D 0; + return is_serial_attached && !is_serial_present(method, path, &error_c= ode) + && error_code =3D=3D ENOENT; +} diff --git a/qga/channel-win32.c b/qga/channel-win32.c index 7e6dc4d..2d51bee 100644 --- a/qga/channel-win32.c +++ b/qga/channel-win32.c @@ -354,3 +354,63 @@ void ga_channel_free(GAChannel *c) g_free(c->rstate.buf); g_free(c); } + +static bool is_serial_present(GAChannelMethod method, const gchar *path, + DWORD *err) +{ + gchar newpath[MAXPATHLEN] =3D { 0 }; + bool ret =3D false; + + assert(err); + + if (method !=3D GA_CHANNEL_VIRTIO_SERIAL && method !=3D GA_CHANNEL_ISA= _SERIAL) { + g_critical("unsupported communication method"); + return false; + } + + if (method =3D=3D GA_CHANNEL_ISA_SERIAL) { + snprintf(newpath, sizeof(newpath), "\\\\.\\%s", path); + } else { + g_strlcpy(newpath, path, sizeof(newpath)); + } + + HANDLE handle =3D CreateFile(newpath, GENERIC_READ | GENERIC_WRITE, 0,= NULL, + OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); + + if (handle =3D=3D INVALID_HANDLE_VALUE) { + *err =3D GetLastError(); + ret =3D false; + } else { + ret =3D true; + } + + CloseHandle(handle); + return ret; +} + +bool ga_channel_serial_is_present(GAChannelMethod method, const gchar *pat= h) +{ + DWORD err_code; + return is_serial_present(method, path, &err_code) || + err_code =3D=3D ERROR_ACCESS_DENIED; +} + +bool ga_channel_was_serial_attached(GAChannelMethod method, const gchar *p= ath, + bool is_serial_attached) +{ + DWORD err_code; + return !is_serial_attached && is_serial_present(method, path, &err_cod= e); +} + +bool ga_channel_was_serial_detached(GAChannelMethod method, const gchar *p= ath, + bool is_serial_attached) +{ + DWORD err_code =3D NO_ERROR; + /* In order to make sure the serial that qemu-ga uses is the one t= hat + * was detached. We'll get the error ERROR_FILE_NOT_FOUND when + * attempting to call CreateFile with the serial path. + */ + return is_serial_attached && !is_serial_present(method, path, &err_= code) + && err_code =3D=3D ERROR_FILE_NOT_FOUND; +} diff --git a/qga/channel.h b/qga/channel.h index 1778416..acb3d73 100644 --- a/qga/channel.h +++ b/qga/channel.h @@ -12,6 +12,10 @@ #ifndef QGA_CHANNEL_H #define QGA_CHANNEL_H =20 +#ifndef _WIN32 +#define SUBSYSTEM_VIRTIO_SERIAL "virtio-ports"; +#define SUBSYSTEM_ISA_SERIAL "isa-serial"; +#endif =20 typedef struct GAChannel GAChannel; =20 @@ -30,5 +34,10 @@ GAChannel *ga_channel_new(GAChannelMethod method, const = gchar *path, void ga_channel_free(GAChannel *c); GIOStatus ga_channel_read(GAChannel *c, gchar *buf, gsize size, gsize *cou= nt); GIOStatus ga_channel_write_all(GAChannel *c, const gchar *buf, gsize size); +bool ga_channel_serial_is_present(GAChannelMethod method, const gchar *pat= h); +bool ga_channel_was_serial_attached(GAChannelMethod method, const gchar *p= ath, + bool is_serial_attached); +bool ga_channel_was_serial_detached(GAChannelMethod method, const gchar *p= ath, + bool is_serial_attached); =20 #endif --=20 2.9.4 From nobody Sun Apr 28 18:56:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1502640061897394.83600211941257; Sun, 13 Aug 2017 09:01:01 -0700 (PDT) Received: from localhost ([::1]:35475 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dgvK0-0001kd-ME for importer@patchew.org; Sun, 13 Aug 2017 12:01:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40057) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dgvIA-0000QQ-HU for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dgvI6-0003lB-Jh for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:06 -0400 Received: from mail-wm0-x244.google.com ([2a00:1450:400c:c09::244]:33393) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dgvI6-0003jj-DM for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:02 -0400 Received: by mail-wm0-x244.google.com with SMTP id q189so11935383wmd.0 for ; Sun, 13 Aug 2017 08:59:00 -0700 (PDT) Received: from bark.daynix ([141.226.163.173]) by smtp.gmail.com with ESMTPSA id c68sm3909025wmh.21.2017.08.13.08.58.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 13 Aug 2017 08:58:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=VaUMBz+Les8fQV/f2p8kly7KfUKxbt4a9CDrxuQ/wFk=; b=0tFC1hdJelJhPLqg4CP91COw/lbW8zRbqlikygCkgawLQdiN4Z/LJqWuGGrfDAnsbt WT7tGopyc57ilrL1NEVd2u+2/cMC6O7Cr/nE5Q3vYFYyNUv6eTth3AekuIrpuAu2nH8/ ajIL0x6zcBC0ldc++ny3tUaGfpgySt3sUigK4S4apZRfAmGPHXJ0akPIWQYUqYDKrXov kYLox2u78V8lDa7NPVZrd+yQ9XMzWUVe+ACAuGQnHX1BVcxs8nnr6zwakf97V/G4Ay0F cIMsLTSGHQzFVG/lfEkYk5NJ8aDM171IWvyvWL08oWrtV1wWuTKTPhIoP0hqlbUt0V20 tR8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=VaUMBz+Les8fQV/f2p8kly7KfUKxbt4a9CDrxuQ/wFk=; b=Fjhxip43aX8quGSU6fsI2kJQVEjfRJzxYUPU6XFNKqbV9aLO+O/PTtIYBHUYZYS0Hf pdcQyS2QrVYQW3dYFiTZgAO8VMl4E6RBPuwYmAVU1dPPJCDJmsu/7DbHgkrJKEWtFg/s X4RXBwpO2I118OEyPb69+W4U40hebr5NKAeb5nTvc/rsL5+mseYuyOjeGp/oIOw1ajxg irsdOajxLpu6WcvtsGRq+BFEwGgopG5gbXST+MFDe27LRKZTtaoRa9gNWLz7Ox9bSLQm TqMQLC9Mo3pPP7NDEB8bq9iC4UgLe6FP3YLVeUw2S5xbhohfO7TtMdy/MDk37CQjNL90 3Nvg== X-Gm-Message-State: AHYfb5idiRXur+tCwQirZeOVPCqr52EHDQpMADRBOW8TECBxDWoVHuAY 5fiOfoxn5O9mcOJ/aEw= X-Received: by 10.28.30.77 with SMTP id e74mr2580044wme.172.1502639939667; Sun, 13 Aug 2017 08:58:59 -0700 (PDT) From: Sameeh Jubran To: qemu-devel@nongnu.org, mdroth@linux.vnet.ibm.com Date: Sun, 13 Aug 2017 18:58:48 +0300 Message-Id: <20170813155849.11368-3-sameeh@daynix.com> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170813155849.11368-1-sameeh@daynix.com> References: <20170813155849.11368-1-sameeh@daynix.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::244 Subject: [Qemu-devel] [PATCH 2/3] qga: main: make qga config and socket activation global X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yan@daynix.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Sameeh Jubran Signed-off-by: Sameeh Jubran --- qga/main.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/qga/main.c b/qga/main.c index 1b381d0..cf312b9 100644 --- a/qga/main.c +++ b/qga/main.c @@ -92,7 +92,28 @@ struct GAState { GAPersistentState pstate; }; =20 +typedef struct GAConfig { + char *channel_path; + char *method; + char *log_filepath; + char *pid_filepath; +#ifdef CONFIG_FSFREEZE + char *fsfreeze_hook; +#endif + char *state_dir; +#ifdef _WIN32 + const char *service; +#endif + gchar *bliststr; /* blacklist may point to this string */ + GList *blacklist; + int daemonize; + GLogLevelFlags log_level; + int dumpconf; +} GAConfig; + struct GAState *ga_state; +struct GAConfig *ga_config; +int ga_socket_activation; QmpCommandList ga_commands; =20 /* commands that are safe to issue while filesystems are frozen */ @@ -942,25 +963,6 @@ static GList *split_list(const gchar *str, const gchar= *delim) return list; } =20 -typedef struct GAConfig { - char *channel_path; - char *method; - char *log_filepath; - char *pid_filepath; -#ifdef CONFIG_FSFREEZE - char *fsfreeze_hook; -#endif - char *state_dir; -#ifdef _WIN32 - const char *service; -#endif - gchar *bliststr; /* blacklist may point to this string */ - GList *blacklist; - int daemonize; - GLogLevelFlags log_level; - int dumpconf; -} GAConfig; - static void config_load(GAConfig *config) { GError *gerr =3D NULL; @@ -1353,7 +1355,7 @@ int main(int argc, char **argv) { int ret =3D EXIT_SUCCESS; GAState *s =3D g_new0(GAState, 1); - GAConfig *config =3D g_new0(GAConfig, 1); + GAConfig *config =3D ga_config =3D g_new0(GAConfig, 1); int socket_activation; =20 config->log_level =3D G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL; @@ -1376,7 +1378,7 @@ int main(int argc, char **argv) config->method =3D g_strdup("virtio-serial"); } =20 - socket_activation =3D check_socket_activation(); + ga_socket_activation =3D socket_activation =3D check_socket_activation= (); if (socket_activation > 1) { g_critical("qemu-ga only supports listening on one socket"); ret =3D EXIT_FAILURE; --=20 2.9.4 From nobody Sun Apr 28 18:56:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1502640226085227.84496683231623; Sun, 13 Aug 2017 09:03:46 -0700 (PDT) Received: from localhost ([::1]:35741 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dgvMe-0004Lq-W5 for importer@patchew.org; Sun, 13 Aug 2017 12:03:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40059) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dgvIA-0000QR-Hp for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dgvI6-0003lU-Nr for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:06 -0400 Received: from mail-wm0-x242.google.com ([2a00:1450:400c:c09::242]:37128) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dgvI6-0003ka-Dr for qemu-devel@nongnu.org; Sun, 13 Aug 2017 11:59:02 -0400 Received: by mail-wm0-x242.google.com with SMTP id t138so11858908wmt.4 for ; Sun, 13 Aug 2017 08:59:02 -0700 (PDT) Received: from bark.daynix ([141.226.163.173]) by smtp.gmail.com with ESMTPSA id c68sm3909025wmh.21.2017.08.13.08.58.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 13 Aug 2017 08:59:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=AbyCQedWP3DXutTbPBM43eKPFZBKOW2sMDmT9vEMGy4=; b=PQq4hepz7MFyhJlPK/LWsSqlGHGO0Ju25H2qc2VvSBHfdTnF4T8vdV3UUFCljzH68u dOkf5fAxsc8Jrzzu8xlX98rU82cvIZBnnxq/L39IqP/z1j9YeuCNpw6Sy2jmzIKvtttz k1S4Goy5EzJAQQlyrlV9edtgvtS84lr7BvYpLquCB6hN1Os/SEGgHuw5cT4WGY9hhf0e negq+HiDYorj/X/FVZzM6FTqPs+ZcVhxhp3PS2fOhCaXADvJbwf03b1adMcBdP5Q5nnb OtAFuhCwC5eMPr2Tq+ICmwFwPvG/S6kgB5JHnW6YvbnTcaod/jEImahghDRN8MCHvQs3 K1dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=AbyCQedWP3DXutTbPBM43eKPFZBKOW2sMDmT9vEMGy4=; b=RKagtdgb2QeiwQ5ZvLvhWX0CWdtDhBWcNZAY5gMFrdoNGApKryJ9F9j8TmaQk7Zhsc +C+hEx6Dk0Q+sTeeIpdSMX3xuaIZIoJIwLXmXIETuDr/ceZpT5uYoAAl22MiBdGHFCXN GmHUW5ue0+eom++WBsNIFOkq70m7nHMuvw6qUiSNaABUROwrQKzSkF19vA+eUMHwAXxw 1Xpjc7GedR1LZugQvaJFBKIW1d+SAgPHCab8NwPnLkz+N5YT2Tl6MiFrU/y+FAAlFtOD VMnGmSzb5T+H6OMoUrRPczxWZQsR1u66PylQzIHQvYrsfmL6Iqvbw7onE1rGIMj3CmZp CMYA== X-Gm-Message-State: AHYfb5jYrAyiEHWvlBeYTrlUmhTy9K39COrGO9NqNc1lbFDXhm6xbwOP mq/15pgwyzjsf6zYqIc= X-Received: by 10.28.165.11 with SMTP id o11mr2680113wme.49.1502639940974; Sun, 13 Aug 2017 08:59:00 -0700 (PDT) From: Sameeh Jubran To: qemu-devel@nongnu.org, mdroth@linux.vnet.ibm.com Date: Sun, 13 Aug 2017 18:58:49 +0300 Message-Id: <20170813155849.11368-4-sameeh@daynix.com> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170813155849.11368-1-sameeh@daynix.com> References: <20170813155849.11368-1-sameeh@daynix.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::242 Subject: [Qemu-devel] [PATCH 3/3] qga: Prevent qemu-ga exit if serial doesn't exist X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yan@daynix.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Sameeh Jubran Currently whenever the qemu-ga's service doesn't find the virtio-serial it terminates. This commit addresses this issue by listening to the serial = events by registering for notifications for the chosen serial and it handles chann= el initialization accordingily. A list of possible scenarios of which could lead to this behavour: * qemu-ga's service is started while the virtio-serial driver hasn't been i= nstalled yet * hotplug/ unplug of the virtio-serial device * upgrading the virtio-serial driver Note: This problem is much more common on Windows as the virtio-serial driver should be installed by the user and isn't shipped with the Windows O= S. Signed-off-by: Sameeh Jubran --- Makefile | 4 + qga/main.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++= ++-- qga/service-win32.h | 4 + 3 files changed, 239 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index ef72148..82f26d5 100644 --- a/Makefile +++ b/Makefile @@ -203,6 +203,10 @@ $(call set-vpath, $(SRC_PATH)) =20 LIBS+=3D-lz $(LIBS_TOOLS) =20 +ifndef CONFIG_WIN32 +LIBS_QGA+=3D-ludev +endif + HELPERS-$(CONFIG_LINUX) =3D qemu-bridge-helper$(EXESUF) =20 ifdef BUILD_DOCS diff --git a/qga/main.c b/qga/main.c index cf312b9..d727880 100644 --- a/qga/main.c +++ b/qga/main.c @@ -16,6 +16,8 @@ #ifndef _WIN32 #include #include +#include +#include #endif #include "qapi/qmp/json-streamer.h" #include "qapi/qmp/json-parser.h" @@ -30,6 +32,7 @@ #include "qemu/sockets.h" #include "qemu/systemd.h" #ifdef _WIN32 +#include #include "qga/service-win32.h" #include "qga/vss-win32.h" #endif @@ -74,6 +77,10 @@ struct GAState { GLogLevelFlags log_level; FILE *log_file; bool logging_enabled; + bool serial_connected; +#ifndef _WIN32 + struct udev_monitor *udev_monitor; +#endif #ifdef _WIN32 GAService service; #endif @@ -130,9 +137,15 @@ static const char *ga_freeze_whitelist[] =3D { #ifdef _WIN32 DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx); +DWORD WINAPI handle_serial_device_events(DWORD type, LPVOID data); VOID WINAPI service_main(DWORD argc, TCHAR *argv[]); #endif =20 +static bool get_channel_method(GAChannelMethod *channel_method, + const gchar *method, GAState *s); +static gboolean channel_init(GAState *s, const gchar *method, const gchar = *path, + int listen_fd, bool *serial_connected); + static void init_dfl_pathnames(void) { @@ -186,6 +199,136 @@ static void quit_handler(int sig) } =20 #ifndef _WIN32 +static int get_method_udev_subsystem(const char **serial_subsystem) +{ + if (strcmp(ga_config->method, "virtio-serial") =3D=3D 0) { + *serial_subsystem =3D SUBSYSTEM_VIRTIO_SERIAL; + } else if (strcmp(ga_config->method, "isa-serial") =3D=3D 0) { + /* try the default path for the serial port - COM1 */ + *serial_subsystem =3D SUBSYSTEM_ISA_SERIAL; + } else { + serial_subsystem =3D NULL; + return -1; + } + return 0; +} + +static gboolean serial_event_callback(GIOChannel *source, + GIOCondition condition, gpointer data) +{ + struct udev_monitor *mon =3D ga_state->udev_monitor; + const char *serial_subsystem =3D NULL; + struct udev_device *dev; + + if (get_method_udev_subsystem(&serial_subsystem) =3D=3D -1) { + return false; + } + dev =3D udev_monitor_receive_device(mon); + + if (dev && serial_subsystem && strcmp(udev_device_get_subsystem(dev), + serial_subsystem) =3D=3D 0) { + + GAChannelMethod channel_method; + get_channel_method(&channel_method, ga_config->method, ga_state); + if (ga_channel_was_serial_attached(channel_method, + ga_config->channel_path, ga_state->serial_connected)) { + ga_state->serial_connected =3D true; + if (!channel_init(ga_state, + ga_config->method, ga_config->channel_path, + ga_socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1, + &ga_state->serial_connected)) { + g_critical("failed to initialize guest agent channel"); + } + } + + if (ga_channel_was_serial_detached(channel_method, + ga_config->channel_path, ga_state->serial_connected)) { + ga_state->serial_connected =3D false; + ga_channel_free(ga_state->channel); + } + udev_device_unref(dev); + } + return true; +} + +static int monitor_serial_events(void) +{ + int ret =3D 0; + const char *serial_subsystem =3D NULL; + struct udev *udev =3D NULL; + ga_state->udev_monitor =3D NULL; + GIOChannel *channel =3D NULL; + GSource *watch_source =3D NULL; + if (get_method_udev_subsystem(&serial_subsystem) =3D=3D -1) { + ret =3D -1; + goto out; + } + + udev =3D udev_new(); + if (!udev) { + g_error("Couldn't create udev\n"); + ret =3D -1; + goto out; + } + + ga_state->udev_monitor =3D + udev_monitor_new_from_netlink(udev, "udev"); + if (!ga_state->udev_monitor) { + ret =3D -1; + goto out; + } else { + /* We don't want the udev_monitor to be freed on out, so increase + * ref count + */ + udev_monitor_ref(ga_state->udev_monitor); + } + + if (udev_monitor_filter_add_match_subsystem_devtype(ga_state->udev_mon= itor, + serial_subsystem, NULL) < 0 || + udev_monitor_enable_receiving(ga_state->udev_monitor) < 0) { + ret =3D -1; + goto out; + } + + channel =3D + g_io_channel_unix_new(udev_monitor_get_fd(ga_state->udev_monitor)); + if (!channel) { + ret =3D -1; + goto out; + } + watch_source =3D g_io_create_watch(channel, G_IO_IN); + if (!watch_source) { + ret =3D -1; + goto out; + } + g_source_set_callback(watch_source, (GSourceFunc)serial_event_callback, + ga_state->udev_monitor, NULL); + g_source_attach(watch_source, g_main_loop_get_context(ga_state->main_l= oop)); + +out: + if (udev) { + udev_unref(udev); + } + if (ga_state->udev_monitor) { + udev_monitor_unref(ga_state->udev_monitor); + } + if (channel) { + g_io_channel_unref(channel); + } + if (watch_source) { + g_source_unref(watch_source); + } + + return ret; +} + +static void free_monitor_resources(void) +{ + if (ga_state->udev_monitor) { + udev_monitor_unref(ga_state->udev_monitor); + } +} + static gboolean register_signal_handlers(void) { struct sigaction sigact; @@ -694,24 +837,38 @@ static gboolean channel_event_cb(GIOCondition conditi= on, gpointer data) return true; } =20 -static gboolean channel_init(GAState *s, const gchar *method, const gchar = *path, - int listen_fd) +static bool get_channel_method(GAChannelMethod *channel_method, + const gchar *method, GAState *s) { - GAChannelMethod channel_method; + assert(channel_method); + assert(method); =20 if (strcmp(method, "virtio-serial") =3D=3D 0) { + assert(s); s->virtio =3D true; /* virtio requires special handling in some ca= ses */ - channel_method =3D GA_CHANNEL_VIRTIO_SERIAL; + *channel_method =3D GA_CHANNEL_VIRTIO_SERIAL; } else if (strcmp(method, "isa-serial") =3D=3D 0) { - channel_method =3D GA_CHANNEL_ISA_SERIAL; + *channel_method =3D GA_CHANNEL_ISA_SERIAL; } else if (strcmp(method, "unix-listen") =3D=3D 0) { - channel_method =3D GA_CHANNEL_UNIX_LISTEN; + *channel_method =3D GA_CHANNEL_UNIX_LISTEN; } else if (strcmp(method, "vsock-listen") =3D=3D 0) { - channel_method =3D GA_CHANNEL_VSOCK_LISTEN; + *channel_method =3D GA_CHANNEL_VSOCK_LISTEN; } else { g_critical("unsupported channel method/type: %s", method); return false; } + return true; +} + +static gboolean channel_init(GAState *s, const gchar *method, const gchar = *path, + int listen_fd, bool *serial_connected) +{ + assert(serial_connected); + GAChannelMethod channel_method; + if (!get_channel_method(&channel_method, method, s)) { + return false; + } + *serial_connected =3D ga_channel_serial_is_present(channel_method, pat= h); =20 s->channel =3D ga_channel_new(channel_method, path, listen_fd, channel_event_cb, s); @@ -724,6 +881,48 @@ static gboolean channel_init(GAState *s, const gchar *= method, const gchar *path, } =20 #ifdef _WIN32 +DWORD WINAPI handle_serial_device_events(DWORD type, LPVOID data) +{ + DWORD ret =3D NO_ERROR; + PDEV_BROADCAST_HDR broadcast_header =3D (PDEV_BROADCAST_HDR)data; + GAChannelMethod channel_method; + + if (broadcast_header->dbch_devicetype =3D=3D DBT_DEVTYP_DEVICEINTERFAC= E) { + get_channel_method(&channel_method, ga_config->method, ga_state); + switch (type) { + /* Device inserted */ + case DBT_DEVICEARRIVAL: + /* Start QEMU-ga's service */ + if (ga_channel_was_serial_attached(channel_method, + ga_config->channel_path, ga_state->serial_connected)) { + if (!channel_init(ga_state, + ga_config->method, ga_config->channel_path, + ga_socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1, + &ga_state->serial_connected)) { + g_critical("failed to initialize guest agent channel"); + ret =3D EXIT_FAILURE; + } + } + break; + /* Device removed */ + case DBT_DEVICEQUERYREMOVE: + case DBT_DEVICEREMOVEPENDING: + case DBT_DEVICEREMOVECOMPLETE: + + /* Stop QEMU-ga's service */ + if (ga_channel_was_serial_detached(channel_method, + ga_config->channel_path, ga_state->serial_connected)) { + ga_state->serial_connected =3D false; + ga_channel_free(ga_state->channel); + } + break; + default: + ret =3D ERROR_CALL_NOT_IMPLEMENTED; + } + } + return ret; +} + DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx) { @@ -738,6 +937,9 @@ DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD typ= e, LPVOID data, service->status.dwCurrentState =3D SERVICE_STOP_PENDING; SetServiceStatus(service->status_handle, &service->status); break; + case SERVICE_CONTROL_DEVICEEVENT: + handle_serial_device_events(type, data); + break; =20 default: ret =3D ERROR_CALL_NOT_IMPLEMENTED; @@ -764,10 +966,24 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) service->status.dwServiceSpecificExitCode =3D NO_ERROR; service->status.dwCheckPoint =3D 0; service->status.dwWaitHint =3D 0; + DEV_BROADCAST_DEVICEINTERFACE notification_filter; + ZeroMemory(¬ification_filter, sizeof(notification_filter)); + notification_filter.dbcc_devicetype =3D DBT_DEVTYP_DEVICEINTERFACE; + notification_filter.dbcc_size =3D sizeof(DEV_BROADCAST_DEVICEINTERFACE= ); + notification_filter.dbcc_classguid =3D GUID_VIOSERIAL_PORT; + + service->device_notification_handle =3D + RegisterDeviceNotification(service->status_handle, + ¬ification_filter, DEVICE_NOTIFY_SERVICE_HANDLE); + if (!service->device_notification_handle) { + g_critical("Failed to register device notification handle!\n"); + return; + } SetServiceStatus(service->status_handle, &service->status); =20 g_main_loop_run(ga_state->main_loop); =20 + UnregisterDeviceNotification(service->device_notification_handle); service->status.dwCurrentState =3D SERVICE_STOPPED; SetServiceStatus(service->status_handle, &service->status); } @@ -1330,20 +1546,26 @@ static int run_agent(GAState *s, GAConfig *config, = int socket_activation) #endif =20 s->main_loop =3D g_main_loop_new(NULL, false); - if (!channel_init(ga_state, config->method, config->channel_path, - socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1)= ) { + socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1, + &ga_state->serial_connected) && + ga_state->serial_connected) { g_critical("failed to initialize guest agent channel"); return EXIT_FAILURE; } #ifndef _WIN32 + monitor_serial_events(); g_main_loop_run(ga_state->main_loop); + free_monitor_resources(); #else if (config->daemonize) { SERVICE_TABLE_ENTRY service_table[] =3D { { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } }; StartServiceCtrlDispatcher(service_table); } else { + if (!ga_state->serial_connected) { + return EXIT_FAILURE; + } g_main_loop_run(ga_state->main_loop); } #endif diff --git a/qga/service-win32.h b/qga/service-win32.h index 89e99df..7b16d69 100644 --- a/qga/service-win32.h +++ b/qga/service-win32.h @@ -20,9 +20,13 @@ #define QGA_SERVICE_NAME "qemu-ga" #define QGA_SERVICE_DESCRIPTION "Enables integration with QEMU machine em= ulator and virtualizer." =20 +static const GUID GUID_VIOSERIAL_PORT =3D { 0x6fde7521, 0x1b65, 0x48ae, +{ 0xb6, 0x28, 0x80, 0xbe, 0x62, 0x1, 0x60, 0x26 } }; + typedef struct GAService { SERVICE_STATUS status; SERVICE_STATUS_HANDLE status_handle; + HDEVNOTIFY device_notification_handle; } GAService; =20 int ga_install_service(const char *path, const char *logfile, --=20 2.9.4