qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/5] backends/hostmem: Report more errors on failures
@ 2024-06-05 10:44 Michal Privoznik
  2024-06-05 10:44 ` [PATCH v4 1/5] meson: Don't even detect posix_madvise() on Darwin Michal Privoznik
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Michal Privoznik @ 2024-06-05 10:44 UTC (permalink / raw)
  To: qemu-devel

v4 of:

https://mail.gnu.org/archive/html/qemu-devel/2024-05/msg06511.html

diff to v3:
- In 2/5 instead of fixing up posix_madvise() retval at runtime, just
  don't use posix_madvise() on Darwin at all (resulted in new patch 1/5).
  Since 2/5 is now the same as 1/4 from v2 I'm including David's
  Reviewed-by line.
- The last patch was tested by Mario, so I've included his Tested-by
  line. Thanks!

Michal Privoznik (5):
  meson: Don't even detect posix_madvise() on Darwin
  osdep: Make qemu_madvise() to set errno in all cases
  osdep: Make qemu_madvise() return ENOSYS on unsupported OSes
  backends/hostmem: Report error on qemu_madvise() failures
  backends/hostmem: Report error when memory size is unaligned

 backends/hostmem.c | 46 ++++++++++++++++++++++++++++++++++++++--------
 meson.build        | 14 ++++++++++----
 util/osdep.c       |  9 +++++++--
 3 files changed, 55 insertions(+), 14 deletions(-)

-- 
2.44.1



^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v4 1/5] meson: Don't even detect posix_madvise() on Darwin
  2024-06-05 10:44 [PATCH v4 0/5] backends/hostmem: Report more errors on failures Michal Privoznik
@ 2024-06-05 10:44 ` Michal Privoznik
  2024-06-05 10:44 ` [PATCH v4 2/5] osdep: Make qemu_madvise() to set errno in all cases Michal Privoznik
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Michal Privoznik @ 2024-06-05 10:44 UTC (permalink / raw)
  To: qemu-devel

On Darwin, posix_madvise() has the same return semantics as plain
madvise() [1]. That's not really what our usage expects.
Fortunately, madvise() is available and preferred anyways so we
may stop detecting posix_madvise() on Darwin.

1: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man2/madvise.2.auto.html

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 meson.build | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/meson.build b/meson.build
index 6386607144..49962cce88 100644
--- a/meson.build
+++ b/meson.build
@@ -2552,10 +2552,16 @@ config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
   #else
   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
   #endif'''))
-config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
-  #include <sys/mman.h>
-  #include <stddef.h>
-  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
+
+# On Darwin posix_madvise() has the same return semantics as plain madvise(),
+# i.e. errno is set and -1 is returned. That's not really how POSIX defines the
+# function. On the flip side, it has madvise() which is preferred anyways.
+if host_os != 'darwin'
+  config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
+    #include <sys/mman.h>
+    #include <stddef.h>
+    int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
+endif
 
 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
   #include <pthread.h>
-- 
2.44.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 2/5] osdep: Make qemu_madvise() to set errno in all cases
  2024-06-05 10:44 [PATCH v4 0/5] backends/hostmem: Report more errors on failures Michal Privoznik
  2024-06-05 10:44 ` [PATCH v4 1/5] meson: Don't even detect posix_madvise() on Darwin Michal Privoznik
@ 2024-06-05 10:44 ` Michal Privoznik
  2024-06-05 10:44 ` [PATCH v4 3/5] osdep: Make qemu_madvise() return ENOSYS on unsupported OSes Michal Privoznik
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Michal Privoznik @ 2024-06-05 10:44 UTC (permalink / raw)
  To: qemu-devel

The unspoken premise of qemu_madvise() is that errno is set on
error. And it is mostly the case except for posix_madvise() which
is documented to return either zero (on success) or a positive
error number. This means, we must set errno ourselves. And while
at it, make the function return a negative value on error, just
like other error paths do.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
---
 util/osdep.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/util/osdep.c b/util/osdep.c
index e996c4744a..e42f4e8121 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -57,7 +57,12 @@ int qemu_madvise(void *addr, size_t len, int advice)
 #if defined(CONFIG_MADVISE)
     return madvise(addr, len, advice);
 #elif defined(CONFIG_POSIX_MADVISE)
