diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2019-02-14 11:10:04 +0800 |
---|---|---|
committer | Eduardo Habkost <ehabkost@redhat.com> | 2019-03-11 10:44:19 -0300 |
commit | 314aec4a6e06844937f1677f6cba21981005f389 (patch) | |
tree | 9321a3ea8b1083ef391d6ca5123f8b73eada42a5 /util | |
parent | 336cfef495f0cd5b1606251c52628d0372e9a809 (diff) |
hostmem-file: reject invalid pmem file sizes
Guests started with NVDIMMs larger than the underlying host file produce
confusing errors inside the guest. This happens because the guest
accesses pages beyond the end of the file.
Check the pmem file size on startup and print a clear error message if
the size is invalid.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1669053
Cc: Wei Yang <richardw.yang@linux.intel.com>
Cc: Zhang Yi <yi.z.zhang@linux.intel.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20190214031004.32522-3-stefanha@redhat.com>
Reviewed-by: Wei Yang <richardw.yang@linux.intel.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Pankaj Gupta <pagupta@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Diffstat (limited to 'util')
-rw-r--r-- | util/oslib-posix.c | 53 | ||||
-rw-r--r-- | util/oslib-win32.c | 5 |
2 files changed, 58 insertions, 0 deletions
diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 37c5854b9c..10d90d1783 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -500,6 +500,59 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, } } +uint64_t qemu_get_pmem_size(const char *filename, Error **errp) +{ + struct stat st; + + if (stat(filename, &st) < 0) { + error_setg(errp, "unable to stat pmem file \"%s\"", filename); + return 0; + } + +#if defined(__linux__) + /* Special handling for devdax character devices */ + if (S_ISCHR(st.st_mode)) { + char *subsystem_path = NULL; + char *subsystem = NULL; + char *size_path = NULL; + char *size_str = NULL; + uint64_t ret = 0; + + subsystem_path = g_strdup_printf("/sys/dev/char/%d:%d/subsystem", + major(st.st_rdev), minor(st.st_rdev)); + subsystem = g_file_read_link(subsystem_path, NULL); + if (!subsystem) { + error_setg(errp, "unable to read subsystem for pmem file \"%s\"", + filename); + goto devdax_err; + } + + if (!g_str_has_suffix(subsystem, "/dax")) { + error_setg(errp, "pmem file \"%s\" is not a dax device", filename); + goto devdax_err; + } + + size_path = g_strdup_printf("/sys/dev/char/%d:%d/size", + major(st.st_rdev), minor(st.st_rdev)); + if (!g_file_get_contents(size_path, &size_str, NULL, NULL)) { + error_setg(errp, "unable to read size for pmem file \"%s\"", + size_path); + goto devdax_err; + } + + ret = g_ascii_strtoull(size_str, NULL, 0); + +devdax_err: + g_free(size_str); + g_free(size_path); + g_free(subsystem); + g_free(subsystem_path); + return ret; + } +#endif /* defined(__linux__) */ + + return st.st_size; +} char *qemu_get_pid_name(pid_t pid) { diff --git a/util/oslib-win32.c b/util/oslib-win32.c index b4c17f5dfa..bd633afab6 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -560,6 +560,11 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, } } +uint64_t qemu_get_pmem_size(const char *filename, Error **errp) +{ + error_setg(errp, "pmem support not available"); + return 0; +} char *qemu_get_pid_name(pid_t pid) { |