On 27.07.23 17:20, ThinerLogoer wrote:

At 2023-07-27 21:18:44, "David Hildenbrand" <da...@redhat.com> wrote:
On 26.07.23 16:59, Thiner Logoer wrote:
Users may give "-mem-path" a read only file and expect the file
to be mapped read-write privately. Allow this but give a warning
since other users may surprise when the ram file is readonly and
qemu suddenly aborts elsewhere.

Suggested-by: David Hildenbrand <da...@redhat.com>
Signed-off-by: Thiner Logoer <logoerthin...@163.com>
---

See the previous version at:
https://lore.kernel.org/qemu-devel/96a462ec-6f9d-fd83-f697-73e132432...@redhat.com/T/

verified, this patch works for my setup, both functionality and the warning
are expected behavior.

Also another problem when I look at the file_ram_open

When readonly is true and the path is a directory, the open will succeed but
any later operations will fail since it is a directory fd. This may require
additional commits which is out of my scope. Merely record the question here.

Maybe you can notice this edge case? I am not sure whether this
case is on your todo list?

I guess we would have to check if we opened a directory. Should be easy to add.

As long as QEMU fails reasonably well later, good for now :)



   softmmu/physmem.c | 14 ++++++++++++++
   1 file changed, 14 insertions(+)

diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 3df73542e1..e8279d69d4 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -1296,6 +1296,7 @@ static int file_ram_open(const char *path,
       char *sanitized_name;
       char *c;
       int fd = -1;
+    bool first_trial = true;
*created = false;
       for (;;) {
@@ -1332,6 +1333,18 @@ static int file_ram_open(const char *path,
                   break;
               }
               g_free(filename);
+        } else if (first_trial && !readonly && errno == EACCES) {

I guess it's better to only retry on private mappings, for shared
mappings that cannot possibly work.

I feel that the retry can be applied in general - for shared mappings,
it will merely fail on the mmap step and should be ok?

I guess a proper "can't open backing store" message is better for the cases 
that obviously can't work.


Though, to retry only on private mapping seems straightforwards -
this function is called only once, and whether the mapping is private
can be passed here with a boolean flag as argument. Nonetheless
it may make the logic of the function more complex and less intuitive.

Quick untested attempt to move retry handling to the caller:

diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 3df73542e1..c826bb78fc 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -1289,8 +1289,7 @@ static int64_t get_file_align(int fd)
 static int file_ram_open(const char *path,
                          const char *region_name,
                          bool readonly,
-                         bool *created,
-                         Error **errp)
+                         bool *created)
 {
     char *filename;
     char *sanitized_name;
@@ -1334,10 +1333,7 @@ static int file_ram_open(const char *path,
             g_free(filename);
         }
         if (errno != EEXIST && errno != EINTR) {
-            error_setg_errno(errp, errno,
-                             "can't open backing store %s for guest RAM",
-                             path);
-            return -1;
+            return -errno;
         }
         /*
          * Try again on EINTR and EEXIST.  The latter happens when
@@ -1946,9 +1942,23 @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, 
MemoryRegion *mr,
     bool created;
     RAMBlock *block;
- fd = file_ram_open(mem_path, memory_region_name(mr), readonly, &created,
-                       errp);
+    fd = file_ram_open(mem_path, memory_region_name(mr), readonly, &created);
+    if (fd == -EACCES && !(ram_flags & RAM_SHARED) && readonly) {
+        /*
+         * We can have a writable MAP_PRIVATE mapping of a readonly file.
+         * However, some operations like ftruncate() or fallocate() might fail
+         * later, let's warn the user.
+         */
+        fd = file_ram_open(mem_path, memory_region_name(mr), true, &created);
+        if (fd >= 0) {
+            warn_report("backing store %s for guest RAM (MAP_PRIVATE) opened"
+                        " readonly because the file is not writable", 
mem_path);
+        }
+    }
     if (fd < 0) {
+        error_setg_errno(errp, -fd,
+                         "can't open backing store %s for guest RAM",
+                         mem_path);
         return NULL;
     }
--
2.41.0




--
Cheers,

David / dhildenb


Reply via email to