]> git.proxmox.com Git - mirror_lxcfs.git/blobdiff - bindings.c
Merge pull request #182 from brauner/2017-05-16/pam_cgv2_improvements
[mirror_lxcfs.git] / bindings.c
index e116ff63ecc4d8491e0d93db683d4bb1cf912144..5b5860e73a889579baaaa618613e345854708e14 100644 (file)
@@ -72,8 +72,8 @@ struct file_info {
        int cached;
 };
 
-/* reserve buffer size, for cpuall in /proc/stat */
-#define BUF_RESERVE_SIZE 256
+/* Reserve buffer size to account for file size changes. */
+#define BUF_RESERVE_SIZE 512
 
 /*
  * A table caching which pid is init for a pid namespace.
@@ -3454,6 +3454,28 @@ err:
        return rv;
 }
 
+static long int getreaperctime(pid_t pid)
+{
+       char fnam[100];
+       struct stat sb;
+       int ret;
+       pid_t qpid;
+
+       qpid = lookup_initpid_in_store(pid);
+       if (qpid <= 0)
+               return 0;
+
+       ret = snprintf(fnam, 100, "/proc/%d", qpid);
+       if (ret < 0 || ret >= 100)
+               return 0;
+
+       if (lstat(fnam, &sb) < 0)
+               return 0;
+
+       return sb.st_ctime;
+}
+
+#define CPUALL_MAX_SIZE (BUF_RESERVE_SIZE / 2)
 static int proc_stat_read(char *buf, size_t size, off_t offset,
                struct fuse_file_info *fi)
 {
@@ -3464,10 +3486,9 @@ static int proc_stat_read(char *buf, size_t size, off_t offset,
        char *line = NULL;
        size_t linelen = 0, total_len = 0, rv = 0;
        int curcpu = -1; /* cpu numbering starts at 0 */
-       unsigned long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0;
+       unsigned long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0;
        unsigned long user_sum = 0, nice_sum = 0, system_sum = 0, idle_sum = 0, iowait_sum = 0,
-                                       irq_sum = 0, softirq_sum = 0, steal_sum = 0, guest_sum = 0;
-#define CPUALL_MAX_SIZE BUF_RESERVE_SIZE
+                                       irq_sum = 0, softirq_sum = 0, steal_sum = 0, guest_sum = 0, guest_nice_sum = 0;
        char cpuall[CPUALL_MAX_SIZE];
        /* reserve for cpu all */
        char *cache = d->buf + CPUALL_MAX_SIZE;
