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.
fnam = alloca(len);
ret = snprintf(fnam, len, "%s%s/%s", *cgroup == '/' ? "." : "", cgroup, file);
if (ret < 0 || (size_t)ret >= len)
- return NULL;
+ return false;
fd = openat(cfd, fnam, O_RDONLY);
if (fd < 0)
- return NULL;
+ return false;
*value = slurp_file(fnam, fd);
return *value != NULL;
*memswlimit_str = NULL, *memswusage_str = NULL;
unsigned long memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0,
cached = 0, hosttotal = 0, active_anon = 0, inactive_anon = 0,
- active_file = 0, inactive_file = 0, unevictable = 0;
+ active_file = 0, inactive_file = 0, unevictable = 0,
+ hostswtotal = 0;
char *line = NULL;
size_t linelen = 0, total_len = 0, rv = 0;
char *cache = d->buf;
memset(lbuf, 0, 100);
if (startswith(line, "MemTotal:")) {
- sscanf(line+14, "%lu", &hosttotal);
+ sscanf(line+sizeof("MemTotal:")-1, "%lu", &hosttotal);
if (hosttotal < memlimit)
memlimit = hosttotal;
snprintf(lbuf, 100, "MemTotal: %8lu kB\n", memlimit);
snprintf(lbuf, 100, "MemAvailable: %8lu kB\n", memlimit - memusage);
printme = lbuf;
} else if (startswith(line, "SwapTotal:") && memswlimit > 0) {
+ sscanf(line+sizeof("SwapTotal:")-1, "%lu", &hostswtotal);
+ if (hostswtotal < memswlimit - memlimit)
+ memswlimit = hostswtotal + memlimit;
snprintf(lbuf, 100, "SwapTotal: %8lu kB\n", memswlimit - memlimit);
printme = lbuf;
} else if (startswith(line, "SwapFree:") && memswlimit > 0 && memswusage > 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)
{
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;
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;
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;
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;
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);
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;
}
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));
}
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, ':');
* 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;
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;