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" #include "vmmapi.h"
extern char *vmname;
#define HUGETLB_LV1 0 #define HUGETLB_LV1 0
#define HUGETLB_LV2 1 #define HUGETLB_LV2 1
#define HUGETLB_LV_MAX 2 #define HUGETLB_LV_MAX 2
@ -139,7 +141,7 @@ static int open_hugetlbfs(struct vmctx *ctx, int level)
path = hugetlb_priv[level].node_path; path = hugetlb_priv[level].node_path;
memset(path, '\0', MAX_PATH_LEN); 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); len = strnlen(path, MAX_PATH_LEN);
/* UUID will use 32 bytes */ /* UUID will use 32 bytes */
@ -336,9 +338,29 @@ static size_t adj_biosmem_param(struct hugetlb_info *htlb,
return htlb->biosmem; 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) static int create_hugetlb_dirs(int level)
{ {
char tmp_path[MAX_PATH_LEN], *path; char path[MAX_PATH_LEN]={0};
int i; int i;
size_t len; size_t len;
@ -347,30 +369,19 @@ static int create_hugetlb_dirs(int level)
return -EINVAL; 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); 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++) { for (i = 1; i < len; i++) {
if (tmp_path[i] == '/') { if (path[i] == '/') {
tmp_path[i] = 0; path[i] = 0;
if (access(tmp_path, F_OK) != 0) { if (access(path, F_OK) != 0) {
if (mkdir(tmp_path, 0755) < 0) { if (mkdir(path, 0755) < 0) {
perror("mkdir failed"); perror("mkdir failed");
return -1; return -1;
} }
} }
tmp_path[i] = '/'; path[i] = '/';
} }
} }
@ -380,6 +391,7 @@ static int create_hugetlb_dirs(int level)
static int mount_hugetlbfs(int level) static int mount_hugetlbfs(int level)
{ {
int ret; int ret;
char path[MAX_PATH_LEN];
if (level >= HUGETLB_LV_MAX) { if (level >= HUGETLB_LV_MAX) {
perror("exceed max hugetlb level"); perror("exceed max hugetlb level");
@ -389,8 +401,10 @@ static int mount_hugetlbfs(int level)
if (hugetlb_priv[level].mounted) if (hugetlb_priv[level].mounted)
return 0; 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*/ /* 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); 0, hugetlb_priv[level].mount_opt);
if (ret == 0) if (ret == 0)
hugetlb_priv[level].mounted = true; hugetlb_priv[level].mounted = true;
@ -400,13 +414,18 @@ static int mount_hugetlbfs(int level)
static void umount_hugetlbfs(int level) static void umount_hugetlbfs(int level)
{ {
char path[MAX_PATH_LEN];
if (level >= HUGETLB_LV_MAX) { if (level >= HUGETLB_LV_MAX) {
perror("exceed max hugetlb level"); perror("exceed max hugetlb level");
return; return;
} }
snprintf(path, MAX_PATH_LEN, "%s%s", hugetlb_priv[level].mount_path,vmname);
if (hugetlb_priv[level].mounted) { if (hugetlb_priv[level].mounted) {
umount(hugetlb_priv[level].mount_path); umount(path);
hugetlb_priv[level].mounted = false; hugetlb_priv[level].mounted = false;
} }
} }
@ -589,7 +608,8 @@ static bool hugetlb_reserve_pages(void)
return true; return true;
} }
bool check_hugetlb_support(void)
bool init_hugetlb(void)
{ {
int level; int level;
@ -615,6 +635,15 @@ bool check_hugetlb_support(void)
return true; 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 hugetlb_setup_memory(struct vmctx *ctx)
{ {
int level; int level;
@ -626,15 +655,6 @@ int hugetlb_setup_memory(struct vmctx *ctx)
goto err; 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 */ /* open hugetlbfs and get pagesize for two level */
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) { for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) {
if (open_hugetlbfs(ctx, level) < 0) { if (open_hugetlbfs(ctx, level) < 0) {
@ -781,7 +801,6 @@ err:
} }
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) { for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) {
close_hugetlbfs(level); close_hugetlbfs(level);
umount_hugetlbfs(level);
} }
return -ENOMEM; return -ENOMEM;
} }
@ -798,6 +817,5 @@ void hugetlb_unsetup_memory(struct vmctx *ctx)
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) { for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) {
close_hugetlbfs(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 int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int c, error, err; int c, error, ret=1;
int max_vcpus, mptgen; int max_vcpus, mptgen;
struct vmctx *ctx; struct vmctx *ctx;
size_t memsize; size_t memsize;
@ -949,23 +949,23 @@ main(int argc, char *argv[])
if (argc != 1) if (argc != 1)
usage(1); usage(1);
if (!check_hugetlb_support()) {
pr_err("check_hugetlb_support failed\n");
exit(1);
}
vmname = argv[0]; vmname = argv[0];
if (strnlen(vmname, MAX_VMNAME_LEN) >= MAX_VMNAME_LEN) { if (strnlen(vmname, MAX_VMNAME_LEN) >= MAX_VMNAME_LEN) {
pr_err("vmname size exceed %u\n", MAX_VMNAME_LEN); pr_err("vmname size exceed %u\n", MAX_VMNAME_LEN);
exit(1); exit(1);
} }
if (!init_hugetlb()) {
pr_err("init_hugetlb failed\n");
exit(1);
}
for (;;) { for (;;) {
pr_notice("vm_create: %s\n", vmname); pr_notice("vm_create: %s\n", vmname);
ctx = vm_create(vmname, (unsigned long)vhm_req_buf); ctx = vm_create(vmname, (unsigned long)vhm_req_buf);
if (!ctx) { if (!ctx) {
pr_err("vm_create failed"); pr_err("vm_create failed");
exit(1); goto create_fail;
} }
if (guest_ncpus < 1) { if (guest_ncpus < 1) {
@ -981,14 +981,14 @@ main(int argc, char *argv[])
} }
pr_notice("vm_setup_memory: size=0x%lx\n", memsize); pr_notice("vm_setup_memory: size=0x%lx\n", memsize);
err = vm_setup_memory(ctx, memsize); error = vm_setup_memory(ctx, memsize);
if (err) { if (error) {
pr_err("Unable to setup memory (%d)\n", errno); pr_err("Unable to setup memory (%d)\n", errno);
goto fail; goto fail;
} }
err = mevent_init(); error = mevent_init();
if (err) { if (error) {
pr_err("Unable to initialize mevent (%d)\n", errno); pr_err("Unable to initialize mevent (%d)\n", errno);
goto mevent_fail; goto mevent_fail;
} }
@ -1050,8 +1050,10 @@ main(int argc, char *argv[])
vm_pause(ctx); vm_pause(ctx);
delete_cpu(ctx, BSP); 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; break;
}
vm_deinit_vdevs(ctx); vm_deinit_vdevs(ctx);
mevent_deinit(); mevent_deinit();
@ -1070,5 +1072,7 @@ mevent_fail:
vm_unsetup_memory(ctx); vm_unsetup_memory(ctx);
fail: fail:
vm_destroy(ctx); 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); uint64_t vma, int prot);
int vm_setup_memory(struct vmctx *ctx, size_t len); int vm_setup_memory(struct vmctx *ctx, size_t len);
void vm_unsetup_memory(struct vmctx *ctx); 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); int hugetlb_setup_memory(struct vmctx *ctx);
void hugetlb_unsetup_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); void *vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len);