-    return posix_madvise(addr, len, advice);
+    int rc = posix_madvise(addr, len, advice);
+    if (rc) {
+        errno = rc;
+        return -1;
+    }
+    return 0;
 #else
     errno = EINVAL;
     return -1;
-- 
2.44.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 3/5] osdep: Make qemu_madvise() return ENOSYS on unsupported OSes
  2024-06-05 10:44 [PATCH v4 0/5] backends/hostmem: Report more errors on failures Michal Privoznik
  2024-06-05 10:44 ` [PATCH v4 1/5] meson: Don't even detect posix_madvise() on Darwin Michal Privoznik
  2024-06-05 10:44 ` [PATCH v4 2/5] osdep: Make qemu_madvise() to set errno in all cases Michal Privoznik
@ 2024-06-05 10:44 ` Michal Privoznik
  2024-06-05 10:44 ` [PATCH v4 4/5] backends/hostmem: Report error on qemu_madvise() failures Michal Privoznik
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Michal Privoznik @ 2024-06-05 10:44 UTC (permalink / raw)
  To: qemu-devel

Not every OS is capable of madvise() or posix_madvise() even. In
that case, errno should be set to ENOSYS as it reflects the cause
better.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: David Hildenbrand <david@redhat.com>
---
 util/osdep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/util/osdep.c b/util/osdep.c
index e42f4e8121..5d23bbfbec 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -64,7 +64,7 @@ int qemu_madvise(void *addr, size_t len, int advice)
     }
     return 0;
 #else
-    errno = EINVAL;
+    errno = ENOSYS;
     return -1;
 #endif
 }
-- 
2.44.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 4/5] backends/hostmem: Report error on qemu_madvise() failures
  2024-06-05 10:44 [PATCH v4 0/5] backends/hostmem: Report more errors on failures Michal Privoznik
                   ` (2 preceding siblings ...)
  2024-06-05 10:44 ` [PATCH v4 3/5] osdep: Make qemu_madvise() return ENOSYS on unsupported OSes Michal Privoznik
@ 2024-06-05 10:44 ` Michal Privoznik
  2024-06-05 10:44 ` [PATCH v4 5/5] backends/hostmem: Report error when memory size is unaligned Michal Privoznik
  2024-06-06  7:36 ` [PATCH v4 0/5] backends/hostmem: Report more errors on failures Paolo Bonzini
  5 siblings, 0 replies; 8+ messages in thread
From: Michal Privoznik @ 2024-06-05 10:44 UTC (permalink / raw)
  To: qemu-devel

If user sets .merge or .dump attributes qemu_madvise() is called
with corresponding advice. But it is never checked for failure
which may mislead users into thinking the attribute is set
correctly. Report an appropriate error.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: David Hildenbrand <david@redhat.com>
---
 backends/hostmem.c | 36 ++++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/backends/hostmem.c b/backends/hostmem.c
index eb9682b4a8..012a8c190f 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -178,8 +178,14 @@ static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp)
         void *ptr = memory_region_get_ram_ptr(&backend->mr);
         uint64_t sz = memory_region_size(&backend->mr);
 
-        qemu_madvise(ptr, sz,
-                     value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE);
+        if (qemu_madvise(ptr, sz,
+                         value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE)) {
+            error_setg_errno(errp, errno,
+                             "Couldn't change property 'merge' on '%s'",
+                             object_get_typename(obj));
+            return;
+        }
+
         backend->merge = value;
     }
 }
@@ -204,8 +210,14 @@ static void host_memory_backend_set_dump(Object *obj, bool value, Error **errp)
         void *ptr = memory_region_get_ram_ptr(&backend->mr);
         uint64_t sz = memory_region_size(&backend->mr);
 
-        qemu_madvise(ptr, sz,
-                     value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP);
+        if (qemu_madvise(ptr, sz,
+                     value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP)) {
+            error_setg_errno(errp, errno,
+                             "Couldn't change property 'dump' on '%s'",
+                             object_get_typename(obj));
+            return;
+        }
+
         backend->dump = value;
     }
 }
@@ -337,11 +349,19 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
     ptr = memory_region_get_ram_ptr(&backend->mr);
     sz = memory_region_size(&backend->mr);
 
-    if (backend->merge) {
-        qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE);
+    if (backend->merge &&
+        qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE)) {
+        error_setg_errno(errp, errno,
+                         "Couldn't set property 'merge' on '%s'",
+                         object_get_typename(OBJECT(uc)));
+        return;
     }
-    if (!backend->dump) {
-        qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP);
+    if (!backend->dump &&
+        qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP)) {
+        error_setg_errno(errp, errno,
+                         "Couldn't set property 'dump' on '%s'",
+                         object_get_typename(OBJECT(uc)));
+        return;
     }
 #ifdef CONFIG_NUMA
     unsigned long lastbit = find_last_bit(backend->host_nodes, MAX_NODES);
-- 
2.44.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 5/5] backends/hostmem: Report error when memory size is unaligned
  2024-06-05 10:44 [PATCH v4 0/5] backends/hostmem: Report more errors on failures Michal Privoznik
                   ` (3 preceding siblings ...)
  2024-06-05 10:44 ` [PATCH v4 4/5] backends/hostmem: Report error on qemu_madvise() failures Michal Privoznik
@ 2024-06-05 10:44 ` Michal Privoznik
  2024-06-06  5:54   ` Mario Casquero
  2024-06-06  7:36 ` [PATCH v4 0/5] backends/hostmem: Report more errors on failures Paolo Bonzini
  5 siblings, 1 reply; 8+ messages in thread
