* 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 <getopt.h>
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/capability.h>
#include <time.h>
#include <unistd.h>
#include <numa.h>
#include <numaif.h>
#include <errno.h>
#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 <policy file> [options]\n");
printf(" -p --policy <file> specify policy config file\n");
printf(" -s --socket <socket_path> 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 <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;
}