qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Steven Sistare <steven.sistare@oracle.com>
To: "Marc-André Lureau" <marcandre.lureau@gmail.com>
Cc: "Jason Zeng" <jason.zeng@linux.intel.com>,
	"Juan Quintela" <quintela@redhat.com>,
	"Eric Blake" <eblake@redhat.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	QEMU <qemu-devel@nongnu.org>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	"Alex Williamson" <alex.williamson@redhat.com>,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Daniel P. Berrange" <berrange@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@redhat.com>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Markus Armbruster" <armbru@redhat.com>
Subject: Re: [PATCH V5 10/25] util: env var helpers
Date: Mon, 12 Jul 2021 15:19:38 -0400	[thread overview]
Message-ID: <a682572b-8d24-c6e3-9036-2ba6349eb4e6@oracle.com> (raw)
In-Reply-To: <CAJ+F1CKEPHdJLNc7gHzsRm8xz7=qXES2v-mjPrp_6WS+73hp6Q@mail.gmail.com>

On 7/8/2021 11:10 AM, Marc-André Lureau wrote:
> Hi
> 
> On Wed, Jul 7, 2021 at 9:30 PM Steve Sistare <steven.sistare@oracle.com <mailto:steven.sistare@oracle.com>> wrote:
> 
>     Add functions for saving fd's and other values in the environment via
>     setenv, and for reading them back via getenv.
> 
> 
> I understand that the rest of the series will rely on environment variables to associate and recover the child-passed FDs, but I am not really convinced that it is a good idea.
> 
> Environment variables have a number of issues that we may encounter down the road: namespace, limits, concurrency, observability etc.. I wonder if the VMState couldn't have a section about the FD to recover. Or maybe just another shared memory region?

They also have some advantages.  Their post-exec value can be observed via /proc/$pid/environ,
and modified values can be observed by calling printenv() in a debugger.  They are naturally carried
across exec, with no external file to create and potentially lose.  Lastly, libcs already defines
put and get methods, so the additional layered code is small and simple.  The number of variables
is small, and I would rather not over-engineer an alternate solution until the env proves
inadequate.  The limits on env size are huge on Linux.  The limits are smaller on Windows, but
that is just one of multiple issues to be addressed to support live update on windows.

For the alternatives, shared memory is no more observable (maybe less) and also has no concurrency
protection.  VMstate does not help because the descriptors are needed before the vmstate file
is opened.
 
> Some comments below. These new utils could also have some unit tests.

OK.

