mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-24 06:29:19 +00:00
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:
parent
e5a25749e5
commit
509af78490
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user