1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci Copyright (c) 2020 Cyril Hrubis <chrubis@suse.cz> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci/* 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci Test if CLOCK_BOOTTIME namespace offset is applied to sysinfo uptime and that 8f08c3bdfSopenharmony_ci it's consistent with /proc/uptime as well. 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci After a call to unshare(CLONE_NEWTIME) a new timer namespace is created, the 11f08c3bdfSopenharmony_ci process that has called the unshare() can adjust offsets for CLOCK_MONOTONIC 12f08c3bdfSopenharmony_ci and CLOCK_BOOTTIME for its children by writing to the '/proc/self/timens_offsets'. 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci */ 15f08c3bdfSopenharmony_ci 16f08c3bdfSopenharmony_ci#include <sys/sysinfo.h> 17f08c3bdfSopenharmony_ci#include "lapi/posix_clocks.h" 18f08c3bdfSopenharmony_ci#include "tst_test.h" 19f08c3bdfSopenharmony_ci#include "lapi/sched.h" 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_cistatic int offsets[] = { 22f08c3bdfSopenharmony_ci 10, 23f08c3bdfSopenharmony_ci -10, 24f08c3bdfSopenharmony_ci 3600, 25f08c3bdfSopenharmony_ci}; 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_cistatic long read_proc_uptime(void) 28f08c3bdfSopenharmony_ci{ 29f08c3bdfSopenharmony_ci long sec, sec_rem; 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci SAFE_FILE_SCANF("/proc/uptime", "%li.%li", &sec, &sec_rem); 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci return sec + (sec_rem ? 1 : 0); 34f08c3bdfSopenharmony_ci} 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_cistatic void verify_sysinfo(unsigned int n) 37f08c3bdfSopenharmony_ci{ 38f08c3bdfSopenharmony_ci struct sysinfo si; 39f08c3bdfSopenharmony_ci long uptime; 40f08c3bdfSopenharmony_ci int off = offsets[n]; 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci SAFE_UNSHARE(CLONE_NEWTIME); 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF("/proc/self/timens_offsets", "%d %d 0", 45f08c3bdfSopenharmony_ci CLOCK_BOOTTIME, off); 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci sysinfo(&si); 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_ci uptime = si.uptime; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci if (!SAFE_FORK()) { 52f08c3bdfSopenharmony_ci sysinfo(&si); 53f08c3bdfSopenharmony_ci long proc_uptime = read_proc_uptime(); 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci long diff = si.uptime - uptime; 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci if (diff < off || diff > off + 1) 58f08c3bdfSopenharmony_ci tst_res(TFAIL, "Wrong sysinfo uptime offset %li", diff); 59f08c3bdfSopenharmony_ci else 60f08c3bdfSopenharmony_ci tst_res(TPASS, "Correct sysinfo uptime offset %i", off); 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci if (si.uptime < proc_uptime || si.uptime > proc_uptime + 1) { 63f08c3bdfSopenharmony_ci tst_res(TFAIL, "/proc/uptime %li differs from sysinfo %li", 64f08c3bdfSopenharmony_ci proc_uptime, si.uptime); 65f08c3bdfSopenharmony_ci } else { 66f08c3bdfSopenharmony_ci tst_res(TPASS, "/proc/uptime is consistent with sysinfo"); 67f08c3bdfSopenharmony_ci } 68f08c3bdfSopenharmony_ci } 69f08c3bdfSopenharmony_ci} 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_cistatic struct tst_test test = { 72f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(offsets), 73f08c3bdfSopenharmony_ci .test = verify_sysinfo, 74f08c3bdfSopenharmony_ci .needs_root = 1, 75f08c3bdfSopenharmony_ci .forks_child = 1, 76f08c3bdfSopenharmony_ci .needs_kconfigs = (const char *[]) { 77f08c3bdfSopenharmony_ci "CONFIG_TIME_NS=y", 78f08c3bdfSopenharmony_ci NULL 79f08c3bdfSopenharmony_ci }, 80f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 81f08c3bdfSopenharmony_ci {"linux-git", "ecc421e05bab"}, 82f08c3bdfSopenharmony_ci {} 83f08c3bdfSopenharmony_ci } 84f08c3bdfSopenharmony_ci}; 85