Index: sys/compat/linprocfs/linprocfs.c =================================================================== --- sys/compat/linprocfs/linprocfs.c +++ sys/compat/linprocfs/linprocfs.c @@ -469,9 +469,51 @@ return (0); } +/* + * Compare a given Linux kernel version string against + * the system / jail version and returns an integer greater than, equal to, + * or less than zero, according as the version is greater than, equal to, or + * less than the system / jail version. + */ +static int +linprocfs_osrelease_cmp(struct thread *td, const char *rel) +{ + char osrelease[LINUX_MAX_UTSNAME]; + int os_ver[3] = {0, 0, 0}; /* OS kernel version, major, minor */ + int cmp_ver[3] = {0, 0, 0}; /* Compare kernel version, major, minor */ + int i; + + linux_get_osrelease(td, osrelease); + + sscanf(osrelease, "%d.%d.%d", &os_ver[0], &os_ver[1], &os_ver[2]); + sscanf(rel, "%d.%d.%d", &cmp_ver[0], &cmp_ver[1], &cmp_ver[2]); + + for (i = 0; i < 3; i++) { + if (os_ver[i] > cmp_ver[i]) { + return (1); + } else if (os_ver[i] < cmp_ver[i]) { + return (-1); + } + } + + return (0); +} /* * Filler function for proc/stat + * + * Output depends on kernel version: + * + * v2.5.40 <= + * user, nice, system, idle + * v2.5.41 + * user, nice, system, idle, iowait + * v2.6.11 + * user, nice, system, idle, iowait, irq, softirq, steal + * v2.6.24 + * user, nice, system, idle, iowait, irq, softirq, steal, guest + * v2.6.33 >= + * user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice */ static int linprocfs_dostat(PFS_FILL_ARGS) @@ -481,22 +523,44 @@ long *cp; struct timeval boottime; int i; + const char *cpu_fmtstr, *cpun_fmtstr; + + if (linprocfs_osrelease_cmp(td, "2.6.33") >= 0) { + cpu_fmtstr = "cpu %lu %lu %lu %lu 0 %lu 0 0 0 0\n"; + cpun_fmtstr = "cpu%d %lu %lu %lu %lu 0 %lu 0 0 0 0\n"; + } else if (linprocfs_osrelease_cmp(td, "2.6.24") >= 0) { + cpu_fmtstr = "cpu %lu %lu %lu %lu 0 %lu 0 0 0\n"; + cpun_fmtstr = "cpu%d %lu %lu %lu %lu 0 %lu 0 0 0\n"; + } else if (linprocfs_osrelease_cmp(td, "2.6.11") >= 0) { + cpu_fmtstr = "cpu %lu %lu %lu %lu 0 %lu 0 0\n"; + cpun_fmtstr = "cpu%d %lu %lu %lu %lu 0 %lu 0 0\n"; + } else if (linprocfs_osrelease_cmp(td, "2.5.41") >= 0) { + /* Note: these format strings purposely drop a parameter */ + cpu_fmtstr = "cpu %lu %lu %lu %lu 0\n"; + cpun_fmtstr = "cpu%d %lu %lu %lu %lu 0\n"; + } else { + /* Note: these format strings purposely drop parameters */ + cpu_fmtstr = "cpu %lu %lu %lu %lu\n"; + cpun_fmtstr = "cpu%d %lu %lu %lu %lu\n"; + } read_cpu_time(cp_time); getboottime(&boottime); - sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", + sbuf_printf(sb, cpu_fmtstr, T2J(cp_time[CP_USER]), T2J(cp_time[CP_NICE]), - T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), - T2J(cp_time[CP_IDLE])); + T2J(cp_time[CP_SYS]), + T2J(cp_time[CP_IDLE]), + T2J(cp_time[CP_INTR])); CPU_FOREACH(i) { pcpu = pcpu_find(i); cp = pcpu->pc_cp_time; - sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, - T2J(cp[CP_USER]), - T2J(cp[CP_NICE]), - T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/), - T2J(cp[CP_IDLE])); + sbuf_printf(sb, cpun_fmtstr, i, + T2J(cp_time[CP_USER]), + T2J(cp_time[CP_NICE]), + T2J(cp_time[CP_SYS]), + T2J(cp_time[CP_IDLE]), + T2J(cp_time[CP_INTR])); } sbuf_printf(sb, "disk 0 0 0 0\n"