mirror of https://gitee.com/openkylin/qemu.git
util/oslib-posix: Let touch_all_pages() return an error
Let's prepare touch_all_pages() for returning differing errors. Return an error from the thread and report the last processed error. Translate SIGBUS to -EFAULT, as a SIGBUS can mean all different kind of things (memory error, read error, out of memory). When allocating memory fails via the current SIGBUS-based mechanism, we'll get: os_mem_prealloc: preallocating memory failed: Bad address Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20211217134611.31172-2-david@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
0a963af3e3
commit
6c427ab926
|
@ -84,7 +84,6 @@ typedef struct MemsetThread MemsetThread;
|
|||
|
||||
static MemsetThread *memset_thread;
|
||||
static int memset_num_threads;
|
||||
static bool memset_thread_failed;
|
||||
|
||||
static QemuMutex page_mutex;
|
||||
static QemuCond page_cond;
|
||||
|
@ -452,6 +451,7 @@ static void *do_touch_pages(void *arg)
|
|||
{
|
||||
MemsetThread *memset_args = (MemsetThread *)arg;
|
||||
sigset_t set, oldset;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* On Linux, the page faults from the loop below can cause mmap_sem
|
||||
|
@ -470,7 +470,7 @@ static void *do_touch_pages(void *arg)
|
|||
pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
|
||||
|
||||
if (sigsetjmp(memset_args->env, 1)) {
|
||||
memset_thread_failed = true;
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
char *addr = memset_args->addr;
|
||||
size_t numpages = memset_args->numpages;
|
||||
|
@ -494,7 +494,7 @@ static void *do_touch_pages(void *arg)
|
|||
}
|
||||
}
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
return NULL;
|
||||
return (void *)(uintptr_t)ret;
|
||||
}
|
||||
|
||||
static inline int get_memset_num_threads(int smp_cpus)
|
||||
|
@ -509,13 +509,13 @@ static inline int get_memset_num_threads(int smp_cpus)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages,
|
||||
int smp_cpus)
|
||||
static int touch_all_pages(char *area, size_t hpagesize, size_t numpages,
|
||||
int smp_cpus)
|
||||
{
|
||||
static gsize initialized = 0;
|
||||
size_t numpages_per_thread, leftover;
|
||||
int ret = 0, i = 0;
|
||||
char *addr = area;
|
||||
int i = 0;
|
||||
|
||||
if (g_once_init_enter(&initialized)) {
|
||||
qemu_mutex_init(&page_mutex);
|
||||
|
@ -523,7 +523,6 @@ static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages,
|
|||
g_once_init_leave(&initialized, 1);
|
||||
}
|
||||
|
||||
memset_thread_failed = false;
|
||||
threads_created_flag = false;
|
||||
memset_num_threads = get_memset_num_threads(smp_cpus);
|
||||
memset_thread = g_new0(MemsetThread, memset_num_threads);
|
||||
|
@ -545,12 +544,16 @@ static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages,
|
|||
qemu_mutex_unlock(&page_mutex);
|
||||
|
||||
for (i = 0; i < memset_num_threads; i++) {
|
||||
qemu_thread_join(&memset_thread[i].pgthread);
|
||||
int tmp = (uintptr_t)qemu_thread_join(&memset_thread[i].pgthread);
|
||||
|
||||
if (tmp) {
|
||||
ret = tmp;
|
||||
}
|
||||
}
|
||||
g_free(memset_thread);
|
||||
memset_thread = NULL;
|
||||
|
||||
return memset_thread_failed;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
|
||||
|
@ -573,9 +576,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
|
|||
}
|
||||
|
||||
/* touch pages simultaneously */
|
||||
if (touch_all_pages(area, hpagesize, numpages, smp_cpus)) {
|
||||
error_setg(errp, "os_mem_prealloc: Insufficient free host memory "
|
||||
"pages available to allocate guest RAM");
|
||||
ret = touch_all_pages(area, hpagesize, numpages, smp_cpus);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, -ret,
|
||||
"os_mem_prealloc: preallocating memory failed");
|
||||
}
|
||||
|
||||
ret = sigaction(SIGBUS, &oldact, NULL);
|
||||
|
|
Loading…
Reference in New Issue