At 2023-07-28 02:30:09, "David Hildenbrand" <da...@redhat.com> wrote:
>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