@@ -3517,7 +3538,10 @@ static int proc_stat_read(char *buf, size_t size, off_t offset,
                        continue;
                if (sscanf(line, "cpu%9[^ ]", cpu_char) != 1) {
                        /* not a ^cpuN line containing a number N, just print it */
-                       l = snprintf(cache, cache_size, "%s", line);
+                       if (strncmp(line, "btime", 5) == 0)
+                               l = snprintf(cache, cache_size, "btime %ld\n", getreaperctime(fc->pid));
+                       else
+                               l = snprintf(cache, cache_size, "%s", line);
                        if (l < 0) {
                                perror("Error writing to cache");
                                rv = 0;
@@ -3560,8 +3584,17 @@ static int proc_stat_read(char *buf, size_t size, off_t offset,
                cache_size -= l;
                total_len += l;
 
-               if (sscanf(line, "%*s %lu %lu %lu %lu %lu %lu %lu %lu %lu", &user, &nice, &system, &idle, &iowait, &irq,
-                       &softirq, &steal, &guest) != 9)
+               if (sscanf(line, "%*s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+                          &user,
+                          &nice,
+                          &system,
+                          &idle,
+                          &iowait,
+                          &irq,
+                          &softirq,
+                          &steal,
+                          &guest,
+                          &guest_nice) != 10)
                        continue;
                user_sum += user;
                nice_sum += nice;
@@ -3572,16 +3605,26 @@ static int proc_stat_read(char *buf, size_t size, off_t offset,
                softirq_sum += softirq;
                steal_sum += steal;
                guest_sum += guest;
+               guest_nice_sum += guest_nice;
        }
 
        cache = d->buf;
 
-       int cpuall_len = snprintf(cpuall, CPUALL_MAX_SIZE, "%s %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
-               "cpu ", user_sum, nice_sum, system_sum, idle_sum, iowait_sum, irq_sum, softirq_sum, steal_sum, guest_sum);
-       if (cpuall_len > 0 && cpuall_len < CPUALL_MAX_SIZE){
+       int cpuall_len = snprintf(cpuall, CPUALL_MAX_SIZE, "cpu  %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+                       user_sum,
+                       nice_sum,
+                       system_sum,
+                       idle_sum,
+                       iowait_sum,
+                       irq_sum,
+                       softirq_sum,
+                       steal_sum,
+                       guest_sum,
+                       guest_nice_sum);
+       if (cpuall_len > 0 && cpuall_len < CPUALL_MAX_SIZE) {
                memcpy(cache, cpuall, cpuall_len);
                cache += cpuall_len;
-       } else{
+       } else {
                /* shouldn't happen */
                lxcfs_error("proc_stat_read copy cpuall failed, cpuall_len=%d.", cpuall_len);
                cpuall_len = 0;
@@ -3591,7 +3634,8 @@ static int proc_stat_read(char *buf, size_t size, off_t offset,
        total_len += cpuall_len;
        d->cached = 1;
        d->size = total_len;
-       if (total_len > size ) total_len = size;
+       if (total_len > size)
+               total_len = size;
 
        memcpy(buf, d->buf, total_len);
        rv = total_len;
@@ -3607,23 +3651,12 @@ err:
 
 static long int getreaperage(pid_t pid)
 {
-       char fnam[100];
-       struct stat sb;
-       int ret;
-       pid_t qpid;
-
-       qpid = lookup_initpid_in_store(pid);
-       if (qpid <= 0)
-               return 0;
-
-       ret = snprintf(fnam, 100, "/proc/%d", qpid);
-       if (ret < 0 || ret >= 100)
-               return 0;
-
-       if (lstat(fnam, &sb) < 0)
-               return 0;
+       long int ctime;
 
-       return time(NULL) - sb.st_ctime;
+       ctime = getreaperctime(pid);
+       if (ctime)
+               return time(NULL) - ctime;
+       return ctime;
 }
 
 static unsigned long get_reaper_busy(pid_t task)
@@ -4350,11 +4383,13 @@ static bool cgfs_mount_hierarchies(void)
 
        for (i = 0; i < num_hierarchies; i++) {
                char *controller = hierarchies[i];
+
                clen = strlen(controller);
                len = strlen(BASEDIR) + clen + 2;
                target = malloc(len);
                if (!target)
                        return false;
+
                ret = snprintf(target, len, "%s/%s", BASEDIR, controller);
                if (ret < 0 || ret >= len) {
                        free(target);
@@ -4364,8 +4399,12 @@ static bool cgfs_mount_hierarchies(void)
                        free(target);
                        return false;
                }
-               if (mount(controller, target, "cgroup", 0, controller) < 0) {
-                       lxcfs_error("Failed mounting cgroup %s\n", controller);
+               if (!strcmp(controller, "unified"))
+                       ret = mount("none", target, "cgroup2", 0, NULL);
+               else
+                       ret = mount(controller, target, "cgroup", 0, controller);
+               if (ret < 0) {
+                       lxcfs_error("Failed mounting cgroup %s: %s\n", controller, strerror(errno));
                        free(target);
                        return false;
                }
@@ -4416,6 +4455,7 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void)
        char cwd[MAXPATHLEN];
        size_t len = 0;
        int i, init_ns = -1;
+       bool found_unified = false;
 
        if ((f = fopen("/proc/self/cgroup", "r")) == NULL) {
                lxcfs_error("Error opening /proc/self/cgroup: %s\n", strerror(errno));
@@ -4423,11 +4463,12 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void)
        }
 
        while (getline(&line, &len, f) != -1) {
-               char *p, *p2;
+               char *idx, *p, *p2;
 
                p = strchr(line, ':');
                if (!p)
                        goto out;
+               idx = line;
                *(p++) = '\0';
 
                p2 = strrchr(p, ':');
@@ -4440,8 +4481,10 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void)
                 * because it parses out the empty string "" and later on passes
                 * it to mount(). Let's skip such entries.
                 */
-               if (!strcmp(p, ""))
-                       continue;
+               if (!strcmp(p, "") && !strcmp(idx, "0") && !found_unified) {
+                       found_unified = true;
+                       p = "unified";
+               }
 
                if (!store_hierarchy(line, p))
                        goto out;
@@ -4454,7 +4497,7 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void)
                goto out;
        }
 
-       fd_hierarchies = malloc(sizeof(int *) * num_hierarchies);
+       fd_hierarchies = malloc(sizeof(int) * num_hierarchies);
        if (!fd_hierarchies) {
                lxcfs_error("%s\n", strerror(errno));
                goto out;