qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 2/2] overcommit: introduce mem-lock=on-fault


From: Peter Xu
Subject: Re: [PATCH v2 2/2] overcommit: introduce mem-lock=on-fault
Date: Wed, 11 Dec 2024 16:52:32 -0500

On Wed, Dec 11, 2024 at 03:04:47AM +0300, Daniil Tatianin wrote:
> Locking the memory without MCL_ONFAULT instantly prefaults any mmaped
> anonymous memory with a write-fault, which introduces a lot of extra
> overhead in terms of memory usage when all you want to do is to prevent
> kcompactd from migrating and compacting QEMU pages. Add an option to
> only lock pages lazily as they're faulted by the process by using
> MCL_ONFAULT if asked.

Looks good but some nitpicks below..

> 
> Signed-off-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
> ---
>  include/sysemu/sysemu.h  |  1 +
>  migration/postcopy-ram.c |  4 ++--
>  qemu-options.hx          | 14 +++++++-----
>  system/globals.c         |  1 +
>  system/vl.c              | 46 ++++++++++++++++++++++++++++++++--------
>  5 files changed, 50 insertions(+), 16 deletions(-)
> 
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 7ec419ce13..b6519c3c1e 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -44,6 +44,7 @@ extern const char *keyboard_layout;
>  extern int old_param;
>  extern uint8_t *boot_splash_filedata;
>  extern bool enable_mlock;
> +extern bool enable_mlock_onfault;
>  extern bool enable_cpu_pm;
>  extern QEMUClockType rtc_clock;
>  
> diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
> index 36ec6a3d75..8ff8c73a27 100644
> --- a/migration/postcopy-ram.c
> +++ b/migration/postcopy-ram.c
> @@ -651,8 +651,8 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState 
> *mis)
>          mis->have_fault_thread = false;
>      }
>  
> -    if (enable_mlock) {
> -        if (os_mlock(false) < 0) {
> +    if (enable_mlock || enable_mlock_onfault) {
> +        if (os_mlock(enable_mlock_onfault) < 0) {
>              error_report("mlock: %s", strerror(errno));
>              /*
>               * It doesn't feel right to fail at this point, we have a valid
> diff --git a/qemu-options.hx b/qemu-options.hx
> index dacc9790a4..6c8360e62e 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -4566,21 +4566,25 @@ SRST
>  ERST
>  
>  DEF("overcommit", HAS_ARG, QEMU_OPTION_overcommit,
> -    "-overcommit [mem-lock=on|off][cpu-pm=on|off]\n"
> +    "-overcommit [mem-lock=on|off|on-fault][cpu-pm=on|off]\n"
>      "                run qemu with overcommit hints\n"
> -    "                mem-lock=on|off controls memory lock support (default: 
> off)\n"
> +    "                mem-lock=on|off|on-fault controls memory lock support 
> (default: off)\n"
>      "                cpu-pm=on|off controls cpu power management (default: 
> off)\n",
>      QEMU_ARCH_ALL)
>  SRST
> -``-overcommit mem-lock=on|off``
> +``-overcommit mem-lock=on|off|on-fault``
>    \ 
>  ``-overcommit cpu-pm=on|off``
>      Run qemu with hints about host resource overcommit. The default is
>      to assume that host overcommits all resources.
>  
>      Locking qemu and guest memory can be enabled via ``mem-lock=on``
> -    (disabled by default). This works when host memory is not
> -    overcommitted and reduces the worst-case latency for guest.
> +    or ``mem-lock=on-fault`` (disabled by default). This works when
> +    host memory is not overcommitted and reduces the worst-case latency for
> +    guest. The on-fault option is better for reducing the memory footprint
> +    since it makes allocations lazy, but the pages still get locked in place
> +    once faulted by the guest or QEMU. Note that the two options are mutually
> +    exclusive.
>  
>      Guest ability to manage power state of host cpus (increasing latency
>      for other processes on the same host cpu, but decreasing latency for
> diff --git a/system/globals.c b/system/globals.c
> index 84ce943ac9..43501fe690 100644
> --- a/system/globals.c
> +++ b/system/globals.c
> @@ -35,6 +35,7 @@ enum vga_retrace_method vga_retrace_method = 
> VGA_RETRACE_DUMB;
>  int display_opengl;
>  const char* keyboard_layout;
>  bool enable_mlock;
> +bool enable_mlock_onfault;
>  bool enable_cpu_pm;
>  int autostart = 1;
>  int vga_interface_type = VGA_NONE;
> diff --git a/system/vl.c b/system/vl.c
> index 03819a80ef..4e2efd3ad4 100644
> --- a/system/vl.c
> +++ b/system/vl.c
> @@ -347,7 +347,7 @@ static QemuOptsList qemu_overcommit_opts = {
>      .desc = {
>          {
>              .name = "mem-lock",
> -            .type = QEMU_OPT_BOOL,
> +            .type = QEMU_OPT_STRING,
>          },
>          {
>              .name = "cpu-pm",
> @@ -792,8 +792,8 @@ static QemuOptsList qemu_run_with_opts = {
>  
>  static void realtime_init(void)
>  {
> -    if (enable_mlock) {
> -        if (os_mlock(false) < 0) {
> +    if (enable_mlock || enable_mlock_onfault) {

IIUC it's still cleaner to make enable_mlock into an enum to be a
tri-state.  IOW, we could have two flags set now with the current patch
when with things like:

  -overcommit mem-lock=on -overcommit mem-lock=on-fault

> +        if (os_mlock(enable_mlock_onfault) < 0) {
>              error_report("locking memory failed");
>              exit(1);
>          }
> @@ -3532,14 +3532,42 @@ void qemu_init(int argc, char **argv)
>                  object_option_parse(optarg);
>                  break;
>              case QEMU_OPTION_overcommit:
> -                opts = qemu_opts_parse_noisily(qemu_find_opts("overcommit"),
> -                                               optarg, false);
> -                if (!opts) {
> +                {
> +                    const char *mem_lock_opt;
> +
> +                    opts = 
> qemu_opts_parse_noisily(qemu_find_opts("overcommit"),
> +                                                   optarg, false);
> +                    if (!opts) {
> +                        exit(1);
> +                    }
> +
> +                    enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", 
> enable_cpu_pm);
> +
> +                    mem_lock_opt = qemu_opt_get(opts, "mem-lock");
> +                    if (!mem_lock_opt) {
> +                        break;
> +                    }
> +
> +                    if (strcmp(mem_lock_opt, "on") == 0) {
> +                        enable_mlock = true;
> +                        break;
> +                    }
> +
> +                    if (strcmp(mem_lock_opt, "off") == 0) {
> +                        enable_mlock = false;
> +                        enable_mlock_onfault = false;
> +                        break;
> +                    }
> +
> +                    if (strcmp(mem_lock_opt, "on-fault") == 0) {
> +                        enable_mlock_onfault = true;
> +                        break;
> +                    }
> +
> +                    error_report("parameter 'mem-lock' expects one of "
> +                                 "'on', 'off', 'on-fault'");

Not the only one that open code this.. but still there're better references
like net_client_parse() or monitor_parse() that we could follow.  So would
be good to put it into a function.

Thanks,

>                      exit(1);
>                  }
> -                enable_mlock = qemu_opt_get_bool(opts, "mem-lock", 
> enable_mlock);
> -                enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", 
> enable_cpu_pm);
> -                break;
>              case QEMU_OPTION_compat:
>                  {
>                      CompatPolicy *opts_policy;
> -- 
> 2.34.1
> 

-- 
Peter Xu




reply via email to

[Prev in Thread] Current Thread [Next in Thread]