* [patch 09/38] iommu/vt-d: Use sched_clock() instead of get_cycles()
From: Thomas Gleixner @ 2026-04-10 12:19 UTC (permalink / raw)
To: LKML
Cc: x86, Lu Baolu, iommu, Arnd Bergmann, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
Calculating the timeout from get_cycles() is a historical leftover without
any functional requirement.
Use ktime_get() instead.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: x86@kernel.org
Cc: Lu Baolu <baolu.lu@linux.intel.com>
Cc: iommu@lists.linux.dev
---
arch/x86/include/asm/iommu.h | 3 ---
drivers/iommu/intel/dmar.c | 4 ++--
drivers/iommu/intel/iommu.h | 8 ++++++--
3 files changed, 8 insertions(+), 7 deletions(-)
--- a/arch/x86/include/asm/iommu.h
+++ b/arch/x86/include/asm/iommu.h
@@ -18,9 +18,6 @@ extern bool x86_swiotlb_enable;
#define x86_swiotlb_enable false
#endif
-/* 10 seconds */
-#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
-
static inline int __init
arch_rmrr_sanity_check(struct acpi_dmar_reserved_memory *rmrr)
{
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -1606,9 +1606,9 @@ void qi_flush_pasid_cache(struct intel_i
*/
void dmar_disable_qi(struct intel_iommu *iommu)
{
+ ktime_t start_time = ktime_get();
unsigned long flags;
u32 sts;
- cycles_t start_time = get_cycles();
if (!ecap_qis(iommu->ecap))
return;
@@ -1624,7 +1624,7 @@ void dmar_disable_qi(struct intel_iommu
*/
while ((readl(iommu->reg + DMAR_IQT_REG) !=
readl(iommu->reg + DMAR_IQH_REG)) &&
- (DMAR_OPERATION_TIMEOUT > (get_cycles() - start_time)))
+ (DMAR_OPERATION_TIMEOUT > (ktime_get() - start_time)))
cpu_relax();
iommu->gcmd &= ~DMA_GCMD_QIE;
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -23,6 +23,7 @@
#include <linux/xarray.h>
#include <linux/perf_event.h>
#include <linux/pci.h>
+#include <linux/timekeeping.h>
#include <linux/generic_pt/iommu.h>
#include <asm/iommu.h>
@@ -360,14 +361,17 @@
/* PERFINTRSTS_REG */
#define DMA_PERFINTRSTS_PIS ((u32)1)
+#define DMAR_OPERATION_TIMEOUT (((ktime_t)10) * NSEC_PER_SEC)
+
#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
do { \
- cycles_t start_time = get_cycles(); \
+ ktime_t start_time = ktime_get(); \
+ \
while (1) { \
sts = op(iommu->reg + offset); \
if (cond) \
break; \
- if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\
+ if (DMAR_OPERATION_TIMEOUT < (ktime_get() - start_time))\
panic("DMAR hardware is malfunctioning\n"); \
cpu_relax(); \
} \
^ permalink raw reply
* [patch 08/38] x86/tsc: Use rdtsc() instead of get_cycles()
From: Thomas Gleixner @ 2026-04-10 12:19 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
This code knows that TSC is available so there is no point to use the TSC
feature guarded get_cycles().
No functional change.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
arch/x86/kernel/tsc.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -371,12 +371,12 @@ static u64 tsc_read_refs(u64 *p, int hpe
int i;
for (i = 0; i < MAX_RETRIES; i++) {
- t1 = get_cycles();
+ t1 = rdtsc();
if (hpet)
*p = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF;
else
*p = acpi_pm_read_early();
- t2 = get_cycles();
+ t2 = rdtsc();
if ((t2 - t1) < thresh)
return t2;
}
@@ -468,13 +468,13 @@ static unsigned long pit_calibrate_tsc(u
outb(latch & 0xff, 0x42);
outb(latch >> 8, 0x42);
- tsc = t1 = t2 = get_cycles();
+ tsc = t1 = t2 = rdtsc();
pitcnt = 0;
tscmax = 0;
tscmin = ULONG_MAX;
while ((inb(0x61) & 0x20) == 0) {
- t2 = get_cycles();
+ t2 = rdtsc();
delta = t2 - tsc;
tsc = t2;
if ((unsigned long) delta < tscmin)
@@ -553,9 +553,9 @@ static inline int pit_expect_msb(unsigne
if (!pit_verify_msb(val))
break;
prev_tsc = tsc;
- tsc = get_cycles();
+ tsc = rdtsc();
}
- *deltap = get_cycles() - prev_tsc;
+ *deltap = rdtsc() - prev_tsc;
*tscp = tsc;
/*
^ permalink raw reply
* [patch 07/38] treewide: Consolidate cycles_t
From: Thomas Gleixner @ 2026-04-10 12:19 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
Most architectures define cycles_t as unsigned long execpt:
- x86 requires it to be 64-bit independent of the 32-bit/64-bit build.
- parisc and mips define it as unsigned int
parisc has no real reason to do so as there are only a few usage sites
which either expand it to a 64-bit value or utilize only the lower
32bits.
mips has no real requirement either.
Move the typedef to types.h and provide a config switch to enforce the
64-bit type for x86.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
arch/Kconfig | 4 ++++
arch/alpha/include/asm/timex.h | 3 ---
arch/arm/include/asm/timex.h | 1 -
arch/loongarch/include/asm/timex.h | 2 --
arch/m68k/include/asm/timex.h | 2 --
arch/mips/include/asm/timex.h | 2 --
arch/nios2/include/asm/timex.h | 2 --
arch/parisc/include/asm/timex.h | 2 --
arch/powerpc/include/asm/timex.h | 4 +---
arch/riscv/include/asm/timex.h | 2 --
arch/s390/include/asm/timex.h | 2 --
arch/sparc/include/asm/timex_64.h | 1 -
arch/x86/Kconfig | 1 +
arch/x86/include/asm/tsc.h | 2 --
include/asm-generic/timex.h | 1 -
include/linux/types.h | 6 ++++++
16 files changed, 12 insertions(+), 25 deletions(-)
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -360,6 +360,10 @@ config ARCH_HAS_DMA_SET_UNCACHED
config ARCH_HAS_DMA_CLEAR_UNCACHED
bool
+# cycles_t is always 64bit wide
+config ARCH_HAS_CYCLES_T_64
+ bool
+
config ARCH_HAS_CPU_FINALIZE_INIT
bool
--- a/arch/alpha/include/asm/timex.h
+++ b/arch/alpha/include/asm/timex.h
@@ -15,9 +15,6 @@
* But this only means we'll force a reschedule every 8 seconds or so,
* which isn't an evil thing.
*/
-
-typedef unsigned int cycles_t;
-
static inline cycles_t get_cycles (void)
{
cycles_t ret;
--- a/arch/arm/include/asm/timex.h
+++ b/arch/arm/include/asm/timex.h
@@ -9,7 +9,6 @@
#ifndef _ASMARM_TIMEX_H
#define _ASMARM_TIMEX_H
-typedef unsigned long cycles_t;
// Temporary workaround
bool delay_read_timer(unsigned long *t);
--- a/arch/loongarch/include/asm/timex.h
+++ b/arch/loongarch/include/asm/timex.h
@@ -12,8 +12,6 @@
#include <asm/cpu.h>
#include <asm/cpu-features.h>
-typedef unsigned long cycles_t;
-
#define get_cycles get_cycles
static inline cycles_t get_cycles(void)
--- a/arch/m68k/include/asm/timex.h
+++ b/arch/m68k/include/asm/timex.h
@@ -7,8 +7,6 @@
#ifndef _ASMm68K_TIMEX_H
#define _ASMm68K_TIMEX_H
-typedef unsigned long cycles_t;
-
static inline cycles_t get_cycles(void)
{
return 0;
--- a/arch/mips/include/asm/timex.h
+++ b/arch/mips/include/asm/timex.h
@@ -29,8 +29,6 @@
* We know that all SMP capable CPUs have cycle counters.
*/
-typedef unsigned int cycles_t;
-
/*
* On R4000/R4400 an erratum exists such that if the cycle counter is
* read in the exact moment that it is matching the compare register,
--- a/arch/nios2/include/asm/timex.h
+++ b/arch/nios2/include/asm/timex.h
@@ -5,8 +5,6 @@
#ifndef _ASM_NIOS2_TIMEX_H
#define _ASM_NIOS2_TIMEX_H
-typedef unsigned long cycles_t;
-
extern cycles_t get_cycles(void);
#define get_cycles get_cycles
--- a/arch/parisc/include/asm/timex.h
+++ b/arch/parisc/include/asm/timex.h
@@ -9,8 +9,6 @@
#include <asm/special_insns.h>
-typedef unsigned long cycles_t;
-
static inline cycles_t get_cycles(void)
{
return mfctl(16);
--- a/arch/powerpc/include/asm/timex.h
+++ b/arch/powerpc/include/asm/timex.h
@@ -11,9 +11,7 @@
#include <asm/cputable.h>
#include <asm/vdso/timebase.h>
-typedef unsigned long cycles_t;
-
-static inline cycles_t get_cycles(void)
+ostatic inline cycles_t get_cycles(void)
{
return mftb();
}
--- a/arch/riscv/include/asm/timex.h
+++ b/arch/riscv/include/asm/timex.h
@@ -8,8 +8,6 @@
#include <asm/csr.h>
-typedef unsigned long cycles_t;
-
#ifdef CONFIG_RISCV_M_MODE
#include <asm/clint.h>
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -177,8 +177,6 @@ static inline void local_tick_enable(uns
set_clock_comparator(get_lowcore()->clock_comparator);
}
-typedef unsigned long cycles_t;
-
static __always_inline unsigned long get_tod_clock(void)
{
union tod_clock clk;
--- a/arch/sparc/include/asm/timex_64.h
+++ b/arch/sparc/include/asm/timex_64.h
@@ -10,7 +10,6 @@
#include <asm/timer.h>
/* Getting on the cycle counter on sparc64. */
-typedef unsigned long cycles_t;
#define get_cycles() tick_ops->get_tick()
#endif
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -79,6 +79,7 @@ config X86
select ARCH_HAS_CPU_FINALIZE_INIT
select ARCH_HAS_CPU_PASID if IOMMU_SVA
select ARCH_HAS_CURRENT_STACK_POINTER
+ select ARCH_HAS_CYCLES_T_64
select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE if !X86_PAE
select ARCH_HAS_DELAY_TIMER
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -67,8 +67,6 @@ static __always_inline u64 rdtsc_ordered
/*
* Standard way to access the cycle counter.
*/
-typedef unsigned long long cycles_t;
-
extern unsigned int cpu_khz;
extern unsigned int tsc_khz;
--- a/include/asm-generic/timex.h
+++ b/include/asm-generic/timex.h
@@ -5,7 +5,6 @@
/*
* If you have a cycle counter, return the value here.
*/
-typedef unsigned long cycles_t;
#ifndef get_cycles
static inline cycles_t get_cycles(void)
{
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -270,5 +270,11 @@ struct rcuwait {
struct task_struct __rcu *task;
};
+#ifdef CONFIG_ARCH_HAS_CYCLES_T_64
+typedef unsigned long long cycles_t;
+#else
+typedef unsigned long cycles_t;
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* _LINUX_TYPES_H */
^ permalink raw reply
* [patch 06/38] calibrate: Rework delay timer calibration
From: Thomas Gleixner @ 2026-04-10 12:18 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The header define in asm/timex,h and the naming of the function to read the
delay timer are confusing at best.
Convert it to a config switch selected by the archictures, which provide
the functionality, and rename the function to delay_read_timer(), which
makes the purpose clear. Move the declaration to linux/delay.h where it
belongs.
Remove the resulting empty asm/timex.h files as well.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
---
arch/Kconfig | 3 +++
arch/arm/Kconfig | 1 +
arch/arm/include/asm/delay.h | 1 -
arch/arm/include/asm/timex.h | 5 ++++-
arch/arm/lib/delay.c | 10 ++++------
arch/hexagon/Kconfig | 1 +
arch/hexagon/include/asm/timex.h | 20 --------------------
arch/hexagon/kernel/time.c | 8 +++++++-
arch/openrisc/Kconfig | 1 +
arch/openrisc/include/asm/timex.h | 2 --
arch/openrisc/lib/delay.c | 9 ++++-----
arch/riscv/Kconfig | 1 +
arch/riscv/include/asm/timex.h | 8 --------
arch/riscv/lib/delay.c | 7 ++++++-
arch/sparc/Kconfig | 1 +
arch/sparc/include/asm/timex_64.h | 2 --
arch/sparc/kernel/time_64.c | 4 ++--
arch/x86/Kconfig | 1 +
arch/x86/include/asm/timex.h | 2 --
arch/x86/lib/delay.c | 8 +++-----
include/asm-generic/timex.h | 7 -------
include/linux/delay.h | 2 ++
include/linux/timex.h | 2 --
init/calibrate.c | 19 +++++++++----------
24 files changed, 50 insertions(+), 75 deletions(-)
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -363,6 +363,9 @@ config ARCH_HAS_DMA_CLEAR_UNCACHED
config ARCH_HAS_CPU_FINALIZE_INIT
bool
+config ARCH_HAS_DELAY_TIMER
+ bool
+
# The architecture has a per-task state that includes the mm's PASID
config ARCH_HAS_CPU_PASID
bool
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -11,6 +11,7 @@ config ARM
select ARCH_HAS_CPU_FINALIZE_INIT if MMU
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL if MMU
+ select ARCH_HAS_DELAY_TIMER
select ARCH_HAS_DMA_ALLOC if MMU
select ARCH_HAS_DMA_OPS
select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE
--- a/arch/arm/include/asm/delay.h
+++ b/arch/arm/include/asm/delay.h
@@ -91,7 +91,6 @@ extern void __loop_udelay(unsigned long
extern void __loop_const_udelay(unsigned long);
/* Delay-loop timer registration. */
-#define ARCH_HAS_READ_CURRENT_TIMER
extern void register_current_timer_delay(const struct delay_timer *timer);
#endif /* __ASSEMBLY__ */
--- a/arch/arm/include/asm/timex.h
+++ b/arch/arm/include/asm/timex.h
@@ -10,7 +10,10 @@
#define _ASMARM_TIMEX_H
typedef unsigned long cycles_t;
-#define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; })
+// Temporary workaround
+bool delay_read_timer(unsigned long *t);
+
+#define get_cycles() ({ cycles_t c; delay_read_timer(&c) ? 0 : c; })
#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())
#endif
--- a/arch/arm/lib/delay.c
+++ b/arch/arm/lib/delay.c
@@ -12,7 +12,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/timex.h>
/*
* Default to the loop-based delay implementation.
@@ -27,15 +26,14 @@ static const struct delay_timer *delay_t
static bool delay_calibrated;
static u64 delay_res;
-int read_current_timer(unsigned long *timer_val)
+bool delay_read_timer(unsigned long *timer_val)
{
if (!delay_timer)
- return -ENXIO;
-
+ return false;
*timer_val = delay_timer->read_current_timer();
- return 0;
+ return true;
}
-EXPORT_SYMBOL_GPL(read_current_timer);
+EXPORT_SYMBOL_GPL(delay_read_timer);
static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
{
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -5,6 +5,7 @@ comment "Linux Kernel Configuration for
config HEXAGON
def_bool y
select ARCH_32BIT_OFF_T
+ select ARCH_HAS_DELAY_TIMER
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select ARCH_NO_PREEMPT
select ARCH_WANT_FRAME_POINTERS
--- a/arch/hexagon/include/asm/timex.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _ASM_TIMEX_H
-#define _ASM_TIMEX_H
-
-#include <asm-generic/timex.h>
-#include <asm/hexagon_vm.h>
-
-#define ARCH_HAS_READ_CURRENT_TIMER
-
-static inline int read_current_timer(unsigned long *timer_val)
-{
- *timer_val = __vmgettime();
- return 0;
-}
-
-#endif
--- a/arch/hexagon/kernel/time.c
+++ b/arch/hexagon/kernel/time.c
@@ -6,6 +6,7 @@
*/
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/interrupt.h>
@@ -17,7 +18,6 @@
#include <linux/of_irq.h>
#include <linux/module.h>
-#include <asm/delay.h>
#include <asm/hexagon_vm.h>
#include <asm/time.h>
@@ -231,3 +231,9 @@ void __udelay(unsigned long usecs)
cpu_relax(); /* not sure how this improves readability */
}
EXPORT_SYMBOL(__udelay);
+
+bool delay_read_timer(unsigned long *timer_val)
+{
+ *timer_val = __vmgettime();
+ return true;
+}
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -7,6 +7,7 @@
config OPENRISC
def_bool y
select ARCH_32BIT_OFF_T
+ select ARCH_HAS_DELAY_TIMER
select ARCH_HAS_DMA_SET_UNCACHED
select ARCH_HAS_DMA_CLEAR_UNCACHED
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
--- a/arch/openrisc/include/asm/timex.h
+++ b/arch/openrisc/include/asm/timex.h
@@ -25,6 +25,4 @@ static inline cycles_t get_cycles(void)
}
#define get_cycles get_cycles
-#define ARCH_HAS_READ_CURRENT_TIMER
-
#endif
--- a/arch/openrisc/lib/delay.c
+++ b/arch/openrisc/lib/delay.c
@@ -13,18 +13,17 @@
*/
#include <linux/kernel.h>
+#include <linux/delay.h>
#include <linux/export.h>
#include <linux/init.h>
-#include <linux/timex.h>
+
#include <asm/param.h>
-#include <asm/delay.h>
-#include <asm/timex.h>
#include <asm/processor.h>
-int read_current_timer(unsigned long *timer_value)
+bool delay_read_timer(unsigned long *timer_value)
{
*timer_value = get_cycles();
- return 0;
+ return true;
}
void __delay(unsigned long cycles)
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -29,6 +29,7 @@ config RISCV
select ARCH_HAS_DEBUG_VIRTUAL if MMU
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_WX
+ select ARCH_HAS_DELAY_TIMER
select ARCH_HAS_ELF_CORE_EFLAGS if BINFMT_ELF && ELF_CORE
select ARCH_HAS_FAST_MULTIPLIER
select ARCH_HAS_FORTIFY_SOURCE
--- a/arch/riscv/include/asm/timex.h
+++ b/arch/riscv/include/asm/timex.h
@@ -80,12 +80,4 @@ static inline u64 get_cycles64(void)
return ((u64)hi << 32) | lo;
}
#endif /* CONFIG_64BIT */
-
-#define ARCH_HAS_READ_CURRENT_TIMER
-static inline int read_current_timer(unsigned long *timer_val)
-{
- *timer_val = get_cycles();
- return 0;
-}
-
#endif /* _ASM_RISCV_TIMEX_H */
--- a/arch/riscv/lib/delay.c
+++ b/arch/riscv/lib/delay.c
@@ -6,7 +6,6 @@
#include <linux/delay.h>
#include <linux/math.h>
#include <linux/param.h>
-#include <linux/timex.h>
#include <linux/types.h>
#include <linux/export.h>
@@ -109,3 +108,9 @@ void ndelay(unsigned long nsecs)
__delay(ncycles >> NDELAY_SHIFT);
}
EXPORT_SYMBOL(ndelay);
+
+bool delay_read_timer(unsigned long *timer_val)
+{
+ *timer_val = get_cycles();
+ return true;
+}
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -70,6 +70,7 @@ config SPARC32
config SPARC64
def_bool 64BIT
select ALTERNATE_USER_ADDRESS_SPACE
+ select ARCH_HAS_DELAY_TIMER
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_KRETPROBES
--- a/arch/sparc/include/asm/timex_64.h
+++ b/arch/sparc/include/asm/timex_64.h
@@ -13,6 +13,4 @@
typedef unsigned long cycles_t;
#define get_cycles() tick_ops->get_tick()
-#define ARCH_HAS_READ_CURRENT_TIMER
-
#endif
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -894,8 +894,8 @@ unsigned long long sched_clock(void)
return ((get_tick() * quotient) >> SPARC64_NSEC_PER_CYC_SHIFT) - offset;
}
-int read_current_timer(unsigned long *timer_val)
+bool delay_read_timer(unsigned long *timer_val)
{
*timer_val = get_tick();
- return 0;
+ return true;
}
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -81,6 +81,7 @@ config X86
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE if !X86_PAE
+ select ARCH_HAS_DELAY_TIMER
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_DMA_OPS if GART_IOMMU || XEN
select ARCH_HAS_EARLY_DEBUG if KGDB
--- a/arch/x86/include/asm/timex.h
+++ b/arch/x86/include/asm/timex.h
@@ -14,6 +14,4 @@ static inline unsigned long random_get_e
}
#define random_get_entropy random_get_entropy
-#define ARCH_HAS_READ_CURRENT_TIMER
-
#endif /* _ASM_X86_TIMEX_H */
--- a/arch/x86/lib/delay.c
+++ b/arch/x86/lib/delay.c
@@ -14,12 +14,10 @@
#include <linux/export.h>
#include <linux/sched.h>
-#include <linux/timex.h>
#include <linux/preempt.h>
#include <linux/delay.h>
#include <asm/processor.h>
-#include <asm/delay.h>
#include <asm/timer.h>
#include <asm/mwait.h>
@@ -189,13 +187,13 @@ void use_mwaitx_delay(void)
delay_fn = delay_halt;
}
-int read_current_timer(unsigned long *timer_val)
+bool delay_read_timer(unsigned long *timer_val)
{
if (delay_fn == delay_tsc) {
*timer_val = rdtsc();
- return 0;
+ return true;
}
- return -1;
+ return false;
}
void __delay(unsigned long loops)
--- a/include/asm-generic/timex.h
+++ b/include/asm-generic/timex.h
@@ -13,11 +13,4 @@ static inline cycles_t get_cycles(void)
}
#endif
-/*
- * Architectures are encouraged to implement read_current_timer
- * and define this in order to avoid the expensive delay loop
- * calibration during boot.
- */
-#undef ARCH_HAS_READ_CURRENT_TIMER
-
#endif /* __ASM_GENERIC_TIMEX_H */
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -17,6 +17,8 @@ extern unsigned long loops_per_jiffy;
#include <asm/delay.h>
+bool delay_read_timer(unsigned long *t);
+
/*
* Using udelay() for intervals greater than a few milliseconds can
* risk overflow for high loops_per_jiffy (high bogomips) machines. The
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -156,8 +156,6 @@ extern int do_clock_adjtime(const clocki
extern void hardpps(const struct timespec64 *, const struct timespec64 *);
-int read_current_timer(unsigned long *timer_val);
-
/* The clock frequency of the i8253/i8254 PIT */
#define PIT_TICK_RATE 1193182ul
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -13,7 +13,6 @@
#include <linux/printk.h>
#include <linux/smp.h>
#include <linux/stddef.h>
-#include <linux/timex.h>
unsigned long lpj_fine;
unsigned long preset_lpj;
@@ -25,9 +24,9 @@ static int __init lpj_setup(char *str)
__setup("lpj=", lpj_setup);
-#ifdef ARCH_HAS_READ_CURRENT_TIMER
+#ifdef CONFIG_ARCH_HAS_DELAY_TIMER
-/* This routine uses the read_current_timer() routine and gets the
+/* This routine uses the delay_read_timer() routine and gets the
* loops per jiffy directly, instead of guessing it using delay().
* Also, this code tries to handle non-maskable asynchronous events
* (like SMIs)
@@ -48,13 +47,13 @@ static unsigned long calibrate_delay_dir
int min = -1;
int i;
- if (read_current_timer(&pre_start) < 0 )
+ if (!delay_read_timer(&pre_start))
return 0;
/*
* A simple loop like
* while ( jiffies < start_jiffies+1)
- * start = read_current_timer();
+ * start = delay_read_timer();
* will not do. As we don't really know whether jiffy switch
* happened first or timer_value was read first. And some asynchronous
* event can happen between these two events introducing errors in lpj.
@@ -72,22 +71,22 @@ static unsigned long calibrate_delay_dir
for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) {
pre_start = 0;
- read_current_timer(&start);
+ delay_read_timer(&start);
start_jiffies = jiffies;
while (time_before_eq(jiffies, start_jiffies + 1)) {
pre_start = start;
- read_current_timer(&start);
+ delay_read_timer(&start);
}
- read_current_timer(&post_start);
+ delay_read_timer(&post_start);
pre_end = 0;
end = post_start;
while (time_before_eq(jiffies, start_jiffies + 1 +
DELAY_CALIBRATION_TICKS)) {
pre_end = end;
- read_current_timer(&end);
+ delay_read_timer(&end);
}
- read_current_timer(&post_end);
+ delay_read_timer(&post_end);
timer_rate_max = (post_end - pre_start) /
DELAY_CALIBRATION_TICKS;
^ permalink raw reply
* [patch 05/38] treewide: Remove CLOCK_TICK_RATE
From: Thomas Gleixner @ 2026-04-10 12:18 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
This has been scheduled for removal more than a decade ago and the comments
related to it have been dutifully ignored. The last dependencies are gone.
Remove it along with various now empty asm/timex.h files.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
arch/alpha/include/asm/timex.h | 4 ----
arch/arc/include/asm/timex.h | 15 ---------------
arch/arm/mach-omap1/Kconfig | 2 +-
arch/hexagon/include/asm/timex.h | 3 ---
arch/m68k/include/asm/timex.h | 15 ---------------
arch/microblaze/include/asm/timex.h | 13 -------------
arch/mips/include/asm/timex.h | 8 --------
arch/openrisc/include/asm/timex.h | 3 ---
arch/parisc/include/asm/timex.h | 2 --
arch/powerpc/include/asm/timex.h | 2 --
arch/s390/include/asm/timex.h | 2 --
arch/sh/include/asm/timex.h | 24 ------------------------
arch/sparc/include/asm/timex.h | 2 +-
arch/sparc/include/asm/timex_32.h | 14 --------------
arch/sparc/include/asm/timex_64.h | 2 --
arch/um/include/asm/timex.h | 9 ---------
arch/x86/include/asm/timex.h | 3 ---
17 files changed, 2 insertions(+), 121 deletions(-)
--- a/arch/alpha/include/asm/timex.h
+++ b/arch/alpha/include/asm/timex.h
@@ -7,10 +7,6 @@
#ifndef _ASMALPHA_TIMEX_H
#define _ASMALPHA_TIMEX_H
-/* With only one or two oddballs, we use the RTC as the ticker, selecting
- the 32.768kHz reference clock, which nicely divides down to our HZ. */
-#define CLOCK_TICK_RATE 32768
-
/*
* Standard way to access the cycle counter.
* Currently only used on SMP for scheduling.
--- a/arch/arc/include/asm/timex.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- */
-
-#ifndef _ASM_ARC_TIMEX_H
-#define _ASM_ARC_TIMEX_H
-
-#define CLOCK_TICK_RATE 80000000 /* slated to be removed */
-
-#include <asm-generic/timex.h>
-
-/* XXX: get_cycles() to be implemented with RTSC insn */
-
-#endif /* _ASM_ARC_TIMEX_H */
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -74,7 +74,7 @@ config OMAP_32K_TIMER
currently only available for OMAP16XX, 24XX, 34XX, OMAP4/5 and DRA7XX.
On OMAP2PLUS this value is only used for CONFIG_HZ and
- CLOCK_TICK_RATE compile time calculation.
+ timer frequency compile time calculation.
The actual timer selection is done in the board file
through the (DT_)MACHINE_START structure.
--- a/arch/hexagon/include/asm/timex.h
+++ b/arch/hexagon/include/asm/timex.h
@@ -9,9 +9,6 @@
#include <asm-generic/timex.h>
#include <asm/hexagon_vm.h>
-/* Using TCX0 as our clock. CLOCK_TICK_RATE scheduled to be removed. */
-#define CLOCK_TICK_RATE 19200
-
#define ARCH_HAS_READ_CURRENT_TIMER
static inline int read_current_timer(unsigned long *timer_val)
--- a/arch/m68k/include/asm/timex.h
+++ b/arch/m68k/include/asm/timex.h
@@ -7,21 +7,6 @@
#ifndef _ASMm68K_TIMEX_H
#define _ASMm68K_TIMEX_H
-#ifdef CONFIG_COLDFIRE
-/*
- * CLOCK_TICK_RATE should give the underlying frequency of the tick timer
- * to make ntp work best. For Coldfires, that's the main clock.
- */
-#include <asm/coldfire.h>
-#define CLOCK_TICK_RATE MCF_CLK
-#else
-/*
- * This default CLOCK_TICK_RATE is probably wrong for many 68k boards
- * Users of those boards will need to check and modify accordingly
- */
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
-#endif
-
typedef unsigned long cycles_t;
static inline cycles_t get_cycles(void)
--- a/arch/microblaze/include/asm/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- */
-
-#ifndef _ASM_MICROBLAZE_TIMEX_H
-#define _ASM_MICROBLAZE_TIMEX_H
-
-#include <asm-generic/timex.h>
-
-#define CLOCK_TICK_RATE 1000 /* Timer input freq. */
-
-#endif /* _ASM_TIMEX_H */
--- a/arch/mips/include/asm/timex.h
+++ b/arch/mips/include/asm/timex.h
@@ -19,14 +19,6 @@
#include <asm/cpu-type.h>
/*
- * This is the clock rate of the i8253 PIT. A MIPS system may not have
- * a PIT by the symbol is used all over the kernel including some APIs.
- * So keeping it defined to the number for the PIT is the only sane thing
- * for now.
- */
-#define CLOCK_TICK_RATE 1193182
-
-/*
* Standard way to access the cycle counter.
* Currently only used on SMP for scheduling.
*
--- a/arch/openrisc/include/asm/timex.h
+++ b/arch/openrisc/include/asm/timex.h
@@ -25,9 +25,6 @@ static inline cycles_t get_cycles(void)
}
#define get_cycles get_cycles
-/* This isn't really used any more */
-#define CLOCK_TICK_RATE 1000
-
#define ARCH_HAS_READ_CURRENT_TIMER
#endif
--- a/arch/parisc/include/asm/timex.h
+++ b/arch/parisc/include/asm/timex.h
@@ -9,8 +9,6 @@
#include <asm/special_insns.h>
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
-
typedef unsigned long cycles_t;
static inline cycles_t get_cycles(void)
--- a/arch/powerpc/include/asm/timex.h
+++ b/arch/powerpc/include/asm/timex.h
@@ -11,8 +11,6 @@
#include <asm/cputable.h>
#include <asm/vdso/timebase.h>
-#define CLOCK_TICK_RATE 1024000 /* Underlying HZ */
-
typedef unsigned long cycles_t;
static inline cycles_t get_cycles(void)
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -177,8 +177,6 @@ static inline void local_tick_enable(uns
set_clock_comparator(get_lowcore()->clock_comparator);
}
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
-
typedef unsigned long cycles_t;
static __always_inline unsigned long get_tod_clock(void)
--- a/arch/sh/include/asm/timex.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * linux/include/asm-sh/timex.h
- *
- * sh architecture timex specifications
- */
-#ifndef __ASM_SH_TIMEX_H
-#define __ASM_SH_TIMEX_H
-
-/*
- * Only parts using the legacy CPG code for their clock framework
- * implementation need to define their own Pclk value. If provided, this
- * can be used for accurately setting CLOCK_TICK_RATE, otherwise we
- * simply fall back on the i8253 PIT value.
- */
-#ifdef CONFIG_SH_PCLK_FREQ
-#define CLOCK_TICK_RATE (CONFIG_SH_PCLK_FREQ / 4) /* Underlying HZ */
-#else
-#define CLOCK_TICK_RATE 1193180
-#endif
-
-#include <asm-generic/timex.h>
-
-#endif /* __ASM_SH_TIMEX_H */
--- a/arch/sparc/include/asm/timex.h
+++ b/arch/sparc/include/asm/timex.h
@@ -4,6 +4,6 @@
#if defined(__sparc__) && defined(__arch64__)
#include <asm/timex_64.h>
#else
-#include <asm/timex_32.h>
+#include <asm-generic/timex.h>
#endif
#endif
--- a/arch/sparc/include/asm/timex_32.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * linux/include/asm/timex.h
- *
- * sparc architecture timex specifications
- */
-#ifndef _ASMsparc_TIMEX_H
-#define _ASMsparc_TIMEX_H
-
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
-
-#include <asm-generic/timex.h>
-
-#endif
--- a/arch/sparc/include/asm/timex_64.h
+++ b/arch/sparc/include/asm/timex_64.h
@@ -9,8 +9,6 @@
#include <asm/timer.h>
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
-
/* Getting on the cycle counter on sparc64. */
typedef unsigned long cycles_t;
#define get_cycles() tick_ops->get_tick()
--- a/arch/um/include/asm/timex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __UM_TIMEX_H
-#define __UM_TIMEX_H
-
-#define CLOCK_TICK_RATE (HZ)
-
-#include <asm-generic/timex.h>
-
-#endif
--- a/arch/x86/include/asm/timex.h
+++ b/arch/x86/include/asm/timex.h
@@ -14,9 +14,6 @@ static inline unsigned long random_get_e
}
#define random_get_entropy random_get_entropy
-/* Assume we use the PIT time source for the clock tick */
-#define CLOCK_TICK_RATE PIT_TICK_RATE
-
#define ARCH_HAS_READ_CURRENT_TIMER
#endif /* _ASM_X86_TIMEX_H */
^ permalink raw reply
* [patch 04/38] x86: Use PIT_TICK_RATE instead of CLOCK_TICK_RATE
From: Thomas Gleixner @ 2026-04-10 12:18 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
CLOCK_TICK_RATE is only used in x86 but defined all over the tree for no
reason with comments that it's scheduled for removal for more than a
decade.
Use PIT_TICK_RATE for registering refined jiffies to get rid of the last
dependency.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
arch/x86/kernel/setup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1268,7 +1268,7 @@ void __init setup_arch(char **cmdline_p)
mcheck_init();
- register_refined_jiffies(CLOCK_TICK_RATE);
+ register_refined_jiffies(PIT_TICK_RATE);
#ifdef CONFIG_EFI
if (efi_enabled(EFI_BOOT))
^ permalink raw reply
* [patch 03/38] x86/apm: Remove last LATCH usage
From: Thomas Gleixner @ 2026-04-10 12:18 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
LATCH is a historical leftover and has been replaced with PIT_LATCH in all
other places a decade ago. Replace the last holdout and remove the
definition from jiffies.h.
This allows to remove the otherwise unused CLOCK_TICK_RATE define in the
next step.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
arch/x86/kernel/apm_32.c | 4 ++--
include/linux/jiffies.h | 3 ---
2 files changed, 2 insertions(+), 5 deletions(-)
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1196,9 +1196,9 @@ static void reinit_timer(void)
/* set the clock to HZ */
outb_p(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */
udelay(10);
- outb_p(LATCH & 0xff, PIT_CH0); /* LSB */
+ outb_p(PIT_LATCH & 0xff, PIT_CH0); /* LSB */
udelay(10);
- outb_p(LATCH >> 8, PIT_CH0); /* MSB */
+ outb_p(PIT_LATCH >> 8, PIT_CH0); /* MSB */
udelay(10);
raw_spin_unlock_irqrestore(&i8253_lock, flags);
#endif
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -56,9 +56,6 @@
#define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \
+ ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN))
-/* LATCH is used in the interval timer and ftape setup. */
-#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
-
extern void register_refined_jiffies(long clock_tick_rate);
/* TICK_USEC is the time between ticks in usec */
^ permalink raw reply
* [patch 02/38] x86: Cleanup include recursion hell
From: Thomas Gleixner @ 2026-04-10 12:18 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
Including a random architecture specific header which requires global
headers just to avoid including that header at the two usage sites is
really beyond lazy and tasteless. Including global headers just to get the
__percpu macro from linux/compiler_types.h falls into the same category.
Remove the linux/percpu.h and asm/cpumask.h includes from msr.h and smp.h
and fix the resulting fallout by a simple forward struct declaration and by
including the x86 specific asm/cpumask.h header where it is actually
required.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
arch/x86/include/asm/msr.h | 5 +++--
arch/x86/include/asm/pvclock.h | 1 +
arch/x86/include/asm/smp.h | 2 --
arch/x86/include/asm/vdso/gettimeofday.h | 5 ++---
arch/x86/kernel/cpu/mce/core.c | 1 +
arch/x86/kernel/nmi.c | 1 +
arch/x86/kernel/smpboot.c | 1 +
7 files changed, 9 insertions(+), 7 deletions(-)
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -8,12 +8,11 @@
#include <asm/asm.h>
#include <asm/errno.h>
-#include <asm/cpumask.h>
#include <uapi/asm/msr.h>
#include <asm/shared/msr.h>
+#include <linux/compiler_types.h>
#include <linux/types.h>
-#include <linux/percpu.h>
struct msr_info {
u32 msr_no;
@@ -256,6 +255,8 @@ int msr_set_bit(u32 msr, u8 bit);
int msr_clear_bit(u32 msr, u8 bit);
#ifdef CONFIG_SMP
+struct cpumask;
+
int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
int rdmsrq_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
--- a/arch/x86/include/asm/pvclock.h
+++ b/arch/x86/include/asm/pvclock.h
@@ -2,6 +2,7 @@
#ifndef _ASM_X86_PVCLOCK_H
#define _ASM_X86_PVCLOCK_H
+#include <asm/barrier.h>
#include <asm/clocksource.h>
#include <asm/pvclock-abi.h>
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -5,8 +5,6 @@
#include <linux/cpumask.h>
#include <linux/thread_info.h>
-#include <asm/cpumask.h>
-
DECLARE_PER_CPU_CACHE_HOT(int, cpu_number);
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -11,13 +11,12 @@
#define __ASM_VDSO_GETTIMEOFDAY_H
#ifndef __ASSEMBLER__
-
+#include <clocksource/hyperv_timer.h>
#include <uapi/linux/time.h>
+
#include <asm/vgtod.h>
#include <asm/unistd.h>
-#include <asm/msr.h>
#include <asm/pvclock.h>
-#include <clocksource/hyperv_timer.h>
#include <asm/vdso/sys_call.h>
#define VDSO_HAS_TIME 1
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -48,6 +48,7 @@
#include <linux/vmcore_info.h>
#include <asm/fred.h>
+#include <asm/cpumask.h>
#include <asm/cpu_device_id.h>
#include <asm/processor.h>
#include <asm/traps.h>
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -26,6 +26,7 @@
#include <linux/sched/clock.h>
#include <linux/kvm_types.h>
+#include <asm/cpumask.h>
#include <asm/cpu_entry_area.h>
#include <asm/traps.h>
#include <asm/mach_traps.h>
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -70,6 +70,7 @@
#include <asm/irq.h>
#include <asm/realmode.h>
#include <asm/cpu.h>
+#include <asm/cpumask.h>
#include <asm/numa.h>
#include <asm/tlbflush.h>
#include <asm/mtrr.h>
^ permalink raw reply
* [patch 01/38] percpu: Sanitize __percpu_qual include hell
From: Thomas Gleixner @ 2026-04-10 12:18 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
Slapping __percpu_qual into the next available header is sloppy at best.
It's required by __percpu which is defined in compiler_types.h and that is
meant to be included without requiring a boatload of other headers so that
a struct or function declaration can contain a __percpu qualifier w/o
further prerequisites.
This implicit dependency on linux/percpu.h makes that impossible and causes
a major problem when trying to seperate headers.
Create asm/percpu_types.h and move it there. Include that from
compiler_types.h and the whole recursion problem goes away.
Signed-off-by: Thomas Gleixner <tglx@kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
---
arch/x86/include/asm/percpu.h | 5 -----
arch/x86/include/asm/percpu_types.h | 17 +++++++++++++++++
include/asm-generic/Kbuild | 1 +
include/asm-generic/percpu_types.h | 20 ++++++++++++++++++++
include/linux/compiler_types.h | 1 +
5 files changed, 39 insertions(+), 5 deletions(-)
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -40,12 +40,10 @@
#endif
#define __percpu_prefix
-#define __percpu_seg_override CONCATENATE(__seg_, __percpu_seg)
#else /* !CONFIG_CC_HAS_NAMED_AS: */
#define __percpu_prefix __force_percpu_prefix
-#define __percpu_seg_override
#endif /* CONFIG_CC_HAS_NAMED_AS */
@@ -82,7 +80,6 @@
#define __force_percpu_prefix
#define __percpu_prefix
-#define __percpu_seg_override
#define PER_CPU_VAR(var) (var)__percpu_rel
@@ -92,8 +89,6 @@
# define __my_cpu_type(var) typeof(var)
# define __my_cpu_ptr(ptr) (ptr)
# define __my_cpu_var(var) (var)
-
-# define __percpu_qual __percpu_seg_override
#else
# define __my_cpu_type(var) typeof(var) __percpu_seg_override
# define __my_cpu_ptr(ptr) (__my_cpu_type(*(ptr))*)(__force uintptr_t)(ptr)
--- /dev/null
+++ b/arch/x86/include/asm/percpu_types.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_PERCPU_TYPES_H
+#define _ASM_X86_PERCPU_TYPES_H
+
+#if defined(CONFIG_SMP) && defined(CONFIG_CC_HAS_NAMED_AS)
+#define __percpu_seg_override CONCATENATE(__seg_, __percpu_seg)
+#else /* !CONFIG_CC_HAS_NAMED_AS: */
+#define __percpu_seg_override
+#endif
+
+#if defined(CONFIG_USE_X86_SEG_SUPPORT) && defined(USE_TYPEOF_UNQUAL)
+#define __percpu_qual __percpu_seg_override
+#endif
+
+#include <asm-generic/percpu_types.h>
+
+#endif
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -44,6 +44,7 @@ mandatory-y += module.lds.h
mandatory-y += msi.h
mandatory-y += pci.h
mandatory-y += percpu.h
+mandatory-y += percpu_types.h
mandatory-y += pgalloc.h
mandatory-y += preempt.h
mandatory-y += rqspinlock.h
--- /dev/null
+++ b/include/asm-generic/percpu_types.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_GENERIC_PERCPU_TYPES_H_
+#define _ASM_GENERIC_PERCPU_TYPES_H_
+
+#ifndef __ASSEMBLER__
+/*
+ * __percpu_qual is the qualifier for the percpu named address space.
+ *
+ * Most arches use generic named address space for percpu variables but
+ * some arches define percpu variables in different named address space
+ * (on the x86 arch, percpu variable may be declared as being relative
+ * to the %fs or %gs segments using __seg_fs or __seg_gs named address
+ * space qualifier).
+ */
+#ifndef __percpu_qual
+# define __percpu_qual
+#endif
+
+#endif /* __ASSEMBLER__ */
+#endif /* _ASM_GENERIC_PERCPU_TYPES_H_ */
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -41,6 +41,7 @@
# define BTF_TYPE_TAG(value) /* nothing */
#endif
+#include <asm/percpu_types.h>
#include <linux/compiler-context-analysis.h>
/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
^ permalink raw reply
* [patch 00/38] treewide: Cleanup LATCH, CLOCK_TICK_RATE and get_cycles() [ab]use
From: Thomas Gleixner @ 2026-04-10 12:18 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
First of all sorry for the insanely big Cc list, but people can't make
their mind up whether they want to be Cc'ed on everything or not. So I'm
opting for the worst case to cater to the people who want to be Cc'ed on
everything and assume that the rest of you got used to it by now. I really
wanted this to be more confined but a treewide cleanup does not give a lot
of options.
That said, let me explain what this is about.
1) LATCH
The LATCH define goes back to Linux version 0.1 and has survived until
today for the very wrong reasons.
Initially it was based on the x86 PIT frequency and also steered the
timekeeping conversions.
With the arrival of non x86 architectures it got changed to be based
on CLOCK_TICK_RATE in order not to change core code which depended on
LATCH.
That all got meaningless when timers, timekeeping and scheduling
infrastructure got rewritten more than two decades ago.
But there is still a lonely survivor in arch/x86/kernel/apm_32.c
which dates back to Linux 1.3.46 (Dec. 1995)
Which causes the next historical gem
2) CLOCK_TICK_RATE
When Linux got expanded beyond i386 LATCH was made "flexible" by
basing it on CLOCK_TICK_RATE to adjust for other frequencies than the
i386 PIT frequency.
As LATCH this got meaningless long ago and for amusement value it got
copied into new architectures arriving way after it got obsolete for
no reason but with comments to the effect that it's meaningless
And of course it had a lonely survivor in arch/x86/kernel/setup.c
despite it being only an alias for PIT_TICK_RATE for a very long time.
3) get_cycles()
That was introduced in 2.1.133pre4 (Dec. 1998) to utilize the back
then brand new TSC. The introduction broke everything except i386 SMP
with a CPU having a TSC and got then fixed up within a couple of days
with empty stubs returning 0 and #ifdeffery for CONFIG_TSC before the
2.2.0 release.
It's amusing that the naming deliberately ignored that TSC is the
acronym for Time Stamp Counter and not Cycle Counter and rather went
for the underlying coincidence that the TSC was running at the same
fixed frequency as the CPU core.
That turned out to be interesting when CPUs started to have frequency
scaling as the TSC then turned into a variable frequency random number
generator.
A decade later CPU designers came to senses and made the TSC invariant
usually running at the nominal CPU frequency, which allowed to use it
for reliable timekeeping purposes.
Non x86 architectures implemented get_cycles() based on whatever
continuously running counter they had available in their CPUs. Some of
them actual CPU cycle counters, but many of them running at a fixed
frequency which was completely unrelated to CPU cycles.
Around 2004/5 the timekeeping subsystem was completely rewritten and
made generic along with the scheduling clock and other related
infrastructure. With that rewrite get_cycles() got mostly obsolete,
but despite it being on the todo list of quite some people it never
ceased to exist and it was just a conveniance vehicle to base other
things like the recent addition of random_get_entropy() on top with a
hideous #ifdef/#define macro maze.
The other remaining use cases are mostly debugging and testing
code. Especially the usage in performance test code is hillarious at
best. While the name get_cycles() suggests that it provides access to
CPU cycles the reality is that it provides a unspecified counter for
most systems, where a lot of architectures simply return 0 because
they either do not have such a counter or did not bother to implement
it at all.
So in fact get_cycles() should have been renamed to get_bogo_cycles()
long ago matching the BogoMIPS "impress your friends" printk which
still exists for historical amusement value.
But the real solution is to remove it all together instead of
proliferating the bogosity.
This is what this series does with the following steps:
1) Cleanup some header dependency hell which got unearthed by the
restructuring and went unnoticed so far. It's amazing how the kernel
build system magically "works". This affects not only x86, but the
main fallout was observed and fixed there. ARM64 and MIPS are at
least as bad as they silently rely on the accidental asm/timex.h
include through a variety of generic headers to make their
architecture code compile. See the changelog and patches specific to
those two.
2) Removal of LATCH
3) Removal of CLOCK_TICK_RATE
4) Consolidation of cycles_t which was a typedef in asm/timex.h
5) Cleanup of read_current_timer() which is only used for delay
calibration and has nothing to do with get_cycles()
6) Cleanup of get_cycles() usage in debug and test code
7) Decoupling of random_get_entropy() from get_cycles()
8) Removal of asm/timex.h includes except for architecture internal
usage where necessary.
At the end get_cycles() survives in a couple of architectures as a purely
architecture internal implementation detail.
This survives compile testing on all architectures except hexagon and nios2
because the current cross tools based on gcc15 do not offer a compiler for
them anymore. Boot tested on x86 and some qemu instances covering only a
few architectures.
The series applies on v7.0-rc7 and with very minor conflicts on -next. It
is also available from git:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git getcycles-v1
Thanks,
tglx
---
arch/alpha/include/asm/timex.h | 33 --------
arch/arc/include/asm/timex.h | 15 ---
arch/arm/include/asm/timex.h | 16 ---
arch/arm64/include/asm/timex.h | 18 ----
arch/hexagon/include/asm/timex.h | 23 -----
arch/m68k/include/asm/timex.h | 42 ----------
arch/microblaze/include/asm/timex.h | 13 ---
arch/mips/include/asm/timex.h | 102 -------------------------
arch/sh/include/asm/timex.h | 24 -----
arch/sparc/include/asm/timex.h | 9 --
arch/sparc/include/asm/timex_32.h | 14 ---
arch/um/include/asm/timex.h | 9 --
b/Documentation/fb/udlfb.rst | 4
b/arch/Kconfig | 10 ++
b/arch/alpha/Kconfig | 1
b/arch/alpha/include/asm/random.h | 14 +++
b/arch/arm/Kconfig | 2
b/arch/arm/include/asm/delay.h | 1
b/arch/arm/include/asm/random.h | 14 +++
b/arch/arm/lib/delay.c | 14 +--
b/arch/arm/mach-omap1/Kconfig | 2
b/arch/arm64/Kconfig | 2
b/arch/arm64/include/asm/io.h | 5 -
b/arch/arm64/include/asm/ptp_vmclock.h | 12 ++
b/arch/arm64/include/asm/random.h | 11 ++
b/arch/arm64/include/asm/rqspinlock.h | 1
b/arch/arm64/kernel/time.c | 6 +
b/arch/arm64/kernel/topology.c | 1
b/arch/arm64/kernel/traps.c | 1
b/arch/arm64/kvm/emulate-nested.c | 1
b/arch/arm64/kvm/hyp/include/hyp/switch.h | 1
b/arch/arm64/lib/delay.c | 1
b/arch/hexagon/Kconfig | 1
b/arch/hexagon/kernel/time.c | 8 +
b/arch/loongarch/Kconfig | 1
b/arch/loongarch/include/asm/random.h | 15 +++
b/arch/loongarch/include/asm/timex.h | 2
b/arch/loongarch/kernel/relocate.c | 1
b/arch/loongarch/kernel/syscall.c | 1
b/arch/loongarch/lib/delay.c | 2
b/arch/m68k/Kconfig | 1
b/arch/m68k/amiga/config.c | 1
b/arch/m68k/include/asm/random.h | 14 +++
b/arch/m68k/kernel/time.c | 2
b/arch/mips/Kconfig | 1
b/arch/mips/generic/init.c | 1
b/arch/mips/include/asm/random.h | 7 +
b/arch/mips/kernel/pm-cps.c | 1
b/arch/mips/kernel/proc.c | 1
b/arch/mips/kernel/relocate.c | 2
b/arch/mips/kernel/time.c | 53 ++++++++++++
b/arch/mips/lib/dump_tlb.c | 1
b/arch/mips/mm/cache.c | 1
b/arch/nios2/Kconfig | 1
b/arch/nios2/include/asm/random.h | 14 +++
b/arch/nios2/include/asm/timex.h | 7 -
b/arch/nios2/kernel/time.c | 4
b/arch/openrisc/Kconfig | 2
b/arch/openrisc/include/asm/random.h | 12 ++
b/arch/openrisc/include/asm/timex.h | 10 --
b/arch/openrisc/lib/delay.c | 8 -
b/arch/parisc/Kconfig | 1
b/arch/parisc/include/asm/random.h | 12 ++
b/arch/parisc/include/asm/timex.h | 10 --
b/arch/parisc/kernel/processor.c | 1
b/arch/parisc/kernel/time.c | 1
b/arch/powerpc/Kconfig | 1
b/arch/powerpc/include/asm/random.h | 13 +++
b/arch/powerpc/include/asm/timex.h | 25 ------
b/arch/powerpc/platforms/cell/spufs/switch.c | 5 -
b/arch/riscv/Kconfig | 2
b/arch/riscv/include/asm/random.h | 25 ++++++
b/arch/riscv/include/asm/timex.h | 23 -----
b/arch/riscv/kernel/unaligned_access_speed.c | 1
b/arch/riscv/kvm/vcpu_timer.c | 1
b/arch/riscv/lib/delay.c | 8 +
b/arch/s390/Kconfig | 1
b/arch/s390/include/asm/random.h | 12 ++
b/arch/s390/include/asm/timex.h | 10 --
b/arch/s390/kernel/time.c | 1
b/arch/s390/kernel/vtime.c | 1
b/arch/sparc/Kconfig | 2
b/arch/sparc/include/asm/random.h | 15 +++
b/arch/sparc/include/asm/timex_64.h | 20 ----
b/arch/sparc/kernel/pcic.c | 1
b/arch/sparc/kernel/time_32.c | 1
b/arch/sparc/kernel/time_64.c | 4
b/arch/sparc/vdso/vclock_gettime.c | 1
b/arch/x86/Kconfig | 4
b/arch/x86/include/asm/iommu.h | 3
b/arch/x86/include/asm/msr.h | 5 -
b/arch/x86/include/asm/percpu.h | 5 -
b/arch/x86/include/asm/percpu_types.h | 17 ++++
b/arch/x86/include/asm/ptp_vmclock.h | 12 ++
b/arch/x86/include/asm/pvclock.h | 1
b/arch/x86/include/asm/random.h | 12 --
b/arch/x86/include/asm/smp.h | 2
b/arch/x86/include/asm/tsc.h | 11 --
b/arch/x86/include/asm/vdso/gettimeofday.h | 5 -
b/arch/x86/kernel/apm_32.c | 4
b/arch/x86/kernel/cpu/mce/core.c | 1
b/arch/x86/kernel/nmi.c | 1
b/arch/x86/kernel/setup.c | 2
b/arch/x86/kernel/smpboot.c | 1
b/arch/x86/kernel/tsc.c | 12 +-
b/arch/x86/lib/delay.c | 8 -
b/crypto/jitterentropy-kcapi.c | 1
b/crypto/tcrypt.c | 84 ++++++++++----------
b/drivers/iommu/intel/dmar.c | 4
b/drivers/iommu/intel/iommu.h | 8 +
b/drivers/irqchip/irq-apple-aic.c | 1
b/drivers/misc/sgi-gru/gruhandles.c | 20 +---
b/drivers/misc/sgi-gru/grukservices.c | 3
b/drivers/misc/sgi-gru/grutlbpurge.c | 5 -
b/drivers/net/arcnet/arc-rimi.c | 4
b/drivers/net/arcnet/arcdevice.h | 20 ----
b/drivers/net/arcnet/com20020.c | 6 -
b/drivers/net/arcnet/com90io.c | 6 -
b/drivers/net/arcnet/com90xx.c | 4
b/drivers/net/hamradio/baycom_epp.c | 51 ------------
b/drivers/net/wireless/ath/wil6210/debugfs.c | 2
b/drivers/net/wireless/ath/wil6210/txrx.c | 6 -
b/drivers/net/wireless/ath/wil6210/txrx_edma.c | 4
b/drivers/net/wireless/ath/wil6210/wil6210.h | 3
b/drivers/ptp/Kconfig | 6 -
b/drivers/ptp/ptp_vmclock.c | 6 -
b/drivers/video/fbdev/udlfb.c | 24 ++---
b/fs/ext4/mballoc.c | 4
b/include/asm-generic/Kbuild | 2
b/include/asm-generic/percpu_types.h | 20 ++++
b/include/linux/compiler_types.h | 1
b/include/linux/delay.h | 2
b/include/linux/jiffies.h | 3
b/include/linux/random.h | 18 ++++
b/include/linux/timex.h | 26 ------
b/include/linux/types.h | 6 +
b/init/calibrate.c | 19 ++--
b/kernel/kcsan/core.c | 3
b/kernel/kcsan/debugfs.c | 8 -
b/kernel/time/timer.c | 1
b/lib/interval_tree_test.c | 17 +---
b/lib/rbtree_test.c | 47 +++++------
b/lib/test_vmalloc.c | 10 +-
b/mm/kasan/sw_tags.c | 2
b/mm/slub.c | 37 +++++----
include/asm-generic/timex.h | 23 -----
146 files changed, 622 insertions(+), 796 deletions(-)
^ permalink raw reply
* Re: [PATCH v2] jbd2: fix deadlock in jbd2_journal_cancel_revoke()
From: Jan Kara @ 2026-04-10 8:52 UTC (permalink / raw)
To: Zhang Yi
Cc: linux-ext4, linux-fsdevel, linux-kernel, dave, tytso,
adilger.kernel, jack, ojaswin, ritesh.list, libaokun, yi.zhang,
yizhang089, yangerkun, yukuai
In-Reply-To: <20260409114204.917154-1-yi.zhang@huaweicloud.com>
On Thu 09-04-26 19:42:03, Zhang Yi wrote:
> From: Zhang Yi <yi.zhang@huawei.com>
>
> Commit f76d4c28a46a ("fs/jbd2: use sleeping version of
> __find_get_block()") changed jbd2_journal_cancel_revoke() to use
> __find_get_block_nonatomic() which holds the folio lock instead of
> i_private_lock. This breaks the lock ordering (folio -> buffer) and
> causes an ABBA deadlock when the filesystem blocksize < pagesize:
>
> T1 T2
> ext4_mkdir()
> ext4_init_new_dir()
> ext4_append()
> ext4_getblk()
> lock_buffer() <- A
> sync_blockdev()
> blkdev_writepages()
> writeback_iter()
> writeback_get_folio()
> folio_lock() <- B
> ext4_journal_get_create_access()
> jbd2_journal_cancel_revoke()
> __find_get_block_nonatomic()
> folio_lock() <- B
> block_write_full_folio()
> lock_buffer() <- A
>
> This can occasionally cause generic/013 to hang.
>
> Fix by only calling __find_get_block_nonatomic() when the passed
> buffer_head doesn't belong to the bdev, which is the only case that we
> need to look up its bdev alias. Otherwise, the lookup is redundant since
> the found buffer_head is equal to the one we passed in.
>
> Fixes: f76d4c28a46a ("fs/jbd2: use sleeping version of __find_get_block()")
> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Indeed, good catch! Sadly, lockep didn't tell us about this as it tracks
neither buffer locks nor folio locks... The patch looks good. Feel free to
add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> v1->v2:
> - Switch to using sb_is_blkdev_sb() to check whether the bh belongs to
> the bdev.
>
> fs/jbd2/revoke.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
> index 9016ddb82447..e4c2fbd381f1 100644
> --- a/fs/jbd2/revoke.c
> +++ b/fs/jbd2/revoke.c
> @@ -428,6 +428,7 @@ void jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
> journal_t *journal = handle->h_transaction->t_journal;
> int need_cancel;
> struct buffer_head *bh = jh2bh(jh);
> + struct address_space *bh_mapping = bh->b_folio->mapping;
>
> jbd2_debug(4, "journal_head %p, cancelling revoke\n", jh);
>
> @@ -464,13 +465,14 @@ void jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
> * buffer_head? If so, we'd better make sure we clear the
> * revoked status on any hashed alias too, otherwise the revoke
> * state machine will get very upset later on. */
> - if (need_cancel) {
> + if (need_cancel && !sb_is_blkdev_sb(bh_mapping->host->i_sb)) {
> struct buffer_head *bh2;
> +
> bh2 = __find_get_block_nonatomic(bh->b_bdev, bh->b_blocknr,
> bh->b_size);
> if (bh2) {
> - if (bh2 != bh)
> - clear_buffer_revoked(bh2);
> + WARN_ON_ONCE(bh2 == bh);
> + clear_buffer_revoked(bh2);
> __brelse(bh2);
> }
> }
> --
> 2.52.0
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH v2] ext4: improve str2hashbuf by processing 4-byte chunks and removing function pointers
From: Guan-Chun Wu @ 2026-04-10 6:28 UTC (permalink / raw)
To: Theodore Tso
Cc: adilger.kernel, linux-ext4, linux-kernel, visitorckw,
david.laight.linux
In-Reply-To: <20260409141050.GA59468@macsyma-wired.lan>
On Thu, Apr 09, 2026 at 10:10:50AM -0400, Theodore Tso wrote:
> On Sat, Nov 22, 2025 at 12:39:29PM +0800, Guan-Chun Wu wrote:
> > The original byte-by-byte implementation with modulo checks is less
> > efficient. Refactor str2hashbuf_unsigned() and str2hashbuf_signed()
> > to process input in explicit 4-byte chunks instead of using a
> > modulus-based loop to emit words byte by byte.
> >
> > Additionally, the use of function pointers for selecting the appropriate
> > str2hashbuf implementation has been removed. Instead, the functions are
> > directly invoked based on the hash type, eliminating the overhead of
> > dynamic function calls.
> >
> > Performance test (x86_64, Intel Core i7-10700 @ 2.90GHz, average over 10000
> > runs, using kernel module for testing):
> >
> > len | orig_s | new_s | orig_u | new_u
> > ----+--------+-------+--------+-------
> > 1 | 70 | 71 | 63 | 63
> > 8 | 68 | 64 | 64 | 62
> > 32 | 75 | 70 | 75 | 63
> > 64 | 96 | 71 | 100 | 68
> > 255 | 192 | 108 | 187 | 84
> >
> > This change improves performance, especially for larger input sizes.
> >
> > Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw>
>
> Apologies for the delay in looking at this. It fell through the
> cracks on my end.
>
> Because of how I'm a bit late with reviewing patches before the merge
> window, I'm going to be very conservative in which patches I'm going
> to land. So this is going to be deferred until the next cycle, but I
> wanted to let you know that I haven't forgotten about it.
>
> If this was a comprehensive set of Kunit tests for fs/ext4/hash.c, I
> might have taken it. And that's something that I would look at adding
> for the next cycle, but if you'd be interested in creating the kunit
> tests for hash.c, that would be great.
>
> - Ted
Thanks for the update.
I'd be happy to add Kunit tests for fs/ext4/hash.c. I'll work on them and
send a v3 patchset with the tests and the optimization in the next cycle.
Best regards,
Guan-Chun
^ permalink raw reply
* [PATCH] ext4: make mballoc max prealloc size configurable
From: guzebing @ 2026-04-10 3:56 UTC (permalink / raw)
To: tytso, adilger.kernel, libaokun, jack, ojaswin, ritesh.list,
yi.zhang, guzebing
Cc: linux-kernel, linux-ext4
From: Guzebing <guzebing@bytedance.com>
Add per-superblock sysfs knob mb_max_prealloc_kb (min 8MiB, roundup
pow2) and use it in request normalization.
When multiple tasks write to different files on the same filesystem
concurrently, each file ends up with 8 MiB extents. If the preallocation
size is increased, the resulting extent size grows accordingly. Due
to the readahead mechanism on NVMe SSDs, files with larger extents
achieve higher sequential read throughput.
On an ext4 filesystem on an NVMe Gen4 data drive, dd read throughput
for a file with 8 MiB extents is 455 MB/s, while for a file with
32 MiB extents it reaches 702 MB/s.
Steps to reproduce:
1.Configure the maximum preallocation size to 8 MiB or 32 MiB:
echo 8192 > /sys/fs/ext4/nvme13n1/mb_max_prealloc_kb
echo 32768 > /sys/fs/ext4/nvme13n1/mb_max_prealloc_kb
2.Run the following commands simultaneously so that the extents of
the two files are physically interleaved, resulting in 8 MiB or 32 MiB
extents:
dd if=/dev/zero of=/mnt/store1/501.txt bs=128K count=80K oflag=direct
dd if=/dev/zero of=/mnt/store1/502.txt bs=128K count=80K oflag=direct
3.Read back the file and measure the read throughput:
dd if=/mnt/store1/501.txt of=/dev/null bs=128K count=80K iflag=direct
Signed-off-by: Guzebing <guzebing@bytedance.com>
---
Documentation/ABI/testing/sysfs-fs-ext4 | 8 +++++++
fs/ext4/ext4.h | 1 +
fs/ext4/mballoc.c | 2 +-
fs/ext4/super.c | 1 +
fs/ext4/sysfs.c | 28 ++++++++++++++++++++++++-
5 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-fs-ext4 b/Documentation/ABI/testing/sysfs-fs-ext4
index 2edd0a6672d3a..316ae1d1ec18b 100644
--- a/Documentation/ABI/testing/sysfs-fs-ext4
+++ b/Documentation/ABI/testing/sysfs-fs-ext4
@@ -48,6 +48,14 @@ Description:
will have its blocks allocated out of its own unique
preallocation pool.
+What: /sys/fs/ext4/<disk>/mb_max_prealloc_kb
+Date: April 2026
+Contact: "Linux Ext4 Development List" <linux-ext4@vger.kernel.org>
+Description:
+ Maximum size (in kilobytes) used by the multiblock allocator's
+ normalized request preallocation heuristic. Values are rounded
+ up to a power of two and clamped to a minimum of 8192 (8MiB).
+
What: /sys/fs/ext4/<disk>/inode_readahead_blks
Date: March 2008
Contact: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 7617e2d454ea5..bce99740740f5 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1634,6 +1634,7 @@ struct ext4_sb_info {
unsigned int s_mb_best_avail_max_trim_order;
unsigned int s_sb_update_sec;
unsigned int s_sb_update_kb;
+ unsigned int s_mb_max_prealloc_kb;
/* where last allocation was done - for stream allocation */
ext4_group_t *s_mb_last_groups;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index bb58eafb87bcd..f5f63c56fcdac 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4589,7 +4589,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
(8<<20)>>bsbits, max, 8 * 1024)) {
start_off = ((loff_t)ac->ac_o_ex.fe_logical >>
(23 - bsbits)) << 23;
- size = 8 * 1024 * 1024;
+ size = (loff_t)sbi->s_mb_max_prealloc_kb << 10;
} else {
start_off = (loff_t) ac->ac_o_ex.fe_logical << bsbits;
size = (loff_t) EXT4_C2B(sbi,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index a34efb44e73d7..f815e31657cc9 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -5447,6 +5447,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
sbi->s_stripe = 0;
}
sbi->s_extent_max_zeroout_kb = 32;
+ sbi->s_mb_max_prealloc_kb = 8 * 1024;
/*
* set up enough so that it can read an inode
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 923b375e017fa..6339492eb2fa7 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -10,6 +10,8 @@
#include <linux/time.h>
#include <linux/fs.h>
+#include <linux/log2.h>
+#include <linux/limits.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
@@ -41,6 +43,7 @@ typedef enum {
attr_pointer_atomic,
attr_journal_task,
attr_err_report_sec,
+ attr_mb_max_prealloc_kb,
} attr_id_t;
typedef enum {
@@ -115,6 +118,25 @@ static ssize_t reserved_clusters_store(struct ext4_sb_info *sbi,
return count;
}
+static ssize_t mb_max_prealloc_kb_store(struct ext4_sb_info *sbi,
+ const char *buf, size_t count)
+{
+ unsigned int v;
+ int ret;
+ unsigned long rounded;
+
+ ret = kstrtouint(skip_spaces(buf), 0, &v);
+ if (ret)
+ return ret;
+ if (v < 8192)
+ v = 8192;
+ rounded = roundup_pow_of_two((unsigned long)v);
+ if (rounded > UINT_MAX)
+ return -EINVAL;
+ sbi->s_mb_max_prealloc_kb = (unsigned int)rounded;
+ return count;
+}
+
static ssize_t trigger_test_error(struct ext4_sb_info *sbi,
const char *buf, size_t count)
{
@@ -288,6 +310,7 @@ EXT4_RW_ATTR_SBI_UI(mb_prefetch_limit, s_mb_prefetch_limit);
EXT4_RW_ATTR_SBI_UL(last_trim_minblks, s_last_trim_minblks);
EXT4_RW_ATTR_SBI_UI(sb_update_sec, s_sb_update_sec);
EXT4_RW_ATTR_SBI_UI(sb_update_kb, s_sb_update_kb);
+EXT4_ATTR_OFFSET(mb_max_prealloc_kb, 0644, mb_max_prealloc_kb, ext4_sb_info, s_mb_max_prealloc_kb);
static unsigned int old_bump_val = 128;
EXT4_ATTR_PTR(max_writeback_mb_bump, 0444, pointer_ui, &old_bump_val);
@@ -341,6 +364,7 @@ static struct attribute *ext4_attrs[] = {
ATTR_LIST(last_trim_minblks),
ATTR_LIST(sb_update_sec),
ATTR_LIST(sb_update_kb),
+ ATTR_LIST(mb_max_prealloc_kb),
ATTR_LIST(err_report_sec),
NULL,
};
@@ -431,6 +455,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a,
case attr_mb_order:
case attr_pointer_pi:
case attr_pointer_ui:
+ case attr_mb_max_prealloc_kb:
if (a->attr_ptr == ptr_ext4_super_block_offset)
return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr));
return sysfs_emit(buf, "%u\n", *((unsigned int *) ptr));
@@ -557,6 +582,8 @@ static ssize_t ext4_attr_store(struct kobject *kobj,
return reserved_clusters_store(sbi, buf, len);
case attr_inode_readahead:
return inode_readahead_blks_store(sbi, buf, len);
+ case attr_mb_max_prealloc_kb:
+ return mb_max_prealloc_kb_store(sbi, buf, len);
case attr_trigger_test_error:
return trigger_test_error(sbi, buf, len);
case attr_err_report_sec:
@@ -695,4 +722,3 @@ void ext4_exit_sysfs(void)
remove_proc_entry(proc_dirname, NULL);
ext4_proc_root = NULL;
}
-
--
2.20.1
^ permalink raw reply related
* Re: [RFC v4 0/7] ext4: fast commit: snapshot inode state for FC log
From: Theodore Tso @ 2026-04-10 1:18 UTC (permalink / raw)
To: Li Chen
Cc: Zhang Yi, Andreas Dilger, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, linux-ext4, linux-trace-kernel, linux-kernel
In-Reply-To: <20260120112538.132774-1-me@linux.beauty>
On Tue, Jan 20, 2026 at 07:25:29PM +0800, Li Chen wrote:
> Hi,
>
> (This RFC v4 series is based on linux-next tag next-20260106, plus the
> prerequisite patch "ext4: fast commit: make s_fc_lock reclaim-safe" posted at:
> https://lore.kernel.org/all/20260106120621.440126-1-me@linux.beauty/)
Can you take a look at the Sashiko reviews here:
https://sashiko.dev/#/patchset/20260408112020.716706-1-me%40linux.beauty
There seems to be at least one legitimate concern, which is the
potential cur_lblk overflow. There are a couple of others which I
think is real; could you please look at their review comments?
Thanks,
- Ted
^ permalink raw reply
* [GIT PULL 2/2] fuse4fs: fork a low level fuse server
From: Darrick J. Wong @ 2026-04-09 20:15 UTC (permalink / raw)
To: tytso; +Cc: amir73il, djwong, linux-ext4
In-Reply-To: <20260409201302.GD6192@frogsfrogsfrogs>
Hi Ted,
Please pull this branch with changes for ext4.
As usual, I did a test-merge with the main upstream branch as of a few
minutes ago, and didn't see any conflicts. Please let me know if you
encounter any problems.
The following changes since commit c137760397ef6671832548bcd256778f57f49c2d:
fuse2fs: drop fuse 2.x support code (2026-04-09 13:00:40 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/djwong/e2fsprogs.git tags/fuse4fs-fork_2026-04-09
for you to fetch changes up to 951a10258cada0508e185c58ebec74c47b0eb774:
fuse4fs: create incore reverse orphan list (2026-04-09 13:00:42 -0700)
----------------------------------------------------------------
fuse4fs: fork a low level fuse server [02/11]
Whilst developing the fuse2fs+iomap prototype, I discovered a
fundamental design limitation of the upper-level libfuse API: hardlinks.
The upper level fuse library really wants to communicate with the fuse
server with file paths, instead of using inode numbers. This works
great for filesystems that don't have inodes, create files dynamically
at runtime, or lack stable inode numbers.
Unfortunately, the libfuse path abstraction assigns a unique nodeid to
every child file in the entire filesystem, without regard to hard links.
In other words, a hardlinked regular file may have one ondisk inode
number but multiple kernel inodes. For classic fuse2fs this isn't a
problem because all file access goes through the fuse server and the big
library lock protects us from corruption.
For fuse2fs + iomap this is a disaster because we rely on the kernel to
coordinate access to inodes. For hardlinked files, we *require* that
there only be one in-kernel inode for each ondisk inode.
The path based mechanism is also very inefficient for fuse2fs. Every
time a file is accessed, the upper level libfuse passes a new nodeid to
the kernel, and on every file access the kernel passes that same nodeid
back to libfuse. libfuse then walks its internal directory entry cache
to construct a path string for that nodeid and hands it to fuse2fs.
fuse2fs then walks the ondisk directory structure to find the ext2 inode
number. Every time.
Create a new fuse4fs server from fuse2fs that uses the lowlevel fuse
API. This affords us direct control over nodeids and eliminates the
path wrangling. Hardlinks can be supported when iomap is turned on,
and metadata-heavy workloads run twice as fast.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
----------------------------------------------------------------
Darrick J. Wong (23):
fuse2fs: separate libfuse3 and fuse2fs detection in configure
fuse2fs: start porting fuse2fs to lowlevel libfuse API
debian: create new package for fuse4fs
fuse4fs: namespace some helpers
fuse4fs: convert to low level API
libsupport: port the kernel list.h to libsupport
libsupport: add a cache
cache: disable debugging
cache: use modern list iterator macros
cache: embed struct cache in the owner
cache: pass cache pointer to callbacks
cache: pass a private data pointer through cache_walk
cache: add a helper to grab a new refcount for a cache_node
cache: return results of a cache flush
cache: add a "get only if incore" flag to cache_node_get
cache: support gradual expansion
cache: support updating maxcount and flags
cache: support channging flags
cache: implement automatic shrinking
fuse4fs: add cache to track open files
fuse4fs: use the orphaned inode list
fuse4fs: implement FUSE_TMPFILE
fuse4fs: create incore reverse orphan list
lib/ext2fs/jfs_compat.h | 2 +-
lib/ext2fs/kernel-list.h | 111 -
lib/support/cache.h | 184 ++
lib/support/list.h | 901 +++++++
lib/support/xbitops.h | 128 +
Makefile.in | 3 +-
configure | 441 ++--
configure.ac | 156 +-
debian/control | 12 +-
debian/fuse4fs.install | 2 +
debian/fuse4fs.links | 3 +
debian/rules | 11 +
debugfs/Makefile.in | 12 +-
e2fsck/Makefile.in | 56 +-
fuse4fs/Makefile.in | 193 ++
fuse4fs/fuse4fs.1.in | 118 +
fuse4fs/fuse4fs.c | 6451 ++++++++++++++++++++++++++++++++++++++++++++++
lib/config.h.in | 3 +
lib/e2p/Makefile.in | 4 +-
lib/ext2fs/Makefile.in | 14 +-
lib/support/Makefile.in | 8 +-
lib/support/cache.c | 882 +++++++
misc/Makefile.in | 18 +-
misc/tune2fs.c | 4 -
24 files changed, 9248 insertions(+), 469 deletions(-)
delete mode 100644 lib/ext2fs/kernel-list.h
create mode 100644 lib/support/cache.h
create mode 100644 lib/support/list.h
create mode 100644 lib/support/xbitops.h
create mode 100644 debian/fuse4fs.install
create mode 100644 debian/fuse4fs.links
create mode 100644 fuse4fs/Makefile.in
create mode 100644 fuse4fs/fuse4fs.1.in
create mode 100644 fuse4fs/fuse4fs.c
create mode 100644 lib/support/cache.c
^ permalink raw reply
* [GIT PULL 1/2] fuse2fs: upgrade to libfuse 3.17
From: Darrick J. Wong @ 2026-04-09 20:14 UTC (permalink / raw)
To: tytso; +Cc: amir73il, djwong, linux-ext4
In-Reply-To: <20260409201302.GD6192@frogsfrogsfrogs>
Hi Ted,
Please pull this branch with changes for ext4.
As usual, I did a test-merge with the main upstream branch as of a few
minutes ago, and didn't see any conflicts. Please let me know if you
encounter any problems.
The following changes since commit 43643a57fb2d3368fbacd181a8cd713102d52a1a:
tests/f_opt_extent: use tune2fs from the build tree in the test script (2026-04-03 11:20:06 -0400)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/djwong/e2fsprogs.git tags/fuse2fs-library-upgrade_2026-04-09
for you to fetch changes up to c137760397ef6671832548bcd256778f57f49c2d:
fuse2fs: drop fuse 2.x support code (2026-04-09 13:00:40 -0700)
----------------------------------------------------------------
fuse2fs: upgrade to libfuse 3.17 [01/11]
In preparation to start hacking on fuse2fs and iomap, upgrade fuse2fs
library support to 3.17, which is the latest upstream release as of this
writing. Drop support for libfuse2, which is now very obsolete.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
----------------------------------------------------------------
Darrick J. Wong (5):
libsupport: change get_thread_id return type to unsigned long long
fuse2fs: bump library version
fuse2fs: wrap the fuse_set_feature_flag helper for older libfuse
fuse2fs: disable nfs exports
fuse2fs: drop fuse 2.x support code
lib/support/thread.h | 2 +-
configure | 358 +++++----------------------------------------------
configure.ac | 85 +++++-------
lib/support/thread.c | 4 +-
misc/fuse2fs.c | 252 ++++++++----------------------------
5 files changed, 118 insertions(+), 583 deletions(-)
^ permalink raw reply
* [PULLBOMB v3 1.48] fuse4fs: drop libfuse2, add new server
From: Darrick J. Wong @ 2026-04-09 20:13 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: linux-ext4, amir73il
Hi Ted,
As promised during this morning's ext4 call, this large patchbomb
contains the remaining improvements that I'd like to make to fuse2fs
before integrating iomap.
The first pull request drops libfuse2 support from e2fsprogs.
The second pull request creates a new fuse ext* server (fuse4fs) which
uses the lowlevel FUSE API instead of the high level one. The major
advantage of using the lowlevel API is that all file operations are
performed in terms of inodes instead of paths. As a result, fuse4fs has
MUCH less overhead than fuse2fs because we avoid the overhead of having
libfuse translate inode numbers to paths only to have fuse2fs translate
paths back into inode numbers.
Obviously, this stuff should go into e2fsprogs 1.48, not a 1.47.x stable
release. This patchbomb hasn't changed much since its last posting on
12 Mar 2026. The range-diff between then and now is appended below;
there aren't really any changes other than the effects of rebasing
against today's next branch and adapting to using autoheader(1).
One curious thing: I saw in [1] that you applied my get_thread_id
change, but it isn't in -next yet. These PRs might not merge properly.
Obviously it's no big deal for me to rebase and send new PRs.
--D
-: -------------- > 1: 91f5b6651553fe fuse2fs: bump library version
1: 7e7bb349a384f7 = 2: cf80ae2e89ba2f fuse2fs: wrap the fuse_set_feature_flag helper for older libfuse
2: 631d3f8d14b613 = 3: c7d947ac718bb4 fuse2fs: disable nfs exports
3: 96ca2a29cc7dcb ! 4: c137760397ef66 fuse2fs: drop fuse 2.x support code
@@ configure.ac: then
AC_DEFINE_UNQUOTED(FUSE_USE_VERSION, $FUSE_USE_VERSION,
[Define to the version of FUSE to use])
fi
## misc/fuse2fs.c ##
@@
- #endif /* __SET_FOB_FOR_FUSE */
#include <inttypes.h>
#include "ext2fs/ext2fs.h"
#include "ext2fs/ext2_fs.h"
#include "ext2fs/ext2fsP.h"
#include "support/bthread.h"
+ #include "support/thread.h"
-#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
-# define FUSE_PLATFORM_OPTS ""
-#else
-# ifdef __linux__
-# define FUSE_PLATFORM_OPTS ",use_ino,big_writes"
-# else
4: e048f198d7b598 = 5: 239f4b7ac05b69 fuse2fs: separate libfuse3 and fuse2fs detection in configure
5: 3b02fa292dda7c ! 6: 1536edf8a93539 fuse2fs: start porting fuse2fs to lowlevel libfuse API
@@ fuse4fs/fuse4fs.c (new)
+#endif /* __SET_FOB_FOR_FUSE */
+#include <inttypes.h>
+#include "ext2fs/ext2fs.h"
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fsP.h"
+#include "support/bthread.h"
++#include "support/thread.h"
+
+#include "../version.h"
+#include "uuid/uuid.h"
+#include "e2p/e2p.h"
+
+#ifdef ENABLE_NLS
@@ fuse4fs/fuse4fs.c (new)
+ m = b % align;
+ return b - m;
+}
+
+#define dbg_printf(fuse4fs, format, ...) \
+ while ((fuse4fs)->debug) { \
-+ printf("FUSE4FS (%s): tid=%d " format, (fuse4fs)->shortdev, gettid(), ##__VA_ARGS__); \
++ printf("FUSE4FS (%s): tid=%llu " format, (fuse4fs)->shortdev, get_thread_id(), ##__VA_ARGS__); \
+ fflush(stdout); \
+ break; \
+ }
+
+#define log_printf(fuse4fs, format, ...) \
+ do { \
@@ fuse4fs/fuse4fs.c (new)
+ ret = -EUCLEAN;
+ break;
+ case EIO:
+#ifdef EILSEQ
+ case EILSEQ:
+#endif
++#if EUCLEAN != EIO
+ case EUCLEAN:
++#endif
+ /* these errnos usually denote corruption or persistence fail */
+ is_err = 1;
+ ret = -err;
+ break;
+ default:
+ if (err < 256) {
@@ fuse4fs/fuse4fs.c (new)
+
+ return ret;
+}
## lib/config.h.in ##
@@
- /* Define to 1 if you have the BSD-style 'qsort_r' function. */
- #undef HAVE_BSD_QSORT_R
+ /* Define to 1 if fuse supports cache_readdir */
+ #undef HAVE_FUSE_CACHE_READDIR
- /* Define to 1 if PR_SET_IO_FLUSHER is present */
- #undef HAVE_PR_SET_IO_FLUSHER
+ /* Define to 1 if you have the <fuse.h> header file. */
+ #undef HAVE_FUSE_H
+/* Define to 1 if fuse supports lowlevel API */
+#undef HAVE_FUSE_LOWLEVEL
+
- /* Define to 1 if you have the Mac OS X function
- CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */
- #undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES
+ /* Define to 1 if you have the 'futimes' function. */
+ #undef HAVE_FUTIMES
+
+ /* Define to 1 if you have the 'getcwd' function. */
+ #undef HAVE_GETCWD
- /* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
- the CoreFoundation framework. */
6: 480ffd57c3152f = 7: de29e11fda2d6b debian: create new package for fuse4fs
7: eb97e1fefbf286 = 8: d4aa426efc0f3c fuse4fs: namespace some helpers
8: 7a2e6084f203a4 = 9: a53dd84ef7ce0c fuse4fs: convert to low level API
9: 8072dafea5ba54 = 10: 37dafcc0894b89 libsupport: port the kernel list.h to libsupport
10: df5e76db0018b3 ! 11: 30b3c80ed6bcc5 libsupport: add a cache
@@ lib/support/xbitops.h (new)
+#define rounddown_pow_of_two(n) __rounddown_pow_of_two(n)
+
+#endif
## lib/support/Makefile.in ##
@@ lib/support/Makefile.in: OBJS= bthread.o \
- profile_helpers.o \
prof_err.o \
quotaio.o \
quotaio_v2.o \
quotaio_tree.o \
+ thread.o \
dict.o \
- devname.o
+ devname.o \
+ cache.o
SRCS= $(srcdir)/argv_parse.c \
$(srcdir)/bthread.c \
$(srcdir)/cstring.c \
$(srcdir)/mkquota.c \
$(srcdir)/parse_qtype.c \
@@ lib/support/Makefile.in: SRCS= $(srcdir)/argv_parse.c \
- $(srcdir)/profile_helpers.c \
prof_err.c \
$(srcdir)/quotaio.c \
$(srcdir)/quotaio_tree.c \
$(srcdir)/quotaio_v2.c \
+ $(srcdir)/thread.c \
$(srcdir)/dict.c \
- $(srcdir)/devname.c
+ $(srcdir)/devname.c \
+ $(srcdir)/cache.c
LIBRARY= libsupport
LIBDIR= support
@MAKEFILE_LIBRARY@
@MAKEFILE_PROFILE@
@@ lib/support/Makefile.in: quotaio_v2.o: $(srcdir)/quotaio_v2.c $(top_builddir)/lib/config.h \
- $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/dqblk_v2.h \
- $(srcdir)/quotaio_tree.h
+ thread.o: $(srcdir)/thread.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/thread.h
dict.o: $(srcdir)/dict.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/dict.h
devname.o: $(srcdir)/devname.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/devname.h $(srcdir)/nls-enable.h
+cache.o: $(srcdir)/cache.c $(top_builddir)/lib/config.h \
+ $(srcdir)/cache.h $(srcdir)/list.h $(srcdir)/xbitops.h
11: f13414a72be32f = 12: fb17b6521f0430 cache: disable debugging
12: 383f3dd0b56f64 = 13: b6d5640bdf0086 cache: use modern list iterator macros
13: a9c0181ee15128 = 14: 0be92e2d351193 cache: embed struct cache in the owner
14: 31e5763e32dfc2 = 15: a486e89007fb55 cache: pass cache pointer to callbacks
15: a5c773947bd56d = 16: ae4911b183fa9d cache: pass a private data pointer through cache_walk
16: 4f017b4dc8920f = 17: 9c5af5b9d39a70 cache: add a helper to grab a new refcount for a cache_node
17: d1dea709493fdc = 18: c6ed3f93d43660 cache: return results of a cache flush
18: e59f4eba2f22f8 = 19: a13c635ef81b43 cache: add a "get only if incore" flag to cache_node_get
19: a999b4c74344cd = 20: cbd9dbc6943267 cache: support gradual expansion
20: 019aa0d8a8c87d = 21: 5d91f82ff155b9 cache: support updating maxcount and flags
21: 0283835cbfa2db = 22: 7134be34c002f5 cache: support channging flags
22: 0f5c83c6c88c3f = 23: 2a8ddebbfa9298 cache: implement automatic shrinking
23: 26f78774c08acc ! 24: dd17627e00495e fuse4fs: add cache to track open files
@@ fuse4fs/fuse4fs.c
#ifdef __SET_FOB_FOR_FUSE
# error Do not set magic value __SET_FOB_FOR_FUSE!!!!
#endif
#ifndef _FILE_OFFSET_BITS
/*
@@
- #endif /* __SET_FOB_FOR_FUSE */
#include <inttypes.h>
#include "ext2fs/ext2fs.h"
#include "ext2fs/ext2_fs.h"
#include "ext2fs/ext2fsP.h"
#include "support/bthread.h"
+ #include "support/thread.h"
+#include "support/list.h"
+#include "support/cache.h"
#include "../version.h"
#include "uuid/uuid.h"
#include "e2p/e2p.h"
24: d6a2e3be991671 = 25: 2ea53b826253b6 fuse4fs: use the orphaned inode list
25: 2a4c9c2e579556 = 26: 6bd1919297a22f fuse4fs: implement FUSE_TMPFILE
26: 38cd25631692e6 = 27: 951a10258cada0 fuse4fs: create incore reverse orphan list
^ permalink raw reply
* Re: [PATCH 2/2] ext4: align preallocation size to stripe width
From: David Laight @ 2026-04-09 18:59 UTC (permalink / raw)
To: Theodore Tso; +Cc: Yu Kuai, adilger.kernel, linux-ext4, linux-kernel
In-Reply-To: <20260409142911.GB59468@macsyma-wired.lan>
On Thu, 9 Apr 2026 10:29:11 -0400
"Theodore Tso" <tytso@mit.edu> wrote:
> On Mon, Dec 08, 2025 at 04:32:46PM +0800, Yu Kuai wrote:
> > When stripe width (io_opt) is configured, align the predicted
> > preallocation size to stripe boundaries. This ensures optimal I/O
> > performance on RAID and other striped storage devices by avoiding
> > partial stripe operations.
> >
> > The current implementation uses hardcoded size predictions (16KB, 32KB,
> > 64KB, etc.) that are not stripe-aware. This causes physical block
> > offsets on disk to be misaligned to stripe boundaries, leading to
> > read-modify-write penalties on RAID arrays and reduced performance.
> >
> > This patch makes size prediction stripe-aware by using multiples of
> > stripe size (1x, 2x, 4x, 8x, 16x, 32x) when s_stripe is set.
> > Additionally, the start offset is aligned to stripe boundaries using
> > rounddown(), which works correctly for both power-of-2 and non-power-of-2
> > stripe sizes. For devices without stripe configuration, the original
> > behavior is preserved.
> > ...
>
> Hi Yu,
>
> Did you see the build failures reported by the kernel build bot on the
> i386[1] and arm[2] platforms? The problem appears to be using
> roundup() and rounddown() on an unsigned long types.
Looks like that whole condition chain should be replaced with something
based on ilog2() (or some other bit-scan function).
David
>
> [1] https://lore.kernel.org/r/202512102331.yweFnVTU-lkp@intel.com
> [2] https://lore.kernel.org/r/202512120613.mM5COVWV-lkp@intel.com
>
> We can't apply your patch until this issue is addressed.
>
> Thanks,
>
> - Ted
>
^ permalink raw reply
* Re: [PATCH 00/61] treewide: Use IS_ERR_OR_NULL over manual NULL check - refactor
From: Al Viro @ 2026-04-09 18:16 UTC (permalink / raw)
To: Philipp Hahn
Cc: amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel, dri-devel,
gfs2, intel-gfx, intel-wired-lan, iommu, kvm, linux-arm-kernel,
linux-block, linux-bluetooth, linux-btrfs, linux-cifs, linux-clk,
linux-erofs, linux-ext4, linux-fsdevel, linux-gpio, linux-hyperv,
linux-input, linux-kernel, linux-leds, linux-media, linux-mips,
linux-mm, linux-modules, linux-mtd, linux-nfs, linux-omap,
linux-phy, linux-pm, linux-rockchip, linux-s390, linux-scsi,
linux-sctp, linux-security-module, linux-sh, linux-sound,
linux-stm32, linux-trace-kernel, linux-usb, linux-wireless,
netdev, ntfs3, samba-technical, sched-ext, target-devel,
tipc-discussion, v9fs, Julia Lawall, Nicolas Palix, Chris Mason,
David Sterba, Ilya Dryomov, Alex Markuze, Viacheslav Dubeyko,
Theodore Ts'o, Andreas Dilger, Steve French, Paulo Alcantara,
Ronnie Sahlberg, Shyam Prasad N, Tom Talpey, Bharath SM,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
Sandeep Dhavale, Hongbo Li, Chunhai Guo, Miklos Szeredi,
Konstantin Komarov, Andreas Gruenbacher, Kees Cook, Tony Luck,
Guilherme G. Piccoli, Jan Kara, Phillip Lougher,
Christian Brauner, Jan Kara, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Tejun Heo, David Vernet, Andrea Righi,
Changwoo Min, Ingo Molnar, Peter Zijlstra, Juri Lelli,
Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
Valentin Schneider, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Sylwester Nawrocki, Liam Girdwood,
Mark Brown, Jaroslav Kysela, Takashi Iwai, Max Filippov,
Paolo Bonzini, John Johansen, Paul Moore, James Morris,
Serge E. Hallyn, Andrew Morton, Alasdair Kergon, Mike Snitzer,
Mikulas Patocka, Benjamin Marzinski, David S. Miller, David Ahern,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Marcel Holtmann, Johan Hedberg, Luiz Augusto von Dentz,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Jamal Hadi Salim, Jiri Pirko,
Marcelo Ricardo Leitner, Xin Long, Trond Myklebust,
Anna Schumaker, Chuck Lever, Jeff Layton, NeilBrown,
Olga Kornievskaia, Dai Ngo, Jon Maloy, Johannes Berg,
Catalin Marinas, Russell King, John Crispin, Thomas Bogendoerfer,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Zhenyu Wang,
Zhi Wang, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, Sandy Huang,
Heiko Stübner, Andy Yan, Igor Russkikh, Andrew Lunn,
Pavan Chebbi, Michael Chan, Potnuri Bharat Teja, Tony Nguyen,
Przemek Kitszel, Taras Chornyi, Maxime Coquelin, Alexandre Torgue,
Iyappan Subramanian, Keyur Chudgar, Quan Nguyen, Heiner Kallweit,
Marc Zyngier, Thomas Gleixner, Andrew Lunn, Gregory Clement,
Sebastian Hesselbarth, Vinod Koul, Linus Walleij, Ulf Hansson,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Christian Borntraeger, Sven Schnelle, Martin K. Petersen,
Eduardo Valentin, Keerthy, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Alex Williamson, Mark Greer,
Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
Shuah Khan, Kieran Bingham, Mauro Carvalho Chehab, Joerg Roedel,
Will Deacon, Robin Murphy, Lee Jones, Pavel Machek, Dave Penkler,
K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Justin Sanders, Jens Axboe, Georgi Djakov, Michael Turquette,
Stephen Boyd, Philipp Zabel, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Pali Rohár, Dmitry Torokhov
In-Reply-To: <20260310-b4-is_err_or_null-v1-0-bd63b656022d@avm.de>
On Tue, Mar 10, 2026 at 12:48:26PM +0100, Philipp Hahn wrote:
> While doing some static code analysis I stumbled over a common pattern,
> where IS_ERR() is combined with a NULL check. For that there is
> IS_ERR_OR_NULL().
... and valid uses of IS_ERR_OR_NULL are rare as hen teeth.
Most of those are "I'm not sure how this function returns an
error, let's use that just in case".
Please, do not introduce more of that crap.
^ permalink raw reply
* Re: BUG: net-next (7.0-rc6 based and later) fails to boot on Jetson Xavier NX
From: Russell King (Oracle) @ 2026-04-09 16:16 UTC (permalink / raw)
To: Linus Torvalds
Cc: Will Deacon, Robin Murphy, netdev, linux-arm-kernel, linux-kernel,
iommu, linux-ext4, dmaengine, Marek Szyprowski, Theodore Ts'o,
Andreas Dilger, Vinod Koul, Frank Li
In-Reply-To: <CAHk-=whO3F1u+nme4cnYMy5baYmb7CH=wE63dcNaPLWD0vKaew@mail.gmail.com>
On Thu, Apr 09, 2026 at 08:37:53AM -0700, Linus Torvalds wrote:
> On Thu, 9 Apr 2026 at 05:24, Will Deacon <will@kernel.org> wrote:
> >
> > On Wed, Apr 08, 2026 at 08:52:32PM +0100, Russell King (Oracle) wrote:
> > > What's the status on the iommu fix? Is it merged into mainline yet?
> > > If it isn't already, that means net-next remains unbootable going
> > > into the merge window without manually carrying the fix locally.
> >
> > I'll pick it up for 7.0 in the iommu tree.
>
> ... and now it's in my tree.
Thanks, I see you merged it prior to the net tree, which should mean
the fix finds its way into net-next! Yay! Double thanks for that!
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* Re: BUG: net-next (7.0-rc6 based and later) fails to boot on Jetson Xavier NX
From: Linus Torvalds @ 2026-04-09 15:37 UTC (permalink / raw)
To: Will Deacon
Cc: Russell King (Oracle), Robin Murphy, netdev, linux-arm-kernel,
linux-kernel, iommu, linux-ext4, dmaengine, Marek Szyprowski,
Theodore Ts'o, Andreas Dilger, Vinod Koul, Frank Li
In-Reply-To: <adeaiSAnkaggqPsA@willie-the-truck>
On Thu, 9 Apr 2026 at 05:24, Will Deacon <will@kernel.org> wrote:
>
> On Wed, Apr 08, 2026 at 08:52:32PM +0100, Russell King (Oracle) wrote:
> > What's the status on the iommu fix? Is it merged into mainline yet?
> > If it isn't already, that means net-next remains unbootable going
> > into the merge window without manually carrying the fix locally.
>
> I'll pick it up for 7.0 in the iommu tree.
... and now it's in my tree.
Linus
^ permalink raw reply
* Re: [PATCH 2/2] ext4: align preallocation size to stripe width
From: Theodore Tso @ 2026-04-09 14:29 UTC (permalink / raw)
To: Yu Kuai; +Cc: adilger.kernel, linux-ext4, linux-kernel
In-Reply-To: <20251208083246.320965-3-yukuai@fnnas.com>
On Mon, Dec 08, 2025 at 04:32:46PM +0800, Yu Kuai wrote:
> When stripe width (io_opt) is configured, align the predicted
> preallocation size to stripe boundaries. This ensures optimal I/O
> performance on RAID and other striped storage devices by avoiding
> partial stripe operations.
>
> The current implementation uses hardcoded size predictions (16KB, 32KB,
> 64KB, etc.) that are not stripe-aware. This causes physical block
> offsets on disk to be misaligned to stripe boundaries, leading to
> read-modify-write penalties on RAID arrays and reduced performance.
>
> This patch makes size prediction stripe-aware by using multiples of
> stripe size (1x, 2x, 4x, 8x, 16x, 32x) when s_stripe is set.
> Additionally, the start offset is aligned to stripe boundaries using
> rounddown(), which works correctly for both power-of-2 and non-power-of-2
> stripe sizes. For devices without stripe configuration, the original
> behavior is preserved.
> ...
Hi Yu,
Did you see the build failures reported by the kernel build bot on the
i386[1] and arm[2] platforms? The problem appears to be using
roundup() and rounddown() on an unsigned long types.
[1] https://lore.kernel.org/r/202512102331.yweFnVTU-lkp@intel.com
[2] https://lore.kernel.org/r/202512120613.mM5COVWV-lkp@intel.com
We can't apply your patch until this issue is addressed.
Thanks,
- Ted
^ permalink raw reply
* Re: [PATCH v2] ext4: improve str2hashbuf by processing 4-byte chunks and removing function pointers
From: Theodore Tso @ 2026-04-09 14:10 UTC (permalink / raw)
To: Guan-Chun Wu
Cc: adilger.kernel, linux-ext4, linux-kernel, visitorckw,
david.laight.linux
In-Reply-To: <20251122043929.1908643-1-409411716@gms.tku.edu.tw>
On Sat, Nov 22, 2025 at 12:39:29PM +0800, Guan-Chun Wu wrote:
> The original byte-by-byte implementation with modulo checks is less
> efficient. Refactor str2hashbuf_unsigned() and str2hashbuf_signed()
> to process input in explicit 4-byte chunks instead of using a
> modulus-based loop to emit words byte by byte.
>
> Additionally, the use of function pointers for selecting the appropriate
> str2hashbuf implementation has been removed. Instead, the functions are
> directly invoked based on the hash type, eliminating the overhead of
> dynamic function calls.
>
> Performance test (x86_64, Intel Core i7-10700 @ 2.90GHz, average over 10000
> runs, using kernel module for testing):
>
> len | orig_s | new_s | orig_u | new_u
> ----+--------+-------+--------+-------
> 1 | 70 | 71 | 63 | 63
> 8 | 68 | 64 | 64 | 62
> 32 | 75 | 70 | 75 | 63
> 64 | 96 | 71 | 100 | 68
> 255 | 192 | 108 | 187 | 84
>
> This change improves performance, especially for larger input sizes.
>
> Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw>
Apologies for the delay in looking at this. It fell through the
cracks on my end.
Because of how I'm a bit late with reviewing patches before the merge
window, I'm going to be very conservative in which patches I'm going
to land. So this is going to be deferred until the next cycle, but I
wanted to let you know that I haven't forgotten about it.
If this was a comprehensive set of Kunit tests for fs/ext4/hash.c, I
might have taken it. And that's something that I would look at adding
for the next cycle, but if you'd be interested in creating the kunit
tests for hash.c, that would be great.
- Ted
^ permalink raw reply
* Re: [RFC PATCH v1 0/6] provenance_time (ptime): a new settable timestamp for cross-filesystem provenance
From: Christian Brauner @ 2026-04-09 13:38 UTC (permalink / raw)
To: Theodore Tso
Cc: Sean Smith, linux-fsdevel, linux-ext4, linux-btrfs, dsterba,
david, osandov, hirofumi, linkinjeon
In-Reply-To: <20260407233618.GB12536@macsyma-wired.lan>
On Tue, Apr 07, 2026 at 07:36:18PM -0400, Theodore Ts'o wrote:
> On Mon, Apr 06, 2026 at 07:05:55PM -0500, Sean Smith wrote:
> > The patches implement rename-over preservation in all 5
> > filesystem rename handlers. When rename(source, target)
> > replaces an existing file, and the source has ptime=0 (the
> > default for any newly-created temp file) while the target
> > has ptime != 0, the filesystem copies the target's ptime to
> > the source before destroying the target's inode. This runs
> > inside the rename transaction, atomic with the rename itself.
>
> Yelch. This is so *very* non-Unixy / non-POSIX / non-Linux.
I think you meant to type "N", "A", and "K".
^ permalink raw reply
* Re: [PATCH v2 3/3] ext4: derive f_fsid from block device to avoid collisions
From: Theodore Tso @ 2026-04-09 13:12 UTC (permalink / raw)
To: Anand Jain
Cc: Christoph Hellwig, Darrick J. Wong, linux-ext4, linux-btrfs,
linux-xfs, Anand Jain, dsterba
In-Reply-To: <22cfbf8d-af9b-462e-b240-67a1de24764f@gmail.com>
On Thu, Apr 09, 2026 at 05:45:24PM +0800, Anand Jain wrote:
>
> Got it. Do you mean that since both filesystems are identical,
> statfs(A) and statfs(B) can legitimately return the same values?
Yes. f_Fsid can legitimately always be zero (which I believe is the
case for FreeBSD, but I understand that there are some programs, like
systemd, which subscribe to the heresy, "All the World's Linux", which
is a variant of the "All the World's a Vax" or "All the World's SunOS"
at the beginning of my career :-).
> I'm not entirely sure what the correct expectation for f_fsid
> should be.
That's my point, there *is* no correct expectation, and I don't
believe there can or should be. What we should be doing instead is
actively discouraging people from using f_fsid. I suspect that's one
of the reasons why FreeBSD may have chosen to just return zero.
Which is why I don't think we should be testing this in xfstests's
generic/791, either. (Unless we get consensus across file system
developers abnd willing to make it be a documented behavior as of a
particular kernel version, and we then adjust the test to skip it if
it's older than that kernel version, so it doesn't break LTS kernel
tests. See below....)
> My initial idea was to make f_fsid behavior consistent across
> major filesystems so that user space benefits from predictable
> semantics.
I'm OK with that, so long as it's unconditional across all file system
types (ideally) or unconditionally across all major file systems (xfs,
btrfs, ext4, f2fs) as of a particular kernel version (which is
probably much more realistic), *and* it is documented in the Linux man
pages as this is the standard behavior starting with 7.1 (or
whatever), and that the man page further cautions that programs that
expect to be portable to other OS's (MacOS, FreeBSD, Solaris, etc.)
should not count on this behavior.
But given that you originally stumbled across this with Overlayfs,
because it was originally using s_uuid, and that didn't work well for
btrfs, why not change overlayfs to just use s_uuid plus kdev_t in its
xattr, and just fix the problem for overlayfs? That has the benefit
that it will work for all file system types in Linux, not just for
those where we have changed what f_fsid does.
Cheers,
- Ted
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox