lxc/0010-Save-pid-ppid-info-into-file-for-isulad.patch

454 lines
14 KiB
Diff
Raw Normal View History

From 523b705fb269a9463b9412aa3a814a9c71a743cc Mon Sep 17 00:00:00 2001
2019-09-30 11:03:07 -04:00
From: LiFeng <lifeng68@huawei.com>
Date: Fri, 11 Jan 2019 22:53:56 -0500
Subject: [PATCH 010/140] Save pid/ppid info into file for isulad
2019-09-30 11:03:07 -04:00
Signed-off-by: LiFeng <lifeng68@huawei.com>
---
src/lxc/conf.c | 1 +
src/lxc/conf.h | 2 +
src/lxc/lxccontainer.c | 24 ++++++++++
2019-09-30 11:03:07 -04:00
src/lxc/lxccontainer.h | 10 ++++
src/lxc/start.c | 41 +++++++++++++++++
2019-09-30 11:03:07 -04:00
src/lxc/tools/arguments.h | 2 +
src/lxc/tools/lxc_start.c | 20 ++++++++
src/lxc/utils.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++
src/lxc/utils.h | 66 +++++++++++++++++++++++++++
2019-09-30 11:03:07 -04:00
9 files changed, 280 insertions(+)
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 7b7f95b..0b4b63b 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -4194,6 +4194,7 @@ void lxc_conf_free(struct lxc_conf *conf)
/* isulad add begin */
lxc_clear_init_args(conf);
lxc_clear_populate_devices(conf);
+ free(conf->container_info_file);
/* isulad add end */
free(conf);
}
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index cced868..e0954f9 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -403,6 +403,8 @@ struct lxc_conf {
size_t init_argc;
/* populate devices*/
struct lxc_list populate_devs;
+
+ char *container_info_file;
/* isulad add end */
};
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 318c71e..5679b9b 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -4988,6 +4988,29 @@ static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const
WRAP_API_2(bool, lxcapi_set_terminal_default_fifos, const char *, const char *)
+/* isulad add set info file path */
+static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const char *info_file)
+{
+ struct lxc_conf *conf;
+
+ if (!c || !c->lxc_conf || !info_file)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ conf = c->lxc_conf;
+ if (conf->container_info_file)
+ free(conf->container_info_file);
+ conf->container_info_file = strdup(info_file);
+
+ container_mem_unlock(c);
+ return true;
+}
+
+WRAP_API_1(bool, lxcapi_set_container_info_file, const char *)
+
struct lxc_container *lxc_container_new(const char *name, const char *configpath)
{
struct lxc_container *c;
@@ -5113,6 +5136,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
/* isulad add begin */
c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos;
+ c->set_container_info_file = lxcapi_set_container_info_file;
/* isulad add end */
return c;
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 486531e..3c845fe 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -857,6 +857,16 @@ struct lxc_container {
* \return \c true on success, else \c false.
*/
bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out);
+
+ /*! isulad add
+ * \brief An API call to set the path of info file
+ *
+ * \param c Container.
+ * \param info_file Value of the path of info file.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*set_container_info_file) (struct lxc_container *c, const char *info_file);
};
/*!
diff --git a/src/lxc/start.c b/src/lxc/start.c
index d64bdac..9d71dd7 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1553,6 +1553,39 @@ static inline int do_share_ns(void *arg)
return 0;
}
+/* isuald: save pid/ppid info */
+static int lxc_save_container_info(char *filename, pid_t pid)
+{
+ FILE *pid_fp = NULL;
+ int ret = 0;
+ pid_t p_pid = 0;
+ unsigned long long start_at = 0;
+ unsigned long long p_start_at = 0;
+
+ pid_fp = fopen(filename, "w");
+ if (pid_fp == NULL) {
+ SYSERROR("Failed to create pidfile '%s'",filename);
+ ret = -1;
+ goto out;
+ }
+
+ start_at = lxc_get_process_startat(pid);
+
+ p_pid = getpid();
+ p_start_at = lxc_get_process_startat(p_pid);
+
+ if (fprintf(pid_fp, "%d %llu %d %llu\n", pid, start_at, p_pid, p_start_at) < 0) {
+ SYSERROR("Failed to write '%s'", filename);
+ ret = -1;
+ goto out;
+ }
+out:
+ if (pid_fp)
+ fclose(pid_fp);
+ pid_fp = NULL;
+ return ret;
+}
+
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which
* exec()s the requested container binary.
* Note that lxc_spawn() runs in the parent namespaces. Any operations performed
@@ -1683,6 +1716,14 @@ static int lxc_spawn(struct lxc_handler *handler)
}
TRACE("Cloned child process %d", handler->pid);
+ /* isulad: save pid/ppid info into file*/
+ if (handler->conf->container_info_file) {
+ if (lxc_save_container_info(handler->conf->container_info_file, handler->pid)) {
+ ERROR("Failed to save cloned container pid");
+ goto out_delete_net;
+ }
+ }
+
for (i = 0; i < LXC_NS_MAX; i++)
if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
INFO("Cloned %s", ns_info[i].flag_name);
diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h
index b7af2b5..b6df23f 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/tools/arguments.h
+++ b/src/lxc/tools/arguments.h
@@ -63,6 +63,7 @@ struct lxc_arguments {
/* for lxc-start */
const char *share_ns[32]; /* size must be greater than LXC_NS_MAX */
const char *terminal_fifos[2]; /* isulad add, fifos used to redirct stdin/out/err */
+ const char *container_info; /* isulad: file used to store pid and ppid info of container */
/* for lxc-console */
unsigned int ttynum;
@@ -176,6 +177,7 @@ struct lxc_arguments {
/* isulad add begin */
#define OPT_INPUT_FIFO OPT_USAGE - 7
#define OPT_OUTPUT_FIFO OPT_USAGE - 8
+#define OPT_CONTAINER_INFO OPT_USAGE - 9
/* isulad add end*/
extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index 8f03f11..2f94d67 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -69,8 +69,11 @@ static const struct option my_longopts[] = {
{"share-ipc", required_argument, 0, OPT_SHARE_IPC},
{"share-uts", required_argument, 0, OPT_SHARE_UTS},
{"share-pid", required_argument, 0, OPT_SHARE_PID},
+ /* isulad add begin */
{"in-fifo", required_argument, 0, OPT_INPUT_FIFO},
{"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO},
+ {"container-pidfile", required_argument, 0, OPT_CONTAINER_INFO},
+ /* isulad add end */
LXC_COMMON_OPTIONS
};
@@ -148,6 +151,9 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
case OPT_OUTPUT_FIFO:
args->terminal_fifos[1] = arg;
break;
+ case OPT_CONTAINER_INFO:
+ args->container_info = arg;
+ break;
}
return 0;
}
@@ -189,6 +195,7 @@ int main(int argc, char *argv[])
struct lxc_log log;
int err = EXIT_FAILURE;
char *rcfile = NULL;
+ char *container_info_file = NULL; /* isulad: info file*/
char *const default_args[] = {
"/sbin/init",
NULL,
@@ -313,6 +320,18 @@ int main(int argc, char *argv[])
goto out;
}
+ /* isulad: container info file used to store pid and ppid info of container*/
+ if (my_args.container_info != NULL) {
+ if (ensure_path(&container_info_file, my_args.container_info) < 0) {
+ ERROR("Failed to ensure container's piddile '%s'", my_args.container_info);
+ goto out;
+ }
+ if (!c->set_container_info_file(c, container_info_file)) {
+ ERROR("Failed to set container's piddile '%s'", container_info_file);
+ goto out;
+ }
+ }
+
if (my_args.console)
if (!c->set_config_item(c, "lxc.console.path", my_args.console))
goto out;
@@ -353,5 +372,6 @@ int main(int argc, char *argv[])
out:
lxc_container_put(c);
+ free(container_info_file);
exit(err);
}
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 67c3b3e..4728284 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1828,3 +1828,117 @@ int lxc_setup_keyring(void)
return ret;
}
+
+/* isulad: read file to buffer */
+static int lxc_file2str(const char *filename, char ret[], int cap)
+{
+ int fd, num_read;
+
+ if ((fd = open(filename, O_RDONLY | O_CLOEXEC)) == -1)
+ return -1;/*lint !e960*/
+ if ((num_read = read(fd, ret, cap - 1)) <= 0)
+ num_read = -1;/*lint !e960*/
+ else
+ ret[num_read] = 0;/*lint !e613*//*lint !e960*/
+ close(fd);
+
+ return num_read;
+}
+
+/* isuald: lxc_stat2proc() makes sure it can handle arbitrary executable file basenames
+ * for `cmd', i.e. those with embedded whitespace or embedded ')'s.
+ * Such names confuse %s (see scanf(3)), so the string is split and %39c
+ * is used instead. (except for embedded ')' "(%[^)]c)" would work.
+ */
+static proc_t *lxc_stat2proc(char *S)
+{
+ int num;
+ proc_t *P = NULL;
+ char *tmp = NULL;
+
+ if (!S)
+ return NULL;/*lint !e960*/
+
+ tmp = strrchr(S, ')'); /* split into "PID (cmd" and "<rest>" *//*lint !e586*/
+ if (!tmp)
+ return NULL;/*lint !e960*/
+ *tmp = '\0'; /* replace trailing ')' with NUL */
+
+ P = malloc(sizeof(proc_t));
+ if (!P)
+ return NULL;/*lint !e960*/
+ memset(P, 0x00, sizeof(proc_t));
+
+ /* parse these two strings separately, skipping the leading "(". */
+ num = sscanf(S, "%d (%15c", &P->pid, P->cmd); /* comm[16] in kernel */
+ if (num < 0 && errno) {
+ ERROR("Call sscanf error: %s", strerror(errno));
+ free(P);
+ return NULL;
+ }
+ num = sscanf(tmp + 2, /* skip space after ')' too */
+ "%c "
+ "%d %d %d %d %d "
+ "%lu %lu %lu %lu %lu "
+ "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime *//*lint !e566*/
+ "%ld %ld %ld %ld "
+ "%Lu " /* start_time *//*lint !e566*/
+ "%lu "
+ "%ld "
+ "%lu %lu %lu %lu %lu %lu "
+ "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */
+ "%lu %lu %lu "
+ "%d %d "
+ "%lu %lu",
+ &P->state,
+ &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid,
+ &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt,
+ &P->utime, &P->stime, &P->cutime, &P->cstime,/*lint !e561*/
+ &P->priority, &P->nice, &P->timeout, &P->it_real_value,
+ &P->start_time,/*lint !e561*/
+ &P->vsize,
+ &P->rss,
+ &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp,
+ &P->kstk_eip,
+ &P->wchan, &P->nswap, &P->cnswap,
+ &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */
+ &P->rtprio, &P->sched /* both added to 2.5.18 */
+ );
+
+ if (P->tty == 0)
+ P->tty = -1; /* the old notty val, update elsewhere bef. moving to 0 *//*lint !e960*/
+ return P;
+}
+
+/* isulad: get starttime of process pid */
+unsigned long long lxc_get_process_startat(pid_t pid)
+{
+ int sret = 0;
+ unsigned long long startat = 0;
+ proc_t *pid_info = NULL;
+ char filename[PATH_MAX] = {0};
+ char sbuf[1024] = {0}; /* bufs for stat */
+
+ sret = snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
+ if (sret < 0 || sret >= sizeof(filename)) {/*lint !e574*/
+ ERROR("Failed to sprintf filename");
+ goto out;
+ }
+
+ if ((lxc_file2str(filename, sbuf, sizeof(sbuf))) == -1) {
+ SYSERROR("Failed to read pidfile %s", filename);
+ goto out;
+ }
+
+ pid_info = lxc_stat2proc(sbuf);
+ if (!pid_info) {/*lint !e574*/
+ ERROR("Failed to get proc stat info");
+ goto out;
+ }
+
+ startat = pid_info->start_time;
+out:
+ free(pid_info);
+ return startat;
+}
+
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 2d38178..8e4ed89 100644
2019-09-30 11:03:07 -04:00
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -56,6 +56,71 @@ extern char *get_rundir(void);
#endif
#endif
+/* isuald:
+ ld cutime, cstime, priority, nice, timeout, it_real_value, rss,
+ c state,
+ d ppid, pgrp, session, tty, tpgid,
+ s signal, blocked, sigignore, sigcatch,
+ lu flags, min_flt, cmin_flt, maj_flt, cmaj_flt, utime, stime,
+ lu rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip,
+ lu start_time, vsize, wchan, nswap, cnswap,
+*/
+
+/* Basic data structure which holds all information we can get about a process.
+ * (unless otherwise specified, fields are read from /proc/#/stat)
+ *
+ * Most of it comes from task_struct in linux/sched.h
+ */
+typedef struct proc_t {
+ // 1st 16 bytes
+ int pid; /* process id */
+ int ppid; /* pid of parent process */
+
+ char state; /* single-char code for process state (S=sleeping) */
+
+ unsigned long long
+ utime, /* user-mode CPU time accumulated by process */
+ stime, /* kernel-mode CPU time accumulated by process */
+ // and so on...
+ cutime, /* cumulative utime of process and reaped children */
+ cstime, /* cumulative stime of process and reaped children */
+ start_time; /* start time of process -- seconds since 1-1-70 */
+
+ long
+ priority, /* kernel scheduling priority */
+ timeout, /* ? */
+ nice, /* standard unix nice level of process */
+ rss, /* resident set size from /proc/#/stat (pages) */
+ it_real_value; /* ? */
+ unsigned long
+ rtprio, /* real-time priority */
+ sched, /* scheduling class */
+ vsize, /* number of pages of virtual memory ... */
+ rss_rlim, /* resident set size limit? */
+ flags, /* kernel flags for the process */
+ min_flt, /* number of minor page faults since process start */
+ maj_flt, /* number of major page faults since process start */
+ cmin_flt, /* cumulative min_flt of process and child processes */
+ cmaj_flt, /* cumulative maj_flt of process and child processes */
+ nswap, /* ? */
+ cnswap, /* cumulative nswap ? */
+ start_code, /* address of beginning of code segment */
+ end_code, /* address of end of code segment */
+ start_stack, /* address of the bottom of stack for the process */
+ kstk_esp, /* kernel stack pointer */
+ kstk_eip, /* kernel instruction pointer */
+ wchan; /* address of kernel wait channel proc is sleeping in */
+
+ char cmd[16]; /* basename of executable file in call to exec(2) */
+ int
+ pgrp, /* process group id */
+ session, /* session id */
+ tty, /* full device number of controlling terminal */
+ tpgid, /* terminal process group id */
+ exit_signal, /* might not be SIGCHLD */
+ processor; /* current (or most recent?) CPU */
+} proc_t;
+
static inline int lxc_set_cloexec(int fd)
{
return fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -245,5 +310,6 @@ extern int recursive_destroy(char *dirname);
extern int lxc_setup_keyring(void);
extern int fd_nonblock(int fd);
+extern int unsigned long long lxc_get_process_startat(pid_t pid);
#endif /* __LXC_UTILS_H */
--
1.8.3.1
2019-09-30 11:03:07 -04:00