exec: split file_ram_alloc()
Move file opening part in a seperate function, file_ram_open(). This allows for reuse of file_ram_alloc() with a given fd. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20170602141229.15326-3-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
e45e7ae281
commit
8d37b030fe
83
exec.c
83
exec.c
@ -1482,19 +1482,17 @@ static int64_t get_file_size(int fd)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *file_ram_alloc(RAMBlock *block,
|
static int file_ram_open(const char *path,
|
||||||
ram_addr_t memory,
|
const char *region_name,
|
||||||
const char *path,
|
bool *created,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
bool unlink_on_error = false;
|
|
||||||
char *filename;
|
char *filename;
|
||||||
char *sanitized_name;
|
char *sanitized_name;
|
||||||
char *c;
|
char *c;
|
||||||
void *area = MAP_FAILED;
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int64_t file_size;
|
|
||||||
|
|
||||||
|
*created = false;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fd = open(path, O_RDWR);
|
fd = open(path, O_RDWR);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
@ -1505,13 +1503,13 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
/* @path names a file that doesn't exist, create it */
|
/* @path names a file that doesn't exist, create it */
|
||||||
fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644);
|
fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
unlink_on_error = true;
|
*created = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (errno == EISDIR) {
|
} else if (errno == EISDIR) {
|
||||||
/* @path names a directory, create a file there */
|
/* @path names a directory, create a file there */
|
||||||
/* Make name safe to use with mkstemp by replacing '/' with '_'. */
|
/* Make name safe to use with mkstemp by replacing '/' with '_'. */
|
||||||
sanitized_name = g_strdup(memory_region_name(block->mr));
|
sanitized_name = g_strdup(region_name);
|
||||||
for (c = sanitized_name; *c != '\0'; c++) {
|
for (c = sanitized_name; *c != '\0'; c++) {
|
||||||
if (*c == '/') {
|
if (*c == '/') {
|
||||||
*c = '_';
|
*c = '_';
|
||||||
@ -1534,7 +1532,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
error_setg_errno(errp, errno,
|
error_setg_errno(errp, errno,
|
||||||
"can't open backing store %s for guest RAM",
|
"can't open backing store %s for guest RAM",
|
||||||
path);
|
path);
|
||||||
goto error;
|
return -1;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Try again on EINTR and EEXIST. The latter happens when
|
* Try again on EINTR and EEXIST. The latter happens when
|
||||||
@ -1542,6 +1540,17 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *file_ram_alloc(RAMBlock *block,
|
||||||
|
ram_addr_t memory,
|
||||||
|
int fd,
|
||||||
|
bool truncate,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
void *area;
|
||||||
|
|
||||||
block->page_size = qemu_fd_getpagesize(fd);
|
block->page_size = qemu_fd_getpagesize(fd);
|
||||||
block->mr->align = block->page_size;
|
block->mr->align = block->page_size;
|
||||||
#if defined(__s390x__)
|
#if defined(__s390x__)
|
||||||
@ -1550,20 +1559,11 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
file_size = get_file_size(fd);
|
|
||||||
|
|
||||||
if (memory < block->page_size) {
|
if (memory < block->page_size) {
|
||||||
error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
|
error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
|
||||||
"or larger than page size 0x%zx",
|
"or larger than page size 0x%zx",
|
||||||
memory, block->page_size);
|
memory, block->page_size);
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (file_size > 0 && file_size < memory) {
|
|
||||||
error_setg(errp, "backing store %s size 0x%" PRIx64
|
|
||||||
" does not match 'size' option 0x" RAM_ADDR_FMT,
|
|
||||||
path, file_size, memory);
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memory = ROUND_UP(memory, block->page_size);
|
memory = ROUND_UP(memory, block->page_size);
|
||||||
@ -1582,7 +1582,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
* those labels. Therefore, extending the non-empty backend file
|
* those labels. Therefore, extending the non-empty backend file
|
||||||
* is disabled as well.
|
* is disabled as well.
|
||||||
*/
|
*/
|
||||||
if (!file_size && ftruncate(fd, memory)) {
|
if (truncate && ftruncate(fd, memory)) {
|
||||||
perror("ftruncate");
|
perror("ftruncate");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1591,30 +1591,19 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
if (area == MAP_FAILED) {
|
if (area == MAP_FAILED) {
|
||||||
error_setg_errno(errp, errno,
|
error_setg_errno(errp, errno,
|
||||||
"unable to map backing store for guest RAM");
|
"unable to map backing store for guest RAM");
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem_prealloc) {
|
if (mem_prealloc) {
|
||||||
os_mem_prealloc(fd, area, memory, smp_cpus, errp);
|
os_mem_prealloc(fd, area, memory, smp_cpus, errp);
|
||||||
if (errp && *errp) {
|
if (errp && *errp) {
|
||||||
goto error;
|
qemu_ram_munmap(area, memory);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
block->fd = fd;
|
block->fd = fd;
|
||||||
return area;
|
return area;
|
||||||
|
|
||||||
error:
|
|
||||||
if (area != MAP_FAILED) {
|
|
||||||
qemu_ram_munmap(area, memory);
|
|
||||||
}
|
|
||||||
if (unlink_on_error) {
|
|
||||||
unlink(path);
|
|
||||||
}
|
|
||||||
if (fd != -1) {
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1931,6 +1920,9 @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
|
|||||||
{
|
{
|
||||||
RAMBlock *new_block;
|
RAMBlock *new_block;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
int fd;
|
||||||
|
bool created;
|
||||||
|
int64_t file_size;
|
||||||
|
|
||||||
if (xen_enabled()) {
|
if (xen_enabled()) {
|
||||||
error_setg(errp, "-mem-path not supported with Xen");
|
error_setg(errp, "-mem-path not supported with Xen");
|
||||||
@ -1954,15 +1946,32 @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fd = file_ram_open(mem_path, memory_region_name(mr), &created, errp);
|
||||||
|
if (fd < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
size = HOST_PAGE_ALIGN(size);
|
size = HOST_PAGE_ALIGN(size);
|
||||||
|
file_size = get_file_size(fd);
|
||||||
|
if (file_size > 0 && file_size < size) {
|
||||||
|
error_setg(errp, "backing store %s size 0x%" PRIx64
|
||||||
|
" does not match 'size' option 0x" RAM_ADDR_FMT,
|
||||||
|
mem_path, file_size, size);
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
new_block = g_malloc0(sizeof(*new_block));
|
new_block = g_malloc0(sizeof(*new_block));
|
||||||
new_block->mr = mr;
|
new_block->mr = mr;
|
||||||
new_block->used_length = size;
|
new_block->used_length = size;
|
||||||
new_block->max_length = size;
|
new_block->max_length = size;
|
||||||
new_block->flags = share ? RAM_SHARED : 0;
|
new_block->flags = share ? RAM_SHARED : 0;
|
||||||
new_block->host = file_ram_alloc(new_block, size,
|
new_block->host = file_ram_alloc(new_block, size, fd, !file_size, errp);
|
||||||
mem_path, errp);
|
|
||||||
if (!new_block->host) {
|
if (!new_block->host) {
|
||||||
|
if (created) {
|
||||||
|
unlink(mem_path);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
g_free(new_block);
|
g_free(new_block);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user