From: Michal Privoznik @ 2024-06-05 10:44 UTC (permalink / raw)
  To: qemu-devel

If memory-backend-{file,ram} has a size that's not aligned to
underlying page size it is not only wasteful, but also may lead
to hard to debug behaviour. For instance, in case
memory-backend-file and hugepages, madvise() and mbind() fail.
Rightfully so, page is the smallest unit they can work with. And
even though an error is reported, the root cause it not very
clear:

  qemu-system-x86_64: Couldn't set property 'dump' on 'memory-backend-file': Invalid argument

After this commit:

  qemu-system-x86_64: backend 'memory-backend-file' memory size must be multiple of 2 MiB

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Mario Casquero <mcasquer@redhat.com>
---
 backends/hostmem.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/backends/hostmem.c b/backends/hostmem.c
index 012a8c190f..4d6c69fe4d 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -20,6 +20,7 @@
 #include "qom/object_interfaces.h"
 #include "qemu/mmap-alloc.h"
 #include "qemu/madvise.h"
+#include "qemu/cutils.h"
 #include "hw/qdev-core.h"
 
 #ifdef CONFIG_NUMA
@@ -337,6 +338,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
     HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
     void *ptr;
     uint64_t sz;
+    size_t pagesize;
     bool async = !phase_check(PHASE_LATE_BACKENDS_CREATED);
 
     if (!bc->alloc) {
@@ -348,6 +350,14 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
 
     ptr = memory_region_get_ram_ptr(&backend->mr);
     sz = memory_region_size(&backend->mr);
+    pagesize = qemu_ram_pagesize(backend->mr.ram_block);
+
+    if (!QEMU_IS_ALIGNED(sz, pagesize)) {
+        g_autofree char *pagesize_str = size_to_str(pagesize);
+        error_setg(errp, "backend '%s' memory size must be multiple of %s",
+                   object_get_typename(OBJECT(uc)), pagesize_str);
+        return;
+    }
 
     if (backend->merge &&
         qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE)) {
-- 
2.44.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 5/5] backends/hostmem: Report error when memory size is unaligned
  2024-06-05 10:44 ` [PATCH v4 5/5] backends/hostmem: Report error when memory size is unaligned Michal Privoznik
@ 2024-06-06  5:54   ` Mario Casquero
  0 siblings, 0 replies; 8+ messages in thread
From: Mario Casquero @ 2024-06-06  5:54 UTC (permalink / raw)
  To: Michal Privoznik; +Cc: qemu-devel

This patch has been successfully tested. Try to allocate some 2M
hugepages in the host, then boot up a VM with the memory size
unaligned and backed by a file, QEMU prompts the following message:
qemu-system-x86_64: backend 'memory-backend-file' memory size must be
multiple of 2 MiB

