summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-12-14 16:35:39 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-12-14 16:35:39 -0800
commit6d93a1971a0ded67887eeab8d00a02074490f071 (patch)
tree7dc6494bde2dec7fc2ddf6ef4bd09f8d5778757e /tools
parent0ca2ce81eb8ee30f3ba8ac7967fef9cfbb44dbdb (diff)
parent5c62634fc65101d350cbd47722fb76f02693059d (diff)
Merge tag 'time-namespace-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux
Pull time namespace updates from Christian Brauner: "When time namespaces were introduced we missed to virtualize the 'btime' field in /proc/stat. This confuses tasks which are in another time namespace with a virtualized boottime which is common in some container workloads. This contains Michael's series to fix 'btime' which Thomas asked me to take through my tree. To fix 'btime' virtualization we simply subtract the offset of the time namespace's boottime from btime before printing the stats. Note that since start_boottime of processes are seconds since boottime and the boottime stamp is now shifted according to the time namespace's offset, the offset of the time namespace also needs to be applied before the process stats are given to userspace. This avoids that processes shown by tools such as 'ps' appear as time travelers in the corresponding time namespace. Selftests are included to verify that btime virtualization in /proc/stat works as expected" * tag 'time-namespace-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux: namespace: make timens_on_fork() return nothing selftests/timens: added selftest for /proc/stat btime fs/proc: apply the time namespace offset to /proc/stat btime timens: additional helper functions for boottime offset handling
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/timens/procfs.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/tools/testing/selftests/timens/procfs.c b/tools/testing/selftests/timens/procfs.c
index 7f14f0fdac84..f2519154208a 100644
--- a/tools/testing/selftests/timens/procfs.c
+++ b/tools/testing/selftests/timens/procfs.c
@@ -93,6 +93,33 @@ static int read_proc_uptime(struct timespec *uptime)
return 0;
}
+static int read_proc_stat_btime(unsigned long long *boottime_sec)
+{
+ FILE *proc;
+ char line_buf[2048];
+
+ proc = fopen("/proc/stat", "r");
+ if (proc == NULL) {
+ pr_perror("Unable to open /proc/stat");
+ return -1;
+ }
+
+ while (fgets(line_buf, 2048, proc)) {
+ if (sscanf(line_buf, "btime %llu", boottime_sec) != 1)
+ continue;
+ fclose(proc);
+ return 0;
+ }
+ if (errno) {
+ pr_perror("fscanf");
+ fclose(proc);
+ return -errno;
+ }
+ pr_err("failed to parse /proc/stat");
+ fclose(proc);
+ return -1;
+}
+
static int check_uptime(void)
{
struct timespec uptime_new, uptime_old;
@@ -123,18 +150,47 @@ static int check_uptime(void)
return 0;
}
+static int check_stat_btime(void)
+{
+ unsigned long long btime_new, btime_old;
+ unsigned long long btime_expected;
+
+ if (switch_ns(parent_ns))
+ return pr_err("switch_ns(%d)", parent_ns);
+
+ if (read_proc_stat_btime(&btime_old))
+ return 1;
+
+ if (switch_ns(child_ns))
+ return pr_err("switch_ns(%d)", child_ns);
+
+ if (read_proc_stat_btime(&btime_new))
+ return 1;
+
+ btime_expected = btime_old - TEN_DAYS_IN_SEC;
+ if (btime_new != btime_expected) {
+ pr_fail("btime in /proc/stat: old %llu, new %llu [%llu]",
+ btime_old, btime_new, btime_expected);
+ return 1;
+ }
+
+ ksft_test_result_pass("Passed for /proc/stat btime\n");
+ return 0;
+}
+
int main(int argc, char *argv[])
{
int ret = 0;
nscheck();
- ksft_set_plan(1);
+ ksft_set_plan(2);
if (init_namespaces())
return 1;
ret |= check_uptime();
+ ret |= check_stat_btime();
if (ret)
ksft_exit_fail();