* [Devel] [PATCH hci-8.1 0/4] timens: Remove dependency on the vDSO
@ 2026-10-09 13:58 Eva Kurchatova
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 1/4] ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS Eva Kurchatova
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Eva Kurchatova @ 2026-10-09 13:58 UTC (permalink / raw)
To: khorenko; +Cc: devel
Patchset for task https://virtuozzo.atlassian.net/browse/VSTOR-148112
Eva Kurchatova (4):
ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS
ms/vdso/timens: Move functions to new file
ms/timens: Remove dependency on the vDSO
timens: freeze the offsets on the first join without the vDSO too
MAINTAINERS | 2 +
arch/arm64/Kconfig | 1 -
arch/loongarch/Kconfig | 1 -
arch/powerpc/Kconfig | 1 -
arch/riscv/Kconfig | 1 -
arch/s390/Kconfig | 1 -
arch/x86/Kconfig | 1 -
include/linux/time_namespace.h | 34 +++----
init/Kconfig | 4 +-
kernel/time/Makefile | 1 +
kernel/time/namespace.c | 147 ++++++---------------------
kernel/time/namespace_internal.h | 38 +++++++
kernel/time/namespace_vdso.c | 132 ++++++++++++++++++++++++
lib/vdso/Kconfig | 6 --
lib/vdso/datastore.c | 25 -----
tools/testing/selftests/pidfd/config | 1 -
16 files changed, 222 insertions(+), 174 deletions(-)
create mode 100644 kernel/time/namespace_internal.h
create mode 100644 kernel/time/namespace_vdso.c
--
2.56.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Devel] [PATCH hci-8.1 1/4] ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS
2026-10-09 13:58 [Devel] [PATCH hci-8.1 0/4] timens: Remove dependency on the vDSO Eva Kurchatova
@ 2026-10-09 13:58 ` Eva Kurchatova
2026-10-09 14:04 ` no-reply
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 2/4] ms/vdso/timens: Move functions to new file Eva Kurchatova
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Eva Kurchatova @ 2026-10-09 13:58 UTC (permalink / raw)
To: khorenko; +Cc: devel
All architectures implementing time-related functionality in the vDSO are
using the generic vDSO library which handles time namespaces properly.
Remove the now unnecessary Kconfig symbol.
Enables the use of time namespaces on architectures, which use the
generic vDSO but did not enable GENERIC_VDSO_TIME_NS, namely MIPS and arm.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/all/20250826-vdso-cleanups-v1-10-d9b65750e49f@linutronix.de
(cherry picked from commit bad53ae2dc425fd3d3ec8a2abb4e4b2d9c8f2fd0)
Rebase note: the context around the six select lines differs, the
change is the same.
https://virtuozzo.atlassian.net/browse/VSTOR-148112
Feature: fix ms/timens
Signed-off-by: Eva Kurchatova <eva.kurchatova@virtuozzo.com>
---
arch/arm64/Kconfig | 1 -
arch/loongarch/Kconfig | 1 -
arch/powerpc/Kconfig | 1 -
arch/riscv/Kconfig | 1 -
arch/s390/Kconfig | 1 -
arch/x86/Kconfig | 1 -
init/Kconfig | 2 +-
lib/vdso/Kconfig | 6 ------
tools/testing/selftests/pidfd/config | 1 -
9 files changed, 1 insertion(+), 14 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 49506a73e5f1..744b39ed11f2 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -164,7 +164,6 @@ config ARM64
select GENERIC_TIME_VSYSCALL
select GENERIC_GETTIMEOFDAY
select GENERIC_VDSO_DATA_STORE
- select GENERIC_VDSO_TIME_NS
select HARDIRQS_SW_RESEND
select HAS_IOPORT
select HAVE_MOVE_PMD
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 45c4096955c5..eeafe6fd62c0 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -104,7 +104,6 @@ config LOONGARCH
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_DATA_STORE
- select GENERIC_VDSO_TIME_NS
select GPIOLIB
select HAS_IOPORT
select HAVE_ARCH_AUDITSYSCALL
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 74884b887203..fd64957b54ab 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -213,7 +213,6 @@ config PPC
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_DATA_STORE
- select GENERIC_VDSO_TIME_NS
select HAS_IOPORT if PCI
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 5c6013a34fb8..3675962b601f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -115,7 +115,6 @@ config RISCV
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
select GENERIC_VDSO_DATA_STORE if MMU
- select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
select HARDIRQS_SW_RESEND
select HAS_IOPORT if MMU
select HAVE_ARCH_AUDITSYSCALL
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 44bfff6c5e88..81532dad4d36 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -153,7 +153,6 @@ config S390
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_DATA_STORE
- select GENERIC_VDSO_TIME_NS
select GENERIC_IOREMAP if PCI
select HAVE_ALIGNED_STRUCT_PAGE
select HAVE_ARCH_AUDITSYSCALL
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 7bd57bc01adb..04f4bcc0d59f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -180,7 +180,6 @@ config X86
select GENERIC_TIME_VSYSCALL
select GENERIC_GETTIMEOFDAY
select GENERIC_VDSO_DATA_STORE
- select GENERIC_VDSO_TIME_NS
select GENERIC_VDSO_OVERFLOW_PROTECT
select GUP_GET_PXX_LOW_HIGH if X86_PAE
select HARDIRQS_SW_RESEND
diff --git a/init/Kconfig b/init/Kconfig
index a9d90db6ed36..f0ad3790a93a 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1306,7 +1306,7 @@ config UTS_NS
config TIME_NS
bool "TIME namespace"
- depends on GENERIC_VDSO_TIME_NS
+ depends on GENERIC_GETTIMEOFDAY
default y
help
In this namespace boottime and monotonic clocks can be set.
diff --git a/lib/vdso/Kconfig b/lib/vdso/Kconfig
index 45df764b49ad..a1cc90133cb9 100644
--- a/lib/vdso/Kconfig
+++ b/lib/vdso/Kconfig
@@ -24,12 +24,6 @@ config GENERIC_COMPAT_VDSO
help
This config option enables the compat VDSO layer.
-config GENERIC_VDSO_TIME_NS
- bool
- help
- Selected by architectures which support time namespaces in the
- VDSO
-
config GENERIC_VDSO_OVERFLOW_PROTECT
bool
help
diff --git a/tools/testing/selftests/pidfd/config b/tools/testing/selftests/pidfd/config
index 6133524710f7..cf7cc0ce0248 100644
--- a/tools/testing/selftests/pidfd/config
+++ b/tools/testing/selftests/pidfd/config
@@ -4,6 +4,5 @@ CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_TIME_NS=y
-CONFIG_GENERIC_VDSO_TIME_NS=y
CONFIG_CGROUPS=y
CONFIG_CHECKPOINT_RESTORE=y
--
2.56.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Devel] [PATCH hci-8.1 2/4] ms/vdso/timens: Move functions to new file
2026-10-09 13:58 [Devel] [PATCH hci-8.1 0/4] timens: Remove dependency on the vDSO Eva Kurchatova
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 1/4] ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS Eva Kurchatova
@ 2026-10-09 13:58 ` Eva Kurchatova
2026-10-09 14:03 ` no-reply
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 3/4] ms/timens: Remove dependency on the vDSO Eva Kurchatova
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 4/4] timens: freeze the offsets on the first join without the vDSO too Eva Kurchatova
3 siblings, 1 reply; 9+ messages in thread
From: Eva Kurchatova @ 2026-10-09 13:58 UTC (permalink / raw)
To: khorenko; +Cc: devel
As a preparation of the untangling of time namespaces and the vDSO, move
the glue functions between those subsystems into a new file.
While at it, switch the mutex lock and mmap_read_lock() in the vDSO
namespace code to guard().
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260326-vdso-timens-decoupling-v2-1-c82693a7775f@linutronix.de
(cherry picked from commit 5dc9cf835aba73c882348aa4f99be83b6e45ad9b)
Rebase note: this kernel has no auxiliary clocks, so the vdso data has
no aux_clock_data to set up. The offset lock was made visible as
offset_lock by 51a228b021a0 ("ve: Add interface for
ve::clock_[monotonic|bootbased] adjustment") and nothing uses it
outside namespace.c, so it takes its mainline name and home in
namespace_internal.h.
https://virtuozzo.atlassian.net/browse/VSTOR-148112
Feature: fix ms/timens
Signed-off-by: Eva Kurchatova <eva.kurchatova@virtuozzo.com>
---
MAINTAINERS | 2 +
include/linux/time_namespace.h | 10 ---
kernel/time/Makefile | 2 +-
kernel/time/namespace.c | 119 +-------------------------
kernel/time/namespace_internal.h | 13 +++
kernel/time/namespace_vdso.c | 141 +++++++++++++++++++++++++++++++
lib/vdso/datastore.c | 25 ------
7 files changed, 161 insertions(+), 151 deletions(-)
create mode 100644 kernel/time/namespace_internal.h
create mode 100644 kernel/time/namespace_vdso.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 9523da3c767c..ac649ee0c43c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9683,6 +9683,7 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/vdso
F: include/asm-generic/vdso/vsyscall.h
F: include/vdso/
+F: kernel/time/namespace_vdso.c
F: kernel/time/vsyscall.c
F: lib/vdso/
F: tools/testing/selftests/vDSO/
@@ -18576,6 +18577,7 @@ F: include/trace/events/timer*
F: kernel/time/itimer.c
F: kernel/time/posix-*
F: kernel/time/namespace.c
+F: kernel/time/namespace_vdso.c
POWER MANAGEMENT CORE
M: "Rafael J. Wysocki" <rafael@kernel.org>
diff --git a/include/linux/time_namespace.h b/include/linux/time_namespace.h
index 3d3b529c5a98..63d0051927f1 100644
--- a/include/linux/time_namespace.h
+++ b/include/linux/time_namespace.h
@@ -32,11 +32,7 @@ struct time_namespace {
extern struct time_namespace init_time_ns;
-extern struct mutex offset_lock;
-
#ifdef CONFIG_TIME_NS
-extern int vdso_join_timens(struct task_struct *task,
- struct time_namespace *ns);
extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
@@ -110,12 +106,6 @@ static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
}
#else
-static inline int vdso_join_timens(struct task_struct *task,
- struct time_namespace *ns)
-{
- return 0;
-}
-
static inline void timens_commit(struct task_struct *tsk,
struct time_namespace *ns)
{
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index fe0ae82124fe..494bd4e41781 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -23,6 +23,6 @@ endif
obj-$(CONFIG_HAVE_GENERIC_VDSO) += vsyscall.o
obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o
obj-$(CONFIG_TEST_UDELAY) += test_udelay.o
-obj-$(CONFIG_TIME_NS) += namespace.o
+obj-$(CONFIG_TIME_NS) += namespace.o namespace_vdso.o
obj-$(CONFIG_TEST_CLOCKSOURCE_WATCHDOG) += clocksource-wdtest.o
obj-$(CONFIG_TIME_KUNIT_TEST) += time_test.o
diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
index e85f947d4063..c82dc9a5d1de 100644
--- a/kernel/time/namespace.c
+++ b/kernel/time/namespace.c
@@ -18,7 +18,7 @@
#include <linux/err.h>
#include <linux/mm.h>
-#include <vdso/datapage.h>
+#include "namespace_internal.h"
ktime_t do_timens_ktime_to_host(clockid_t clockid, ktime_t tim,
struct timens_offsets *ns_offsets)
@@ -139,112 +139,7 @@ struct time_namespace *copy_time_ns(unsigned long flags,
return clone_time_ns(user_ns, old_ns);
}
-static struct timens_offset offset_from_ts(struct timespec64 off)
-{
- struct timens_offset ret;
-
- ret.sec = off.tv_sec;
- ret.nsec = off.tv_nsec;
-
- return ret;
-}
-
-/*
- * A time namespace VVAR page has the same layout as the VVAR page which
- * contains the system wide VDSO data.
- *
- * For a normal task the VVAR pages are installed in the normal ordering:
- * VVAR
- * PVCLOCK
- * HVCLOCK
- * TIMENS <- Not really required
- *
- * Now for a timens task the pages are installed in the following order:
- * TIMENS
- * PVCLOCK
- * HVCLOCK
- * VVAR
- *
- * The check for vdso_clock->clock_mode is in the unlikely path of
- * the seq begin magic. So for the non-timens case most of the time
- * 'seq' is even, so the branch is not taken.
- *
- * If 'seq' is odd, i.e. a concurrent update is in progress, the extra check
- * for vdso_clock->clock_mode is a non-issue. The task is spin waiting for the
- * update to finish and for 'seq' to become even anyway.
- *
- * Timens page has vdso_clock->clock_mode set to VDSO_CLOCKMODE_TIMENS which
- * enforces the time namespace handling path.
- */
-static void timens_setup_vdso_clock_data(struct vdso_clock *vc,
- struct time_namespace *ns)
-{
- struct timens_offset *offset = vc->offset;
- struct timens_offset monotonic = offset_from_ts(ns->offsets.monotonic);
- struct timens_offset boottime = offset_from_ts(ns->offsets.boottime);
-
- vc->seq = 1;
- vc->clock_mode = VDSO_CLOCKMODE_TIMENS;
- offset[CLOCK_MONOTONIC] = monotonic;
- offset[CLOCK_MONOTONIC_RAW] = monotonic;
- offset[CLOCK_MONOTONIC_COARSE] = monotonic;
- offset[CLOCK_BOOTTIME] = boottime;
- offset[CLOCK_BOOTTIME_ALARM] = boottime;
-}
-
-struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- if (likely(vma->vm_mm == current->mm))
- return current->nsproxy->time_ns->vvar_page;
-
- /*
- * VM_PFNMAP | VM_IO protect .fault() handler from being called
- * through interfaces like /proc/$pid/mem or
- * process_vm_{readv,writev}() as long as there's no .access()
- * in special_mapping_vmops().
- * For more details check_vma_flags() and __access_remote_vm()
- */
-
- WARN(1, "vvar_page accessed remotely");
-
- return NULL;
-}
-
-/*
- * Protects possibly multiple offsets writers racing each other
- * and tasks entering the namespace.
- */
-DEFINE_MUTEX(offset_lock);
-
-static void timens_set_vvar_page(struct task_struct *task,
- struct time_namespace *ns)
-{
- struct vdso_time_data *vdata;
- struct vdso_clock *vc;
- unsigned int i;
-
- if (ns == &init_time_ns)
- return;
-
- /* Fast-path, taken by every task in namespace except the first. */
- if (likely(ns->frozen_offsets))
- return;
-
- mutex_lock(&offset_lock);
- /* Nothing to-do: vvar_page has been already initialized. */
- if (ns->frozen_offsets)
- goto out;
-
- ns->frozen_offsets = true;
- vdata = page_address(ns->vvar_page);
- vc = vdata->clock_data;
-
- for (i = 0; i < CS_BASES; i++)
- timens_setup_vdso_clock_data(&vc[i], ns);
-
-out:
- mutex_unlock(&offset_lock);
-}
+DEFINE_MUTEX(timens_offset_lock);
void free_time_ns(struct time_namespace *ns)
{
@@ -297,12 +192,6 @@ static void timens_put(struct ns_common *ns)
put_time_ns(to_time_ns(ns));
}
-void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
-{
- timens_set_vvar_page(tsk, ns);
- vdso_join_timens(tsk, ns);
-}
-
static int timens_install(struct nsset *nsset, struct ns_common *new)
{
struct nsproxy *nsproxy = nsset->nsproxy;
@@ -427,7 +316,7 @@ int proc_timens_set_offset(struct file *file, struct task_struct *p,
goto out;
}
- mutex_lock(&offset_lock);
+ mutex_lock(&timens_offset_lock);
if (time_ns->frozen_offsets) {
err = -EACCES;
goto out_unlock;
@@ -452,7 +341,7 @@ int proc_timens_set_offset(struct file *file, struct task_struct *p,
}
out_unlock:
- mutex_unlock(&offset_lock);
+ mutex_unlock(&timens_offset_lock);
out:
put_time_ns(time_ns);
diff --git a/kernel/time/namespace_internal.h b/kernel/time/namespace_internal.h
new file mode 100644
index 000000000000..e85da11abb4d
--- /dev/null
+++ b/kernel/time/namespace_internal.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _TIME_NAMESPACE_INTERNAL_H
+#define _TIME_NAMESPACE_INTERNAL_H
+
+#include <linux/mutex.h>
+
+/*
+ * Protects possibly multiple offsets writers racing each other
+ * and tasks entering the namespace.
+ */
+extern struct mutex timens_offset_lock;
+
+#endif /* _TIME_NAMESPACE_INTERNAL_H */
diff --git a/kernel/time/namespace_vdso.c b/kernel/time/namespace_vdso.c
new file mode 100644
index 000000000000..558bf5208588
--- /dev/null
+++ b/kernel/time/namespace_vdso.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Andrei Vagin <avagin@openvz.org>
+ * Author: Dmitry Safonov <dima@arista.com>
+ */
+
+#include <linux/cleanup.h>
+#include <linux/mm.h>
+#include <linux/time_namespace.h>
+#include <linux/time.h>
+#include <linux/vdso_datastore.h>
+
+#include <vdso/clocksource.h>
+#include <vdso/datapage.h>
+
+#include "namespace_internal.h"
+
+static struct timens_offset offset_from_ts(struct timespec64 off)
+{
+ struct timens_offset ret;
+
+ ret.sec = off.tv_sec;
+ ret.nsec = off.tv_nsec;
+
+ return ret;
+}
+
+/*
+ * A time namespace VVAR page has the same layout as the VVAR page which
+ * contains the system wide VDSO data.
+ *
+ * For a normal task the VVAR pages are installed in the normal ordering:
+ * VVAR
+ * PVCLOCK
+ * HVCLOCK
+ * TIMENS <- Not really required
+ *
+ * Now for a timens task the pages are installed in the following order:
+ * TIMENS
+ * PVCLOCK
+ * HVCLOCK
+ * VVAR
+ *
+ * The check for vdso_clock->clock_mode is in the unlikely path of
+ * the seq begin magic. So for the non-timens case most of the time
+ * 'seq' is even, so the branch is not taken.
+ *
+ * If 'seq' is odd, i.e. a concurrent update is in progress, the extra check
+ * for vdso_clock->clock_mode is a non-issue. The task is spin waiting for the
+ * update to finish and for 'seq' to become even anyway.
+ *
+ * Timens page has vdso_clock->clock_mode set to VDSO_CLOCKMODE_TIMENS which
+ * enforces the time namespace handling path.
+ */
+static void timens_setup_vdso_clock_data(struct vdso_clock *vc,
+ struct time_namespace *ns)
+{
+ struct timens_offset *offset = vc->offset;
+ struct timens_offset monotonic = offset_from_ts(ns->offsets.monotonic);
+ struct timens_offset boottime = offset_from_ts(ns->offsets.boottime);
+
+ vc->seq = 1;
+ vc->clock_mode = VDSO_CLOCKMODE_TIMENS;
+ offset[CLOCK_MONOTONIC] = monotonic;
+ offset[CLOCK_MONOTONIC_RAW] = monotonic;
+ offset[CLOCK_MONOTONIC_COARSE] = monotonic;
+ offset[CLOCK_BOOTTIME] = boottime;
+ offset[CLOCK_BOOTTIME_ALARM] = boottime;
+}
+
+struct page *find_timens_vvar_page(struct vm_area_struct *vma)
+{
+ if (likely(vma->vm_mm == current->mm))
+ return current->nsproxy->time_ns->vvar_page;
+
+ /*
+ * VM_PFNMAP | VM_IO protect .fault() handler from being called
+ * through interfaces like /proc/$pid/mem or
+ * process_vm_{readv,writev}() as long as there's no .access()
+ * in special_mapping_vmops().
+ * For more details check_vma_flags() and __access_remote_vm()
+ */
+
+ WARN(1, "vvar_page accessed remotely");
+
+ return NULL;
+}
+
+static void timens_set_vvar_page(struct task_struct *task,
+ struct time_namespace *ns)
+{
+ struct vdso_time_data *vdata;
+ struct vdso_clock *vc;
+ unsigned int i;
+
+ if (ns == &init_time_ns)
+ return;
+
+ /* Fast-path, taken by every task in namespace except the first. */
+ if (likely(ns->frozen_offsets))
+ return;
+
+ guard(mutex)(&timens_offset_lock);
+ /* Nothing to-do: vvar_page has been already initialized. */
+ if (ns->frozen_offsets)
+ return;
+
+ ns->frozen_offsets = true;
+ vdata = page_address(ns->vvar_page);
+ vc = vdata->clock_data;
+
+ for (i = 0; i < CS_BASES; i++)
+ timens_setup_vdso_clock_data(&vc[i], ns);
+}
+
+/*
+ * The vvar page layout depends on whether a task belongs to the root or
+ * non-root time namespace. Whenever a task changes its namespace, the VVAR
+ * page tables are cleared and then they will be re-faulted with a
+ * corresponding layout.
+ * See also the comment near timens_setup_vdso_clock_data() for details.
+ */
+static int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
+{
+ struct mm_struct *mm = task->mm;
+ struct vm_area_struct *vma;
+ VMA_ITERATOR(vmi, mm, 0);
+
+ guard(mmap_read_lock)(mm);
+ for_each_vma(vmi, vma) {
+ if (vma_is_special_mapping(vma, &vdso_vvar_mapping))
+ zap_vma_pages(vma);
+ }
+ return 0;
+}
+
+void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
+{
+ timens_set_vvar_page(tsk, ns);
+ vdso_join_timens(tsk, ns);
+}
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
index 46192c1d8542..7713fd392dd0 100644
--- a/lib/vdso/datastore.c
+++ b/lib/vdso/datastore.c
@@ -102,28 +102,3 @@ struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned
VM_READ | VM_MAYREAD | VM_IO | VM_DONTDUMP | VM_PFNMAP,
&vdso_vvar_mapping);
}
-
-#ifdef CONFIG_TIME_NS
-/*
- * The vvar page layout depends on whether a task belongs to the root or
- * non-root time namespace. Whenever a task changes its namespace, the VVAR
- * page tables are cleared and then they will be re-faulted with a
- * corresponding layout.
- * See also the comment near timens_setup_vdso_clock_data() for details.
- */
-int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
-{
- struct mm_struct *mm = task->mm;
- struct vm_area_struct *vma;
- VMA_ITERATOR(vmi, mm, 0);
-
- mmap_read_lock(mm);
- for_each_vma(vmi, vma) {
- if (vma_is_special_mapping(vma, &vdso_vvar_mapping))
- zap_vma_pages(vma);
- }
- mmap_read_unlock(mm);
-
- return 0;
-}
-#endif
--
2.56.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Devel] [PATCH hci-8.1 3/4] ms/timens: Remove dependency on the vDSO
2026-10-09 13:58 [Devel] [PATCH hci-8.1 0/4] timens: Remove dependency on the vDSO Eva Kurchatova
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 1/4] ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS Eva Kurchatova
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 2/4] ms/vdso/timens: Move functions to new file Eva Kurchatova
@ 2026-10-09 13:58 ` Eva Kurchatova
2026-10-09 14:06 ` no-reply
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 4/4] timens: freeze the offsets on the first join without the vDSO too Eva Kurchatova
3 siblings, 1 reply; 9+ messages in thread
From: Eva Kurchatova @ 2026-10-09 13:58 UTC (permalink / raw)
To: khorenko; +Cc: devel
Previously, missing time namespace support in the vDSO meant that time
namespaces needed to be disabled globally. This was expressed in a hard
dependency on the generic vDSO library. This also meant that architectures
without any vDSO or only a stub vDSO could not enable time namespaces.
Now that all architectures using a real vDSO are using the generic library,
that dependency is not necessary anymore.
Remove the dependency and let all architectures enable time namespaces.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260326-vdso-timens-decoupling-v2-2-c82693a7775f@linutronix.de
(cherry picked from commit 1b6c89285d37114d7efe8ab04102a542581cd7da)
The User Mode Linux KUnit kernel has no generic vDSO, so it could not
have CONFIG_TIME_NS, which every x86_64 configuration has; a change
under review for VSTOR-146839 named init_time_ns and failed to link
there. With the dependency gone the UML build keeps the option.
https://virtuozzo.atlassian.net/browse/VSTOR-148112
Feature: fix ms/timens
Signed-off-by: Eva Kurchatova <eva.kurchatova@virtuozzo.com>
---
include/linux/time_namespace.h | 29 ++++++++++++++++-------------
init/Kconfig | 4 +++-
kernel/time/Makefile | 3 ++-
kernel/time/namespace.c | 8 ++++----
kernel/time/namespace_internal.h | 15 +++++++++++++++
kernel/time/namespace_vdso.c | 14 ++++++++++++++
6 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/include/linux/time_namespace.h b/include/linux/time_namespace.h
index 63d0051927f1..6c1872e7bb73 100644
--- a/include/linux/time_namespace.h
+++ b/include/linux/time_namespace.h
@@ -25,7 +25,9 @@ struct time_namespace {
struct ucounts *ucounts;
struct ns_common ns;
struct timens_offsets offsets;
+#ifdef CONFIG_TIME_NS_VDSO
struct page *vvar_page;
+#endif
/* If set prevents changing offsets after any task joined namespace. */
bool frozen_offsets;
} __randomize_layout;
@@ -33,8 +35,6 @@ struct time_namespace {
extern struct time_namespace init_time_ns;
#ifdef CONFIG_TIME_NS
-extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
-
static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
{
refcount_inc(&ns->ns.count);
@@ -46,7 +46,6 @@ struct time_namespace *copy_time_ns(unsigned long flags,
struct time_namespace *old_ns);
void free_time_ns(struct time_namespace *ns);
void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);
-struct page *find_timens_vvar_page(struct vm_area_struct *vma);
static inline void put_time_ns(struct time_namespace *ns)
{
@@ -106,11 +105,6 @@ static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
}
#else
-static inline void timens_commit(struct task_struct *tsk,
- struct time_namespace *ns)
-{
-}
-
static inline struct time_namespace *get_time_ns(struct time_namespace *ns)
{
return NULL;
@@ -137,11 +131,6 @@ static inline void timens_on_fork(struct nsproxy *nsproxy,
return;
}
-static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- return NULL;
-}
-
static inline void timens_add_monotonic(struct timespec64 *ts) { }
static inline void timens_add_boottime(struct timespec64 *ts) { }
@@ -158,4 +147,18 @@ static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
}
#endif
+#ifdef CONFIG_TIME_NS_VDSO
+extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
+struct page *find_timens_vvar_page(struct vm_area_struct *vma);
+#else /* !CONFIG_TIME_NS_VDSO */
+static inline void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
+{
+}
+
+static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
+{
+ return NULL;
+}
+#endif /* CONFIG_TIME_NS_VDSO */
+
#endif /* _LINUX_TIMENS_H */
diff --git a/init/Kconfig b/init/Kconfig
index f0ad3790a93a..44b2d4426109 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1306,12 +1306,14 @@ config UTS_NS
config TIME_NS
bool "TIME namespace"
- depends on GENERIC_GETTIMEOFDAY
default y
help
In this namespace boottime and monotonic clocks can be set.
The time will keep going with the same pace.
+config TIME_NS_VDSO
+ def_bool TIME_NS && GENERIC_GETTIMEOFDAY
+
config IPC_NS
bool "IPC namespace"
depends on (SYSVIPC || POSIX_MQUEUE)
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index 494bd4e41781..dd3ea6997064 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -23,6 +23,7 @@ endif
obj-$(CONFIG_HAVE_GENERIC_VDSO) += vsyscall.o
obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o
obj-$(CONFIG_TEST_UDELAY) += test_udelay.o
-obj-$(CONFIG_TIME_NS) += namespace.o namespace_vdso.o
+obj-$(CONFIG_TIME_NS) += namespace.o
+obj-$(CONFIG_TIME_NS_VDSO) += namespace_vdso.o
obj-$(CONFIG_TEST_CLOCKSOURCE_WATCHDOG) += clocksource-wdtest.o
obj-$(CONFIG_TIME_KUNIT_TEST) += time_test.o
diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
index c82dc9a5d1de..cf95f9e0ad94 100644
--- a/kernel/time/namespace.c
+++ b/kernel/time/namespace.c
@@ -94,8 +94,8 @@ static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
refcount_set(&ns->ns.count, 1);
- ns->vvar_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
- if (!ns->vvar_page)
+ err = timens_vdso_alloc_vvar_page(ns);
+ if (err)
goto fail_free;
err = ns_alloc_inum(&ns->ns);
@@ -110,7 +110,7 @@ static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
return ns;
fail_free_page:
- __free_page(ns->vvar_page);
+ timens_vdso_free_vvar_page(ns);
fail_free:
kfree(ns);
fail_dec:
@@ -146,7 +146,7 @@ void free_time_ns(struct time_namespace *ns)
dec_time_namespaces(ns->ucounts);
put_user_ns(ns->user_ns);
ns_free_inum(&ns->ns);
- __free_page(ns->vvar_page);
+ timens_vdso_free_vvar_page(ns);
kfree(ns);
}
diff --git a/kernel/time/namespace_internal.h b/kernel/time/namespace_internal.h
index e85da11abb4d..b37ba179f43b 100644
--- a/kernel/time/namespace_internal.h
+++ b/kernel/time/namespace_internal.h
@@ -4,10 +4,25 @@
#include <linux/mutex.h>
+struct time_namespace;
+
/*
* Protects possibly multiple offsets writers racing each other
* and tasks entering the namespace.
*/
extern struct mutex timens_offset_lock;
+#ifdef CONFIG_TIME_NS_VDSO
+int timens_vdso_alloc_vvar_page(struct time_namespace *ns);
+void timens_vdso_free_vvar_page(struct time_namespace *ns);
+#else /* !CONFIG_TIME_NS_VDSO */
+static inline int timens_vdso_alloc_vvar_page(struct time_namespace *ns)
+{
+ return 0;
+}
+static inline void timens_vdso_free_vvar_page(struct time_namespace *ns)
+{
+}
+#endif /* CONFIG_TIME_NS_VDSO */
+
#endif /* _TIME_NAMESPACE_INTERNAL_H */
diff --git a/kernel/time/namespace_vdso.c b/kernel/time/namespace_vdso.c
index 558bf5208588..08d69270eb2c 100644
--- a/kernel/time/namespace_vdso.c
+++ b/kernel/time/namespace_vdso.c
@@ -139,3 +139,17 @@ void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
timens_set_vvar_page(tsk, ns);
vdso_join_timens(tsk, ns);
}
+
+int timens_vdso_alloc_vvar_page(struct time_namespace *ns)
+{
+ ns->vvar_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
+ if (!ns->vvar_page)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void timens_vdso_free_vvar_page(struct time_namespace *ns)
+{
+ __free_page(ns->vvar_page);
+}
--
2.56.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Devel] [PATCH hci-8.1 4/4] timens: freeze the offsets on the first join without the vDSO too
2026-10-09 13:58 [Devel] [PATCH hci-8.1 0/4] timens: Remove dependency on the vDSO Eva Kurchatova
` (2 preceding siblings ...)
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 3/4] ms/timens: Remove dependency on the vDSO Eva Kurchatova
@ 2026-10-09 13:58 ` Eva Kurchatova
2026-10-09 14:06 ` no-reply
3 siblings, 1 reply; 9+ messages in thread
From: Eva Kurchatova @ 2026-10-09 13:58 UTC (permalink / raw)
To: khorenko; +Cc: devel
A time namespace's offsets may be written until the first task joins
it; from then on they are read without a lock, so that join freezes
them. The freeze sat in the code that fills the namespace's vDSO
page, and since 1b6c89285d37 ("timens: Remove dependency on the vDSO")
a kernel without a generic vDSO, User Mode Linux now, never froze: the
owner could rewrite the offsets under the tasks already running there,
and the clocks they read moved with them.
Freeze in timens_commit() itself and fill the vDSO page from there,
where there is one.
Fixes: 1b6c89285d37 ("timens: Remove dependency on the vDSO")
https://virtuozzo.atlassian.net/browse/VSTOR-148112
Feature: fix ms/timens
Signed-off-by: Eva Kurchatova <eva.kurchatova@virtuozzo.com>
---
include/linux/time_namespace.h | 11 ++++++-----
kernel/time/namespace.c | 28 +++++++++++++++++++++++++++
kernel/time/namespace_internal.h | 10 ++++++++++
kernel/time/namespace_vdso.c | 33 +++++---------------------------
4 files changed, 49 insertions(+), 33 deletions(-)
diff --git a/include/linux/time_namespace.h b/include/linux/time_namespace.h
index 6c1872e7bb73..a8b4403e8630 100644
--- a/include/linux/time_namespace.h
+++ b/include/linux/time_namespace.h
@@ -46,6 +46,7 @@ struct time_namespace *copy_time_ns(unsigned long flags,
struct time_namespace *old_ns);
void free_time_ns(struct time_namespace *ns);
void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);
+void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
static inline void put_time_ns(struct time_namespace *ns)
{
@@ -131,6 +132,11 @@ static inline void timens_on_fork(struct nsproxy *nsproxy,
return;
}
+static inline void timens_commit(struct task_struct *tsk,
+ struct time_namespace *ns)
+{
+}
+
static inline void timens_add_monotonic(struct timespec64 *ts) { }
static inline void timens_add_boottime(struct timespec64 *ts) { }
@@ -148,13 +154,8 @@ static inline ktime_t timens_ktime_to_host(clockid_t clockid, ktime_t tim)
#endif
#ifdef CONFIG_TIME_NS_VDSO
-extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
struct page *find_timens_vvar_page(struct vm_area_struct *vma);
#else /* !CONFIG_TIME_NS_VDSO */
-static inline void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
-{
-}
-
static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
index cf95f9e0ad94..9bd21eb8bf2d 100644
--- a/kernel/time/namespace.c
+++ b/kernel/time/namespace.c
@@ -192,6 +192,34 @@ static void timens_put(struct ns_common *ns)
put_time_ns(to_time_ns(ns));
}
+/*
+ * The offsets are read without a lock once a task runs in the namespace,
+ * so the first task to join freezes them, and sets up the vDSO page from
+ * them where there is one.
+ */
+static void timens_freeze_offsets(struct time_namespace *ns)
+{
+ if (ns == &init_time_ns)
+ return;
+
+ /* Fast-path, taken by every task in namespace except the first. */
+ if (likely(ns->frozen_offsets))
+ return;
+
+ guard(mutex)(&timens_offset_lock);
+ if (ns->frozen_offsets)
+ return;
+
+ timens_vdso_setup_vvar_page(ns);
+ ns->frozen_offsets = true;
+}
+
+void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
+{
+ timens_freeze_offsets(ns);
+ timens_vdso_join(tsk, ns);
+}
+
static int timens_install(struct nsset *nsset, struct ns_common *new)
{
struct nsproxy *nsproxy = nsset->nsproxy;
diff --git a/kernel/time/namespace_internal.h b/kernel/time/namespace_internal.h
index b37ba179f43b..564c22b639dc 100644
--- a/kernel/time/namespace_internal.h
+++ b/kernel/time/namespace_internal.h
@@ -4,6 +4,7 @@
#include <linux/mutex.h>
+struct task_struct;
struct time_namespace;
/*
@@ -15,6 +16,8 @@ extern struct mutex timens_offset_lock;
#ifdef CONFIG_TIME_NS_VDSO
int timens_vdso_alloc_vvar_page(struct time_namespace *ns);
void timens_vdso_free_vvar_page(struct time_namespace *ns);
+void timens_vdso_setup_vvar_page(struct time_namespace *ns);
+void timens_vdso_join(struct task_struct *task, struct time_namespace *ns);
#else /* !CONFIG_TIME_NS_VDSO */
static inline int timens_vdso_alloc_vvar_page(struct time_namespace *ns)
{
@@ -23,6 +26,13 @@ static inline int timens_vdso_alloc_vvar_page(struct time_namespace *ns)
static inline void timens_vdso_free_vvar_page(struct time_namespace *ns)
{
}
+static inline void timens_vdso_setup_vvar_page(struct time_namespace *ns)
+{
+}
+static inline void timens_vdso_join(struct task_struct *task,
+ struct time_namespace *ns)
+{
+}
#endif /* CONFIG_TIME_NS_VDSO */
#endif /* _TIME_NAMESPACE_INTERNAL_H */
diff --git a/kernel/time/namespace_vdso.c b/kernel/time/namespace_vdso.c
index 08d69270eb2c..8a2fc9d23687 100644
--- a/kernel/time/namespace_vdso.c
+++ b/kernel/time/namespace_vdso.c
@@ -86,29 +86,13 @@ struct page *find_timens_vvar_page(struct vm_area_struct *vma)
return NULL;
}
-static void timens_set_vvar_page(struct task_struct *task,
- struct time_namespace *ns)
+/* Called once per namespace, under timens_offset_lock, before any task reads */
+void timens_vdso_setup_vvar_page(struct time_namespace *ns)
{
- struct vdso_time_data *vdata;
- struct vdso_clock *vc;
+ struct vdso_time_data *vdata = page_address(ns->vvar_page);
+ struct vdso_clock *vc = vdata->clock_data;
unsigned int i;
- if (ns == &init_time_ns)
- return;
-
- /* Fast-path, taken by every task in namespace except the first. */
- if (likely(ns->frozen_offsets))
- return;
-
- guard(mutex)(&timens_offset_lock);
- /* Nothing to-do: vvar_page has been already initialized. */
- if (ns->frozen_offsets)
- return;
-
- ns->frozen_offsets = true;
- vdata = page_address(ns->vvar_page);
- vc = vdata->clock_data;
-
for (i = 0; i < CS_BASES; i++)
timens_setup_vdso_clock_data(&vc[i], ns);
}
@@ -120,7 +104,7 @@ static void timens_set_vvar_page(struct task_struct *task,
* corresponding layout.
* See also the comment near timens_setup_vdso_clock_data() for details.
*/
-static int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
+void timens_vdso_join(struct task_struct *task, struct time_namespace *ns)
{
struct mm_struct *mm = task->mm;
struct vm_area_struct *vma;
@@ -131,13 +115,6 @@ static int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
if (vma_is_special_mapping(vma, &vdso_vvar_mapping))
zap_vma_pages(vma);
}
- return 0;
-}
-
-void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
-{
- timens_set_vvar_page(tsk, ns);
- vdso_join_timens(tsk, ns);
}
int timens_vdso_alloc_vvar_page(struct time_namespace *ns)
--
2.56.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Devel] [PATCH hci-8.1 2/4] ms/vdso/timens: Move functions to new file
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 2/4] ms/vdso/timens: Move functions to new file Eva Kurchatova
@ 2026-10-09 14:03 ` no-reply
0 siblings, 0 replies; 9+ messages in thread
From: no-reply @ 2026-10-09 14:03 UTC (permalink / raw)
To: khorenko, Eva Kurchatova; +Cc: devel
> As a preparation of the untangling of time namespaces and the vDSO, move
> the glue functions between those subsystems into a new file.
>
> While at it, switch the mutex lock and mmap_read_lock() in the vDSO
> namespace code to guard().
>
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> Link: https://patch.msgid.link/20260326-vdso-timens-decoupling-v2-1-c82693a7775f@linutronix.de
> (cherry picked from commit 5dc9cf835aba73c882348aa4f99be83b6e45ad9b)
>
> Rebase note: this kernel has no auxiliary clocks, so the vdso data has
> no aux_clock_data to set up. The offset lock was made visible as
> offset_lock by 51a228b021a0 ("ve: Add interface for
> ve::clock_[monotonic|bootbased] adjustment") and nothing uses it
> outside namespace.c, so it takes its mainline name and home in
> namespace_internal.h.
>
> https://virtuozzo.atlassian.net/browse/VSTOR-148112
> Feature: fix ms/timens
>
> Signed-off-by: Eva Kurchatova <eva.kurchatova@virtuozzo.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261009135929.3274885-1-eva.kurchatova@virtuozzo.com?part=2
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Devel] [PATCH hci-8.1 1/4] ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 1/4] ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS Eva Kurchatova
@ 2026-10-09 14:04 ` no-reply
0 siblings, 0 replies; 9+ messages in thread
From: no-reply @ 2026-10-09 14:04 UTC (permalink / raw)
To: Eva Kurchatova, khorenko; +Cc: devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] config: stale CONFIG_GENERIC_VDSO_TIME_NS=y left in shipped Virtuozzo configs
--
commit 6f298fef5110add3238fa534d536cbb04d9561a1
Author: Eva Kurchatova <eva.kurchatova@virtuozzo.com>
ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS
This is a backport of the upstream change that removes the
GENERIC_VDSO_TIME_NS Kconfig symbol. TIME_NS now depends on
GENERIC_GETTIMEOFDAY instead, and the per-architecture selects and the
selftests config entry are dropped.
Link: https://lore.kernel.org/all/20250826-vdso-cleanups-v1-10-d9b65750e49f@linutronix.de
> diff --git a/lib/vdso/Kconfig b/lib/vdso/Kconfig
> index 45df764b49ad6..a1cc90133cb9e 100644
> --- a/lib/vdso/Kconfig
> +++ b/lib/vdso/Kconfig
> @@ -24,12 +24,6 @@ config GENERIC_COMPAT_VDSO
> help
> This config option enables the compat VDSO layer.
>
> -config GENERIC_VDSO_TIME_NS
> - bool
> - help
> - Selected by architectures which support time namespaces in the
> - VDSO
> -
[Severity: Low]
This removes the Kconfig symbol, but the shipped Virtuozzo config files
still set it:
config.vz10.minimal:
CONFIG_GENERIC_VDSO_TIME_NS=y
configs/kernel-6.12.0-x86_64.config:
CONFIG_GENERIC_VDSO_TIME_NS=y
configs/kernel-6.12.0-x86_64-debug.config:
CONFIG_GENERIC_VDSO_TIME_NS=y
Should these three lines be dropped in this patch as well?
As it stands, make oldconfig or olddefconfig will silently discard the
unknown symbol. The next config regeneration would then produce a spurious
diff, and any check comparing the shipped configs against regenerated
output would report a mismatch.
The effective x86 configuration should not change, since TIME_NS now
depends on GENERIC_GETTIMEOFDAY, which x86 selects unconditionally. The
upstream commit has no equivalent files, so this gap appears specific to
the downstream backport.
The later patches in the series do not appear to remove these references
either.
[ ... ]
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261009135929.3274885-1-eva.kurchatova@virtuozzo.com?part=1
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Devel] [PATCH hci-8.1 4/4] timens: freeze the offsets on the first join without the vDSO too
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 4/4] timens: freeze the offsets on the first join without the vDSO too Eva Kurchatova
@ 2026-10-09 14:06 ` no-reply
0 siblings, 0 replies; 9+ messages in thread
From: no-reply @ 2026-10-09 14:06 UTC (permalink / raw)
To: Eva Kurchatova, khorenko; +Cc: devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] timens: lockless frozen_offsets fast path lacks acquire/release ordering
--
commit 0c3eee5060109c37a2e00993e54d077407012d3c
Author: Eva Kurchatova <eva.kurchatova@virtuozzo.com>
timens: freeze the offsets on the first join without the vDSO too
This moves the freezing of a time namespace's offsets out of the vDSO
page setup code and into timens_commit(), so that kernels without a
generic vDSO also freeze the offsets on the first task join. The vDSO
page is now filled from the same place, where one exists.
Link: https://virtuozzo.atlassian.net/browse/VSTOR-148112
> diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
> --- a/kernel/time/namespace.c
> +++ b/kernel/time/namespace.c
[ ... ]
> +static void timens_freeze_offsets(struct time_namespace *ns)
> +{
> + if (ns == &init_time_ns)
> + return;
> +
> + /* Fast-path, taken by every task in namespace except the first. */
> + if (likely(ns->frozen_offsets))
> + return;
> +
> + guard(mutex)(&timens_offset_lock);
> + if (ns->frozen_offsets)
> + return;
> +
> + timens_vdso_setup_vvar_page(ns);
> + ns->frozen_offsets = true;
> +}
[Severity: Low]
Is the lockless fast path in timens_freeze_offsets() ordered against the
vvar page setup on weakly ordered CPUs?
The first joiner runs timens_vdso_setup_vvar_page() and then publishes the
flag with a plain store:
timens_vdso_setup_vvar_page(ns);
ns->frozen_offsets = true;
A second task joining the same namespace (via timens_on_fork() or
commit_nsset()) reads the flag without taking the mutex:
if (likely(ns->frozen_offsets))
return;
Neither side has release/acquire semantics. On arm64, powerpc or riscv,
could the second task observe frozen_offsets == true before the stores done
in timens_vdso_setup_vvar_page() (seq, clock_mode and the offsets set up by
timens_setup_vdso_clock_data()) are visible to it?
If so, that task would go on to read an un-namespaced or zeroed vvar page,
and its clocks would be wrong. This would be wrong output rather than
memory corruption. The window is very small and incidental
synchronisation, such as passing the namespace reference between tasks,
probably hides it in practice, so this may be speculative.
Would it make sense to use smp_store_release(&ns->frozen_offsets, true) for
the publication and smp_load_acquire(&ns->frozen_offsets) on the fast path?
> diff --git a/kernel/time/namespace_vdso.c b/kernel/time/namespace_vdso.c
> --- a/kernel/time/namespace_vdso.c
> +++ b/kernel/time/namespace_vdso.c
[ ... ]
> +/* Called once per namespace, under timens_offset_lock, before any task reads */
> +void timens_vdso_setup_vvar_page(struct time_namespace *ns)
> {
> + struct vdso_time_data *vdata = page_address(ns->vvar_page);
> + struct vdso_clock *vc = vdata->clock_data;
> unsigned int i;
>
> for (i = 0; i < CS_BASES; i++)
> timens_setup_vdso_clock_data(&vc[i], ns);
> }
[Severity: Low]
These are the plain stores to the shared vvar page that must be visible to
any task that sees frozen_offsets set through the lockless fast path in
timens_freeze_offsets(), as described above.
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261009135929.3274885-1-eva.kurchatova@virtuozzo.com?part=4
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Devel] [PATCH hci-8.1 3/4] ms/timens: Remove dependency on the vDSO
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 3/4] ms/timens: Remove dependency on the vDSO Eva Kurchatova
@ 2026-10-09 14:06 ` no-reply
0 siblings, 0 replies; 9+ messages in thread
From: no-reply @ 2026-10-09 14:06 UTC (permalink / raw)
To: khorenko, Eva Kurchatova; +Cc: devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] timens: TIME_NS now selectable on SPARC, whose private vDSO ignores offsets
--
commit 07e6081c6b5ec1169db1364534dcb49acce62383
Author: Eva Kurchatova <eva.kurchatova@virtuozzo.com>
ms/timens: Remove dependency on the vDSO
This backport drops "depends on GENERIC_GETTIMEOFDAY" from TIME_NS. It adds
a TIME_NS_VDSO symbol that gates the vDSO-specific code, and it stubs out
timens_commit() and find_timens_vvar_page() when TIME_NS_VDSO is not set.
Link: https://patch.msgid.link/20260326-vdso-timens-decoupling-v2-2-c82693a7775f@linutronix.de
> diff --git a/init/Kconfig b/init/Kconfig
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1306,12 +1306,14 @@ config UTS_NS
>
> config TIME_NS
> bool "TIME namespace"
> - depends on GENERIC_GETTIMEOFDAY
> default y
> help
> In this namespace boottime and monotonic clocks can be set.
> The time will keep going with the same pace.
>
> +config TIME_NS_VDSO
> + def_bool TIME_NS && GENERIC_GETTIMEOFDAY
> +
[Severity: Medium]
Can TIME_NS now be enabled on SPARC with a vDSO that ignores the offsets?
The commit message says "Now that all architectures using a real vDSO are
using the generic library, that dependency is not necessary anymore."
That does not appear to hold for SPARC in this tree. arch/sparc/Kconfig
selects only GENERIC_TIME_VSYSCALL. It does not select
GENERIC_GETTIMEOFDAY or HAVE_GENERIC_VDSO. The tree still contains
arch/sparc/vdso/vclock_gettime.c and
arch/sparc/vdso/vdso32/vclock_gettime.c.
Those files read the host vvar page directly:
arch/sparc/vdso/vclock_gettime.c:__vdso_clock_gettime() {
...
case CLOCK_MONOTONIC:
if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
break;
return do_monotonic(vvd, ts);
...
}
They have no time namespace offset handling. Before this patch, the
GENERIC_GETTIMEOFDAY dependency kept TIME_NS (default y) off on SPARC.
With the dependency gone, TIME_NS is on by default there.
TIME_NS_VDSO is then n, so these two stubs do nothing:
include/linux/time_namespace.h:
#else /* !CONFIG_TIME_NS_VDSO */
static inline void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
{
}
static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
On SPARC, unshare(CLONE_NEWTIME), setns() and writes to
/proc/<pid>/timens_offsets would all succeed. A task in a non-init time
namespace would still get host CLOCK_MONOTONIC and CLOCK_MONOTONIC_COARSE
from the vDSO, with no offset applied. The syscall path, /proc/uptime and
timerfd do apply the offset, so the two paths would disagree, and nothing
reports an error.
Should TIME_NS keep a dependency that excludes architectures whose vDSO is
not the generic one, such as SPARC? Alternatively, should the commit
message be corrected?
> diff --git a/include/linux/time_namespace.h b/include/linux/time_namespace.h
> --- a/include/linux/time_namespace.h
> +++ b/include/linux/time_namespace.h
[ ... ]
> +#ifdef CONFIG_TIME_NS_VDSO
> +extern void timens_commit(struct task_struct *tsk, struct time_namespace *ns);
> +struct page *find_timens_vvar_page(struct vm_area_struct *vma);
> +#else /* !CONFIG_TIME_NS_VDSO */
> +static inline void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
> +{
> +}
> +
> +static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
> +{
> + return NULL;
> +}
> +#endif /* CONFIG_TIME_NS_VDSO */
> +
> #endif /* _LINUX_TIMENS_H */
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261009135929.3274885-1-eva.kurchatova@virtuozzo.com?part=3
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-09 14:08 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-09 13:58 [Devel] [PATCH hci-8.1 0/4] timens: Remove dependency on the vDSO Eva Kurchatova
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 1/4] ms/vdso: Drop Kconfig GENERIC_VDSO_TIME_NS Eva Kurchatova
2026-10-09 14:04 ` no-reply
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 2/4] ms/vdso/timens: Move functions to new file Eva Kurchatova
2026-10-09 14:03 ` no-reply
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 3/4] ms/timens: Remove dependency on the vDSO Eva Kurchatova
2026-10-09 14:06 ` no-reply
2026-10-09 13:58 ` [Devel] [PATCH hci-8.1 4/4] timens: freeze the offsets on the first join without the vDSO too Eva Kurchatova
2026-10-09 14:06 ` no-reply
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox