diff --git a/fork/_lxc_fork b/fork/_lxc_fork new file mode 100755 index 00000000..a1a0c77b Binary files /dev/null and b/fork/_lxc_fork differ diff --git a/fork/_lxc_fork.c b/fork/_lxc_fork.c new file mode 100644 index 00000000..70aecc20 --- /dev/null +++ b/fork/_lxc_fork.c @@ -0,0 +1,96 @@ +#include +#include +#include + +#include +#include +#include + + +#include +#include +#include "lxc_fork.h" + +/* + * _lxc_fork: fork the process set of lxc container "orig" + * orig: forked container name + */ +int main(int argc, char *argv[]) +{ + char *orig; + char buf[64] = { '\0' }; + pid_t init_pid; + int fd, ret, len; + int test = 0; + char c; + int i = 0; + FILE *f; + struct timeval time; + unsigned long start, end; //milliseconds + + lf_debug("This is for debug lxc_start new container: %s.\n", argv[1]); + + //get initial pid of original contianer by get_init_pid + orig = argv[1]; + //init_pid = get_init_pid(orig); + /* + * Since we can't use get_init_pid to read the initial process pid of + * original contianer, read from file first :( + */ + printf("Please input the initial pid of original container %s.\n", orig); + if (test) + f = fopen("./pid.txt", "r+"); + else + f = fopen("/root/pid.txt", "r+"); + if (f == NULL) { + lf_debug("Can't find pid file.\n"); + return -1; + } + /* + while ((c = fgetc(f)) != ' ') { + buf[i++] = c; + } + */ + if (fgets(buf, 64, f) == NULL) { + lf_debug("Can't get initial pid, exit.\n"); + return 1; + } + fclose(f); + + init_pid = atol(buf); + if (argc > 2) { + init_pid = atol(argv[2]); + } + + lf_debug("Get inital pid of original container %s : %d\n", orig, init_pid); + + if (init_pid < 0) { + lf_debug("failed to get the initial pid of original container.\n"); + return -1; + } + //len = sprintf(buf, "echo \"fork %d\" > /proc/cgroups", init_pid); + len = sprintf(buf, "fork %d", init_pid); + lf_debug("echo cmd: %s\n", buf); + //system(buf); + //write "fork orig-container" to /proc/cgroups for call __lxc_fork in kernel + ///* + fd = open("/proc/cgroups", O_WRONLY); + if (fd < 0) { + lf_debug("failed to open cgroup for lxc-fork.\n"); + return -1; + } + //before we call lxc fork in kernel + gettimeofday(&time, NULL); + start = time.tv_sec * 1000 + time.tv_usec / 1000; + + ret = write(fd, buf, len + 1); + + //after lxc fork done + gettimeofday(&time, NULL); + end = time.tv_sec * 1000 + time.tv_usec / 1000; + printf("The time of lxc fork without fs copy: %ld ms\n", end - start); + + close(fd); + //*/ + return 0; +} diff --git a/fork/log.h b/fork/log.h new file mode 100644 index 00000000..b11093d1 --- /dev/null +++ b/fork/log.h @@ -0,0 +1,294 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * Cedric Le Goater + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _log_h +#define _log_h + +#include +#include +#include +#include + +#ifndef O_CLOEXEC +#define O_CLOEXEC 02000000 +#endif + +#ifndef F_DUPFD_CLOEXEC +#define F_DUPFD_CLOEXEC 1030 +#endif + +#define LXC_LOG_PREFIX_SIZE 32 +#define LXC_LOG_BUFFER_SIZE 512 + +/* predefined priorities. */ +enum { + LXC_LOG_PRIORITY_TRACE, + LXC_LOG_PRIORITY_DEBUG, + LXC_LOG_PRIORITY_INFO, + LXC_LOG_PRIORITY_NOTICE, + LXC_LOG_PRIORITY_WARN, + LXC_LOG_PRIORITY_ERROR, + LXC_LOG_PRIORITY_CRIT, + LXC_LOG_PRIORITY_ALERT, + LXC_LOG_PRIORITY_FATAL, + LXC_LOG_PRIORITY_NOTSET, +}; + +/* location information of the logging event */ +struct lxc_log_locinfo { + const char *file; + const char *func; + int line; +}; + +#define LXC_LOG_LOCINFO_INIT \ + { .file = __FILE__, .func = __func__, .line = __LINE__ } + +/* brief logging event object */ +struct lxc_log_event { + const char* category; + int priority; + struct timeval timestamp; + struct lxc_log_locinfo *locinfo; + const char *fmt; + va_list *vap; +}; + +/* log appender object */ +struct lxc_log_appender { + const char* name; + int (*append)(const struct lxc_log_appender *, struct lxc_log_event *); + + /* + * appenders can be stacked + */ + struct lxc_log_appender *next; +}; + +/* log category object */ +struct lxc_log_category { + const char *name; + int priority; + struct lxc_log_appender *appender; + const struct lxc_log_category *parent; +}; + +/* + * Returns true if the chained priority is equal to or higher than + * given priority. + */ +static inline int +lxc_log_priority_is_enabled(const struct lxc_log_category* category, + int priority) +{ + while (category->priority == LXC_LOG_PRIORITY_NOTSET && + category->parent) + category = category->parent; + + return priority >= category->priority; +} + +/* + * converts a priority to a literal string + */ +static inline const char* lxc_log_priority_to_string(int priority) +{ + switch (priority) { + case LXC_LOG_PRIORITY_TRACE: return "TRACE"; + case LXC_LOG_PRIORITY_DEBUG: return "DEBUG"; + case LXC_LOG_PRIORITY_INFO: return "INFO"; + case LXC_LOG_PRIORITY_NOTICE: return "NOTICE"; + case LXC_LOG_PRIORITY_WARN: return "WARN"; + case LXC_LOG_PRIORITY_ERROR: return "ERROR"; + case LXC_LOG_PRIORITY_CRIT: return "CRIT"; + case LXC_LOG_PRIORITY_ALERT: return "ALERT"; + case LXC_LOG_PRIORITY_FATAL: return "FATAL"; + default: + return "NOTSET"; + } +} +/* + * converts a literal priority to an int + */ +static inline int lxc_log_priority_to_int(const char* name) +{ + if (!strcasecmp("TRACE", name)) return LXC_LOG_PRIORITY_TRACE; + if (!strcasecmp("DEBUG", name)) return LXC_LOG_PRIORITY_DEBUG; + if (!strcasecmp("INFO", name)) return LXC_LOG_PRIORITY_INFO; + if (!strcasecmp("NOTICE", name)) return LXC_LOG_PRIORITY_NOTICE; + if (!strcasecmp("WARN", name)) return LXC_LOG_PRIORITY_WARN; + if (!strcasecmp("ERROR", name)) return LXC_LOG_PRIORITY_ERROR; + if (!strcasecmp("CRIT", name)) return LXC_LOG_PRIORITY_CRIT; + if (!strcasecmp("ALERT", name)) return LXC_LOG_PRIORITY_ALERT; + if (!strcasecmp("FATAL", name)) return LXC_LOG_PRIORITY_FATAL; + + return LXC_LOG_PRIORITY_NOTSET; +} + +static inline void +__lxc_log_append(const struct lxc_log_appender *appender, + struct lxc_log_event* event) +{ + va_list va, *va_keep; + va_keep = event->vap; + + while (appender) { + va_copy(va, *va_keep); + event->vap = &va; + appender->append(appender, event); + appender = appender->next; + va_end(va); + } +} + +static inline void +__lxc_log(const struct lxc_log_category* category, + struct lxc_log_event* event) +{ + while (category) { + __lxc_log_append(category->appender, event); + category = category->parent; + } +} + +/* + * Helper macro to define log fonctions. + */ +#define lxc_log_priority_define(acategory, PRIORITY) \ + \ +static inline void LXC_##PRIORITY(struct lxc_log_locinfo *, \ + const char *, ...) __attribute__ ((format (printf, 2, 3))); \ + \ +static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \ + const char* format, ...) \ +{ \ + if (lxc_log_priority_is_enabled(acategory, \ + LXC_LOG_PRIORITY_##PRIORITY)) { \ + struct lxc_log_event evt = { \ + .category = (acategory)->name, \ + .priority = LXC_LOG_PRIORITY_##PRIORITY, \ + .fmt = format, \ + .locinfo = locinfo \ + }; \ + va_list va_ref; \ + \ + gettimeofday(&evt.timestamp, NULL); \ + \ + va_start(va_ref, format); \ + evt.vap = &va_ref; \ + __lxc_log(acategory, &evt); \ + va_end(va_ref); \ + } \ +} + +/* + * Helper macro to define and use static categories. + */ +#define lxc_log_category_define(name, parent) \ + extern struct lxc_log_category lxc_log_category_##parent; \ + struct lxc_log_category lxc_log_category_##name = { \ + #name, \ + LXC_LOG_PRIORITY_NOTSET, \ + NULL, \ + &lxc_log_category_##parent \ + }; + +#define lxc_log_define(name, parent) \ + lxc_log_category_define(name, parent) \ + \ + lxc_log_priority_define(&lxc_log_category_##name, TRACE) \ + lxc_log_priority_define(&lxc_log_category_##name, DEBUG) \ + lxc_log_priority_define(&lxc_log_category_##name, INFO) \ + lxc_log_priority_define(&lxc_log_category_##name, NOTICE) \ + lxc_log_priority_define(&lxc_log_category_##name, WARN) \ + lxc_log_priority_define(&lxc_log_category_##name, ERROR) \ + lxc_log_priority_define(&lxc_log_category_##name, CRIT) \ + lxc_log_priority_define(&lxc_log_category_##name, ALERT) \ + lxc_log_priority_define(&lxc_log_category_##name, FATAL) + +#define lxc_log_category_priority(name) \ + (lxc_log_priority_to_string(lxc_log_category_##name.priority)) + +/* + * top categories + */ +extern struct lxc_log_category lxc_log_category_lxc; + +#define TRACE(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_TRACE(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + +#define DEBUG(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_DEBUG(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + +#define INFO(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_INFO(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + +#define NOTICE(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_NOTICE(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + +#define WARN(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_WARN(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + +#define ERROR(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_ERROR(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + +#define CRIT(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_CRIT(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + +#define ALERT(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_ALERT(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + +#define FATAL(format, ...) do { \ + struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ + LXC_FATAL(&locinfo, format, ##__VA_ARGS__); \ +} while (0) + + + +#define SYSERROR(format, ...) do { \ + ERROR("%s - " format, strerror(errno), ##__VA_ARGS__); \ +} while (0) + +extern int lxc_log_fd; + +extern int lxc_log_init(const char *file, const char *priority, + const char *prefix, int quiet); + +extern void lxc_log_setprefix(const char *a_prefix); +#endif diff --git a/fork/lxc-app2.c b/fork/lxc-app2.c new file mode 100644 index 00000000..ea66afbb --- /dev/null +++ b/fork/lxc-app2.c @@ -0,0 +1,19 @@ +/* + * Simple application running in the container. + */ + +#include +#include +#include +#include + +int main() { + unsigned int slot = 0; + //say something to prove i am live + while (1) { + printf("I am process %d from process %d, Now it's %d.\n", + getpid(), getppid(), slot); + slot++; + sleep(10); + } +} diff --git a/fork/lxc-app3.c b/fork/lxc-app3.c new file mode 100644 index 00000000..14667fd7 --- /dev/null +++ b/fork/lxc-app3.c @@ -0,0 +1,37 @@ +/* + * lxc test app 3: + * open a file and write some information into it continuously + */ + +#include +#include +#include +#include + +int main() +{ + unsigned int time = 0; + int len = 0; + FILE *f = fopen("./pid.me", "w+"); + + if (!f) { + printf("open pid.me file failed, exit.\n"); + return -1; + } + + while (1) { + len = fprintf(f, "I'm process %d from process %d, i'm %d seconds old\n", + getpid(), getppid(), time * 10); + if (!len) { + printf("Something wrong, write to file 0 bytes.\n"); + return -2; + } else { + printf("I'm process %d from process %d, i'm %d seconds old\n", + getpid(), getppid(), time * 10); + //fclose(f); + fflush(f); + } + time++; + sleep(10); + } +} diff --git a/fork/lxc-app4 b/fork/lxc-app4 new file mode 100755 index 00000000..240d5254 Binary files /dev/null and b/fork/lxc-app4 differ diff --git a/fork/lxc-app4.c b/fork/lxc-app4.c new file mode 100644 index 00000000..3d0b8bed --- /dev/null +++ b/fork/lxc-app4.c @@ -0,0 +1,170 @@ +/* + * lxc test app4: + * test parent-child/brother relationship between processes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SLEEPTIME 20 + +/* + * root + * / \ + * child1 child2 + * / \ \ + * grandson1 grandson2 grandson3 + * | + * grand - grand son + */ + +void multiprocesses() { + int i; + pid_t child; + char space[16] = { '\0' }; + unsigned int slot = 0; + + if ((child = fork()) == 0) { //child + space[0] = '-'; + goto loop; + } + + if ((child = fork()) == 0) { //second child + space[0] = '-'; + for (i = 0; i < 3; i++) { + if ((child = fork()) == 0) { + space[1] = '-'; + if (i == 1) + if (fork() == 0) + space[2] = '-'; + goto loop; + } + } + } + + loop: + while (1) { + printf("%sI am process %d from process %d, Now it's %d.\n", + space, getpid(), getppid(), slot); + slot++; + sleep(SLEEPTIME); + } +} + +/* + * lxc fork mmap test function + */ +int lxc_mmap() +{ + int fd = -1; + void *map = NULL; + char *ptr; + size_t length = 8192 * 5; + off_t off = 0; + size_t wsize; + unsigned long slot = 0; + mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO; + //S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWGRP | S_IWOTH; + + fd = open("./mmap.file", O_RDWR | O_CREAT, mode); + if (fd == -1) { + printf("open mmap file failed.\n"); + return -1; + } + + //Make the file big enough + lseek (fd, length + 1, SEEK_SET); + write (fd, "*\n", 2); + lseek (fd, 0, SEEK_SET); + + map = mmap(NULL, length, PROT_WRITE | PROT_READ, MAP_SHARED, fd, off); + + if (!map) { + close(fd); + printf("map file failed.\n"); + return -2; + } + ptr = (char *)map; + while (1) { + wsize = sprintf(ptr, "I am process %d from process %d, Now it's %ld\n", + getpid(), getppid(), slot); + printf("---I am process %d from process %d, Now it's %ld\n", + getpid(), getppid(), slot); + slot++; + sleep(SLEEPTIME); + ptr += wsize; + } + sync(); + munmap(map, length); + return 0; +} + +int lxc_mpmap() +{ + int i; + pid_t child; + char space[16] = { '\0' }; + unsigned int slot = 0; + + if ((child = fork()) == 0) { //child + space[0] = '-'; + goto loop; + } + + if ((child = fork()) == 0) { //second child + space[0] = '-'; + for (i = 0; i < 3; i++) { + if ((child = fork()) == 0) { + space[1] = '-'; + if (i == 1) + if (fork() == 0) { + //space[2] = '-'; + lxc_mmap(); + return 0; + } + goto loop; + } + } + } + + loop: + while (1) { + printf("%sI am process %d from process %d, Now it's %d.\n", + space, getpid(), getppid(), slot); + slot++; + sleep(SLEEPTIME); + } +} + +int main(int argc, char *argv[]) { + int type = 0; + + if (argc > 1) { + type = atol(argv[1]); + } + + switch (type) { + case 0: //print + break; + case 1: //write file + break; + case 2: //multiple process + multiprocesses(); + break; + case 3: //mmap + lxc_mmap(); + break; + case 4: //mp + mmap + lxc_mpmap(); + break; + default: + break; + } + return 0; +} diff --git a/fork/lxc_fork b/fork/lxc_fork new file mode 100755 index 00000000..dd664e1c Binary files /dev/null and b/fork/lxc_fork differ diff --git a/fork/lxc_fork.c b/fork/lxc_fork.c new file mode 100644 index 00000000..efe181af --- /dev/null +++ b/fork/lxc_fork.c @@ -0,0 +1,88 @@ +/* + * lxc: linux Container library + * lxc_fork: fork a exsiting container by COW + * First line of code added at 20120320 by Jin Chen + */ + +#include +#include +#include + +#include "lxc_fork.h" +#include "log.h" + +int main(int argc, char *argv[]) +{ + int opt, ret; + char *orig, *new, *pidbuf; + char clonecmd[256] = { 0 }; + char startcmd[256] = { 0 }; + char cpcmd[256] = { 0 }; + char freezecmd[256] = { 0 }; + char *rcfile = NULL; + struct lxc_conf *conf = NULL; + + //parse the arguments + while ((opt = getopt(argc, argv, "o:n:p:")) != -1) { + switch (opt) { + case 'o': + //FIXME: we need to do string boundary check to avoid buffer overflow ! + orig = optarg; + break; + case 'n': + new = optarg; + break; + case 'p': + pidbuf = optarg; + break; + default: /* ? */ + printf("unrecognized argu: %s.\n", optarg); + break; + } + } + lf_debug("Parse argument, old container name: %s, new name: %s, pid: %s.\n", + orig, new, pidbuf); + + //freeze the original container first, + // maybe we need to flush in-memory dirty data to disk before lxc-clone + sprintf(freezecmd, "lxc-freeze -n %s", orig); + lf_debug("freeze original container: %s.\n", freezecmd); + ret = system(freezecmd); + + //copy lxc container config by lxc-clone + sprintf(clonecmd, "lxc-clone -o %s -n %s", orig, new); + lf_debug("clone command: %s.\n", clonecmd); + + ret = system(clonecmd); + if (ret == -1) { + printf("lxc clone error: %d, exit now.\n", ret); + return ret; + } + + //check if the new lxc files exist, config, fstab, file system + ret = asprintf(&rcfile, LXC_PATH "/%s/config", new); + if (ret == -1) { + lf_debug("failed to allocate memory"); + return ret; + } + + if (access(rcfile, F_OK)) { + free(rcfile); + rcfile = NULL; + lf_debug("failed to find the config file %s", rcfile); + return -1; + } + + sprintf(cpcmd, "cp ./_lxc_fork ./pid.txt /var/lib/lxc/%s/rootfs/root/", new); + //copy binary to root directory at new container + system(cpcmd); + + //initial new lxc contianer + sprintf(startcmd, "lxc-start -n %s /root/_lxc_fork %s %s", new, orig, pidbuf); + ret = system(startcmd); + + //unfreeze original contianer + sprintf(freezecmd, "lxc-unfreeze -n %s", orig); + ret = system(freezecmd); + return 0; +} diff --git a/fork/lxc_fork.h b/fork/lxc_fork.h new file mode 100644 index 00000000..4c4e2516 --- /dev/null +++ b/fork/lxc_fork.h @@ -0,0 +1,14 @@ +#ifndef __LXC_FORK_H__ +#define __LXC_FORK_H__ + +#define LF_DEBUG + +#ifdef LF_DEBUG +#define lf_debug(fmt, args...) printf("%s%s:%d "fmt, "[D]", __FILE__, __LINE__, ##args) +#else +#define lf_debug(fmt, args...) +#endif + +#define LXC_PATH "/var/lib/lxc" + +#endif /* __LXC_FORK_H__ */ diff --git a/fork/make.sh b/fork/make.sh new file mode 100755 index 00000000..ceb39e5e --- /dev/null +++ b/fork/make.sh @@ -0,0 +1,3 @@ +gcc -o lxc-app4 lxc-app4.c +gcc -o lxc_fork lxc_fork.c +gcc -o _lxc_fork _lxc_fork.c diff --git a/fork/mmap.file b/fork/mmap.file new file mode 100755 index 00000000..c2e3fdf9 Binary files /dev/null and b/fork/mmap.file differ diff --git a/fork/pid.txt b/fork/pid.txt new file mode 100644 index 00000000..0ece43ab --- /dev/null +++ b/fork/pid.txt @@ -0,0 +1 @@ +2756 diff --git a/fs/file.c b/fs/file.c index 88db5a4c..43d1b759 100644 --- a/fs/file.c +++ b/fs/file.c @@ -357,6 +357,7 @@ struct file *lxc_find_new_file(struct file *old_file, struct task_struct *tsk, */ #include extern int aa_get_name(struct path *path, int flags, char **buffer, const char **name); +extern void show_sock_info(void *); struct files_struct *deep_dup_fd(struct files_struct *oldf, struct files_struct *parentf, int *errorp, struct task_struct *tsk, struct task_struct *otsk, @@ -554,9 +555,11 @@ struct files_struct *deep_dup_fd(struct files_struct *oldf, struct files_struct } break; } - case S_IFSOCK: //socket - printk("[%d] socket file.\n", open_files - i); + case S_IFSOCK: {//socket + printk("[%d]socket: ", open_files - i); + show_sock_info(of->private_data); break; + } default: //unknown type printk("[%d] unknown file i_mode: 0%o[0x%x].\n", open_files - i, i_mode, i_mode); diff --git a/net/socket.c b/net/socket.c index 1ad42d36..9310750f 100644 --- a/net/socket.c +++ b/net/socket.c @@ -3382,3 +3382,21 @@ int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) return sock->ops->shutdown(sock, how); } EXPORT_SYMBOL(kernel_sock_shutdown); + +/* + * cj-hack @ April-29-2012 + * print socket related information, family, type, protocol, address.... + */ +#include +void show_sock_info(void *sockp) +{ + struct socket *sock = (struct socket *)sockp; + struct sock *sk = sock->sk; + printk("family:%d, type:%d, protocol:%d.\n", + sk->sk_family, sk->sk_type, sk->sk_protocol); + if (sk->sk_family == AF_INET) { + struct inet_sock *inet = (struct inet_sock *)sk; + printk("\t\tport=%x\n", inet->inet_sport); + } +} +EXPORT_SYMBOL(show_sock_info);