diff --git a/0047-move-all-the-files-to-sub-directory-of-etmem.patch b/0047-move-all-the-files-to-sub-directory-of-etmem.patch new file mode 100644 index 0000000..f010a7d --- /dev/null +++ b/0047-move-all-the-files-to-sub-directory-of-etmem.patch @@ -0,0 +1,335 @@ +From b89f142798ebb23ad58ad3a0d1fe34f74e7801a6 Mon Sep 17 00:00:00 2001 +From: louhongxiang +Date: Thu, 30 Sep 2021 14:15:50 +0800 +Subject: [PATCH 47/50] move all the files to sub directory of etmem. + +--- + CMakeLists.txt => etmem/CMakeLists.txt | 0 + {conf => etmem/conf}/example_conf.yaml | 0 + {inc => etmem/inc}/etmem_inc/etmem.h | 0 + {inc => etmem/inc}/etmem_inc/etmem_common.h | 0 + {inc => etmem/inc}/etmem_inc/etmem_engine.h | 0 + {inc => etmem/inc}/etmem_inc/etmem_obj.h | 0 + {inc => etmem/inc}/etmem_inc/etmem_project.h | 0 + {inc => etmem/inc}/etmem_inc/etmem_rpc.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_common.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_cslide.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_engine.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_engine_exp.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_exp.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_file.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_log.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_migrate.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_pool_adapter.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_project.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_project_exp.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_rpc.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_scan.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_scan_exp.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_scan_export.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_slide.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_task.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_task_exp.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_thirdparty.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_thirdparty_export.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_threadpool.h | 0 + {inc => etmem/inc}/etmemd_inc/etmemd_threadtimer.h | 0 + {src => etmem/src}/etmem_src/etmem.c | 0 + {src => etmem/src}/etmem_src/etmem_common.c | 0 + {src => etmem/src}/etmem_src/etmem_engine.c | 0 + {src => etmem/src}/etmem_src/etmem_obj.c | 0 + {src => etmem/src}/etmem_src/etmem_project.c | 0 + {src => etmem/src}/etmem_src/etmem_rpc.c | 0 + {src => etmem/src}/etmemd_src/etmemd.c | 0 + {src => etmem/src}/etmemd_src/etmemd_common.c | 0 + {src => etmem/src}/etmemd_src/etmemd_cslide.c | 0 + {src => etmem/src}/etmemd_src/etmemd_engine.c | 0 + {src => etmem/src}/etmemd_src/etmemd_file.c | 0 + {src => etmem/src}/etmemd_src/etmemd_log.c | 0 + {src => etmem/src}/etmemd_src/etmemd_migrate.c | 0 + {src => etmem/src}/etmemd_src/etmemd_pool_adapter.c | 0 + {src => etmem/src}/etmemd_src/etmemd_project.c | 0 + {src => etmem/src}/etmemd_src/etmemd_rpc.c | 0 + {src => etmem/src}/etmemd_src/etmemd_scan.c | 0 + {src => etmem/src}/etmemd_src/etmemd_scan.version | 0 + {src => etmem/src}/etmemd_src/etmemd_slide.c | 0 + {src => etmem/src}/etmemd_src/etmemd_task.c | 0 + {src => etmem/src}/etmemd_src/etmemd_thirdparty.c | 0 + {src => etmem/src}/etmemd_src/etmemd_threadpool.c | 0 + {src => etmem/src}/etmemd_src/etmemd_threadtimer.c | 0 + 56 files changed, 0 insertions(+), 0 deletions(-) + rename CMakeLists.txt => etmem/CMakeLists.txt (100%) + rename {conf => etmem/conf}/example_conf.yaml (100%) + rename {inc => etmem/inc}/etmem_inc/etmem.h (100%) + rename {inc => etmem/inc}/etmem_inc/etmem_common.h (100%) + rename {inc => etmem/inc}/etmem_inc/etmem_engine.h (100%) + rename {inc => etmem/inc}/etmem_inc/etmem_obj.h (100%) + rename {inc => etmem/inc}/etmem_inc/etmem_project.h (100%) + rename {inc => etmem/inc}/etmem_inc/etmem_rpc.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_common.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_cslide.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_engine.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_engine_exp.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_exp.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_file.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_log.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_migrate.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_pool_adapter.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_project.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_project_exp.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_rpc.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_scan.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_scan_exp.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_scan_export.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_slide.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_task.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_task_exp.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_thirdparty.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_thirdparty_export.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_threadpool.h (100%) + rename {inc => etmem/inc}/etmemd_inc/etmemd_threadtimer.h (100%) + rename {src => etmem/src}/etmem_src/etmem.c (100%) + rename {src => etmem/src}/etmem_src/etmem_common.c (100%) + rename {src => etmem/src}/etmem_src/etmem_engine.c (100%) + rename {src => etmem/src}/etmem_src/etmem_obj.c (100%) + rename {src => etmem/src}/etmem_src/etmem_project.c (100%) + rename {src => etmem/src}/etmem_src/etmem_rpc.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_common.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_cslide.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_engine.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_file.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_log.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_migrate.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_pool_adapter.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_project.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_rpc.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_scan.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_scan.version (100%) + rename {src => etmem/src}/etmemd_src/etmemd_slide.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_task.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_thirdparty.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_threadpool.c (100%) + rename {src => etmem/src}/etmemd_src/etmemd_threadtimer.c (100%) + +diff --git a/CMakeLists.txt b/etmem/CMakeLists.txt +similarity index 100% +rename from CMakeLists.txt +rename to etmem/CMakeLists.txt +diff --git a/conf/example_conf.yaml b/etmem/conf/example_conf.yaml +similarity index 100% +rename from conf/example_conf.yaml +rename to etmem/conf/example_conf.yaml +diff --git a/inc/etmem_inc/etmem.h b/etmem/inc/etmem_inc/etmem.h +similarity index 100% +rename from inc/etmem_inc/etmem.h +rename to etmem/inc/etmem_inc/etmem.h +diff --git a/inc/etmem_inc/etmem_common.h b/etmem/inc/etmem_inc/etmem_common.h +similarity index 100% +rename from inc/etmem_inc/etmem_common.h +rename to etmem/inc/etmem_inc/etmem_common.h +diff --git a/inc/etmem_inc/etmem_engine.h b/etmem/inc/etmem_inc/etmem_engine.h +similarity index 100% +rename from inc/etmem_inc/etmem_engine.h +rename to etmem/inc/etmem_inc/etmem_engine.h +diff --git a/inc/etmem_inc/etmem_obj.h b/etmem/inc/etmem_inc/etmem_obj.h +similarity index 100% +rename from inc/etmem_inc/etmem_obj.h +rename to etmem/inc/etmem_inc/etmem_obj.h +diff --git a/inc/etmem_inc/etmem_project.h b/etmem/inc/etmem_inc/etmem_project.h +similarity index 100% +rename from inc/etmem_inc/etmem_project.h +rename to etmem/inc/etmem_inc/etmem_project.h +diff --git a/inc/etmem_inc/etmem_rpc.h b/etmem/inc/etmem_inc/etmem_rpc.h +similarity index 100% +rename from inc/etmem_inc/etmem_rpc.h +rename to etmem/inc/etmem_inc/etmem_rpc.h +diff --git a/inc/etmemd_inc/etmemd.h b/etmem/inc/etmemd_inc/etmemd.h +similarity index 100% +rename from inc/etmemd_inc/etmemd.h +rename to etmem/inc/etmemd_inc/etmemd.h +diff --git a/inc/etmemd_inc/etmemd_common.h b/etmem/inc/etmemd_inc/etmemd_common.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_common.h +rename to etmem/inc/etmemd_inc/etmemd_common.h +diff --git a/inc/etmemd_inc/etmemd_cslide.h b/etmem/inc/etmemd_inc/etmemd_cslide.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_cslide.h +rename to etmem/inc/etmemd_inc/etmemd_cslide.h +diff --git a/inc/etmemd_inc/etmemd_engine.h b/etmem/inc/etmemd_inc/etmemd_engine.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_engine.h +rename to etmem/inc/etmemd_inc/etmemd_engine.h +diff --git a/inc/etmemd_inc/etmemd_engine_exp.h b/etmem/inc/etmemd_inc/etmemd_engine_exp.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_engine_exp.h +rename to etmem/inc/etmemd_inc/etmemd_engine_exp.h +diff --git a/inc/etmemd_inc/etmemd_exp.h b/etmem/inc/etmemd_inc/etmemd_exp.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_exp.h +rename to etmem/inc/etmemd_inc/etmemd_exp.h +diff --git a/inc/etmemd_inc/etmemd_file.h b/etmem/inc/etmemd_inc/etmemd_file.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_file.h +rename to etmem/inc/etmemd_inc/etmemd_file.h +diff --git a/inc/etmemd_inc/etmemd_log.h b/etmem/inc/etmemd_inc/etmemd_log.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_log.h +rename to etmem/inc/etmemd_inc/etmemd_log.h +diff --git a/inc/etmemd_inc/etmemd_migrate.h b/etmem/inc/etmemd_inc/etmemd_migrate.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_migrate.h +rename to etmem/inc/etmemd_inc/etmemd_migrate.h +diff --git a/inc/etmemd_inc/etmemd_pool_adapter.h b/etmem/inc/etmemd_inc/etmemd_pool_adapter.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_pool_adapter.h +rename to etmem/inc/etmemd_inc/etmemd_pool_adapter.h +diff --git a/inc/etmemd_inc/etmemd_project.h b/etmem/inc/etmemd_inc/etmemd_project.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_project.h +rename to etmem/inc/etmemd_inc/etmemd_project.h +diff --git a/inc/etmemd_inc/etmemd_project_exp.h b/etmem/inc/etmemd_inc/etmemd_project_exp.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_project_exp.h +rename to etmem/inc/etmemd_inc/etmemd_project_exp.h +diff --git a/inc/etmemd_inc/etmemd_rpc.h b/etmem/inc/etmemd_inc/etmemd_rpc.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_rpc.h +rename to etmem/inc/etmemd_inc/etmemd_rpc.h +diff --git a/inc/etmemd_inc/etmemd_scan.h b/etmem/inc/etmemd_inc/etmemd_scan.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_scan.h +rename to etmem/inc/etmemd_inc/etmemd_scan.h +diff --git a/inc/etmemd_inc/etmemd_scan_exp.h b/etmem/inc/etmemd_inc/etmemd_scan_exp.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_scan_exp.h +rename to etmem/inc/etmemd_inc/etmemd_scan_exp.h +diff --git a/inc/etmemd_inc/etmemd_scan_export.h b/etmem/inc/etmemd_inc/etmemd_scan_export.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_scan_export.h +rename to etmem/inc/etmemd_inc/etmemd_scan_export.h +diff --git a/inc/etmemd_inc/etmemd_slide.h b/etmem/inc/etmemd_inc/etmemd_slide.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_slide.h +rename to etmem/inc/etmemd_inc/etmemd_slide.h +diff --git a/inc/etmemd_inc/etmemd_task.h b/etmem/inc/etmemd_inc/etmemd_task.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_task.h +rename to etmem/inc/etmemd_inc/etmemd_task.h +diff --git a/inc/etmemd_inc/etmemd_task_exp.h b/etmem/inc/etmemd_inc/etmemd_task_exp.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_task_exp.h +rename to etmem/inc/etmemd_inc/etmemd_task_exp.h +diff --git a/inc/etmemd_inc/etmemd_thirdparty.h b/etmem/inc/etmemd_inc/etmemd_thirdparty.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_thirdparty.h +rename to etmem/inc/etmemd_inc/etmemd_thirdparty.h +diff --git a/inc/etmemd_inc/etmemd_thirdparty_export.h b/etmem/inc/etmemd_inc/etmemd_thirdparty_export.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_thirdparty_export.h +rename to etmem/inc/etmemd_inc/etmemd_thirdparty_export.h +diff --git a/inc/etmemd_inc/etmemd_threadpool.h b/etmem/inc/etmemd_inc/etmemd_threadpool.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_threadpool.h +rename to etmem/inc/etmemd_inc/etmemd_threadpool.h +diff --git a/inc/etmemd_inc/etmemd_threadtimer.h b/etmem/inc/etmemd_inc/etmemd_threadtimer.h +similarity index 100% +rename from inc/etmemd_inc/etmemd_threadtimer.h +rename to etmem/inc/etmemd_inc/etmemd_threadtimer.h +diff --git a/src/etmem_src/etmem.c b/etmem/src/etmem_src/etmem.c +similarity index 100% +rename from src/etmem_src/etmem.c +rename to etmem/src/etmem_src/etmem.c +diff --git a/src/etmem_src/etmem_common.c b/etmem/src/etmem_src/etmem_common.c +similarity index 100% +rename from src/etmem_src/etmem_common.c +rename to etmem/src/etmem_src/etmem_common.c +diff --git a/src/etmem_src/etmem_engine.c b/etmem/src/etmem_src/etmem_engine.c +similarity index 100% +rename from src/etmem_src/etmem_engine.c +rename to etmem/src/etmem_src/etmem_engine.c +diff --git a/src/etmem_src/etmem_obj.c b/etmem/src/etmem_src/etmem_obj.c +similarity index 100% +rename from src/etmem_src/etmem_obj.c +rename to etmem/src/etmem_src/etmem_obj.c +diff --git a/src/etmem_src/etmem_project.c b/etmem/src/etmem_src/etmem_project.c +similarity index 100% +rename from src/etmem_src/etmem_project.c +rename to etmem/src/etmem_src/etmem_project.c +diff --git a/src/etmem_src/etmem_rpc.c b/etmem/src/etmem_src/etmem_rpc.c +similarity index 100% +rename from src/etmem_src/etmem_rpc.c +rename to etmem/src/etmem_src/etmem_rpc.c +diff --git a/src/etmemd_src/etmemd.c b/etmem/src/etmemd_src/etmemd.c +similarity index 100% +rename from src/etmemd_src/etmemd.c +rename to etmem/src/etmemd_src/etmemd.c +diff --git a/src/etmemd_src/etmemd_common.c b/etmem/src/etmemd_src/etmemd_common.c +similarity index 100% +rename from src/etmemd_src/etmemd_common.c +rename to etmem/src/etmemd_src/etmemd_common.c +diff --git a/src/etmemd_src/etmemd_cslide.c b/etmem/src/etmemd_src/etmemd_cslide.c +similarity index 100% +rename from src/etmemd_src/etmemd_cslide.c +rename to etmem/src/etmemd_src/etmemd_cslide.c +diff --git a/src/etmemd_src/etmemd_engine.c b/etmem/src/etmemd_src/etmemd_engine.c +similarity index 100% +rename from src/etmemd_src/etmemd_engine.c +rename to etmem/src/etmemd_src/etmemd_engine.c +diff --git a/src/etmemd_src/etmemd_file.c b/etmem/src/etmemd_src/etmemd_file.c +similarity index 100% +rename from src/etmemd_src/etmemd_file.c +rename to etmem/src/etmemd_src/etmemd_file.c +diff --git a/src/etmemd_src/etmemd_log.c b/etmem/src/etmemd_src/etmemd_log.c +similarity index 100% +rename from src/etmemd_src/etmemd_log.c +rename to etmem/src/etmemd_src/etmemd_log.c +diff --git a/src/etmemd_src/etmemd_migrate.c b/etmem/src/etmemd_src/etmemd_migrate.c +similarity index 100% +rename from src/etmemd_src/etmemd_migrate.c +rename to etmem/src/etmemd_src/etmemd_migrate.c +diff --git a/src/etmemd_src/etmemd_pool_adapter.c b/etmem/src/etmemd_src/etmemd_pool_adapter.c +similarity index 100% +rename from src/etmemd_src/etmemd_pool_adapter.c +rename to etmem/src/etmemd_src/etmemd_pool_adapter.c +diff --git a/src/etmemd_src/etmemd_project.c b/etmem/src/etmemd_src/etmemd_project.c +similarity index 100% +rename from src/etmemd_src/etmemd_project.c +rename to etmem/src/etmemd_src/etmemd_project.c +diff --git a/src/etmemd_src/etmemd_rpc.c b/etmem/src/etmemd_src/etmemd_rpc.c +similarity index 100% +rename from src/etmemd_src/etmemd_rpc.c +rename to etmem/src/etmemd_src/etmemd_rpc.c +diff --git a/src/etmemd_src/etmemd_scan.c b/etmem/src/etmemd_src/etmemd_scan.c +similarity index 100% +rename from src/etmemd_src/etmemd_scan.c +rename to etmem/src/etmemd_src/etmemd_scan.c +diff --git a/src/etmemd_src/etmemd_scan.version b/etmem/src/etmemd_src/etmemd_scan.version +similarity index 100% +rename from src/etmemd_src/etmemd_scan.version +rename to etmem/src/etmemd_src/etmemd_scan.version +diff --git a/src/etmemd_src/etmemd_slide.c b/etmem/src/etmemd_src/etmemd_slide.c +similarity index 100% +rename from src/etmemd_src/etmemd_slide.c +rename to etmem/src/etmemd_src/etmemd_slide.c +diff --git a/src/etmemd_src/etmemd_task.c b/etmem/src/etmemd_src/etmemd_task.c +similarity index 100% +rename from src/etmemd_src/etmemd_task.c +rename to etmem/src/etmemd_src/etmemd_task.c +diff --git a/src/etmemd_src/etmemd_thirdparty.c b/etmem/src/etmemd_src/etmemd_thirdparty.c +similarity index 100% +rename from src/etmemd_src/etmemd_thirdparty.c +rename to etmem/src/etmemd_src/etmemd_thirdparty.c +diff --git a/src/etmemd_src/etmemd_threadpool.c b/etmem/src/etmemd_src/etmemd_threadpool.c +similarity index 100% +rename from src/etmemd_src/etmemd_threadpool.c +rename to etmem/src/etmemd_src/etmemd_threadpool.c +diff --git a/src/etmemd_src/etmemd_threadtimer.c b/etmem/src/etmemd_src/etmemd_threadtimer.c +similarity index 100% +rename from src/etmemd_src/etmemd_threadtimer.c +rename to etmem/src/etmemd_src/etmemd_threadtimer.c +-- +2.27.0 + diff --git a/0048-Commit-new-features-memRouter-and-userswap-to-etmem.patch b/0048-Commit-new-features-memRouter-and-userswap-to-etmem.patch new file mode 100644 index 0000000..c09c539 --- /dev/null +++ b/0048-Commit-new-features-memRouter-and-userswap-to-etmem.patch @@ -0,0 +1,3286 @@ +From 3d4006defc9ac08581b1cbc7fb5c0ad06473273c Mon Sep 17 00:00:00 2001 +From: Yangxin <245051644@qq.com> +Date: Thu, 30 Sep 2021 17:40:21 +0800 +Subject: [PATCH 48/50] Commit new features memRouter and userswap to etmem. + +Signed-off-by: Yangxin <245051644@qq.com> +--- + memRouter/CMakeLists.txt | 74 +++ + memRouter/README.md | 90 +++ + memRouter/include/memdcd_cmd.h | 21 + + memRouter/include/memdcd_daemon.h | 23 + + memRouter/include/memdcd_log.h | 34 + + memRouter/include/memdcd_message.h | 75 +++ + memRouter/include/memdcd_migrate.h | 21 + + memRouter/include/memdcd_policy.h | 42 ++ + memRouter/include/memdcd_policy_threshold.h | 22 + + memRouter/include/memdcd_process.h | 41 ++ + memRouter/src/memdcd.c | 143 +++++ + memRouter/src/memdcd_cmd.c | 93 +++ + memRouter/src/memdcd_daemon.c | 257 ++++++++ + memRouter/src/memdcd_log.c | 80 +++ + memRouter/src/memdcd_migrate.c | 150 +++++ + memRouter/src/memdcd_policy.c | 132 ++++ + memRouter/src/memdcd_policy_threshold.c | 209 ++++++ + memRouter/src/memdcd_process.c | 345 ++++++++++ + userswap/CMakeLists.txt | 36 ++ + userswap/License/LICENSE | 127 ++++ + userswap/README.md | 7 + + userswap/configure.sh | 4 + + userswap/include/uswap_api.h | 69 ++ + userswap/include/uswap_log.h | 30 + + userswap/include/uswap_server.h | 40 ++ + userswap/src/lib_uswap.c | 663 ++++++++++++++++++++ + userswap/src/uswap_log.c | 81 +++ + userswap/src/uswap_server.c | 138 ++++ + 28 files changed, 3047 insertions(+) + create mode 100644 memRouter/CMakeLists.txt + create mode 100644 memRouter/README.md + create mode 100644 memRouter/include/memdcd_cmd.h + create mode 100644 memRouter/include/memdcd_daemon.h + create mode 100644 memRouter/include/memdcd_log.h + create mode 100644 memRouter/include/memdcd_message.h + create mode 100644 memRouter/include/memdcd_migrate.h + create mode 100644 memRouter/include/memdcd_policy.h + create mode 100644 memRouter/include/memdcd_policy_threshold.h + create mode 100644 memRouter/include/memdcd_process.h + create mode 100644 memRouter/src/memdcd.c + create mode 100644 memRouter/src/memdcd_cmd.c + create mode 100644 memRouter/src/memdcd_daemon.c + create mode 100644 memRouter/src/memdcd_log.c + create mode 100644 memRouter/src/memdcd_migrate.c + create mode 100644 memRouter/src/memdcd_policy.c + create mode 100644 memRouter/src/memdcd_policy_threshold.c + create mode 100644 memRouter/src/memdcd_process.c + create mode 100644 userswap/CMakeLists.txt + create mode 100644 userswap/License/LICENSE + create mode 100644 userswap/README.md + create mode 100644 userswap/configure.sh + create mode 100644 userswap/include/uswap_api.h + create mode 100644 userswap/include/uswap_log.h + create mode 100644 userswap/include/uswap_server.h + create mode 100644 userswap/src/lib_uswap.c + create mode 100644 userswap/src/uswap_log.c + create mode 100644 userswap/src/uswap_server.c + +diff --git a/memRouter/CMakeLists.txt b/memRouter/CMakeLists.txt +new file mode 100644 +index 0000000..1e55115 +--- /dev/null ++++ b/memRouter/CMakeLists.txt +@@ -0,0 +1,74 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: YangXin ++# * Create: 2020-09-08 ++# * Description: CMakefileList for memRouter to compile ++# ******************************************************************************/ ++ ++cmake_minimum_required (VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) ++project(memdcd C) ++ ++set(CMAKE_C_STANDARD 99) ++ ++set(LOCAL_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) ++ ++IF(CMAKE_BUILD_TYPE STREQUAL Test) ++ IF(COVERAGE_ENABLE) ++ MESSAGE(STATUS "Enable coverage compile option") ++ SET(COVERAGE_OPTION "${COVERAGE_OPTION} -fprofile-arcs -ftest-coverage") ++ ENDIF(COVERAGE_ENABLE) ++ IF(ASAN_ENABLE) ++ MESSAGE(STATUS "Enable asan compile option") ++ SET(ASAN_OPTIONS "${ASAN_OPTION} -fsanitize=address -fsanitize-recover=address") ++ ENDIF(ASAN_ENABLE) ++ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_DEBUG} ${COVERAGE_OPTION} ${ASAN_OPTIONS}") ++ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEBUG} ${COVERAGE_OPTION} ${ASAN_OPTIONS}") ++ add_subdirectory(test) ++ENDIF() ++ ++set(CMAKE_POSITION_INDEPENDENT_CODE ON) ++ ++set(SRC_DIR ${PROJECT_SOURCE_DIR}/src) ++set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) ++set(BUILD_DIR ${PROJECT_SOURCE_DIR}/build) ++ ++set(MEMROUTER_SRC ++ ${SRC_DIR}/memdcd.c ++ ${SRC_DIR}/memdcd_policy.c ++ ${SRC_DIR}/memdcd_policy_threshold.c ++ ${SRC_DIR}/memdcd_migrate.c ++ ${SRC_DIR}/memdcd_process.c ++ ${SRC_DIR}/memdcd_daemon.c ++ ${SRC_DIR}/memdcd_cmd.c ++ ${SRC_DIR}/memdcd_log.c ++ ) ++ ++add_executable(memdcd ${MEMROUTER_SRC}) ++ ++target_include_directories(memdcd PRIVATE ++ ${INCLUDE_DIR}/) ++ ++add_definitions(-D_GNU_SOURCE -DNDEBUG -D_FORTIFY_SOURCE=2) ++target_compile_options(memdcd PRIVATE -fsigned-char --param ssp-buffer-size=4 -fno-omit-frame-pointer -Wall -Wextra ++-Wno-missing-field-initializers -Wmissing-declarations -fno-strict-aliasing ++-Wformat -Wformat-security -fPIE -pie -fPIC -ftrapv ++-Wno-error=deprecated-declarations -fstack-protector-all -fno-common -O2 -Wall -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -pthread -Wstrict-prototypes -Wl,--no-whole-archive -Wold-style-definition -std=gnu99 -Wno-error=unused-result -Wno-error=strict-prototypes -Wno-error=old-style-definition -Wno-error=missing-declarations -Wno-error=format-overflow -I${INCLUDE_DIR}) ++ ++if(CONFIG_DEBUG STREQUAL "y") ++ target_compile_options(memdcd PRIVATE -g) ++endif() ++ ++target_link_libraries(memdcd PRIVATE pthread dl rt numa json-c cap -s) ++ ++install(TARGETS memdcd ++ PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE ++ RUNTIME DESTINATION /usr/bin ++ ) +diff --git a/memRouter/README.md b/memRouter/README.md +new file mode 100644 +index 0000000..4350a4c +--- /dev/null ++++ b/memRouter/README.md +@@ -0,0 +1,90 @@ ++# memRouter ++ ++## 介绍 ++ ++随着CPU算力的发展,尤其是ARM核成本的降低,内存成本和内存容量成为约束业务成本和性能的核心痛点,因此如何节省内存成本,如何扩大内存容量成为存储迫切要解决的问题。 ++ ++memRouter内存分级扩展,根据用户选择内存迁移策略对内存进行分级,分发到不同级别的介质上,降低dram的使用量,来达到内存容量扩展的目的。 ++ ++## 编译方法 ++ ++1. 下载memRouter源码 ++``` ++git clone https://gitee.com/openeuler/etmem.git ++``` ++2. 编译和运行依赖 ++ ++ memRouter的编译和运行依赖于libcap-devel、json-c-devel、numactl-devel软件包 ++ ++3. 编译 ++``` ++cd memRouter ++mkdir build ++cd build ++cmake .. ++make ++``` ++ ++## 使用说明 ++ ++### 启动memdcd进程 ++ ++#### 使用方法 ++ ++通过运行memdcd二进制运行服务端进程,例如: ++``` ++memdcd -p xx.json ++``` ++策略配置文件的权限需为600,属主需为当前memRouter启动者 ++#### 命令行参数说明 ++ ++| 参数 | 参数含义 | 是否必须 | 是否有参数 | 参数范围 | 示例说明 | ++| --------------- | ---------------------------------- | -------- | ---------- | --------------------- | ------------------------------------------------------------ | ++| -p或--policy | memRouter日志级别 | 是 | 是 | 有效地址 | memdcd所采用的页面分级策略 ++| -s或--socket | memRouter监听的名称,用于与客户端交互 | 否 | 是 | 107个字符之内的字符串 | 指定服务端监听的unix socket名称 | ++| -l或--log | 帮助信息 | 否 | 是 | LOG_INFO/LOG_DEBUG | LOG_INFO: info级别 LOG_DEBUG: debug级别出 | ++| -t或--timeout | 帮助信息 | 否 | 是 | 0-4294967295 | 收集进程页面信息的时长限制 | ++| -h或--help | 帮助信息 | 否 | 否 | NA | 执行时带有此参数会打印后退出 | ++ ++### 配置文件 ++目前仅支持阈值策略 ++ ++#### 阈值策略配置文件 ++``` ++{ ++ "type": "mig_policy_threshold", ++ "policy": { ++ "unit": "KB", ++ "threshold": 20 ++ } ++} ++``` ++ ++| **配置项** | **配置项含义** | **是否必须** | **是否有参数** | **参数范围** | **示例说明** | ++| ----------- | ------------------------------------------------------------ | ------------ | -------------- | ------------------------- | ------------------------------------------------------------ | ++| type | 采取的分级策略 | 是 | 是 | 暂时支支持mig_policy_threshold | "type": "mig_policy_threshold" | ++| policy | 采取的策略 | 是 | 是 | NA | NA | ++| unit | 采用的单位 | 是 | 是 | KB/MB/GB | "unit": "KB"以KB作为单位 | ++| threshold | 被监控进程的内存阈值 | 是 | 是 | 0~INT32_MAX | "threshold": 20 //限制配监控进程内存上限20KB | ++ ++ ++#### 所需etmemd配置文件: ++各字段含义参见[etmemd](https://gitee.com/openeuler/etmem/blob/master/README.md) ++``` ++options: ++ loop : ${loop} ++ interval : ${interval} ++ sleep: ${sleep} ++ policies: ++ type : pid/name ++ value : ${pid}/${name} ++ max_threads: ${max_threads} ++ engine : memdcd ++``` ++ ++## 参与贡献 ++ ++1. Fork本仓库 ++2. 新建个人分支 ++3. 提交代码 ++4. 新建Pull Request +diff --git a/memRouter/include/memdcd_cmd.h b/memRouter/include/memdcd_cmd.h +new file mode 100644 +index 0000000..757d50c +--- /dev/null ++++ b/memRouter/include/memdcd_cmd.h +@@ -0,0 +1,21 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: handle receive buffer. ++ ******************************************************************************/ ++#ifndef MEMDCD_CMD_H ++#define MEMDCD_CMD_H ++ ++int handle_recv_buffer(const void *buf, int msg_len); ++ ++#endif // MEMDCD_H ++ +diff --git a/memRouter/include/memdcd_daemon.h b/memRouter/include/memdcd_daemon.h +new file mode 100644 +index 0000000..fa2b641 +--- /dev/null ++++ b/memRouter/include/memdcd_daemon.h +@@ -0,0 +1,23 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: init memdcd daemon. ++ ******************************************************************************/ ++#ifndef MEMDCD_DAEMON_H ++#define MEMDCD_DAEMON_H ++ ++#define MAX_MESSAGE_LENGTH 40960 ++ ++void *memdcd_daemon_start(const char *sock_path); ++ ++#endif ++ +diff --git a/memRouter/include/memdcd_log.h b/memRouter/include/memdcd_log.h +new file mode 100644 +index 0000000..b29b412 +--- /dev/null ++++ b/memRouter/include/memdcd_log.h +@@ -0,0 +1,34 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2020-10-30 ++ * Description: print log. ++ ******************************************************************************/ ++#ifndef MEMDCD_LOG_H__ ++#define MEMDCD_LOG_H__ ++ ++ ++#define ERROR_STR_MAX_LEN 256 ++ ++enum _log_level { ++ _LOG_ERROR = 0, ++ _LOG_WARN, ++ _LOG_INFO, ++ _LOG_DEBUG, ++}; ++ ++ ++int init_log_level(const char *log_level_str); ++int set_log_level(const int level); ++void memdcd_log(const int level, const char *, ...); ++ ++#endif ++ +diff --git a/memRouter/include/memdcd_message.h b/memRouter/include/memdcd_message.h +new file mode 100644 +index 0000000..9663ef2 +--- /dev/null ++++ b/memRouter/include/memdcd_message.h +@@ -0,0 +1,75 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: data structure used in interprocess communication. ++ ******************************************************************************/ ++#ifndef MEMDCD_MESSAGE_H ++#define MEMDCD_MESSAGE_H ++#include ++ ++enum memdcd_cmd_type { ++ MEMDCD_CMD_MEM, ++ MEMDCD_CMD_NODE, ++ MEMDCD_CMD_POLICY, ++}; ++ ++enum SwapType { ++ SWAP_TYPE_VMA_ADDR = 0xFFFFFF01, ++ SWAP_TYPE_MAX ++}; ++ ++#define MAX_VMA_NUM 512 ++struct vma_addr { ++ uint64_t start_addr; ++ uint64_t vma_len; ++}; ++ ++struct vma_addr_with_count { ++ struct vma_addr vma; ++ int count; ++}; ++ ++struct swap_vma { ++ enum SwapType type; ++ uint64_t length; ++ struct vma_addr vma_addrs[MAX_VMA_NUM]; ++}; ++ ++enum MEMDCD_MESSAGE_STATUS { ++ MEMDCD_SEND_START, ++ MEMDCD_SEND_PROCESS, ++ MEMDCD_SEND_END, ++}; ++ ++struct swap_vma_with_count { ++ enum SwapType type; ++ uint64_t length; ++ uint64_t total_length; ++ enum MEMDCD_MESSAGE_STATUS status; ++ struct vma_addr_with_count vma_addrs[MAX_VMA_NUM]; ++}; ++ ++struct memory_message { ++ int pid; ++ uint32_t enable_uswap; ++ struct swap_vma_with_count vma; ++}; ++ ++struct memdcd_message { ++ enum memdcd_cmd_type cmd_type; ++ union { ++ struct memory_message memory_msg; ++ }; ++}; ++ ++#endif ++ +diff --git a/memRouter/include/memdcd_migrate.h b/memRouter/include/memdcd_migrate.h +new file mode 100644 +index 0000000..22598e2 +--- /dev/null ++++ b/memRouter/include/memdcd_migrate.h +@@ -0,0 +1,21 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhangxuzhou ++ * Create: 2020-09-18 ++ * Description: engines migrating memory pages ++ ******************************************************************************/ ++#ifndef MEMDCD_CONNECT_H ++#define MEMDCD_CONNECT_H ++#include "memdcd_process.h" ++ ++int send_to_userswap(int pid, const struct migrate_page_list *pages); ++ ++#endif /* MEMDCD_CONNECT_H */ +diff --git a/memRouter/include/memdcd_policy.h b/memRouter/include/memdcd_policy.h +new file mode 100644 +index 0000000..47c40f5 +--- /dev/null ++++ b/memRouter/include/memdcd_policy.h +@@ -0,0 +1,42 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhangxuzhou ++ * Create: 2020-09-08 ++ * Description: init policy ++ ******************************************************************************/ ++ ++#ifndef MEMDCD_POLICY_H ++#define MEMDCD_POLICY_H ++#include "memdcd_process.h" ++ ++enum mem_policy_type { ++ POL_TYPE_THRESHOLD, ++ POL_TYPE_MAX, ++}; ++ ++struct mem_policy { ++ enum mem_policy_type type; ++ void *private; ++ struct memdcd_policy_opt *opt; ++}; ++ ++struct memdcd_policy_opt { ++ int (*init)(struct mem_policy *policy, const char *path); ++ int (*parse)(const struct mem_policy *policy, int pid, struct migrate_page_list *page_list, ++ struct migrate_page_list **pages_to_numa, struct migrate_page_list **pages_to_swap); ++ int (*destroy)(struct mem_policy *policy); ++}; ++ ++struct mem_policy *get_policy(void); ++int init_mem_policy(char *path); ++ ++#endif /* MEMDCD_POLICY_H */ ++ +diff --git a/memRouter/include/memdcd_policy_threshold.h b/memRouter/include/memdcd_policy_threshold.h +new file mode 100644 +index 0000000..f75d3e7 +--- /dev/null ++++ b/memRouter/include/memdcd_policy_threshold.h +@@ -0,0 +1,22 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: head file of threshold policy ++ ******************************************************************************/ ++#ifndef MEMDCD_POLICY_THRESHOLD_H ++#define MEMDCD_POLICY_THRESHOLD_H ++#include "memdcd_policy.h" ++ ++struct memdcd_policy_opt *get_threshold_policy(void); ++ ++#endif ++ +diff --git a/memRouter/include/memdcd_process.h b/memRouter/include/memdcd_process.h +new file mode 100644 +index 0000000..eaa86f8 +--- /dev/null ++++ b/memRouter/include/memdcd_process.h +@@ -0,0 +1,41 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: process received pages ++ ******************************************************************************/ ++#ifndef MEMDCD_PROCESS_H ++#define MEMDCD_PROCESS_H ++ ++#include ++#include "memdcd_message.h" ++ ++#define DEFAULT_COLLECT_PAGE_TIMEOUT 3 ++ ++struct migrate_page { ++ uint64_t addr; ++ uint64_t length; ++ int visit_count; ++ ++ int numanode; ++}; ++ ++struct migrate_page_list { ++ uint64_t length; ++ struct migrate_page pages[]; ++}; ++ ++void init_collect_pages_timeout(time_t timeout); ++int migrate_process_get_pages(int pid, const struct swap_vma_with_count *vma); ++void migrate_process_exit(void); ++ ++#endif /* MEMDCD_MIGRATE_H */ ++ +diff --git a/memRouter/src/memdcd.c b/memRouter/src/memdcd.c +new file mode 100644 +index 0000000..70f9f7b +--- /dev/null ++++ b/memRouter/src/memdcd.c +@@ -0,0 +1,143 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhangxuzhou ++ * Create: 2020-09-08 ++ * Description: main function of memdcd. ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "memdcd_policy.h" ++#include "memdcd_daemon.h" ++#include "memdcd_log.h" ++ ++#define DEFAULT_SOCK_PATH "@_memdcd.server" ++#define REQUIRE_CAP_MAX 1 ++#define TIMEOUT_VALID_LEN 10 ++ ++static void usage(void) ++{ ++ printf("Usage: memdcd -p|--policy [options]\n"); ++ printf(" -p --policy specify policy config file\n"); ++ printf(" -s --socket specify socket path. default: %s\n", DEFAULT_SOCK_PATH); ++ printf(" -l --log LOG_INFO|LOG_DEBUG set log level to print. default: LOG_INFO\n"); ++ printf(" -t --timeout set timeout for collect pages by second.\n"); ++ printf(" set 0 to disable timeout. default: %d\n", DEFAULT_COLLECT_PAGE_TIMEOUT); ++ printf(" -h --help show this help info\n"); ++} ++ ++static int check_permission(void) ++{ ++ cap_t cap = NULL; ++ cap_flag_value_t cap_flag_value = CAP_CLEAR; ++ cap_value_t cap_val = 0; ++ const char *req_cap[REQUIRE_CAP_MAX] = { ++ "cap_sys_nice" ++ }; ++ ++ cap = cap_get_proc(); ++ if (cap == NULL) { ++ memdcd_log(_LOG_ERROR, "Get capability error."); ++ return -1; ++ } ++ for (int i = 0; i < REQUIRE_CAP_MAX; i++) { ++ cap_from_name(req_cap[i], &cap_val); ++ cap_get_flag(cap, cap_val, CAP_EFFECTIVE, &cap_flag_value); ++ if (cap_flag_value != CAP_SET) { ++ memdcd_log(_LOG_ERROR, "Not sufficient capacity: %s.", req_cap[i]); ++ cap_free(cap); ++ return -1; ++ } ++ } ++ cap_free(cap); ++ return 0; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int opt; ++ struct option long_options[] = { ++ {"policy", required_argument, NULL, 'p'}, ++ {"socket", required_argument, NULL, 's'}, ++ {"log", required_argument, NULL, 'l'}, ++ {"timeout", required_argument, NULL, 't'}, ++ {"help", no_argument, NULL, 'h'}, ++ {NULL, 0, NULL, 0}, ++ }; ++ time_t timeout; ++ char *policy_file = NULL, *socket_path = NULL; ++ char *endptr = NULL; ++ ++ while ((opt = getopt_long(argc, argv, "p:s:l:t:h", long_options, NULL)) != -1) { ++ switch (opt) { ++ case 'p': ++ policy_file = optarg; ++ break; ++ case 's': ++ socket_path = optarg; ++ break; ++ case 'l': ++ if (init_log_level(optarg) < 0) { ++ printf("error parsing log level: %s\n", optarg); ++ return -EINVAL; ++ } ++ break; ++ case 't': ++ errno = 0; ++ timeout = strtol(optarg, &endptr, TIMEOUT_VALID_LEN); ++ if (errno || optarg == endptr || (endptr && *endptr != ' ' && *endptr != '\0') || timeout < 0) { ++ printf("error parsing timeout %s\n", optarg); ++ return -EINVAL; ++ } ++ init_collect_pages_timeout(timeout); ++ break; ++ case 'h': ++ usage(); ++ return 0; ++ default: ++ usage(); ++ return -EINVAL; ++ } ++ } ++ ++ if (policy_file == NULL) { ++ printf("policy file should be assigned\n"); ++ usage(); ++ return 0; ++ } ++ if (socket_path == NULL) ++ socket_path = DEFAULT_SOCK_PATH; ++ ++ if (check_permission() != 0) { ++ memdcd_log(_LOG_ERROR, "This program is lack of nessary privileges."); ++ return -1; ++ } ++ ++ if (init_mem_policy(policy_file) != 0) { ++ memdcd_log(_LOG_ERROR, "Error parsing policy from policy config file %s.", policy_file); ++ return -1; ++ } ++ ++ memdcd_daemon_start(socket_path); ++ ++ return 0; ++} +diff --git a/memRouter/src/memdcd_cmd.c b/memRouter/src/memdcd_cmd.c +new file mode 100644 +index 0000000..9f3fcc0 +--- /dev/null ++++ b/memRouter/src/memdcd_cmd.c +@@ -0,0 +1,93 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: handle receive buffer. ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "memdcd_process.h" ++#include "memdcd_log.h" ++#include "memdcd_cmd.h" ++ ++#define FILEPATH_MAX_LEN 64 ++ ++static uint64_t get_process_vmsize(int pid) ++{ ++ char statm_path[FILEPATH_MAX_LEN]; ++ FILE *fp = NULL; ++ uint64_t vmsize; ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ ++ if (snprintf(statm_path, FILEPATH_MAX_LEN, "/proc/%d/statm", pid) <= 0) { ++ memdcd_log(_LOG_ERROR, "memdcd_uswap: snprintf for statm_path from pid %d failed.", pid); ++ return -1; ++ } ++ fp = fopen(statm_path, "r"); ++ if (fp == NULL) { ++ memdcd_log(_LOG_ERROR, "Error opening statm file %s: %s.", statm_path, error_str); ++ return 0; ++ } ++ if (fscanf(fp, "%lu", &vmsize) <= 0) { ++ memdcd_log(_LOG_ERROR, "Error reading file %s. err: %s", ++ statm_path, strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ fclose(fp); ++ return 0; ++ } ++ fclose(fp); ++ return vmsize; ++} ++ ++static int handle_mem_message(const struct memory_message *msg) ++{ ++ uint64_t total_pages = get_process_vmsize(msg->pid); ++ if (total_pages == 0) { ++ memdcd_log(_LOG_ERROR, "Error getting vmsize of process %d.", msg->pid); ++ return -1; ++ } else if (total_pages < msg->vma.total_length) { ++ memdcd_log(_LOG_ERROR, "Total page num of process %lu is less than incoming page num %lu.", ++ total_pages, msg->vma.total_length); ++ return -1; ++ } ++ ++ if (msg->vma.length / sizeof(struct vma_addr_with_count) > MAX_VMA_NUM) { ++ memdcd_log(_LOG_ERROR, "Invalid message length %lu.", msg->vma.length); ++ return -1; ++ } ++ ++ return migrate_process_get_pages(msg->pid, &msg->vma); ++} ++ ++int handle_recv_buffer(const void *buffer, int msg_len) ++{ ++ struct memdcd_message *msg = (struct memdcd_message *)buffer; ++ if (msg_len != sizeof(struct memdcd_message)) { ++ memdcd_log(_LOG_ERROR, "Invalid recv message length %d.", msg_len); ++ return -1; ++ } ++ memdcd_log(_LOG_DEBUG, "Type: %d.", msg->cmd_type); ++ ++ switch (msg->cmd_type) { ++ case MEMDCD_CMD_MEM: ++ return handle_mem_message(&msg->memory_msg); ++ default: ++ memdcd_log(_LOG_ERROR, "Invalid cmd type."); ++ return -1; ++ } ++ return 0; ++} +\ No newline at end of file +diff --git a/memRouter/src/memdcd_daemon.c b/memRouter/src/memdcd_daemon.c +new file mode 100644 +index 0000000..f88593d +--- /dev/null ++++ b/memRouter/src/memdcd_daemon.c +@@ -0,0 +1,257 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: init memdcd daemon. ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "memdcd_log.h" ++#include "memdcd_process.h" ++#include "memdcd_cmd.h" ++#include "memdcd_daemon.h" ++ ++#define MAX_PENDING_QUEUE_LENGTH 64 ++#define MAX_SOCK_PATH_LENGTH 108 ++ ++static volatile sig_atomic_t g_sock_fd; ++static volatile sig_atomic_t g_exit_signal; ++ ++static void _set_exit_flag(int s) ++{ ++ (void)s; ++ g_exit_signal = 1; ++ if (g_sock_fd > 0) { ++ close(g_sock_fd); ++ } ++ g_sock_fd = -1; ++} ++ ++static void memdcd_install_signal(void) ++{ ++ signal(SIGINT, _set_exit_flag); ++ signal(SIGTERM, _set_exit_flag); ++} ++ ++ ++static int _set_socket_option(int sock_fd) ++{ ++ int rc; ++ int buf_len = MAX_MESSAGE_LENGTH; ++ struct timeval timeout = {5, 0}; ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ ++ /* set timeout limit to socket for sending */ ++ rc = setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)); ++ if (rc < 0) { ++ memdcd_log(_LOG_ERROR, "Set send timeout for socket failed. err: %s", ++ strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return -1; ++ } ++ ++ /* set max length of buffer to recive */ ++ rc = setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, (const char *)&buf_len, sizeof(buf_len)); ++ if (rc < 0) { ++ memdcd_log(_LOG_ERROR, "Set recive buffer length for socket failed. err: %s", ++ strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return -1; ++ } ++ ++ /* set max length of buffer to send */ ++ rc = setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, (const char *)&buf_len, sizeof(buf_len)); ++ if (rc < 0) { ++ memdcd_log(_LOG_ERROR, "Set send buffer length for socket failed. err: %s", ++ strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int memdcd_server_init(const char *sock_path) ++{ ++ int sock_fd; ++ struct sockaddr_un sock_addr; ++ size_t sock_len; ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ ++ memset(&sock_addr, 0, sizeof(struct sockaddr_un)); ++ ++ sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (sock_fd < 0) { ++ memdcd_log(_LOG_ERROR, "Create socket for fail. err: %s", strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return -1; ++ } ++ ++ sock_len = strlen(sock_path); ++ if (sock_len >= MAX_SOCK_PATH_LENGTH) { ++ memdcd_log(_LOG_ERROR, "Socket path is too long."); ++ close(sock_fd); ++ return -1; ++ } ++ sock_addr.sun_family = AF_UNIX; ++ memcpy(sock_addr.sun_path, sock_path, sock_len); ++ ++ sock_addr.sun_path[0] = 0; ++ sock_len += offsetof(struct sockaddr_un, sun_path); ++ ++ if (_set_socket_option(sock_fd) != 0) { ++ memdcd_log(_LOG_ERROR, "Set for socket fail. err: %s", strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ close(sock_fd); ++ return -1; ++ } ++ ++ if (bind(sock_fd, (struct sockaddr *)&sock_addr, sock_len) != 0) { ++ memdcd_log(_LOG_ERROR, "Socket bind %s fail. err: %s", ++ (char *)&sock_addr.sun_path[1], strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ close(sock_fd); ++ return -1; ++ } ++ ++ return sock_fd; ++} ++ ++static int check_socket_permission(int sock_fd) ++{ ++ struct ucred cred; ++ socklen_t len; ++ ssize_t rc; ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ ++ len = sizeof(struct ucred); ++ ++ rc = getsockopt(sock_fd, ++ SOL_SOCKET, ++ SO_PEERCRED, ++ &cred, ++ &len); ++ if (rc < 0) { ++ memdcd_log(_LOG_ERROR, "Getsockopt failed. err: %s\n", strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return -1; ++ } ++ ++ if (cred.uid != 0 || cred.gid != 0) { ++ memdcd_log(_LOG_ERROR, "Socket connect failed, need recieving from app of root privilege.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int memdcd_accept(char *recv_buf) ++{ ++ int accp_fd = -1; ++ int ret = 0; ++ ssize_t rc; ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ ++ accp_fd = accept(g_sock_fd, NULL, NULL); ++ if (accp_fd < 0) { ++ memdcd_log(_LOG_ERROR, "Accept message failed. err: %s", strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return -1; ++ } ++ ++ rc = check_socket_permission(accp_fd); ++ if (rc != 0) { ++ ret = rc; ++ goto close_fd; ++ } ++ ++ rc = recv(accp_fd, recv_buf, MAX_MESSAGE_LENGTH, 0); ++ if (rc <= 0) { ++ memdcd_log(_LOG_WARN, "Socket recive from client fail. err: %s", \ ++ strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ ret = -1; ++ goto close_fd; ++ } ++ ++ if (rc > MAX_MESSAGE_LENGTH) { ++ memdcd_log(_LOG_WARN, "Buffer sent to memdcd is too long, should be less than %d.", MAX_MESSAGE_LENGTH); ++ ret = -1; ++ goto close_fd; ++ } ++ ++ memdcd_log(_LOG_DEBUG, "Memdcd got one connection."); ++ ret = rc; ++ ++close_fd: ++ close(accp_fd); ++ return ret; ++} ++ ++void *memdcd_daemon_start(const char *sock_path) ++{ ++ char *recv_buf = NULL; ++ int msg_len; ++ int sock_fd; ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ ++ if (sock_path == NULL) { ++ return NULL; ++ } ++ g_exit_signal = 0; ++ g_sock_fd = 0; ++ memdcd_install_signal(); ++ ++ sock_fd = memdcd_server_init(sock_path); ++ if (sock_fd < 0) ++ return NULL; ++ ++ recv_buf = (char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH); ++ if (recv_buf == NULL) { ++ memdcd_log(_LOG_ERROR, "Failed to alloc buffer to receive message."); ++ close(sock_fd); ++ sock_fd = -1; ++ return NULL; ++ } ++ ++ /* allow RPC_CLIENT_MAX clients to connect at the same time */ ++ if (listen(sock_fd, MAX_PENDING_QUEUE_LENGTH) != 0) { ++ memdcd_log(_LOG_ERROR, "Error listening on socket %s. err: %s", ++ sock_path, strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ close(sock_fd); ++ sock_fd = -1; ++ goto free_buf; ++ } ++ ++ if (g_sock_fd < 0) { ++ close(sock_fd); ++ sock_fd = -1; ++ goto free_buf; ++ } ++ g_sock_fd = sock_fd; ++ memdcd_log(_LOG_INFO, "Start listening on %s.", sock_path); ++ while (g_exit_signal == 0) { ++ msg_len = memdcd_accept(recv_buf); ++ if (msg_len < 0) { ++ memdcd_log(_LOG_ERROR, "Error accepting message. err: %s", strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ continue; ++ } ++ if (handle_recv_buffer(recv_buf, msg_len) < 0) ++ memdcd_log(_LOG_DEBUG, "Error handling message."); ++ } ++ migrate_process_exit(); ++ ++ if (g_sock_fd > 0) { ++ close(g_sock_fd); ++ g_sock_fd = -1; ++ } ++free_buf: ++ free(recv_buf); ++ return NULL; ++} +diff --git a/memRouter/src/memdcd_log.c b/memRouter/src/memdcd_log.c +new file mode 100644 +index 0000000..125fced +--- /dev/null ++++ b/memRouter/src/memdcd_log.c +@@ -0,0 +1,80 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2020-10-30 ++ * Description: print log. ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "memdcd_log.h" ++ ++static int log_level = 0; ++ ++int set_log_level(const int level) ++{ ++ log_level = level; ++ return log_level; ++} ++ ++int init_log_level(const char *log_level_str) ++{ ++ if (log_level_str == NULL) ++ return set_log_level(_LOG_INFO); ++ if (strcmp(log_level_str, "LOG_DEBUG") == 0) ++ return set_log_level(_LOG_DEBUG); ++ if (strcmp(log_level_str, "LOG_INFO") == 0) ++ return set_log_level(_LOG_INFO); ++ if (strcmp(log_level_str, "LOG_WARN") == 0) ++ return set_log_level(_LOG_WARN); ++ if (strcmp(log_level_str, "LOG_ERROR") == 0) ++ return set_log_level(_LOG_ERROR); ++ memdcd_log(_LOG_ERROR, "Error initint log_level: %s.", log_level_str); ++ return -EINVAL; ++} ++ ++void memdcd_log(const int level, const char *va_alist, ...) ++{ ++ va_list ap; ++ ++ if (level > log_level) ++ return; ++ ++ va_start(ap, va_alist); ++ switch (level) { ++ case _LOG_INFO: ++ openlog("[MEMDCD_INFO] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_INFO, va_alist, ap); ++ break; ++ case _LOG_DEBUG: ++ openlog("[MEMDCD_DEBUG] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_INFO, va_alist, ap); ++ break; ++ case _LOG_WARN: ++ openlog("[MEMDCD_WARNING] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_WARNING, va_alist, ap); ++ break; ++ case _LOG_ERROR: ++ openlog("[MEMDCD_ERROR] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_ERR, va_alist, ap); ++ break; ++ default: ++ va_end(ap); ++ return; ++ } ++ ++ va_end(ap); ++ closelog(); ++ return; ++} +\ No newline at end of file +diff --git a/memRouter/src/memdcd_migrate.c b/memRouter/src/memdcd_migrate.c +new file mode 100644 +index 0000000..4017033 +--- /dev/null ++++ b/memRouter/src/memdcd_migrate.c +@@ -0,0 +1,150 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhangxuzhou ++ * Create: 2020-09-18 ++ * Description: engines migrating memory pages ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "memdcd_policy.h" ++#include "memdcd_process.h" ++#include "memdcd_log.h" ++#include "memdcd_migrate.h" ++ ++#define CLIENT_RECV_DEFAULT_TIME 10 // default 10s ++#define RESP_MSG_MAX_LEN 10 ++#define FILEPATH_MAX_LEN 64 ++ ++static int uswap_init_connection(int server_pid, time_t recv_timeout) ++{ ++ socklen_t addrlen; ++ struct timeval timeout; ++ struct sockaddr_un addr; ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ ++ int socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); ++ if (socket_fd < 0) { ++ memdcd_log(_LOG_ERROR, "memdcd_uswap: Error opening socket."); ++ return -1; ++ } ++ ++ /* set recv timeout */ ++ timeout.tv_sec = recv_timeout; ++ timeout.tv_usec = 0; ++ if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(struct timeval)) != 0) { ++ memdcd_log(_LOG_ERROR, "memdcd_uswap: Setsockopt set recv timeout failed!"); ++ close(socket_fd); ++ return -1; ++ } ++ ++ bzero(&addr, sizeof(struct sockaddr_un)); ++ /* UNIX domain Socket abstract namespace */ ++ addr.sun_family = AF_UNIX; ++ addr.sun_path[0] = 0; ++ ++ if (snprintf(addr.sun_path + 1, FILEPATH_MAX_LEN, "userswap%d.sock", server_pid) <= 0) { ++ memdcd_log(_LOG_ERROR, "memdcd_uswap: Snprintf_s for abtract_path from pid %d failed.", server_pid); ++ close(socket_fd); ++ return -1; ++ } ++ ++ addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path + 1) + 1; ++ if (connect(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) { ++ memdcd_log(_LOG_ERROR, "memdcd_uswap: Connect failed. err: %s! ", \ ++ strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ close(socket_fd); ++ return -1; ++ } ++ ++ return socket_fd; ++} ++ ++static int uswap_send_data(int client_fd, int server_pid, const struct swap_vma *swap_vma) ++{ ++ int ret = 0; ++ int read_bytes; ++ int write_bytes; ++ int in_datalen; ++ char buff[RESP_MSG_MAX_LEN] = {0}; ++ int len = strlen("success"); ++ ++ in_datalen = swap_vma->length + sizeof(int) + sizeof(long); ++ write_bytes = write(client_fd, swap_vma, in_datalen); ++ if (write_bytes <= 0) { ++ memdcd_log(_LOG_DEBUG, "memdcd_uswap: Write to pid %d server, bytes: %d.", server_pid, write_bytes); ++ return -1; ++ } ++ ++ read_bytes = read(client_fd, buff, RESP_MSG_MAX_LEN - 1); ++ if (read_bytes >= len && strncmp(buff, "success", len) == 0) { ++ memdcd_log(_LOG_DEBUG, "memdcd_uswap: Recv respond success."); ++ } else { ++ memdcd_log(_LOG_DEBUG, "memdcd_uswap: Recv respond failed."); ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++static int min(int a, int b) ++{ ++ return a < b ? a : b; ++} ++ ++int send_to_userswap(int pid, const struct migrate_page_list *page_list) ++{ ++ int ret = 0; ++ struct swap_vma *swap_vma = NULL; ++ int client_fd; ++ uint64_t i, rest, size; ++ uint64_t dst; ++ if (page_list->pages == NULL) { ++ memdcd_log(_LOG_WARN, "memdcd_uswap: Mig_addrs NULL."); ++ return 0; ++ } ++ memdcd_log(_LOG_INFO, "Send %lu addresses to userswap: pid %d.", page_list->length, pid); ++ swap_vma = (struct swap_vma *)malloc(sizeof(struct swap_vma)); ++ if (swap_vma == NULL) { ++ memdcd_log(_LOG_WARN, "memdcd_uswap: Malloc for swap vma failed."); ++ return -ENOMEM; ++ } ++ swap_vma->type = SWAP_TYPE_VMA_ADDR; ++ rest = page_list->length; ++ while (rest > 0) { ++ client_fd = uswap_init_connection(pid, CLIENT_RECV_DEFAULT_TIME); ++ if (client_fd < 0) { ++ ret = -1; ++ break; ++ } ++ size = min(rest, MAX_VMA_NUM); ++ ++ swap_vma->length = size * sizeof(struct vma_addr); ++ for (i = 0; i < size; i++) { ++ dst = page_list->length - rest + i; ++ swap_vma->vma_addrs[i].start_addr = page_list->pages[dst].addr; ++ swap_vma->vma_addrs[i].vma_len = page_list->pages[dst].length; ++ } ++ if (uswap_send_data(client_fd, pid, swap_vma) != 0) ++ ret = -1; ++ close(client_fd); ++ rest -= size; ++ } ++ ++ free(swap_vma); ++ return ret; ++} +\ No newline at end of file +diff --git a/memRouter/src/memdcd_policy.c b/memRouter/src/memdcd_policy.c +new file mode 100644 +index 0000000..063dbfc +--- /dev/null ++++ b/memRouter/src/memdcd_policy.c +@@ -0,0 +1,132 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhangxuzhou ++ * Create: 2020-09-08 ++ * Description: init policy ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "memdcd_log.h" ++#include "memdcd_policy_threshold.h" ++#include "memdcd_policy.h" ++ ++#define FULL_PERMISSION 0777 ++ ++static struct { ++ char *name; ++ enum mem_policy_type type; ++ struct memdcd_policy_opt * (*get_opt)(void); ++} mem_policy_opts[] = { ++ {"mig_policy_threshold", POL_TYPE_THRESHOLD, get_threshold_policy}, ++ {NULL, POL_TYPE_MAX, NULL}, ++}; ++ ++struct mem_policy g_policy; ++ ++static int check_policy_file_permission(const char *path) ++{ ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ struct stat permission_buffer; ++ ++ if (stat(path, &permission_buffer) != 0) { ++ memdcd_log(_LOG_ERROR, "Get file stat failed. err: %s", ++ strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return -1; ++ } ++ ++ if (permission_buffer.st_uid != geteuid()) { ++ memdcd_log(_LOG_ERROR, "Owner of config file is not same with user of this process."); ++ return -EACCES; ++ } ++ ++ if ((permission_buffer.st_mode & FULL_PERMISSION) != (S_IRUSR | S_IWUSR)) { ++ memdcd_log(_LOG_ERROR, "Access permission of config file is not 600."); ++ return -EACCES; ++ } ++ ++ return 0; ++} ++ ++static int parse_policy_type(const char *path) ++{ ++ int i; ++ const char *str = NULL; ++ ++ json_object *root = json_object_from_file(path); ++ if (root == NULL) ++ return -1; ++ ++ json_object *type = json_object_object_get(root, "type"); ++ if (type == NULL) ++ return -1; ++ ++ str = json_object_get_string(type); ++ if (str == NULL) ++ return -1; ++ ++ for (i = 0; mem_policy_opts[i].name != NULL; i++) { ++ if (strcmp(str, mem_policy_opts[i].name) == 0) { ++ return i; ++ } ++ } ++ ++ return -1; ++} ++ ++int init_mem_policy(char *path) ++{ ++ int ret; ++ int type; ++ struct memdcd_policy_opt *opt = NULL; ++ char file_path[PATH_MAX] = {0}; ++ ++ if (!realpath(path, file_path)) { ++ memdcd_log(_LOG_ERROR, "Config file not exist."); ++ return -EEXIST; ++ } ++ ret = check_policy_file_permission(file_path); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ type = parse_policy_type(file_path); ++ if (type < 0) ++ return -EINVAL; ++ ++ memdcd_log(_LOG_DEBUG, "%s: type: %d.", __func__, g_policy.type); ++ ++ opt = mem_policy_opts[type].get_opt(); ++ ++ ret = opt->init(&g_policy, file_path); ++ if (ret != 0) ++ return ret; ++ ++ return 0; ++} ++ ++struct mem_policy *get_policy(void) ++{ ++ return &g_policy; ++} +diff --git a/memRouter/src/memdcd_policy_threshold.c b/memRouter/src/memdcd_policy_threshold.c +new file mode 100644 +index 0000000..3b5e1dc +--- /dev/null ++++ b/memRouter/src/memdcd_policy_threshold.c +@@ -0,0 +1,209 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: function of threshold policy ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "memdcd_log.h" ++#include "memdcd_policy.h" ++#include "memdcd_process.h" ++#include "memdcd_policy_threshold.h" ++ ++struct threshold_policy { ++ uint64_t threshold; ++}; ++ ++int threshold_policy_init(struct mem_policy *policy, const char *path); ++int threshold_policy_parse(const struct mem_policy *policy, int pid, struct migrate_page_list *page_list, ++ struct migrate_page_list **pages_to_numa, struct migrate_page_list **pages_to_swap); ++int threshold_policy_destroy(struct mem_policy *policy); ++ ++struct memdcd_policy_opt threshold_policy_opt = { ++ .init = threshold_policy_init, ++ .parse = threshold_policy_parse, ++ .destroy = threshold_policy_destroy, ++}; ++ ++int threshold_policy_init(struct mem_policy *policy, const char *path) ++{ ++ int ret = 0; ++ json_object *root = NULL, *obj_policy = NULL, *unit = NULL, *threshold = NULL; ++ int th_val = -1; ++ const char *str = NULL; ++ struct threshold_policy *t = (struct threshold_policy *)malloc(sizeof(struct threshold_policy)); ++ if (t == NULL) ++ return -1; ++ ++ root = json_object_from_file(path); ++ if (root == NULL) { ++ ret = -1; ++ goto err_out; ++ } ++ ++ obj_policy = json_object_object_get(root, "policy"); ++ if (obj_policy == NULL) { ++ ret = -1; ++ goto err_out; ++ } ++ ++ unit = json_object_object_get(obj_policy, "unit"); ++ if (unit == NULL) { ++ ret = -1; ++ goto err_out; ++ } ++ ++ threshold = json_object_object_get(obj_policy, "threshold"); ++ if (threshold == NULL) { ++ ret = -1; ++ goto err_out; ++ } ++ ++ th_val = json_object_get_int(threshold); ++ if (th_val == INT32_MAX || th_val < 0) { ++ memdcd_log(_LOG_ERROR, "Invalid threshold value, allowed range is [0, INT_MAX)."); ++ ret = -1; ++ goto err_out; ++ } ++ ++ str = json_object_get_string(unit); ++ if (str == NULL) { ++ ret = -1; ++ goto err_out; ++ } ++ ++ memdcd_log(_LOG_INFO, "Threshold policy loaded."); ++ if (strcmp("B", str) == 0) { ++ t->threshold = th_val; ++ } else if (strcmp("KB", str) == 0) { ++ t->threshold = (uint64_t)th_val * 1024; ++ } else if (strcmp("MB", str) == 0) { ++ t->threshold = (uint64_t)th_val * 1024 * 1024; ++ } else if (strcmp("GB", str) == 0) { ++ t->threshold = (uint64_t)th_val * 1024 * 1024 * 1024; ++ } else { ++ memdcd_log(_LOG_ERROR, "Detected invalid threshold setting. Abort."); ++ ret = -1; ++ goto err_out; ++ } ++ ++ policy->type = POL_TYPE_THRESHOLD; ++ policy->opt = &threshold_policy_opt; ++ policy->private = t; ++ ++ return 0; ++ ++err_out: ++ free(t); ++ return ret; ++} ++ ++static int addr_cmp_by_count(const void *a, const void *b) ++{ ++ return ((struct migrate_page *)a)->visit_count - ((struct migrate_page *)b)->visit_count; ++} ++ ++int threshold_policy_parse(const struct mem_policy *policy, int pid, struct migrate_page_list *page_list, ++ struct migrate_page_list **pages_to_numa, struct migrate_page_list **pages_to_swap) ++{ ++ int ret = 0; ++ uint64_t swap_count = 0; ++ uint64_t sum_size = 0; ++ int *status = NULL; ++ uint64_t *move_addr = NULL; ++ uint64_t length = page_list->length; ++ ++ (void)pages_to_numa; ++ ++ qsort(page_list->pages, length, sizeof(struct migrate_page), addr_cmp_by_count); ++ ++ status = malloc(sizeof(int) * length); ++ if (status == NULL) ++ return -1; ++ ++ move_addr = malloc(sizeof(uint64_t) * length); ++ if (move_addr == NULL) { ++ free(status); ++ return -1; ++ } ++ ++ for (uint64_t i = 0; i < length; i++) ++ move_addr[i] = page_list->pages[i].addr; ++ ++ if (move_pages(pid, length, (void **)move_addr, NULL, status, MPOL_MF_MOVE) < 0) { ++ memdcd_log(_LOG_ERROR, "Error when locate node for src_addr by move_page."); ++ ret = -1; ++ goto tpp_err_out; ++ } ++ ++ for (int64_t i = length - 1; i >= 0; i--) { ++ page_list->pages[i].numanode = status[i]; ++ if (status[i] < 0) { // negative means not on a numa node ++ memdcd_log(_LOG_DEBUG, "memdcd_migrate: Error getting current node of page %lx: %d, %ld.", ++ move_addr[i], status[i], i); ++ continue; ++ } ++ ++ /*judge if Integer Overflow happen*/ ++ if (sum_size + page_list->pages[i].length < sum_size) { ++ ret = -1; ++ goto tpp_err_out; ++ } ++ sum_size += page_list->pages[i].length; ++ if (sum_size < ((struct threshold_policy *)policy->private)->threshold) ++ continue; ++ ++ swap_count++; ++ // reuse the second half array ++ page_list->pages[length - swap_count] = page_list->pages[i]; ++ } ++ ++ *pages_to_swap = malloc(sizeof(struct migrate_page) * swap_count + sizeof(struct migrate_page_list)); ++ if (*pages_to_swap == NULL) { ++ memdcd_log(_LOG_ERROR, "memdcd_migrate: error allocating space for pages_to_swap."); ++ ret = -1; ++ goto tpp_err_out; ++ } ++ ++ memcpy((*pages_to_swap)->pages, page_list->pages + length - swap_count, sizeof(struct migrate_page) * swap_count); ++ (*pages_to_swap)->length = swap_count; ++ ++tpp_err_out: ++ free(status); ++ free(move_addr); ++ return ret; ++} ++ ++int threshold_policy_destroy(struct mem_policy *policy) ++{ ++ if (policy == NULL) { ++ return -1; ++ } ++ if (policy->private == NULL) { ++ return -1; ++ } ++ free(policy->private); ++ policy->private = NULL; ++ return 0; ++} ++ ++struct memdcd_policy_opt *get_threshold_policy(void) ++{ ++ return &threshold_policy_opt; ++} +diff --git a/memRouter/src/memdcd_process.c b/memRouter/src/memdcd_process.c +new file mode 100644 +index 0000000..8b2ef71 +--- /dev/null ++++ b/memRouter/src/memdcd_process.c +@@ -0,0 +1,345 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++ * etmem/memRouter licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liruilin ++ * Create: 2021-02-26 ++ * Description: process received pages ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "memdcd_log.h" ++#include "memdcd_policy.h" ++#include "memdcd_migrate.h" ++#include "memdcd_message.h" ++ ++#define PID_MAX_FILE "/proc/sys/kernel/pid_max" ++#define PID_MAX_LEN 256 ++ ++struct migrate_process { ++ int pid; ++ ++ struct migrate_page_list *page_list; ++ uint64_t offset; ++ struct timeval timestamp; ++ ++ pthread_t worker; ++ ++ struct migrate_process *prev; ++ struct migrate_process *next; ++}; ++ ++struct migrate_process g_process_head = { ++ .prev = &g_process_head, ++ .next = &g_process_head, ++}; ++pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++time_t collect_page_timeout = DEFAULT_COLLECT_PAGE_TIMEOUT; ++ ++static void migrate_process_free(struct migrate_process *p) ++{ ++ p->prev->next = p->next; ++ p->next->prev = p->prev; ++ ++ if (p->page_list) ++ free(p->page_list); ++ free(p); ++} ++ ++static void migrate_process_remove(int pid) ++{ ++ struct migrate_process *cur; ++ ++ cur = g_process_head.next; ++ ++ memdcd_log(_LOG_DEBUG, "Remove process %d.", pid); ++ while (cur != &g_process_head) { ++ if (cur->pid == pid) ++ break; ++ cur = cur->next; ++ } ++ if (cur == &g_process_head) { ++ memdcd_log(_LOG_DEBUG, "Failed to remove process %d: not exist.", pid); ++ return; ++ } ++ ++ migrate_process_free(cur); ++ memdcd_log(_LOG_DEBUG, "End free process %d.", pid); ++} ++ ++static struct migrate_process *migrate_process_search(int pid) ++{ ++ struct migrate_process *cur; ++ ++ cur = g_process_head.next; ++ while (cur != &g_process_head) { ++ if (cur->pid == pid) { ++ return cur; ++ } ++ cur = cur->next; ++ } ++ ++ return NULL; ++} ++ ++static struct migrate_process *migrate_process_add(int pid, uint64_t len) ++{ ++ struct migrate_process *process = NULL; ++ ++ process = (struct migrate_process *)malloc(sizeof(struct migrate_process)); ++ if (process == NULL) ++ return NULL; ++ ++ process->page_list = ++ (struct migrate_page_list *)malloc(sizeof(struct migrate_page) * len + sizeof(struct migrate_page_list)); ++ if (process->page_list == NULL) { ++ free(process); ++ return NULL; ++ } ++ ++ process->pid = pid; ++ process->page_list->length = len; ++ process->offset = 0; ++ process->worker = 0; ++ ++ process->next = g_process_head.next; ++ process->next->prev = process; ++ g_process_head.next = process; ++ process->prev = &g_process_head; ++ ++ memdcd_log(_LOG_INFO, "Add new process %d.", pid); ++ ++ return process; ++} ++ ++static void migrate_process_recycle(void) ++{ ++ static struct timeval last = {0}; ++ struct timeval now; ++ struct migrate_process *iter = g_process_head.next, *next = NULL; ++ time_t time_lag; ++ ++ if (collect_page_timeout == 0) ++ return; ++ ++ gettimeofday(&now, NULL); ++ if (last.tv_sec == 0 || now.tv_sec - last.tv_sec < collect_page_timeout) { ++ last = now; ++ return; ++ } ++ last = now; ++ ++ pthread_mutex_lock(&mutex); ++ while (iter != &g_process_head) { ++ next = iter->next; ++ time_lag = now.tv_sec - iter->timestamp.tv_sec; ++ if (time_lag > collect_page_timeout && !(iter->worker && pthread_tryjoin_np(iter->worker, NULL) == EBUSY)) { ++ memdcd_log(_LOG_WARN, "Process exceed collect page timeout %ld: %ld.", time_lag, collect_page_timeout); ++ migrate_process_free(iter); ++ } ++ iter = next; ++ } ++ pthread_mutex_unlock(&mutex); ++ ++} ++ ++static pthread_t get_active_tid(void) ++{ ++ pthread_mutex_lock(&mutex); ++ struct migrate_process *iter = g_process_head.next; ++ pthread_t tid = iter->worker; ++ pthread_mutex_unlock(&mutex); ++ return (iter == &g_process_head) ? 0 : tid; ++} ++ ++void migrate_process_exit(void) ++{ ++ pthread_t tid; ++ migrate_process_recycle(); ++ while ((tid = get_active_tid()) != 0) { ++ pthread_join(tid, NULL); ++ } ++} ++ ++static struct migrate_process *migrate_process_collect_pages(int pid, const struct swap_vma_with_count *vma) ++{ ++ uint64_t count = vma->length / sizeof(struct vma_addr_with_count); ++ struct migrate_process *process = NULL; ++ uint64_t i; ++ ++ migrate_process_recycle(); ++ ++ pthread_mutex_lock(&mutex); ++ process = migrate_process_search(pid); ++ if (process != NULL) { ++ if (process->worker != 0 && pthread_tryjoin_np(process->worker, NULL) == EBUSY) { ++ memdcd_log(_LOG_DEBUG, "Previous send work of process %d has been doing. discard pages.", pid); ++ pthread_mutex_unlock(&mutex); ++ return NULL; ++ } ++ ++ if (vma->status == MEMDCD_SEND_START) { ++ memdcd_log(_LOG_DEBUG, "Previous send work of process %d is interrupted.", pid); ++ migrate_process_remove(pid); ++ process = NULL; ++ } ++ } ++ if (process == NULL) { ++ if (vma->status != MEMDCD_SEND_START) { ++ memdcd_log(_LOG_DEBUG, "Current send work of process %d is incomplete.", pid); ++ pthread_mutex_unlock(&mutex); ++ return NULL; ++ } ++ ++ process = migrate_process_add(pid, vma->total_length); ++ if (process == NULL) { ++ memdcd_log(_LOG_ERROR, "Cannot allocate space for process %d.", pid); ++ pthread_mutex_unlock(&mutex); ++ return NULL; ++ } ++ } ++ pthread_mutex_unlock(&mutex); ++ ++ memdcd_log(_LOG_DEBUG, "Collect %d pages for process %d; %lu has been collected; total %lu.", count, pid, ++ process->offset, process->page_list->length); ++ ++ if (process->offset + count > process->page_list->length) { ++ memdcd_log(_LOG_ERROR, "Collected pages of process %d is greater than total count: %lu %lu %lu.", pid, ++ process->offset, count, process->page_list->length); ++ migrate_process_remove(pid); ++ return NULL; ++ } ++ ++ for (i = 0; i < count; i++) { ++ process->page_list->pages[process->offset + i].addr = vma->vma_addrs[i].vma.start_addr; ++ process->page_list->pages[process->offset + i].length = vma->vma_addrs[i].vma.vma_len; ++ process->page_list->pages[process->offset + i].visit_count = vma->vma_addrs[i].count; ++ } ++ process->offset += count; ++ gettimeofday(&process->timestamp, NULL); ++ ++ if (vma->status == MEMDCD_SEND_END && process->offset != process->page_list->length) { ++ memdcd_log(_LOG_ERROR, "Count of pages of process %d is not equal to total count: %lu %lu.", ++ pid, process->offset, process->page_list->length); ++ migrate_process_remove(pid); ++ return NULL; ++ } ++ if (vma->status != MEMDCD_SEND_PROCESS && process->offset == process->page_list->length) { ++ memdcd_log(_LOG_INFO, "Collected %lu vmas for process %d.", process->page_list->length, pid); ++ return process; ++ } ++ ++ return NULL; ++} ++ ++void init_collect_pages_timeout(time_t timeout) ++{ ++ collect_page_timeout = timeout; ++} ++ ++static void *memdcd_migrate(void *args) ++{ ++ struct migrate_process *process = (struct migrate_process *)args; ++ struct mem_policy *policy = NULL; ++ struct migrate_page_list *pages = NULL, *pages_to_numa = NULL, *pages_to_swap = NULL; ++ ++ if (process == NULL) { ++ memdcd_log(_LOG_ERROR, "Process freed."); ++ return NULL; ++ } ++ ++ policy = get_policy(); ++ if (policy == NULL) { ++ memdcd_log(_LOG_ERROR, "Policy not initialized."); ++ return NULL; ++ } ++ ++ pages = (struct migrate_page_list *)malloc(sizeof(struct migrate_page_list) + ++ sizeof(struct migrate_page) * process->page_list->length); ++ if (pages == NULL) ++ return NULL; ++ memcpy(pages, process->page_list, ++ sizeof(struct migrate_page_list) + sizeof(struct migrate_page) * process->page_list->length); ++ ++ if (policy->opt->parse(policy, process->pid, pages, &pages_to_numa, &pages_to_swap)) { ++ memdcd_log(_LOG_ERROR, "Error parsing policy."); ++ goto free_pages; ++ } ++ ++ if (pages_to_swap->pages != NULL) ++ send_to_userswap(process->pid, pages_to_swap); ++ ++ if (pages_to_numa != NULL) ++ free(pages_to_numa); ++ if (pages_to_swap != NULL) ++ free(pages_to_swap); ++ ++free_pages: ++ free(pages); ++ ++ pthread_mutex_lock(&mutex); ++ migrate_process_remove(process->pid); ++ pthread_mutex_unlock(&mutex); ++ return NULL; ++} ++ ++static int get_pid_max(void) ++{ ++ FILE *fp; ++ char buf[PID_MAX_LEN] = {0}; ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ ++ fp = fopen(PID_MAX_FILE, "r"); ++ if (fp == NULL) { ++ memdcd_log(_LOG_ERROR, "Error opening pid_max file %s. err: %s", ++ PID_MAX_FILE, strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return 0; ++ } ++ if (fread(buf, sizeof(buf), 1, fp) == 0) { ++ if (feof(fp) == 0) { ++ memdcd_log(_LOG_ERROR, "Error reading pid_max file %s.", PID_MAX_FILE); ++ fclose(fp); ++ return 0; ++ } ++ } ++ fclose(fp); ++ return atoi(buf); ++} ++ ++int migrate_process_get_pages(int pid, const struct swap_vma_with_count *vma) ++{ ++ char error_str[ERROR_STR_MAX_LEN] = {0}; ++ struct migrate_process *process = NULL; ++ if (pid <= 0 || pid > get_pid_max()) { ++ memdcd_log(_LOG_ERROR, "Invalid input pid:%d.\n ", pid); ++ return -1; ++ } ++ ++ process = migrate_process_collect_pages(pid, vma); ++ ++ if (process != NULL) { ++ if (pthread_create(&process->worker, NULL, memdcd_migrate, (void *)process) != 0) { ++ memdcd_log(_LOG_ERROR, "Error creating pthread for process %d. err: %s", ++ process->pid, strerror_r(errno, error_str, ERROR_STR_MAX_LEN)); ++ return -1; ++ } ++ } else { ++ return -1; ++ } ++ return 0; ++} ++ +diff --git a/userswap/CMakeLists.txt b/userswap/CMakeLists.txt +new file mode 100644 +index 0000000..415b0f7 +--- /dev/null ++++ b/userswap/CMakeLists.txt +@@ -0,0 +1,36 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: LiuYongqiang ++# * Create: 2020-11-06 ++# * Description: CMakefileList for userswap to compile ++# ******************************************************************************/ ++ ++cmake_minimum_required (VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) ++ ++project(libuswap) ++ ++set(SRC_DIR ${PROJECT_SOURCE_DIR}/src) ++set(BUILD_DIR ${PROJECT_SOURCE_DIR}/build) ++ ++set(USWAP_SRC ++ ${SRC_DIR}/lib_uswap.c ++ ${SRC_DIR}/uswap_server.c ++ ${SRC_DIR}/uswap_log.c) ++ ++include_directories(${PROJECT_SOURCE_DIR}/include) ++ ++add_library(uswap STATIC ${USWAP_SRC}) ++ ++target_compile_options(uswap PRIVATE -fPIC -ftrapv -D_FORTIFY_SOURCE=2 -O2 ++-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -fvisibility=hidden) ++ ++install(TARGETS uswap PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE DESTINATION /usr/lib64) ++install(FILES ${PROJECT_SOURCE_DIR}/include/uswap_api.h DESTINATION /usr/include) +diff --git a/userswap/License/LICENSE b/userswap/License/LICENSE +new file mode 100644 +index 0000000..0db93af +--- /dev/null ++++ b/userswap/License/LICENSE +@@ -0,0 +1,127 @@ ++木兰宽松许可证, 第2版 ++ ++ 木兰宽松许可证, 第2版 ++ 2020年1月 http://license.coscl.org.cn/MulanPSL2 ++ ++ ++ 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: ++ ++ 0. 定义 ++ ++ “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 ++ ++ “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 ++ ++ “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 ++ ++ “法人实体”是指提交贡献的机构及其“关联实体”。 ++ ++ “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 ++ ++ 1. 授予版权许可 ++ ++ 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 ++ ++ 2. 授予专利许可 ++ ++ 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 ++ ++ 3. 无商标许可 ++ ++ “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 ++ ++ 4. 分发限制 ++ ++ 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 ++ ++ 5. 免责声明与责任限制 ++ ++ “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 ++ ++ 6. 语言 ++ “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 ++ ++ 条款结束 ++ ++ 如何将木兰宽松许可证,第2版,应用到您的软件 ++ ++ 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: ++ ++ 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; ++ ++ 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; ++ ++ 3, 请将如下声明文本放入每个源文件的头部注释中。 ++ ++ Copyright (c) [Year] [name of copyright holder] ++ [Software Name] is licensed under Mulan PSL v2. ++ You can use this software according to the terms and conditions of the Mulan PSL v2. ++ You may obtain a copy of Mulan PSL v2 at: ++ http://license.coscl.org.cn/MulanPSL2 ++ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ See the Mulan PSL v2 for more details. ++ ++ ++ Mulan Permissive Software License,Version 2 ++ ++ Mulan Permissive Software License,Version 2 (Mulan PSL v2) ++ January 2020 http://license.coscl.org.cn/MulanPSL2 ++ ++ Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: ++ ++ 0. Definition ++ ++ Software means the program and related documents which are licensed under this License and comprise all Contribution(s). ++ ++ Contribution means the copyrightable work licensed by a particular Contributor under this License. ++ ++ Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. ++ ++ Legal Entity means the entity making a Contribution and all its Affiliates. ++ ++ Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. ++ ++ 1. Grant of Copyright License ++ ++ Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. ++ ++ 2. Grant of Patent License ++ ++ Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. ++ ++ 3. No Trademark License ++ ++ No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. ++ ++ 4. Distribution Restriction ++ ++ You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. ++ ++ 5. Disclaimer of Warranty and Limitation of Liability ++ ++ THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ++ ++ 6. Language ++ ++ THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. ++ ++ END OF THE TERMS AND CONDITIONS ++ ++ How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software ++ ++ To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: ++ ++ i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; ++ ++ ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; ++ ++ iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. ++ ++ ++ Copyright (c) [Year] [name of copyright holder] ++ [Software Name] is licensed under Mulan PSL v2. ++ You can use this software according to the terms and conditions of the Mulan PSL v2. ++ You may obtain a copy of Mulan PSL v2 at: ++ http://license.coscl.org.cn/MulanPSL2 ++ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ See the Mulan PSL v2 for more details. +diff --git a/userswap/README.md b/userswap/README.md +new file mode 100644 +index 0000000..b02edfe +--- /dev/null ++++ b/userswap/README.md +@@ -0,0 +1,7 @@ ++# Introduction ++userswap is a component of RAA memory-fabric. It supplies a userswap method for ++storage and net devices which is designed by user-mode protocol. It works with ++special kernel. ++ ++# Build ++./configure +diff --git a/userswap/configure.sh b/userswap/configure.sh +new file mode 100644 +index 0000000..6bca78d +--- /dev/null ++++ b/userswap/configure.sh +@@ -0,0 +1,4 @@ ++mkdir build ++cd ./build ++cmake .. ++make +diff --git a/userswap/include/uswap_api.h b/userswap/include/uswap_api.h +new file mode 100644 +index 0000000..9e26dfe +--- /dev/null ++++ b/userswap/include/uswap_api.h +@@ -0,0 +1,69 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * userswap licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liuyongqiang ++ * Create: 2020-11-06 ++ * Description: userswap interface ++ ******************************************************************************/ ++ ++#ifndef __USWAP_API_H__ ++#define __USWAP_API_H__ ++ ++#include ++ ++#define USWAP_SUCCESS 0 ++#define USWAP_ERROR (-1) ++#define USWAP_UNREGISTER_MEM (-2) ++#define USWAP_ALREADY_SWAPPED (-3) ++#define USWAP_ABORT (-4) ++#define USWAP_ALREADY_SWAPIN (-5) ++ ++#define MAX_USWAP_NAME_LEN 32 ++#define MAX_SWAPIN_THREAD_NUMS 5 ++ ++/* flag field of struct swap_data */ ++#define USWAP_DATA_DIRTY 0x1 ++#define USWAP_DATA_ABORT 0x2 ++ ++struct swap_data { ++ void *start_va; ++ size_t len; ++ void *buf; ++ /* ++ * Bit 0 (Dirty Flag): ++ * indicate the data in the range of 'start_va ~ start_va+len' is ++ * dirty if this bit is set. ++ * Bit 1 (Abort Flag): ++ * This bit only takes affect in do_swapout. It indicates ++ * aborting the swapout operation if it is set. ++ */ ++ size_t flag; ++}; ++ ++struct uswap_operations { ++ int (*get_swapout_buf) (const void *, size_t, struct swap_data *); ++ int (*do_swapout) (struct swap_data *); ++ int (*do_swapin) (const void *, struct swap_data *); ++ int (*release_buf) (struct swap_data *); ++}; ++ ++int set_uswap_log_level(int log_level); ++ ++int register_userfaultfd(void *addr, size_t size); ++ ++int unregister_userfaultfd(void *addr, size_t size); ++ ++int register_uswap(const char *name, size_t len, ++ const struct uswap_operations *ops); ++ ++int force_swapout(const void *addr, size_t len); ++ ++int uswap_init(int swapin_nums); ++#endif +diff --git a/userswap/include/uswap_log.h b/userswap/include/uswap_log.h +new file mode 100644 +index 0000000..1084d16 +--- /dev/null ++++ b/userswap/include/uswap_log.h +@@ -0,0 +1,30 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * userswap licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liuyongqiang ++ * Create: 2020-11-06 ++ * Description: userswap log headfile ++ ******************************************************************************/ ++ ++#ifndef __USWAP_LOG_H__ ++#define __USWAP_LOG_H__ ++ ++enum log_level { ++ USWAP_LOG_DEBUG = 0, ++ USWAP_LOG_INFO, ++ USWAP_LOG_WARN, ++ USWAP_LOG_ERR, ++ USWAP_LOG_INVAL, ++}; ++ ++int uswap_log_level_init(enum log_level level); ++ ++void uswap_log(enum log_level level, const char *format, ...); ++#endif +diff --git a/userswap/include/uswap_server.h b/userswap/include/uswap_server.h +new file mode 100644 +index 0000000..bcfb16f +--- /dev/null ++++ b/userswap/include/uswap_server.h +@@ -0,0 +1,40 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * userswap licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liuyongqiang ++ * Create: 2020-11-06 ++ * Description: userswap server interface ++ ******************************************************************************/ ++ ++#ifndef __USWAP_SERVER_H__ ++#define __USWAP_SERVER_H__ ++ ++#define MAX_VMA_NUM 512 ++ ++enum swap_type { ++ SWAP_TYPE_VMA_ADDR = 0xFFFFFF01, ++ SWAP_TYPE_MAX ++}; ++ ++struct vma_addr { ++ unsigned long start_addr; ++ unsigned long vma_len; ++}; ++ ++struct swap_vma { ++ enum swap_type type; ++ unsigned long length; ++ struct vma_addr vma_addrs[MAX_VMA_NUM]; ++}; ++ ++int init_socket(void); ++int sock_handle_rec(int fd, struct swap_vma *swap_vma); ++int sock_handle_respond(int client_fd, int result); ++#endif +diff --git a/userswap/src/lib_uswap.c b/userswap/src/lib_uswap.c +new file mode 100644 +index 0000000..0dc1337 +--- /dev/null ++++ b/userswap/src/lib_uswap.c +@@ -0,0 +1,663 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * userswap licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liuyongqiang ++ * Create: 2020-11-06 ++ * Description: userswap interface definition. ++ ******************************************************************************/ ++ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "uswap_server.h" ++#include "uswap_log.h" ++#include "uswap_api.h" ++ ++#define MAP_REPLACE 0x1000000 ++#ifndef UFFDIO_REGISTER_MODE_USWAP ++#define UFFDIO_REGISTER_MODE_USWAP (1 << 2) ++#endif ++#define MMAP_RETVAL_DIRTY_MASK 0x01L ++#define MAX_TRY_NUMS 10 ++ ++struct uswap_dev { ++ char name[MAX_USWAP_NAME_LEN]; ++ struct uswap_operations *ops; ++ bool enabled; ++ bool alive; ++ int uffd; ++ pthread_cond_t cond; ++ pthread_mutex_t mutex; ++}; ++ ++static struct uswap_dev g_dev = { ++ .name = "", ++ .ops = NULL, ++ .enabled = false, ++ .alive = false, ++ .uffd = -1, ++ .cond = PTHREAD_COND_INITIALIZER, ++ .mutex = PTHREAD_MUTEX_INITIALIZER, ++}; ++ ++static size_t get_page_size(void) ++{ ++ static size_t page_size = 0; ++ if (page_size != 0) { ++ return page_size; ++ } ++ ++ page_size = sysconf(_SC_PAGESIZE); ++ return page_size; ++} ++ ++static bool is_uswap_enabled(void) ++{ ++ return g_dev.enabled; ++} ++ ++static bool is_uswap_threads_alive(void) ++{ ++ return g_dev.alive; ++} ++ ++static int set_uswap_uffd(int uffd) ++{ ++ if (g_dev.uffd != -1) { ++ return USWAP_ERROR; ++ } ++ g_dev.uffd = uffd; ++ return USWAP_SUCCESS; ++} ++ ++static int get_uswap_uffd(void) ++{ ++ return g_dev.uffd; ++} ++ ++static void uswap_mutex_lock(void) ++{ ++ pthread_mutex_lock(&g_dev.mutex); ++} ++ ++static void uswap_mutex_unlock(void) ++{ ++ pthread_mutex_unlock(&g_dev.mutex); ++} ++ ++static void uswap_cond_wait(void) ++{ ++ pthread_cond_wait(&g_dev.cond, &g_dev.mutex); ++} ++ ++static void uswap_cond_wake(void) ++{ ++ pthread_cond_signal(&g_dev.cond); ++} ++ ++static int call_get_swapout_buf(const void *start_va, size_t len, ++ struct swap_data *swapout_data) ++{ ++ return g_dev.ops->get_swapout_buf(start_va, len, swapout_data); ++} ++ ++static int call_do_swapout(struct swap_data *swapout_data) ++{ ++ return g_dev.ops->do_swapout(swapout_data); ++} ++ ++static int call_do_swapin(const void *fault_addr, struct swap_data *swapin_data) ++{ ++ return g_dev.ops->do_swapin(fault_addr, swapin_data); ++} ++ ++static int call_release_buf(struct swap_data *swap_data) ++{ ++ return g_dev.ops->release_buf(swap_data); ++} ++ ++static int init_userfaultfd(void) ++{ ++ struct uffdio_api uffdio_api; ++ int uswap_uffd; ++ int ret; ++ ++ uswap_uffd = syscall(__NR_userfaultfd, O_NONBLOCK); ++ if (uswap_uffd < 0) { ++ return USWAP_ERROR; ++ } ++ ++ uffdio_api.api = UFFD_API; ++ uffdio_api.features = 0; ++ ret = ioctl(uswap_uffd, UFFDIO_API, &uffdio_api); ++ if (ret < 0) { ++ return ret; ++ } ++ ret = set_uswap_uffd(uswap_uffd); ++ return ret; ++} ++ ++int register_userfaultfd(void *addr, size_t size) ++{ ++ struct uffdio_register uffdio_register; ++ int ret; ++ int uswap_uffd; ++ size_t page_size; ++ ++ if (size > SSIZE_MAX || addr == NULL) { ++ return USWAP_ERROR; ++ } ++ ++ uswap_uffd = get_uswap_uffd(); ++ if (uswap_uffd < 0) { ++ uswap_mutex_lock(); ++ ret = init_userfaultfd(); ++ uswap_cond_wake(); ++ uswap_mutex_unlock(); ++ if (ret == USWAP_ERROR) { ++ uswap_log(USWAP_LOG_ERR, "init userfaultfd failed\n"); ++ return USWAP_ERROR; ++ } ++ uswap_uffd = get_uswap_uffd(); ++ } ++ ++ page_size = get_page_size(); ++ if (size >= page_size) { ++ uffdio_register.range.start = (unsigned long)addr; ++ uffdio_register.range.len = size; ++ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING | ++ UFFDIO_REGISTER_MODE_USWAP; ++ ret = ioctl(uswap_uffd, UFFDIO_REGISTER, &uffdio_register); ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "register uffd failed\n"); ++ return USWAP_ERROR; ++ } ++ return USWAP_SUCCESS; ++ } ++ uswap_log(USWAP_LOG_ERR, "register uffd: the size smaller than page_size\n"); ++ return USWAP_ERROR; ++} ++ ++int unregister_userfaultfd(void *addr, size_t size) ++{ ++ struct uffdio_register uffdio_register; ++ int uswap_uffd; ++ int ret; ++ ++ uswap_uffd = get_uswap_uffd(); ++ if (uswap_uffd < 0 || size > SSIZE_MAX || addr == NULL) { ++ return USWAP_ERROR; ++ } ++ ++ uffdio_register.range.start = (unsigned long)addr; ++ uffdio_register.range.len = size; ++ ret = ioctl(uswap_uffd, UFFDIO_UNREGISTER, &uffdio_register); ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "unregister userfaultfd failed\n"); ++ return USWAP_ERROR; ++ } ++ return USWAP_SUCCESS; ++} ++ ++int register_uswap(const char *name, size_t len, ++ const struct uswap_operations *ops) ++{ ++ static struct uswap_operations uswap_ops; ++ if (name == NULL || len > MAX_USWAP_NAME_LEN - 1) { ++ return USWAP_ERROR; ++ } ++ ++ if (ops == NULL) { ++ return USWAP_ERROR; ++ } ++ ++ if (ops->get_swapout_buf == NULL || ops->do_swapout == NULL || ++ ops->do_swapin == NULL || ops->release_buf == NULL) { ++ return USWAP_ERROR; ++ } ++ ++ uswap_ops = *ops; ++ ++ snprintf(g_dev.name, MAX_USWAP_NAME_LEN, "%s", name); ++ g_dev.ops = &uswap_ops; ++ g_dev.enabled = true; ++ uswap_log(USWAP_LOG_INFO, "register uswap ops [%s] success\n", g_dev.name); ++ return USWAP_SUCCESS; ++} ++ ++static int mlock_pthread_stack(pthread_t tid) ++{ ++ int ret; ++ pthread_attr_t attr_t; ++ void *stack_addr = NULL; ++ size_t stack_size; ++ ++ ret = pthread_getattr_np(tid, &attr_t); ++ if (ret < 0) { ++ return USWAP_ERROR; ++ } ++ ret = pthread_attr_getstack(&attr_t, &stack_addr, &stack_size); ++ pthread_attr_destroy(&attr_t); ++ if (ret < 0) { ++ return USWAP_ERROR; ++ } ++ ++ ret = mlock(stack_addr, stack_size); ++ if (ret < 0) { ++ return USWAP_ERROR; ++ } ++ return USWAP_SUCCESS; ++} ++ ++static int read_uffd_msg(int uffd, struct uffd_msg *msg) ++{ ++ int ret; ++ int msg_len = sizeof(struct uffd_msg); ++ ++ for (int i = 0; i < MAX_TRY_NUMS; i++) { ++ ret = read(uffd, msg, msg_len); ++ if (ret != msg_len) { ++ if (errno == EAGAIN) { ++ continue; ++ } ++ return USWAP_ERROR; ++ } ++ ++ if (msg->event != UFFD_EVENT_PAGEFAULT) { ++ uswap_log(USWAP_LOG_ERR, "unexpected event on userfaultfd\n"); ++ return USWAP_ERROR; ++ } ++ return USWAP_SUCCESS; ++ } ++ return USWAP_ABORT; ++} ++ ++static int ioctl_uffd_copy_pages(int uffd, const struct swap_data *swapin_data) ++{ ++ int ret; ++ int offset = 0; ++ size_t page_size = get_page_size(); ++ struct uffdio_copy uffdio_copy = { ++ .len = page_size, ++ .mode = 0, ++ .copy = 0, ++ }; ++ ++ while (offset < swapin_data->len) { ++ uffdio_copy.src = (unsigned long)swapin_data->buf + offset; ++ uffdio_copy.dst = (unsigned long)swapin_data->start_va + offset; ++ ret = ioctl(uffd, UFFDIO_COPY, &uffdio_copy); ++ if (ret < 0 && errno != EEXIST) { ++ uswap_log(USWAP_LOG_ERR, "uffd ioctl copy one page failed\n"); ++ return USWAP_ERROR; ++ } ++ offset += page_size; ++ } ++ ++ return USWAP_SUCCESS; ++} ++ ++static int ioctl_uffd_copy(int uffd, struct swap_data *swapin_data) ++{ ++ int ret; ++ struct uffdio_copy uffdio_copy = { ++ .src = (unsigned long)swapin_data->buf, ++ .dst = (unsigned long)swapin_data->start_va, ++ .len = swapin_data->len, ++ .mode = 0, ++ .copy = 0, ++ }; ++ for (int i = 0; i < MAX_TRY_NUMS; i++) { ++ ret = ioctl(uffd, UFFDIO_COPY, &uffdio_copy); ++ if (ret < 0) { ++ if (errno == EAGAIN) { ++ continue; ++ } ++ ++ if (errno == EEXIST) { ++ return USWAP_ALREADY_SWAPIN; ++ } ++ /* ++ * 'start_va ~ start_va+len' may exceed the range of one vma. ++ * If that is the case, copy one page at a time. ++ */ ++ ret = ioctl_uffd_copy_pages(uffd, swapin_data); ++ if (ret == USWAP_ERROR) { ++ return USWAP_ERROR; ++ } ++ } ++ return USWAP_SUCCESS; ++ } ++ uswap_log(USWAP_LOG_ERR, "ioctl copy max try failed\n"); ++ return USWAP_ERROR; ++} ++ ++static void *swapin_thread(void *arg) ++{ ++ struct swap_data swapin_data; ++ struct uffd_msg uffd_msg; ++ struct pollfd pollfd; ++ unsigned long fault_addr; ++ int uswap_uffd; ++ int ret; ++ ++ prctl(PR_SET_NAME, "uswap-swapin", 0, 0, 0); ++ ++ uswap_mutex_lock(); ++ uswap_uffd = get_uswap_uffd(); ++ while (uswap_uffd < 0) { ++ uswap_cond_wait(); ++ uswap_uffd = get_uswap_uffd(); ++ } ++ uswap_mutex_unlock(); ++ while (1) { ++ pollfd.fd = uswap_uffd; ++ pollfd.events = POLLIN; ++ ret = poll(&pollfd, 1, -1); ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "poll failed\n"); ++ usleep(10); ++ continue; ++ } ++ ret = read_uffd_msg(uswap_uffd, &uffd_msg); ++ if (ret == USWAP_ABORT) { ++ continue; ++ } else if (ret == USWAP_ERROR) { ++ uswap_log(USWAP_LOG_ERR, "read uffd failed\n"); ++ continue; ++ } ++ ++ fault_addr = uffd_msg.arg.pagefault.address; ++ ++ ret = call_do_swapin((void *)fault_addr, &swapin_data); ++ if (ret == USWAP_ERROR) { ++ uswap_log(USWAP_LOG_ERR, "do_swapin failed\n"); ++ exit(-1); ++ } ++ ++ ret = ioctl_uffd_copy(uswap_uffd, &swapin_data); ++ if (ret == USWAP_ERROR) { ++ uswap_log(USWAP_LOG_ERR, "uffd ioctl copy failed\n"); ++ exit(-1); ++ } ++ ret = call_release_buf(&swapin_data); ++ if (ret == USWAP_ERROR) { ++ uswap_log(USWAP_LOG_ERR, "release buf failed\n"); ++ } ++ } ++} ++ ++static void* mmap_tmpva(const void *start, size_t len, int *is_dirty) ++{ ++ unsigned long new_addr; ++ new_addr = syscall(__NR_mmap, start, len, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS | MAP_REPLACE, -1, 0); ++ if ((void *)new_addr == MAP_FAILED) { ++ if (errno != ENODEV) { ++ uswap_log(USWAP_LOG_ERR, "the addr can't be swapout\n"); ++ } ++ return MAP_FAILED; ++ } else { ++ *is_dirty = new_addr & MMAP_RETVAL_DIRTY_MASK; ++ new_addr = new_addr & (~MMAP_RETVAL_DIRTY_MASK); ++ } ++ return (void *)new_addr; ++} ++ ++static int do_swapout_once(const void *start, size_t len, ++ struct swap_data *swapout_data) ++{ ++ int ret; ++ int is_dirty = 1; ++ void *tmpva = NULL; ++ ++ ret = call_get_swapout_buf(start, len, swapout_data); ++ if (ret == USWAP_ALREADY_SWAPPED) { ++ return USWAP_SUCCESS; ++ } ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "get swapout buf error\n"); ++ return ret; ++ } ++ ++ tmpva = mmap_tmpva(swapout_data->start_va, swapout_data->len, &is_dirty); ++ ++ swapout_data->flag = 0; ++ if (tmpva != MAP_FAILED) { ++ memcpy(swapout_data->buf, tmpva, swapout_data->len); ++ munmap(tmpva, swapout_data->len); ++ } else { ++ swapout_data->flag |= USWAP_DATA_ABORT; ++ } ++ ++ if (is_dirty != 0) { ++ swapout_data->flag |= USWAP_DATA_DIRTY; ++ } ++ ++ ret = call_do_swapout(swapout_data); ++ ++ return ret; ++} ++ ++static int do_swapout(const void *start, size_t len) ++{ ++ int ret; ++ size_t succ_len = 0; ++ struct swap_data swapout_data; ++ ++ while (succ_len < len) { ++ ret = do_swapout_once(start + succ_len, len - succ_len, &swapout_data); ++ if (ret < 0) { ++ return ret; ++ } ++ if (succ_len >= len - swapout_data.len) { ++ break; ++ } ++ succ_len += swapout_data.len; ++ } ++ uswap_log(USWAP_LOG_DEBUG, "do swapout addr: %p, len %lx\n", start, len); ++ return succ_len; ++} ++ ++static int vma_merge(const struct swap_vma *src, struct swap_vma *dst) ++{ ++ int index = 0; ++ int swapout_nums; ++ size_t page_size = get_page_size(); ++ ++ swapout_nums = src->length / sizeof(struct vma_addr); ++ if (swapout_nums > MAX_VMA_NUM) { ++ swapout_nums = MAX_VMA_NUM; ++ } ++ for (int i = 0; i < swapout_nums; i++) { ++ if (src->vma_addrs[i].vma_len == 0 || ++ src->vma_addrs[i].vma_len > SSIZE_MAX) { ++ continue; ++ } ++ if (src->vma_addrs[i].vma_len == page_size) { ++ int j = i + 1; ++ dst->vma_addrs[index].start_addr = src->vma_addrs[i].start_addr; ++ dst->vma_addrs[index].vma_len = page_size; ++ while (j < swapout_nums && ++ src->vma_addrs[j - 1].start_addr + page_size == ++ src->vma_addrs[j].start_addr) { ++ j++; ++ dst->vma_addrs[index].vma_len += page_size; ++ } ++ i = j - 1; ++ index++; ++ } else { ++ dst->vma_addrs[index].start_addr = src->vma_addrs[i].start_addr; ++ dst->vma_addrs[index].vma_len = src->vma_addrs[i].vma_len; ++ index++; ++ } ++ } ++ dst->length = index * sizeof(struct vma_addr); ++ return USWAP_SUCCESS; ++} ++ ++static int swapout_source_init(void) ++{ ++ size_t page_size; ++ int socket_fd = -1; ++ ++ page_size = get_page_size(); ++ socket_fd = init_socket(); ++ if (socket_fd < 0) { ++ uswap_log(USWAP_LOG_DEBUG, "init_socket failed err:%d\n", errno); ++ return USWAP_ERROR; ++ } ++ return socket_fd; ++} ++ ++static void *swapout_thread(void *arg) ++{ ++ struct swap_vma src, dst; ++ unsigned long start; ++ size_t len; ++ int swapout_nums; ++ int succ_count = 0; ++ int socket_fd, client_fd; ++ int ret; ++ ++ prctl(PR_SET_NAME, "uswap-swapout", 0, 0, 0); ++ ret = swapout_source_init(); ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "swapout source init failed\n"); ++ return NULL; ++ } ++ socket_fd = ret; ++ while (1) { ++ client_fd = sock_handle_rec(socket_fd, &src); ++ if (client_fd <= 0) { ++ uswap_log(USWAP_LOG_DEBUG, "sock_handle_rec failed\n"); ++ continue; ++ } ++ ++ vma_merge(&src, &dst); ++ ret = USWAP_SUCCESS; ++ swapout_nums = dst.length / sizeof(struct vma_addr); ++ for (int i = 0; i < swapout_nums; i++) { ++ len = dst.vma_addrs[i].vma_len; ++ start = dst.vma_addrs[i].start_addr; ++ succ_count = do_swapout((void *)start, len); ++ if (succ_count < 0) { ++ uswap_log(USWAP_LOG_ERR, "do swapout once failed\n"); ++ ret = USWAP_ERROR; ++ } ++ } ++ sock_handle_respond(client_fd, ret); ++ } ++ close(socket_fd); ++} ++ ++int force_swapout(const void *addr, size_t len) ++{ ++ int ret; ++ size_t page_size = get_page_size(); ++ if (!is_uswap_enabled() || !is_uswap_threads_alive()) { ++ return USWAP_ERROR; ++ } ++ if (addr == NULL || len > SSIZE_MAX) { ++ return USWAP_ERROR; ++ } ++ ++ ret = do_swapout(addr, len); ++ return ret; ++} ++ ++static int create_uswap_threads(int swapin_nums) ++{ ++ int ret; ++ pthread_t swapout_tid; ++ pthread_t swapin_tid[MAX_SWAPIN_THREAD_NUMS]; ++ ++ if (swapin_nums <= 0 || swapin_nums > MAX_SWAPIN_THREAD_NUMS) { ++ return USWAP_ERROR; ++ } ++ ++ ret = pthread_create(&swapout_tid, NULL, swapout_thread, NULL); ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "can't create swapout thread"); ++ return USWAP_ERROR; ++ } ++ ret = mlock_pthread_stack(swapout_tid); ++ if (ret == USWAP_ERROR) { ++ uswap_log(USWAP_LOG_ERR, "mlock swapout thread stack failed\n"); ++ pthread_cancel(swapout_tid); ++ return USWAP_ERROR; ++ } ++ ++ for (int i = 0; i < swapin_nums; i++) { ++ ret = pthread_create(&swapin_tid[i], NULL, swapin_thread, NULL); ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "can't create swapin thread\n"); ++ pthread_cancel(swapout_tid); ++ for (int j = 0; j < i; j++) { ++ pthread_cancel(swapin_tid[j]); ++ } ++ return USWAP_ERROR; ++ } ++ ret = mlock_pthread_stack(swapin_tid[i]); ++ if (ret == USWAP_ERROR) { ++ uswap_log(USWAP_LOG_ERR, "mlock swapin thread stack failed\n"); ++ pthread_cancel(swapout_tid); ++ for (int j = 0; j <= i; j++) { ++ pthread_cancel(swapin_tid[j]); ++ } ++ return USWAP_ERROR; ++ } ++ } ++ ++ return USWAP_SUCCESS; ++} ++ ++int set_uswap_log_level(int log_level) ++{ ++ return uswap_log_level_init(log_level); ++} ++ ++int uswap_init(int swapin_nums) ++{ ++ int ret; ++ ++ if (!is_uswap_enabled() || is_uswap_threads_alive()) { ++ return USWAP_ERROR; ++ } ++ ++ ret = create_uswap_threads(swapin_nums); ++ if (ret == USWAP_ERROR) { ++ return USWAP_ERROR; ++ } ++ ++ g_dev.alive = true; ++ return USWAP_SUCCESS; ++} +diff --git a/userswap/src/uswap_log.c b/userswap/src/uswap_log.c +new file mode 100644 +index 0000000..09bdff6 +--- /dev/null ++++ b/userswap/src/uswap_log.c +@@ -0,0 +1,81 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * userswap licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liuyongqiang ++ * Create: 2020-11-06 ++ * Description: userswap log definition. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include "uswap_log.h" ++ ++enum log_level g_log_level = USWAP_LOG_ERR; ++ ++static void log_level_usage(void) ++{ ++ printf("\n" ++ "[0] for debug level\n" ++ "[1] for info level\n" ++ "[2] for warning level\n" ++ "[3] for error level\n" ++ "default level is error\n" ++ "\n"); ++} ++ ++int uswap_log_level_init(enum log_level level) ++{ ++ if (level < 0 || level >= USWAP_LOG_INVAL) { ++ printf("error: invalid log level [%d]\n", level); ++ log_level_usage(); ++ return -EINVAL; ++ } ++ g_log_level = level; ++ return 0; ++} ++ ++void uswap_log(enum log_level level, const char *format, ...) ++{ ++ va_list args; ++ ++ if (level < g_log_level) { ++ return; ++ } ++ ++ va_start(args, format); ++ ++ switch (level) { ++ case USWAP_LOG_DEBUG: ++ openlog("[uswap_debug] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_INFO, format, args); ++ break; ++ case USWAP_LOG_INFO: ++ openlog("[uswap_info] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_INFO, format, args); ++ break; ++ case USWAP_LOG_WARN: ++ openlog("[uswap_warn] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_WARNING, format, args); ++ break; ++ case USWAP_LOG_ERR: ++ openlog("[uswap_error] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_ERR, format, args); ++ break; ++ default: ++ openlog("[uswap_error] ", LOG_PID, LOG_USER); ++ vsyslog(LOG_ERR, "invalid uswap_log_level\n", args); ++ } ++ ++ va_end(args); ++ closelog(); ++ return; ++} +diff --git a/userswap/src/uswap_server.c b/userswap/src/uswap_server.c +new file mode 100644 +index 0000000..ecb16a9 +--- /dev/null ++++ b/userswap/src/uswap_server.c +@@ -0,0 +1,138 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. ++ * userswap licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liuyongqiang ++ * Create: 2020-11-06 ++ * Description: userswap server definition. ++ ******************************************************************************/ ++ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "uswap_log.h" ++#include "uswap_server.h" ++ ++#define MAX_LISTENQ_NUM 1 ++#define RESP_MSG_MAX_LEN 10 ++#define PATH_MAX_LEN 127 ++ ++ ++int init_socket(void) ++{ ++ int socket_fd; ++ int addrlen; ++ struct sockaddr_un addr; ++ char abstract_path[PATH_MAX_LEN] = {0}; ++ pid_t pid = getpid(); ++ ++ socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); ++ if (socket_fd < 0) { ++ uswap_log(USWAP_LOG_ERR, "create socket failed\n"); ++ return -EINVAL; ++ } ++ ++ bzero(&addr, sizeof(struct sockaddr_un)); ++ addr.sun_family = AF_UNIX; ++ addr.sun_path[0] = 0; ++ snprintf(abstract_path, sizeof(abstract_path), "userswap%d.sock", pid); ++ memcpy(addr.sun_path + 1, abstract_path, strlen(abstract_path) + 1); ++ addrlen = sizeof(addr.sun_family) + strlen(abstract_path) + 1; ++ if (bind(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) { ++ uswap_log(USWAP_LOG_ERR, "bind socket failed\n"); ++ close(socket_fd); ++ return -EINVAL; ++ } ++ ++ listen(socket_fd, MAX_LISTENQ_NUM); ++ ++ return socket_fd; ++} ++ ++static int check_socket_permission(int fd, int client_fd) ++{ ++ struct ucred local_cred, client_cred; ++ socklen_t len; ++ int ret; ++ ++ len = sizeof(struct ucred); ++ ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &local_cred, &len); ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "get server sockopt failed\n"); ++ return ret; ++ } ++ ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &client_cred, &len); ++ if (ret < 0) { ++ uswap_log(USWAP_LOG_ERR, "get client sockopt failed\n"); ++ return ret; ++ } ++ ++ if (local_cred.uid != client_cred.uid || ++ local_cred.gid != client_cred.gid) { ++ return -EPERM; ++ } ++ return 0; ++} ++ ++int sock_handle_rec(int fd, struct swap_vma *swap_vma) ++{ ++ int client_fd; ++ int readbytes; ++ struct sockaddr_un clientun; ++ socklen_t clientun_len = sizeof(clientun); ++ ++ client_fd = accept(fd, (struct sockaddr *)&clientun, &clientun_len); ++ if (client_fd < 0) { ++ return -EINVAL; ++ } ++ ++ if (check_socket_permission(fd, client_fd) < 0) { ++ close(client_fd); ++ return -EPERM; ++ } ++ ++ readbytes = read(client_fd, swap_vma, sizeof(struct swap_vma)); ++ if (readbytes <= 0) { ++ close(client_fd); ++ return -EINVAL; ++ } ++ ++ return client_fd; ++} ++ ++int sock_handle_respond(int client_fd, int result) ++{ ++ int writebytes; ++ char buff[RESP_MSG_MAX_LEN] = {0}; ++ ++ if (client_fd < 0) { ++ return -EINVAL; ++ } ++ ++ if (result == 0) { ++ snprintf(buff, sizeof(buff), "success"); ++ } else { ++ snprintf(buff, sizeof(buff), "failed"); ++ } ++ ++ writebytes = write(client_fd, buff, (strlen(buff) + 1)); ++ if (writebytes != (strlen(buff) + 1)) { ++ close(client_fd); ++ return -EIO; ++ } ++ ++ close(client_fd); ++ return 0; ++} +-- +2.27.0 + diff --git a/etmem.spec b/etmem.spec index b7bb4de..46752a8 100644 --- a/etmem.spec +++ b/etmem.spec @@ -53,7 +53,8 @@ Patch42: 0043-update-README.md.patch Patch43: 0044-etmem-cleancode.patch Patch44: 0045-add-dram_percent-to-etmem.patch Patch45: 0046-Fix-memory-leak-in-slide-engine.patch - +Patch46: 0047-move-all-the-files-to-sub-directory-of-etmem.patch +Patch47: 0048-Commit-new-features-memRouter-and-userswap-to-etmem.patch #Dependency BuildRequires: cmake gcc gcc-c++