diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2021-01-04 17:13:18 +0000 |
---|---|---|
committer | Eduardo Habkost <ehabkost@redhat.com> | 2021-02-01 17:07:34 -0500 |
commit | 369d6dc4de45b8e5e35a851f5719e7fd59a0462f (patch) | |
tree | 9b7bf91786c4866c63bab05090e83964a7bbbf33 /softmmu | |
parent | 74208cd252c5da9d867270a178799abd802b9338 (diff) |
memory: add readonly support to memory_region_init_ram_from_file()
There is currently no way to open(O_RDONLY) and mmap(PROT_READ) when
creating a memory region from a file. This functionality is needed since
the underlying host file may not allow writing.
Add a bool readonly argument to memory_region_init_ram_from_file() and
the APIs it calls.
Extend memory_region_init_ram_from_file() rather than introducing a
memory_region_init_rom_from_file() API so that callers can easily make a
choice between read/write and read-only at runtime without calling
different APIs.
No new RAMBlock flag is introduced for read-only because it's unclear
whether RAMBlocks need to know that they are read-only. Pass a bool
readonly argument instead.
Both of these design decisions can be changed in the future. It just
seemed like the simplest approach to me.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Liam Merwick <liam.merwick@oracle.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20210104171320.575838-2-stefanha@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Diffstat (limited to 'softmmu')
-rw-r--r-- | softmmu/memory.c | 7 | ||||
-rw-r--r-- | softmmu/physmem.c | 18 |
2 files changed, 16 insertions, 9 deletions
diff --git a/softmmu/memory.c b/softmmu/memory.c index 333e1ed7b0..676c298b60 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1587,15 +1587,18 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, uint64_t align, uint32_t ram_flags, const char *path, + bool readonly, Error **errp) { Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; + mr->readonly = readonly; mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->align = align; - mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, &err); + mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, + readonly, &err); if (err) { mr->size = int128_zero(); object_unparent(OBJECT(mr)); @@ -1618,7 +1621,7 @@ void memory_region_init_ram_from_fd(MemoryRegion *mr, mr->destructor = memory_region_destructor_ram; mr->ram_block = qemu_ram_alloc_from_fd(size, mr, share ? RAM_SHARED : 0, - fd, &err); + fd, false, &err); if (err) { mr->size = int128_zero(); object_unparent(OBJECT(mr)); diff --git a/softmmu/physmem.c b/softmmu/physmem.c index cdcd197656..60760a3bdc 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -1398,6 +1398,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) { @@ -1408,7 +1409,7 @@ static int file_ram_open(const char *path, *created = false; for (;;) { - fd = open(path, O_RDWR); + fd = open(path, readonly ? O_RDONLY : O_RDWR); if (fd >= 0) { /* @path names an existing file, use it */ break; @@ -1460,6 +1461,7 @@ static int file_ram_open(const char *path, static void *file_ram_alloc(RAMBlock *block, ram_addr_t memory, int fd, + bool readonly, bool truncate, Error **errp) { @@ -1510,7 +1512,7 @@ static void *file_ram_alloc(RAMBlock *block, perror("ftruncate"); } - area = qemu_ram_mmap(fd, memory, block->mr->align, + area = qemu_ram_mmap(fd, memory, block->mr->align, readonly, block->flags & RAM_SHARED, block->flags & RAM_PMEM); if (area == MAP_FAILED) { error_setg_errno(errp, errno, @@ -1942,7 +1944,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared) #ifdef CONFIG_POSIX RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, - uint32_t ram_flags, int fd, + uint32_t ram_flags, int fd, bool readonly, Error **errp) { RAMBlock *new_block; @@ -1996,7 +1998,8 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, new_block->used_length = size; new_block->max_length = size; new_block->flags = ram_flags; - new_block->host = file_ram_alloc(new_block, size, fd, !file_size, errp); + new_block->host = file_ram_alloc(new_block, size, fd, readonly, + !file_size, errp); if (!new_block->host) { g_free(new_block); return NULL; @@ -2015,18 +2018,19 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, uint32_t ram_flags, const char *mem_path, - Error **errp) + bool readonly, Error **errp) { int fd; bool created; RAMBlock *block; - fd = file_ram_open(mem_path, memory_region_name(mr), &created, errp); + fd = file_ram_open(mem_path, memory_region_name(mr), readonly, &created, + errp); if (fd < 0) { return NULL; } - block = qemu_ram_alloc_from_fd(size, mr, ram_flags, fd, errp); + block = qemu_ram_alloc_from_fd(size, mr, ram_flags, fd, readonly, errp); if (!block) { if (created) { unlink(mem_path); |