#define _GNU_SOURCE #include #include #include #include #include #include #include #define MNTPOINT "cpuacct_mnt" #define STACK_SIZE 1024*1024 #define NEW_ROOT "new_root" static char container_stack[STACK_SIZE] __attribute__((aligned(16))); struct test_args { unsigned long now; }; static int flag_ready = 0; void sigusr_handler(int signo) { flag_ready = 1; } static void setup(void) { int ret; SAFE_MKDIR(MNTPOINT, 0755); ret = system("mount | grep cpu | grep cpuacct | grep cpuset"); if (ret == 0) { SAFE_MOUNT("cpuset", MNTPOINT, "cgroup", MS_MGC_VAL, "cpuacct,cpu,cpuset"); } else { SAFE_MOUNT("cpuset", MNTPOINT, "cgroup", MS_MGC_VAL, "cpuset"); } SAFE_MKDIR(MNTPOINT "/testaaaa", 0755); SAFE_MKDIR(NEW_ROOT, 0755); SAFE_MKDIR(NEW_ROOT "/proc", 0755); } static void cleanup(void) { SAFE_UMOUNT(NEW_ROOT "/proc"); SAFE_RMDIR(NEW_ROOT "/proc"); SAFE_RMDIR(NEW_ROOT); SAFE_RMDIR(MNTPOINT "/testaaaa"); SAFE_UMOUNT(MNTPOINT); SAFE_RMDIR(MNTPOINT); } static int container_main(void *args) { int count = 0; int cpu_idx0; int wait_time = 5; int Hertz = sysconf(_SC_CLK_TCK); float uptime = 0.0; unsigned long btime = 0, start_time = 0, now; struct test_args *base = (struct test_args *) args; FILE *ptr; char buf[100]; while (!flag_ready) { usleep(100); } // wait a while, let uptime great than 0 sleep(wait_time); SAFE_MOUNT("proc", NEW_ROOT "/proc", "proc", MS_MGC_VAL, NULL); SAFE_FILE_LINES_SCANF(NEW_ROOT "/proc/uptime", "%f", &uptime); SAFE_FILE_LINES_SCANF(NEW_ROOT "/proc/stat", "btime %ld", &btime); SAFE_FILE_LINES_SCANF(NEW_ROOT "/proc/stat", "cpu%[^ ]", buf); cpu_idx0 = atoi(buf); ptr = fopen(NEW_ROOT "/proc/self/stat", "r"); if (ptr == NULL) { perror("fopen() error"); return 1; } while (fscanf(ptr, "%s", buf) != EOF) { count++; if (count == 22) break; } if (count == 22) start_time = atoi(buf) / Hertz; else printf("Failed to read pp->start_time from /proc/self/stat\n"); if (ptr != NULL) fclose(ptr); tst_res(TINFO, "[container] mypid: %d", getpid()); tst_res(TINFO, "[container] uptime: %.2f", uptime); if (uptime > wait_time - 1 && uptime < wait_time + 3) tst_res(TPASS, "correct /proc/uptime in container"); else tst_res(TFAIL, "incorrect /proc/uptime in container"); now = (unsigned long)time(NULL); tst_res(TINFO, "[container] btime: %ld", btime); tst_res(TINFO, "[container] now: %ld", now); tst_res(TINFO, "[host] now: %ld", base->now); if (btime > base->now && btime < now) tst_res(TPASS, "correct /proc/stat:btime in container"); else tst_res(TFAIL, "incorrect /proc/stat:btime in container"); tst_res(TINFO, "[container] process start_time: %ld", start_time); if (start_time <= 1) tst_res(TPASS, "correct process start_time (/proc/self/stat:22)" " in container"); else tst_res(TFAIL, "incorrect process start_time (/proc/self/stat:22)" " in container"); tst_res(TINFO, "[container] cpu_idx0: %d", cpu_idx0); if (cpu_idx0 == 0) tst_res(TPASS, "cpu index starts from 0 in container"); else tst_res(TFAIL, "cpu index doesn't start from 0 in container"); return 0; } static void do_test(void) { int cpid; int cpunum = sysconf(_SC_NPROCESSORS_ONLN); int clone_flags = CLONE_NEWPID | CLONE_NEWNS | SIGCHLD; struct test_args targs; char path[128]; if (cpunum < 2) { tst_brk(TCONF, "CPU number: %d", cpunum); } signal(SIGUSR1, sigusr_handler); targs.now = (unsigned long)time(NULL); sleep(2); cpid = ltp_clone(clone_flags, container_main, (void *)&targs, STACK_SIZE, container_stack); snprintf(path, sizeof(path), "%s/cpuset.mems", MNTPOINT "/testaaaa"); SAFE_FILE_PRINTF(path, "%d", 0); snprintf(path, sizeof(path), "%s/cpuset.cpus", MNTPOINT "/testaaaa"); SAFE_FILE_PRINTF(path, "%d", 1); snprintf(path, sizeof(path), "%s/tasks", MNTPOINT "/testaaaa"); SAFE_FILE_PRINTF(path, "%d", cpid); kill(cpid, SIGUSR1); waitpid(cpid, NULL, 0); } static struct tst_test test = { .test_all = do_test, .setup = setup, .cleanup = cleanup, .needs_root =1, .needs_tmpdir = 1, };