Tested-by: Mario Casquero <mcasquer@redhat.com>

On Wed, Jun 5, 2024 at 12:45 PM Michal Privoznik <mprivozn@redhat.com> wrote:
>
> If memory-backend-{file,ram} has a size that's not aligned to
> underlying page size it is not only wasteful, but also may lead
> to hard to debug behaviour. For instance, in case
> memory-backend-file and hugepages, madvise() and mbind() fail.
> Rightfully so, page is the smallest unit they can work with. And
> even though an error is reported, the root cause it not very
> clear:
>
>   qemu-system-x86_64: Couldn't set property 'dump' on 'memory-backend-file': Invalid argument
>
> After this commit:
>
>   qemu-system-x86_64: backend 'memory-backend-file' memory size must be multiple of 2 MiB
>
> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Tested-by: Mario Casquero <mcasquer@redhat.com>
> ---
>  backends/hostmem.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/backends/hostmem.c b/backends/hostmem.c
> index 012a8c190f..4d6c69fe4d 100644
> --- a/backends/hostmem.c
> +++ b/backends/hostmem.c
> @@ -20,6 +20,7 @@
>  #include "qom/object_interfaces.h"
>  #include "qemu/mmap-alloc.h"
>  #include "qemu/madvise.h"
> +#include "qemu/cutils.h"
>  #include "hw/qdev-core.h"
>
>  #ifdef CONFIG_NUMA
> @@ -337,6 +338,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
>      HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
>      void *ptr;
>      uint64_t sz;
> +    size_t pagesize;
>      bool async = !phase_check(PHASE_LATE_BACKENDS_CREATED);
>
>      if (!bc->alloc) {
> @@ -348,6 +350,14 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
>
>      ptr = memory_region_get_ram_ptr(&backend->mr);
>      sz = memory_region_size(&backend->mr);
> +    pagesize = qemu_ram_pagesize(backend->mr.ram_block);
> +
> +    if (!QEMU_IS_ALIGNED(sz, pagesize)) {
> +        g_autofree char *pagesize_str = size_to_str(pagesize);
> +        error_setg(errp, "backend '%s' memory size must be multiple of %s",
> +                   object_get_typename(OBJECT(uc)), pagesize_str);
> +        return;
> +    }
>
>      if (backend->merge &&
>          qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE)) {
> --
> 2.44.1
>
>



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 0/5] backends/hostmem: Report more errors on failures
  2024-06-05 10:44 [PATCH v4 0/5] backends/hostmem: Report more errors on failures Michal Privoznik
                   ` (4 preceding siblings ...)
  2024-06-05 10:44 ` [PATCH v4 5/5] backends/hostmem: Report error when memory size is unaligned Michal Privoznik
@ 2024-06-06  7:36 ` Paolo Bonzini
  5 siblings, 0 replies; 8+ messages in thread
From: Paolo Bonzini @ 2024-06-06  7:36 UTC (permalink / raw)
  To: Michal Privoznik; +Cc: qemu-devel

Queued, thanks.

Paolo



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-06-06  7:38 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-05 10:44 [PATCH v4 0/5] backends/hostmem: Report more errors on failures Michal Privoznik
2024-06-05 10:44 ` [PATCH v4 1/5] meson: Don't even detect posix_madvise() on Darwin Michal Privoznik
2024-06-05 10:44 ` [PATCH v4 2/5] osdep: Make qemu_madvise() to set errno in all cases Michal Privoznik
2024-06-05 10:44 ` [PATCH v4 3/5] osdep: Make qemu_madvise() return ENOSYS on unsupported OSes Michal Privoznik
2024-06-05 10:44 ` [PATCH v4 4/5] backends/hostmem: Report error on qemu_madvise() failures Michal Privoznik
2024-06-05 10:44 ` [PATCH v4 5/5] backends/hostmem: Report error when memory size is unaligned Michal Privoznik
2024-06-06  5:54   ` Mario Casquero
2024-06-06  7:36 ` [PATCH v4 0/5] backends/hostmem: Report more errors on failures Paolo Bonzini

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).