dm: Solve the problem of repeat mount hugetblfs

If you run two acrn-dm processes at the same time,
hugetblfs will be mounted twice, which will cause a memory leak.
The specific solution is :different virtual machines mount hugetblfs
into different directories.

Tracked-On:#2854
Signed-off-by: bing.li <bingx.li@intel.com>
Reviewed-by: Minggui Cao<minggui.cao@intel.com>
Acked-by: Yin Fengwei<fengwei.yin@intel.com>
This commit is contained in:
bing.li 2019-06-04 17:20:26 +08:00 committed by ACRN System Integration
parent e5a25749e5
commit 509af78490
3 changed files with 71 additions and 48 deletions

View File

@ -40,6 +40,8 @@
#include "vmmapi.h"
extern char *vmname;
#define HUGETLB_LV1 0
#define HUGETLB_LV2 1
#define HUGETLB_LV_MAX 2
@ -139,7 +141,7 @@ static int open_hugetlbfs(struct vmctx *ctx, int level)
path = hugetlb_priv[level].node_path;
memset(path, '\0', MAX_PATH_LEN);
strncpy(path, hugetlb_priv[level].mount_path, MAX_PATH_LEN);
snprintf(path, MAX_PATH_LEN, "%s%s/", hugetlb_priv[level].mount_path, ctx->name);
len = strnlen(path, MAX_PATH_LEN);
/* UUID will use 32 bytes */
@ -336,9 +338,29 @@ static size_t adj_biosmem_param(struct hugetlb_info *htlb,
return htlb->biosmem;
}
static int rm_hugetlb_dirs(int level)
{
char path[MAX_PATH_LEN]={0};
if (level >= HUGETLB_LV_MAX) {
perror("exceed max hugetlb level");
return -EINVAL;
}
snprintf(path,MAX_PATH_LEN, "%s%s/",hugetlb_priv[level].mount_path,vmname);
if (access(path, F_OK) == 0) {
if (rmdir(path) < 0) {
perror("rmdir failed");
return -1;
}
}
return 0;
}
static int create_hugetlb_dirs(int level)
{
char tmp_path[MAX_PATH_LEN], *path;
char path[MAX_PATH_LEN]={0};
int i;
size_t len;
@ -347,30 +369,19 @@ static int create_hugetlb_dirs(int level)
return -EINVAL;
}
path = hugetlb_priv[level].mount_path;
snprintf(path,MAX_PATH_LEN, "%s%s/",hugetlb_priv[level].mount_path,vmname);
len = strnlen(path, MAX_PATH_LEN);
if (len == MAX_PATH_LEN || len == 0) {
perror("invalid path len");
return -EINVAL;
}
memset(tmp_path, '\0', MAX_PATH_LEN);
strncpy(tmp_path, path, MAX_PATH_LEN);
if ((tmp_path[len - 1] != '/') && (len < MAX_PATH_LEN - 1))
tmp_path[len] = '/';
len = strnlen(tmp_path, MAX_PATH_LEN);
for (i = 1; i < len; i++) {
if (tmp_path[i] == '/') {
tmp_path[i] = 0;
if (access(tmp_path, F_OK) != 0) {
if (mkdir(tmp_path, 0755) < 0) {
if (path[i] == '/') {
path[i] = 0;
if (access(path, F_OK) != 0) {
if (mkdir(path, 0755) < 0) {
perror("mkdir failed");
return -1;
}
}
tmp_path[i] = '/';
path[i] = '/';
}
}
@ -380,6 +391,7 @@ static int create_hugetlb_dirs(int level)
static int mount_hugetlbfs(int level)
{
int ret;
char path[MAX_PATH_LEN];
if (level >= HUGETLB_LV_MAX) {
perror("exceed max hugetlb level");
@ -389,8 +401,10 @@ static int mount_hugetlbfs(int level)
if (hugetlb_priv[level].mounted)
return 0;
snprintf(path, MAX_PATH_LEN, "%s%s", hugetlb_priv[level].mount_path,vmname);
/* only support x86 as HUGETLB level-1 2M page, level-2 1G page*/
ret = mount("none", hugetlb_priv[level].mount_path, "hugetlbfs",
ret = mount("none", path, "hugetlbfs",
0, hugetlb_priv[level].mount_opt);
if (ret == 0)
hugetlb_priv[level].mounted = true;
@ -400,13 +414,18 @@ static int mount_hugetlbfs(int level)
static void umount_hugetlbfs(int level)
{
char path[MAX_PATH_LEN];
if (level >= HUGETLB_LV_MAX) {
perror("exceed max hugetlb level");
return;
}
snprintf(path, MAX_PATH_LEN, "%s%s", hugetlb_priv[level].mount_path,vmname);
if (hugetlb_priv[level].mounted) {
umount(hugetlb_priv[level].mount_path);
umount(path);
hugetlb_priv[level].mounted = false;
}
}
@ -589,7 +608,8 @@ static bool hugetlb_reserve_pages(void)
return true;
}
bool check_hugetlb_support(void)
bool init_hugetlb(void)
{
int level;
@ -615,6 +635,15 @@ bool check_hugetlb_support(void)
return true;
}
void uninit_hugetlb(void)
{
int level;
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) {
umount_hugetlbfs(level);
rm_hugetlb_dirs(level);
}
}
int hugetlb_setup_memory(struct vmctx *ctx)
{
int level;
@ -626,15 +655,6 @@ int hugetlb_setup_memory(struct vmctx *ctx)
goto err;
}
/* for first time DM start UOS, hugetlbfs is already mounted by
* check_hugetlb_support; but for reboot, here need re-mount
* it as it already be umount by hugetlb_unsetup_memory
* TODO: actually, correct reboot process should not change memory
* layout, the setup_memory should be removed from reboot process
*/
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++)
mount_hugetlbfs(level);
/* open hugetlbfs and get pagesize for two level */
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) {
if (open_hugetlbfs(ctx, level) < 0) {
@ -781,7 +801,6 @@ err:
}
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) {
close_hugetlbfs(level);
umount_hugetlbfs(level);
}
return -ENOMEM;
}
@ -798,6 +817,5 @@ void hugetlb_unsetup_memory(struct vmctx *ctx)
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) {
close_hugetlbfs(level);
umount_hugetlbfs(level);
}
}

