diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 42efb2f..c2df14c 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -32,6 +32,7 @@ struct HostMemoryBackendFile {
     HostMemoryBackend parent_obj;
 
     bool share;
+    bool notrunc;
     char *mem_path;
 };
 
@@ -57,7 +58,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
         path = object_get_canonical_path(OBJECT(backend));
         memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
                                  path,
-                                 backend->size, fb->share,
+                                 backend->size, fb->share, fb->notrunc,
                                  fb->mem_path, errp);
         g_free(path);
     }
@@ -103,6 +104,25 @@ static void file_memory_backend_set_share(Object *o, bool value, Error **errp)
     fb->share = value;
 }
 
+static bool file_memory_backend_get_notrunc(Object *o, Error **errp)
+{
+    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+
+    return fb->notrunc;
+}
+
+static void file_memory_backend_set_notrunc(Object *o, bool value, Error **errp)
+{
+    HostMemoryBackend *backend = MEMORY_BACKEND(o);
+    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+
+    if (memory_region_size(&backend->mr)) {
+        error_setg(errp, "cannot change property value");
+        return;
+    }
+    fb->notrunc = value;
+}
+
 static void
 file_backend_class_init(ObjectClass *oc, void *data)
 {
@@ -116,6 +136,9 @@ file_backend_class_init(ObjectClass *oc, void *data)
     object_class_property_add_str(oc, "mem-path",
         get_mem_path, set_mem_path,
         &error_abort);
+    object_class_property_add_bool(oc, "notrunc",
+        file_memory_backend_get_notrunc, file_memory_backend_set_notrunc,
+        &error_abort);
 }
 
 static void file_backend_instance_finalize(Object *o)
diff --git a/exec.c b/exec.c
index e63c5a1..aacaee1 100644
--- a/exec.c
+++ b/exec.c
@@ -63,6 +63,11 @@
 #include "qemu/mmap-alloc.h"
 #endif
 
+#include <sys/ioctl.h>
+#ifdef CONFIG_LINUX
+#include <linux/fs.h>
+#endif
+
 //#define DEBUG_SUBPAGE
 
 #if !defined(CONFIG_USER_ONLY)
@@ -91,6 +96,12 @@ static MemoryRegion io_mem_unassigned;
  */
 #define RAM_RESIZEABLE (1 << 2)
 
+/* If the backend of RAM is a file and the RAM size is not identical
+ * to the file size, do not truncate the file to the RAM size. This
+ * flag is used to avoid corrupting the existing data on the file.
+ */
+#define RAM_NOTRUNC    (1 << 3)
+
 #endif
 
 struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
@@ -1188,6 +1199,48 @@ void qemu_mutex_unlock_ramlist(void)
 }
 
 #ifdef __linux__
+static uint64_t get_file_size(const char *path, Error **errp)
+{
+    int fd;
+    struct stat st;
+    uint64_t size = 0;
+    Error *local_err = NULL;
+
+    fd = qemu_open(path, O_RDONLY);
+    if (fd < 0) {
+        error_setg(&local_err, "cannot open file");
+        goto out;
+    }
+
+    if (stat(path, &st)) {
+        error_setg(&local_err, "cannot get file stat");
+        goto out_fclose;
+    }
+
+    switch (st.st_mode & S_IFMT) {
+    case S_IFREG:
+        size = st.st_size;
+        break;
+
+    case S_IFBLK:
+        if (ioctl(fd, BLKGETSIZE64, &size)) {
+            error_setg(&local_err, "cannot get size of block device");
+            size = 0;
+        }
+        break;
+
+    default:
+        error_setg(&local_err,
+                   "only block device on Linux and regular file are supported");
+    }
+
+ out_fclose:
+    close(fd);
+ out:
+    error_propagate(errp, local_err);
+    return size;
+}
+
 static void *file_ram_alloc(RAMBlock *block,
                             ram_addr_t memory,
                             const char *path,
@@ -1271,7 +1324,7 @@ static void *file_ram_alloc(RAMBlock *block,
      * If anything goes wrong with it under other filesystems,
      * mmap will fail.
      */
-    if (ftruncate(fd, memory)) {
+    if (!(block->flags & RAM_NOTRUNC) && ftruncate(fd, memory)) {
         perror("ftruncate");
     }
 
@@ -1597,7 +1650,8 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
 
 #ifdef __linux__
 RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
-                                   bool share, const char *mem_path,
+                                   bool share, bool notrunc,
+                                   const char *mem_path,
                                    Error **errp)
 {
     RAMBlock *new_block;
@@ -1619,12 +1673,28 @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
         return NULL;
     }
 
+    if (notrunc) {
+        uint64_t file_size = get_file_size(mem_path, &local_err);
+
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return NULL;
+        }
+
+        if (size > file_size) {
+            error_setg(errp,
+                       "notrunc enabled, but size is larger than file size");
+            return NULL;
+        }
+    }
+
     size = HOST_PAGE_ALIGN(size);
     new_block = g_malloc0(sizeof(*new_block));
     new_block->mr = mr;
     new_block->used_length = size;
     new_block->max_length = size;
     new_block->flags = share ? RAM_SHARED : 0;
+    new_block->flags |= notrunc ? RAM_NOTRUNC : 0;
     new_block->host = file_ram_alloc(new_block, size,
                                      mem_path, errp);
     if (!new_block->host) {
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 10d7eac..c0116e1 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -418,6 +418,8 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
  * @name: the name of the region.
  * @size: size of the region.
  * @share: %true if memory must be mmaped with the MAP_SHARED flag
+ * @notrunc: %true do not truncate the file @path to @size if the
+ *           file size is not identical to @size
  * @path: the path in which to allocate the RAM.
  * @errp: pointer to Error*, to store an error if it happens.
  */
@@ -426,6 +428,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
                                       const char *name,
                                       uint64_t size,
                                       bool share,
+                                      bool notrunc,
                                       const char *path,
                                       Error **errp);
 #endif
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 54d7108..4fd3ec8 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -96,7 +96,8 @@ void qemu_mutex_lock_ramlist(void);
 void qemu_mutex_unlock_ramlist(void);
 
 RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
-                                   bool share, const char *mem_path,
+                                   bool share, bool notrunc,
+                                   const char *mem_path,
                                    Error **errp);
 RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
                                   MemoryRegion *mr, Error **errp);
diff --git a/memory.c b/memory.c
index 58f9269..5430412 100644
--- a/memory.c
+++ b/memory.c
@@ -1334,6 +1334,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
                                       const char *name,
                                       uint64_t size,
                                       bool share,
+                                      bool trunc,
                                       const char *path,
                                       Error **errp)
 {
@@ -1341,7 +1342,8 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
     mr->ram = true;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram;
-    mr->ram_block = qemu_ram_alloc_from_file(size, mr, share, path, errp);
+    mr->ram_block = qemu_ram_alloc_from_file(size, mr, share, trunc, path,
+                                             errp);
     mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
 }
 #endif
diff --git a/numa.c b/numa.c
index 9c09e45..6cf1fb5 100644
--- a/numa.c
+++ b/numa.c
@@ -412,7 +412,7 @@ static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner,
 #ifdef __linux__
         Error *err = NULL;
         memory_region_init_ram_from_file(mr, owner, name, ram_size, false,
-                                         mem_path, &err);
+                                         false, mem_path, &err);
         if (err) {
             error_report_err(err);
             if (mem_prealloc) {