>     Signed-off-by: Steve Sistare <steven.sistare@oracle.com <mailto:steven.sistare@oracle.com>>
>     ---
>      MAINTAINERS        |  2 ++
>      include/qemu/env.h | 23 +++++++++++++
>      util/env.c         | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>      util/meson.build   |  1 +
>      4 files changed, 121 insertions(+)
>      create mode 100644 include/qemu/env.h
>      create mode 100644 util/env.c
> 
>     diff --git a/MAINTAINERS b/MAINTAINERS
>     index c48dd37..8647a97 100644
>     --- a/MAINTAINERS
>     +++ b/MAINTAINERS
>     @@ -2865,6 +2865,8 @@ S: Maintained
>      F: include/migration/cpr.h
>      F: migration/cpr.c
>      F: qapi/cpr.json
>     +F: include/qemu/env.h
>     +F: util/env.c
> 
>      Record/replay
>      M: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru <mailto:pavel.dovgaluk@ispras.ru>>
>     diff --git a/include/qemu/env.h b/include/qemu/env.h
>     new file mode 100644
>     index 0000000..3dad503
>     --- /dev/null
>     +++ b/include/qemu/env.h
>     @@ -0,0 +1,23 @@
>     +/*
>     + * Copyright (c) 2021 Oracle and/or its affiliates.
>     + *
>     + * This work is licensed under the terms of the GNU GPL, version 2.
>     + * See the COPYING file in the top-level directory.
>     + *
>     + */
>     +
>     +#ifndef QEMU_ENV_H
>     +#define QEMU_ENV_H
>     +
>     +#define FD_PREFIX "QEMU_FD_"
>     +
>     +typedef int (*walkenv_cb)(const char *name, const char *val, void *handle);
>     +
>     +int getenv_fd(const char *name);
>     +void setenv_fd(const char *name, int fd);
>     +void unsetenv_fd(const char *name);
>     +void unsetenv_fdv(const char *fmt, ...);
>     +int walkenv(const char *prefix, walkenv_cb cb, void *handle);
>     +void printenv(void);
> 
> 
> Please use qemu prefix, that avoids potential confusion with system libraries.
> 
>     +
>     +#endif
>     diff --git a/util/env.c b/util/env.c
>     new file mode 100644
>     index 0000000..863678d
>     --- /dev/null
>     +++ b/util/env.c
>     @@ -0,0 +1,95 @@
>     +/*
>     + * Copyright (c) 2021 Oracle and/or its affiliates.
>     + *
>     + * This work is licensed under the terms of the GNU GPL, version 2.
>     + * See the COPYING file in the top-level directory.
>     + */
>     +
>     +#include "qemu/osdep.h"
>     +#include "qemu/cutils.h"
>     +#include "qemu/env.h"
>     +
>     +static uint64_t getenv_ulong(const char *prefix, const char *name, int *err)
>     +{
>     +    char var[80], *val;
>     +    uint64_t res = 0;
>     +
>     +    snprintf(var, sizeof(var), "%s%s", prefix, name);
> 
> 
> No check for success / truncation...
> 
> Please use g_autofree char *var = g_strdup_printf()..
> 
>     +    val = getenv(var);
> 
> 
> For consistency, I'd use g_getenv()
> 
>     +    if (val) {
>     +        *err = qemu_strtoul(val, NULL, 10, &res);
>     +    } else {
>     +        *err = -ENOENT;
>     +    }
>     +    return res;
>     +}
>     +
>     +static void setenv_ulong(const char *prefix, const char *name, uint64_t val)
>     +{
>     +    char var[80], val_str[80];
>     +    snprintf(var, sizeof(var), "%s%s", prefix, name);
>     +    snprintf(val_str, sizeof(val_str), "%"PRIu64, val);
> 
> 
> g_strdup_printf
> 
>     +    setenv(var, val_str, 1);
> 
> 
> g_setenv(), and return error value (or assert() if that makes more sense)
> 
>     +}
>     +
>     +static void unsetenv_ulong(const char *prefix, const char *name)
>     +{
>     +    char var[80];
>     +    snprintf(var, sizeof(var), "%s%s", prefix, name);
> 
> 
> g_strdup_printf
>  
> 
>     +    unsetenv(var);
> 
> 
> g_unsetenv
> 
>     +}
>     +
>     +int getenv_fd(const char *name)
>     +{
>     +    int err;
>     +    int fd = getenv_ulong(FD_PREFIX, name, &err);
> 
> 
> I'd try to use qemu_parse_fd() instead.
> 
>     +    return err ? -1 : fd;
>     +}
>     +
>     +void setenv_fd(const char *name, int fd)
>     +{
> 
> 
> Maybe check fd >= 0 ?
> 
>     +    setenv_ulong(FD_PREFIX, name, fd);
>     +}
>     +
>     +void unsetenv_fd(const char *name)
>     +{
>     +    unsetenv_ulong(FD_PREFIX, name);
>     +}
>     +
>     +void unsetenv_fdv(const char *fmt, ...)
>     +{
>     +    va_list args;
>     +    char buf[80];
>     +    va_start(args, fmt);
>     +    vsnprintf(buf, sizeof(buf), fmt, args);
>     +    va_end(args);
> 
> 
> That seems to be a leftover.

It is called in the subsequent vfio cpr patches.

>     +}
>     +
>     +int walkenv(const char *prefix, walkenv_cb cb, void *handle)
> 
>     +{
>     +    char *str, name[128];
>     +    char **envp = environ;
>     +    size_t prefix_len = strlen(prefix);
>     +
>     +    while (*envp) {
>     +        str = *envp++;
>     +        if (!strncmp(str, prefix, prefix_len)) {
> 
>     +            char *val = strchr(str, '=');
>     +            str += prefix_len;
>     +            strncpy(name, str, val - str);
> 
> 
> g_strndup() to avoid potential buffer overflow.
> 
>     +            name[val - str] = 0;
>     +            if (cb(name, val + 1, handle)) {
>     +                return 1;
>     +            }
>     +        }
>     +    }
>     +    return 0;
>     +}
>     +
>     +void printenv(void)
>     +{
>     +    char **ptr = environ;
>     +    while (*ptr) {
>     +        puts(*ptr++);
>     +    }
>     +}
> 
> 
> Is this really useful? I doubt it.

I call it from gdb for debugging, but I can delete it and cast g_listenv() instead:
  print *(((char ** (*)(void))g_listenv)())@100

Will do on the rest.

- Steve