View File

@ -770,7 +770,7 @@ static char optstr[] = "hAWYvE:k:r:B:p:c:s:m:l:U:G:i:";
int
main(int argc, char *argv[])
{
int c, error, err;
int c, error, ret=1;
int max_vcpus, mptgen;
struct vmctx *ctx;
size_t memsize;
@ -949,23 +949,23 @@ main(int argc, char *argv[])
if (argc != 1)
usage(1);
if (!check_hugetlb_support()) {
pr_err("check_hugetlb_support failed\n");
exit(1);
}
vmname = argv[0];
if (strnlen(vmname, MAX_VMNAME_LEN) >= MAX_VMNAME_LEN) {
pr_err("vmname size exceed %u\n", MAX_VMNAME_LEN);
exit(1);
}
if (!init_hugetlb()) {
pr_err("init_hugetlb failed\n");
exit(1);
}
for (;;) {
pr_notice("vm_create: %s\n", vmname);
ctx = vm_create(vmname, (unsigned long)vhm_req_buf);
if (!ctx) {
pr_err("vm_create failed");
exit(1);
goto create_fail;
}
if (guest_ncpus < 1) {
@ -981,14 +981,14 @@ main(int argc, char *argv[])
}
pr_notice("vm_setup_memory: size=0x%lx\n", memsize);
err = vm_setup_memory(ctx, memsize);
if (err) {
error = vm_setup_memory(ctx, memsize);
if (error) {
pr_err("Unable to setup memory (%d)\n", errno);
goto fail;
}
err = mevent_init();
if (err) {
error = mevent_init();
if (error) {
pr_err("Unable to initialize mevent (%d)\n", errno);
goto mevent_fail;
}
@ -1050,8 +1050,10 @@ main(int argc, char *argv[])
vm_pause(ctx);
delete_cpu(ctx, BSP);
if (vm_get_suspend_mode() != VM_SUSPEND_FULL_RESET)
if (vm_get_suspend_mode() != VM_SUSPEND_FULL_RESET){
ret = 0;
break;
}
vm_deinit_vdevs(ctx);
mevent_deinit();
@ -1070,5 +1072,7 @@ mevent_fail:
vm_unsetup_memory(ctx);
fail:
vm_destroy(ctx);
exit(0);
create_fail:
uninit_hugetlb();
exit(ret);
}

View File

@ -108,7 +108,8 @@ int vm_map_memseg_vma(struct vmctx *ctx, size_t len, vm_paddr_t gpa,
uint64_t vma, int prot);
int vm_setup_memory(struct vmctx *ctx, size_t len);
void vm_unsetup_memory(struct vmctx *ctx);
bool check_hugetlb_support(void);
bool init_hugetlb(void);
void uninit_hugetlb(void);
int hugetlb_setup_memory(struct vmctx *ctx);
void hugetlb_unsetup_memory(struct vmctx *ctx);
void *vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len);