From nobody Mon Feb 9 07:56:00 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1610749826; cv=none; d=zohomail.com; s=zohoarc; b=Dl9McbnCdM1zoR1RsrIKkqAooe4lm3mbWhTfK4h+nHKfWb9nPPNa/+HfbIpC0X3yEZnNApqHmT7URAnVffHZlwq4WlCZ2mReECt5VDsPdriPGprVh0Jhkyg85WT1CNGgSsfv2/2DV2FK1pp0JXvaJ0qx2jvK025kHKci/nxgT4Q= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1610749826; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=KWgjrTEuiayZF8/BgvVMzkhWJRnIaXA0O75FslQATXA=; b=aR1gvsVib9ykftQy0kWW5sX2SkgeJpfxDGaWj8KLA2svHDq09Dz/zhnHezyVj35u57TZcFxNfxVVKZPiptNz93D0XfqN3JkG5LNqUojEUyIdohbsz2sodc7uNIlEdljFstQ2cBK+vOGOclKuZnVi4FzAAL4G22exvuZOGmwXmmQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) header.from= Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1610749826333482.3759595091981; Fri, 15 Jan 2021 14:30:26 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.68669.123008 (Exim 4.92) (envelope-from ) id 1l0Xbe-00078G-Cp; Fri, 15 Jan 2021 22:30:10 +0000 Received: by outflank-mailman (output) from mailman id 68669.123008; Fri, 15 Jan 2021 22:30:10 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1l0Xbe-000788-8I; Fri, 15 Jan 2021 22:30:10 +0000 Received: by outflank-mailman (input) for mailman id 68669; Fri, 15 Jan 2021 22:30:09 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1l0Xbd-00062b-8R for xen-devel@lists.xenproject.org; Fri, 15 Jan 2021 22:30:09 +0000 Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id a99ab02d-4f0e-4962-a36f-76d7ea59a394; Fri, 15 Jan 2021 22:29:50 +0000 (UTC) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: a99ab02d-4f0e-4962-a36f-76d7ea59a394 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1610749790; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/5XsBUrTdTecpeweYTHsOPIvx533UyFebG9xiAWZm4o=; b=S523PR3ikHZ7+pu6Yhh7EbWptRIrCQya3MIk5ARLG737ltHYZ9jEK0g3 P3WdNHMyUQbgsm6di+0r4LzsYgeOx9Ytz2Da6wO0vbJfFhoF+yzVNiwyQ iValc2/YSi1lBPspFEAQLJNc75mEvsUgUv1J8Ki1fTRtG4PkzrYfmJL0k 4=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: +uE/EqKNKp6zxkGhJ1iFDx0/H3s4L/hLIdbYsNOxuclIOzTmKkH7g1lAlqt/OS6Mm1z9ukDUWp L51Dq689FH+nGPOeW1r8RyMmBDDHgG+kWd1nIC4LOwWRn6gZKev1gp8uFWCMSTqNFf6SJnRfv8 LuztWlWKqlIpZVGyvEW68dX/VaobgPthen1Eri0UbZ83FP8Wg1a0FH5TIsjfC8ruN+AA+U4+zm 5M1Efb4fjrrQlRGtFfhN96YAlyZFTLGZFJhXnOs0D4KrPM8KalfTARsQpJZTMtOJFyA4wi8hoM WWs= X-SBRS: 5.1 X-MesageID: 35434452 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.79,350,1602561600"; d="scan'208";a="35434452" From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= To: CC: Juergen Gross , Andrew Cooper , George Dunlap , "Ian Jackson" , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu , Paul Durrant , Julien Grall Subject: [PATCH v2 1/8] tools/xenstore: add live update command to xenstore-control Date: Fri, 15 Jan 2021 22:28:43 +0000 Message-ID: <89d027f191af20c39dbf9d37dfcd602c2669511d.1610748224.git.edvin.torok@citrix.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @citrix.com) Content-Type: text/plain; charset="utf-8" From: Juergen Gross Add the "live-update" command to xenstore-control enabling updating xenstored to a new version in a running Xen system. With -c it is possible to pass a different command line to the new instance of xenstored. This will replace the command line used for the invocation of the just running xenstored instance. The running xenstored (or xenstore-stubdom) needs to support live updating, of course. For now just add a small dummy handler to C xenstore denying any live update action. Signed-off-by: Juergen Gross Reviewed-by: Paul Durrant Reviewed-by: Julien Grall --- docs/misc/xenstore.txt | 21 ++ tools/xenstore/Makefile | 3 +- tools/xenstore/xenstore_control.c | 332 ++++++++++++++++++++++++++++-- 3 files changed, 339 insertions(+), 17 deletions(-) diff --git a/docs/misc/xenstore.txt b/docs/misc/xenstore.txt index 2081f20f55..1480742330 100644 --- a/docs/misc/xenstore.txt +++ b/docs/misc/xenstore.txt @@ -317,6 +317,27 @@ CONTROL |[|] Current commands are: check checks xenstored innards + live-update||+ + perform a live-update of the Xenstore daemon, only to + be used via xenstore-control command. + are implementation specific and are used for + different steps of the live-update processing. Currently + supported are: + -f specify new daemon binary + -b specify size of new stubdom binary + -d transfer chunk of new + stubdom binary + -c specify new command line to use + -s [-t ] [-F] start live update process (-t specifies + timeout in seconds to wait for active transactions + to finish, default is 60 seconds; -F will force + live update to happen even with running transactions + after timeout elapsed) + -a abort live update handling + All sub-options will return "OK" in case of success or an + error string in case of failure. -s can return "BUSY" in case + of an active transaction, a retry of -s can be done in that + case. log|on turn xenstore logging on log|off diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile index 9a0f0d012d..ab89e22d3a 100644 --- a/tools/xenstore/Makefile +++ b/tools/xenstore/Makefile @@ -11,6 +11,7 @@ CFLAGS +=3D -include $(XEN_ROOT)/tools/config.h CFLAGS +=3D -I./include CFLAGS +=3D $(CFLAGS_libxenevtchn) CFLAGS +=3D $(CFLAGS_libxenctrl) +CFLAGS +=3D $(CFLAGS_libxenguest) CFLAGS +=3D $(CFLAGS_libxentoolcore) CFLAGS +=3D -DXEN_LIB_STORED=3D"\"$(XEN_LIB_STORED)\"" CFLAGS +=3D -DXEN_RUN_STORED=3D"\"$(XEN_RUN_STORED)\"" @@ -81,7 +82,7 @@ xenstore: xenstore_client.o $(CC) $< $(LDFLAGS) $(LDLIBS_libxenstore) $(LDLIBS_libxentoolcore) $(SOCK= ET_LIBS) -o $@ $(APPEND_LDFLAGS) =20 xenstore-control: xenstore_control.o - $(CC) $< $(LDFLAGS) $(LDLIBS_libxenstore) $(LDLIBS_libxentoolcore) $(SOCK= ET_LIBS) -o $@ $(APPEND_LDFLAGS) + $(CC) $< $(LDFLAGS) $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_l= ibxenguest) $(LDLIBS_libxentoolcore) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS) =20 xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o $(CC) $^ $(LDFLAGS) -o $@ $(APPEND_LDFLAGS) diff --git a/tools/xenstore/xenstore_control.c b/tools/xenstore/xenstore_co= ntrol.c index afa04495a7..5ca015a07d 100644 --- a/tools/xenstore/xenstore_control.c +++ b/tools/xenstore/xenstore_control.c @@ -1,9 +1,311 @@ +#define _GNU_SOURCE +#include #include #include #include +#include +#include +#include =20 #include "xenstore.h" =20 +/* Add a string plus terminating 0 byte to buf, returning new len. */ +static int add_to_buf(char **buf, const char *val, int len) +{ + int vallen =3D strlen(val) + 1; + + if (len < 0) + return -1; + + *buf =3D realloc(*buf, len + vallen); + if (!*buf) + return -1; + + strcpy(*buf + len, val); + + return len + vallen; +} + +static int live_update_start(struct xs_handle *xsh, bool force, unsigned i= nt to) +{ + int len =3D 0; + char *buf =3D NULL, *ret; + time_t time_start; + + if (asprintf(&ret, "%u", to) < 0) + return 1; + len =3D add_to_buf(&buf, "-s", len); + len =3D add_to_buf(&buf, "-t", len); + len =3D add_to_buf(&buf, ret, len); + free(ret); + if (force) + len =3D add_to_buf(&buf, "-F", len); + if (len < 0) + return 1; + + for (time_start =3D time(NULL); time(NULL) - time_start < to;) { + ret =3D xs_control_command(xsh, "live-update", buf, len); + if (!ret) + goto err; + if (strcmp(ret, "BUSY")) + break; + } + + if (strcmp(ret, "OK")) + goto err; + + free(buf); + free(ret); + + return 0; + + err: + fprintf(stderr, "Starting live update failed:\n%s\n", + ret ? : strerror(errno)); + free(buf); + free(ret); + + return 3; +} + +static int live_update_cmdline(struct xs_handle *xsh, const char *cmdline) +{ + int len =3D 0, rc =3D 0; + char *buf =3D NULL, *ret; + + len =3D add_to_buf(&buf, "-c", len); + len =3D add_to_buf(&buf, cmdline, len); + if (len < 0) + return 1; + + ret =3D xs_control_command(xsh, "live-update", buf, len); + free(buf); + if (!ret || strcmp(ret, "OK")) { + fprintf(stderr, "Setting update binary failed:\n%s\n", + ret ? : strerror(errno)); + rc =3D 3; + } + free(ret); + + return rc; +} + +static int send_kernel_blob(struct xs_handle *xsh, const char *binary) +{ + int rc =3D 0, len =3D 0; + xc_interface *xch; + struct xc_dom_image *dom; + char *ret, *buf =3D NULL; + size_t off, sz; +#define BLOB_CHUNK_SZ 2048 + + xch =3D xc_interface_open(NULL, NULL, 0); + if (!xch) { + fprintf(stderr, "xc_interface_open() failed\n"); + return 1; + } + + dom =3D xc_dom_allocate(xch, NULL, NULL); + if (!dom) { + rc =3D 1; + goto out_close; + } + + rc =3D xc_dom_kernel_file(dom, binary); + if (rc) { + rc =3D 1; + goto out_rel; + } + + if (asprintf(&ret, "%zu", dom->kernel_size) < 0) { + rc =3D 1; + goto out_rel; + } + len =3D add_to_buf(&buf, "-b", len); + len =3D add_to_buf(&buf, ret, len); + free(ret); + if (len < 0) { + rc =3D 1; + goto out_rel; + } + ret =3D xs_control_command(xsh, "live-update", buf, len); + free(buf); + if (!ret || strcmp(ret, "OK")) { + fprintf(stderr, "Starting live update failed:\n%s\n", + ret ? : strerror(errno)); + rc =3D 3; + } + free(ret); + if (rc) + goto out_rel; + + /* buf capable to hold "-d" <1..2048> BLOB_CHUNK_SZ and a terminating = 0. */ + buf =3D malloc(3 + 5 + BLOB_CHUNK_SZ + 1); + if (!buf) { + rc =3D 1; + goto out_rel; + } + + strcpy(buf, "-d"); + sz =3D BLOB_CHUNK_SZ; + for (off =3D 0; off < dom->kernel_size; off +=3D BLOB_CHUNK_SZ) { + if (dom->kernel_size - off < BLOB_CHUNK_SZ) + sz =3D dom->kernel_size - off; + sprintf(buf + 3, "%zu", sz); + len =3D 3 + strlen(buf + 3) + 1; + memcpy(buf + len, dom->kernel_blob + off, sz); + buf[len + sz] =3D 0; + len +=3D sz + 1; + ret =3D xs_control_command(xsh, "live-update", buf, len); + if (!ret || strcmp(ret, "OK")) { + fprintf(stderr, "Transfer of new binary failed:\n%s\n", + ret ? : strerror(errno)); + rc =3D 3; + free(ret); + break; + } + free(ret); + } + + free(buf); + + out_rel: + xc_dom_release(dom); + + out_close: + xc_interface_close(xch); + + return rc; +} + +/* + * Live update of Xenstore stubdom + * + * Sequence of actions: + * 1. transfer new stubdom binary + * a) specify size + * b) transfer unpacked binary in chunks + * 2. transfer new cmdline (optional) + * 3. start update (includes flags) + */ +static int live_update_stubdom(struct xs_handle *xsh, const char *binary, + const char *cmdline, bool force, unsigned i= nt to) +{ + int rc; + + rc =3D send_kernel_blob(xsh, binary); + if (rc) + goto abort; + + if (cmdline) { + rc =3D live_update_cmdline(xsh, cmdline); + if (rc) + goto abort; + } + + rc =3D live_update_start(xsh, force, to); + if (rc) + goto abort; + + return 0; + + abort: + xs_control_command(xsh, "live-update", "-a", 3); + return rc; +} + +/* + * Live update of Xenstore daemon + * + * Sequence of actions: + * 1. transfer new binary filename + * 2. transfer new cmdline (optional) + * 3. start update (includes flags) + */ +static int live_update_daemon(struct xs_handle *xsh, const char *binary, + const char *cmdline, bool force, unsigned in= t to) +{ + int len =3D 0, rc; + char *buf =3D NULL, *ret; + + len =3D add_to_buf(&buf, "-f", len); + len =3D add_to_buf(&buf, binary, len); + if (len < 0) + return 1; + ret =3D xs_control_command(xsh, "live-update", buf, len); + free(buf); + if (!ret || strcmp(ret, "OK")) { + fprintf(stderr, "Setting update binary failed:\n%s\n", + ret ? : strerror(errno)); + free(ret); + return 3; + } + free(ret); + + if (cmdline) { + rc =3D live_update_cmdline(xsh, cmdline); + if (rc) + goto abort; + } + + rc =3D live_update_start(xsh, force, to); + if (rc) + goto abort; + + return 0; + + abort: + xs_control_command(xsh, "live-update", "-a", 3); + return rc; +} + +static int live_update(struct xs_handle *xsh, int argc, char **argv) +{ + int rc =3D 0; + unsigned int i, to =3D 60; + char *binary =3D NULL, *cmdline =3D NULL, *val; + bool force =3D false; + + for (i =3D 0; i < argc; i++) { + if (!strcmp(argv[i], "-c")) { + i++; + if (i =3D=3D argc) { + fprintf(stderr, "Missing command line value\n"); + rc =3D 2; + goto out; + } + cmdline =3D argv[i]; + } else if (!strcmp(argv[i], "-t")) { + i++; + if (i =3D=3D argc) { + fprintf(stderr, "Missing timeout value\n"); + rc =3D 2; + goto out; + } + to =3D atoi(argv[i]); + } else if (!strcmp(argv[i], "-F")) + force =3D true; + else + binary =3D argv[i]; + } + + if (!binary) { + fprintf(stderr, "Missing binary specification\n"); + rc =3D 2; + goto out; + } + + val =3D xs_read(xsh, XBT_NULL, "/tool/xenstored/domid", &i); + if (val) + rc =3D live_update_stubdom(xsh, binary, cmdline, force, to); + else + rc =3D live_update_daemon(xsh, binary, cmdline, force, to); + + free(val); + + out: + return rc; +} =20 int main(int argc, char **argv) { @@ -20,22 +322,6 @@ int main(int argc, char **argv) goto out; } =20 - for (p =3D 2; p < argc; p++) - len +=3D strlen(argv[p]) + 1; - if (len) { - par =3D malloc(len); - if (!par) { - fprintf(stderr, "Allocation error.\n"); - rc =3D 1; - goto out; - } - len =3D 0; - for (p =3D 2; p < argc; p++) { - memcpy(par + len, argv[p], strlen(argv[p]) + 1); - len +=3D strlen(argv[p]) + 1; - } - } - xsh =3D xs_open(0); if (xsh =3D=3D NULL) { fprintf(stderr, "Failed to contact Xenstored.\n"); @@ -43,6 +329,19 @@ int main(int argc, char **argv) goto out; } =20 + if (!strcmp(argv[1], "live-update")) { + rc =3D live_update(xsh, argc - 2, argv + 2); + goto out_close; + } + + for (p =3D 2; p < argc; p++) + len =3D add_to_buf(&par, argv[p], len); + if (len < 0) { + fprintf(stderr, "Allocation error.\n"); + rc =3D 1; + goto out_close; + } + ret =3D xs_control_command(xsh, argv[1], par, len); if (!ret) { rc =3D 3; @@ -59,6 +358,7 @@ int main(int argc, char **argv) } else if (strlen(ret) > 0) printf("%s\n", ret); =20 + out_close: xs_close(xsh); =20 out: --=20 2.29.2