>     diff --git a/util/meson.build b/util/meson.build
>     index 0ffd7f4..5e8097a 100644
>     --- a/util/meson.build
>     +++ b/util/meson.build
>     @@ -23,6 +23,7 @@ util_ss.add(files('host-utils.c'))
>      util_ss.add(files('bitmap.c', 'bitops.c'))
>      util_ss.add(files('fifo8.c'))
>      util_ss.add(files('cacheinfo.c', 'cacheflush.c'))
>     +util_ss.add(files('env.c'))
>      util_ss.add(files('error.c', 'qemu-error.c'))
>      util_ss.add(files('qemu-print.c'))
>      util_ss.add(files('id.c'))
>     -- 
>     1.8.3.1
> 
> 
> 
> 
> -- 
> Marc-André Lureau


  reply	other threads:[~2021-07-12 19:22 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-07 17:20 [PATCH V5 00/25] Live Update Steve Sistare
2021-07-07 17:20 ` [PATCH V5 01/25] qemu_ram_volatile Steve Sistare
2021-07-08 12:01   ` Marc-André Lureau
2021-07-12 17:06     ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 02/25] cpr: reboot mode Steve Sistare
2021-07-08 12:25   ` Marc-André Lureau
2021-07-12 17:07     ` Steven Sistare
2021-08-04 15:48   ` Eric Blake
2021-07-07 17:20 ` [PATCH V5 03/25] cpr: QMP interfaces for reboot Steve Sistare
2021-07-08 13:27   ` Marc-André Lureau
2021-07-12 17:07     ` Steven Sistare
2021-08-04 15:48   ` Eric Blake
2021-08-04 20:27     ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 04/25] cpr: HMP " Steve Sistare
2021-07-28  4:55   ` Zheng Chuan
2021-07-07 17:20 ` [PATCH V5 05/25] as_flat_walk Steve Sistare
2021-07-08 13:49   ` Marc-André Lureau
2021-07-12 17:07     ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 06/25] oslib: qemu_clr_cloexec Steve Sistare
2021-07-08 13:58   ` Marc-André Lureau
2021-07-12 17:07     ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 07/25] machine: memfd-alloc option Steve Sistare
2021-07-08 14:20   ` Marc-André Lureau
2021-07-12 17:07     ` Steven Sistare
2021-07-12 17:45       ` Marc-André Lureau
2021-07-07 17:20 ` [PATCH V5 08/25] vl: add helper to request re-exec Steve Sistare
2021-07-08 14:31   ` Marc-André Lureau
2021-07-12 17:07     ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 09/25] string to strList Steve Sistare
2021-07-08 14:37   ` Marc-André Lureau
2021-07-07 17:20 ` [PATCH V5 10/25] util: env var helpers Steve Sistare
2021-07-08 15:10   ` Marc-André Lureau
2021-07-12 19:19     ` Steven Sistare [this message]
2021-07-12 19:36       ` Marc-André Lureau
2021-07-13 16:15         ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 11/25] cpr: restart mode Steve Sistare
2021-07-08 15:43   ` Marc-André Lureau
2021-07-08 15:54     ` Marc-André Lureau
2021-07-12 19:19       ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 12/25] cpr: QMP interfaces for restart Steve Sistare
2021-07-08 15:49   ` Marc-André Lureau
2021-07-12 19:19     ` Steven Sistare
2021-08-04 16:00   ` Eric Blake
2021-08-04 20:22     ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 13/25] cpr: HMP " Steve Sistare
2021-07-28  4:56   ` Zheng Chuan
2021-07-07 17:20 ` [PATCH V5 14/25] pci: export functions for cpr Steve Sistare
2021-07-07 17:20 ` [PATCH V5 15/25] vfio-pci: refactor " Steve Sistare
2021-07-07 17:20 ` [PATCH V5 16/25] vfio-pci: cpr part 1 Steve Sistare
2021-07-16 17:45   ` Alex Williamson
2021-07-19 17:43     ` Steven Sistare
2021-07-28  4:56   ` Zheng Chuan
2021-07-30 12:50     ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 17/25] vfio-pci: cpr part 2 Steve Sistare
2021-07-16 20:51   ` Alex Williamson
2021-07-19 17:44     ` Steven Sistare
2021-07-19 18:10       ` Alex Williamson
2021-07-19 18:38         ` Steven Sistare
2021-07-28  4:56           ` Zheng Chuan
2021-07-30 12:52             ` Steven Sistare
2021-07-31  6:07               ` Zheng Chuan
2021-07-07 17:20 ` [PATCH V5 18/25] vhost: reset vhost devices upon cprsave Steve Sistare
2021-07-07 17:20 ` [PATCH V5 19/25] hostmem-memfd: cpr support Steve Sistare
2021-07-07 17:20 ` [PATCH V5 20/25] chardev: cpr framework Steve Sistare
2021-07-08 16:03   ` Marc-André Lureau
2021-07-12 19:20     ` Steven Sistare
2021-07-12 19:49       ` Marc-André Lureau
2021-07-13 14:34         ` Steven Sistare
2021-07-07 17:20 ` [PATCH V5 21/25] chardev: cpr for simple devices Steve Sistare
2021-07-07 17:20 ` [PATCH V5 22/25] chardev: cpr for pty Steve Sistare
2021-07-07 17:20 ` [PATCH V5 23/25] chardev: cpr for sockets Steve Sistare
2021-07-29  4:04   ` Zheng Chuan
2021-07-07 17:20 ` [PATCH V5 24/25] cpr: only-cpr-capable option Steve Sistare
2021-07-07 17:20 ` [PATCH V5 25/25] simplify savevm Steve Sistare

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a682572b-8d24-c6e3-9036-2ba6349eb4e6@oracle.com \
    --to=steven.sistare@oracle.com \
    --cc=alex.bennee@linaro.org \
    --cc=alex.williamson@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=eblake@redhat.com \
    --cc=jason.zeng@linux.intel.com \
    --cc=marcandre.lureau@gmail.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).