* [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
@ 2025-11-19 22:40 ` david.laight.linux
2025-11-20 15:54 ` Yury Norov
2025-11-19 22:40 ` [PATCH 02/44] ext4: Fix saturation of 64bit inode times for old filesystems david.laight.linux
` (46 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:40 UTC (permalink / raw)
To: linux-kernel
Cc: Borislav Petkov, Dave Hansen, Ingo Molnar, Thomas Gleixner, x86,
Yury Norov, David Laight
From: David Laight <david.laight.linux@gmail.com>
The return type of variable__ffs() is currently 'unsigned long'.
This makes the x86 __ffs() be 'unsigned long' whereas the generic
version is 'unsigned int'.
Similarly change variable_ffz() and ffz().
This may save some REX prefix on 64bit.
Detected by some extra checks added to min_t() to detect possible
truncation of large values.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
arch/x86/include/asm/bitops.h | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index c2ce213f2b9b..2e8a954d2e2d 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -240,7 +240,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
variable_test_bit(nr, addr);
}
-static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
+static __always_inline __attribute_const__ unsigned int variable__ffs(unsigned long word)
{
asm("tzcnt %1,%0"
: "=r" (word)
@@ -254,12 +254,10 @@ static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned
*
* Undefined if no bit exists, so code should check against 0 first.
*/
-#define __ffs(word) \
- (__builtin_constant_p(word) ? \
- (unsigned long)__builtin_ctzl(word) : \
- variable__ffs(word))
+#define __ffs(word) \
+ (__builtin_constant_p(word) ? __builtin_ctzl(word) : variable__ffs(word))
-static __always_inline __attribute_const__ unsigned long variable_ffz(unsigned long word)
+static __always_inline __attribute_const__ unsigned int variable_ffz(unsigned long word)
{
return variable__ffs(~word);
}
@@ -270,10 +268,8 @@ static __always_inline __attribute_const__ unsigned long variable_ffz(unsigned l
*
* Undefined if no zero exists, so code should check against ~0UL first.
*/
-#define ffz(word) \
- (__builtin_constant_p(word) ? \
- (unsigned long)__builtin_ctzl(~word) : \
- variable_ffz(word))
+#define ffz(word) \
+ (__builtin_constant_p(word) ? __builtin_ctzl(~word) : variable_ffz(word))
/*
* __fls: find last set bit in word
@@ -281,7 +277,7 @@ static __always_inline __attribute_const__ unsigned long variable_ffz(unsigned l
*
* Undefined if no set bit exists, so code should check against 0 first.
*/
-static __always_inline __attribute_const__ unsigned long __fls(unsigned long word)
+static __always_inline __attribute_const__ unsigned int __fls(unsigned long word)
{
if (__builtin_constant_p(word))
return BITS_PER_LONG - 1 - __builtin_clzl(word);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int
2025-11-19 22:40 ` [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int david.laight.linux
@ 2025-11-20 15:54 ` Yury Norov
2025-11-20 18:29 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Yury Norov @ 2025-11-20 15:54 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, Borislav Petkov, Dave Hansen, Ingo Molnar,
Thomas Gleixner, x86
On Wed, Nov 19, 2025 at 10:40:57PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> The return type of variable__ffs() is currently 'unsigned long'.
> This makes the x86 __ffs() be 'unsigned long' whereas the generic
> version is 'unsigned int'.
>
> Similarly change variable_ffz() and ffz().
>
> This may save some REX prefix on 64bit.
>
> Detected by some extra checks added to min_t() to detect possible
> truncation of large values.
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> arch/x86/include/asm/bitops.h | 18 +++++++-----------
> 1 file changed, 7 insertions(+), 11 deletions(-)
>
> diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> index c2ce213f2b9b..2e8a954d2e2d 100644
> --- a/arch/x86/include/asm/bitops.h
> +++ b/arch/x86/include/asm/bitops.h
> @@ -240,7 +240,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
> variable_test_bit(nr, addr);
> }
>
> -static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
> +static __always_inline __attribute_const__ unsigned int variable__ffs(unsigned long word)
There's a mismatch with the generic ffs() in asm-generic/bitops/ffs.h.
The generic_ffs() returns int. There is another variable__ffs() defined
in arch/risk, also returning int.
So I believe, the correct fix would be to switch x86 to int as well.
And anyways, I believe this deserves a separate series.
Thanks,
Yury
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int
2025-11-20 15:54 ` Yury Norov
@ 2025-11-20 18:29 ` David Laight
2025-11-20 18:33 ` Yury Norov
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 18:29 UTC (permalink / raw)
To: Yury Norov
Cc: linux-kernel, Borislav Petkov, Dave Hansen, Ingo Molnar,
Thomas Gleixner, x86
On Thu, 20 Nov 2025 10:54:01 -0500
Yury Norov <yury.norov@gmail.com> wrote:
> On Wed, Nov 19, 2025 at 10:40:57PM +0000, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > The return type of variable__ffs() is currently 'unsigned long'.
> > This makes the x86 __ffs() be 'unsigned long' whereas the generic
> > version is 'unsigned int'.
> >
> > Similarly change variable_ffz() and ffz().
> >
> > This may save some REX prefix on 64bit.
> >
> > Detected by some extra checks added to min_t() to detect possible
> > truncation of large values.
> >
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > ---
> > arch/x86/include/asm/bitops.h | 18 +++++++-----------
> > 1 file changed, 7 insertions(+), 11 deletions(-)
> >
> > diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> > index c2ce213f2b9b..2e8a954d2e2d 100644
> > --- a/arch/x86/include/asm/bitops.h
> > +++ b/arch/x86/include/asm/bitops.h
> > @@ -240,7 +240,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
> > variable_test_bit(nr, addr);
> > }
> >
> > -static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
> > +static __always_inline __attribute_const__ unsigned int variable__ffs(unsigned long word)
>
> There's a mismatch with the generic ffs() in asm-generic/bitops/ffs.h.
>
> The generic_ffs() returns int. There is another variable__ffs() defined
> in arch/risk, also returning int.
>
> So I believe, the correct fix would be to switch x86 to int as well.
> And anyways, I believe this deserves a separate series.
It is a single patch, do you want me to resend the patch on its own?
(With a different commit message)
David
>
> Thanks,
> Yury
>
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int
2025-11-20 18:29 ` David Laight
@ 2025-11-20 18:33 ` Yury Norov
2025-11-20 21:18 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Yury Norov @ 2025-11-20 18:33 UTC (permalink / raw)
To: David Laight
Cc: linux-kernel, Borislav Petkov, Dave Hansen, Ingo Molnar,
Thomas Gleixner, x86
On Thu, Nov 20, 2025 at 06:29:09PM +0000, David Laight wrote:
> On Thu, 20 Nov 2025 10:54:01 -0500
> Yury Norov <yury.norov@gmail.com> wrote:
>
> > On Wed, Nov 19, 2025 at 10:40:57PM +0000, david.laight.linux@gmail.com wrote:
> > > From: David Laight <david.laight.linux@gmail.com>
> > >
> > > The return type of variable__ffs() is currently 'unsigned long'.
> > > This makes the x86 __ffs() be 'unsigned long' whereas the generic
> > > version is 'unsigned int'.
> > >
> > > Similarly change variable_ffz() and ffz().
> > >
> > > This may save some REX prefix on 64bit.
> > >
> > > Detected by some extra checks added to min_t() to detect possible
> > > truncation of large values.
> > >
> > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > ---
> > > arch/x86/include/asm/bitops.h | 18 +++++++-----------
> > > 1 file changed, 7 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> > > index c2ce213f2b9b..2e8a954d2e2d 100644
> > > --- a/arch/x86/include/asm/bitops.h
> > > +++ b/arch/x86/include/asm/bitops.h
> > > @@ -240,7 +240,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
> > > variable_test_bit(nr, addr);
> > > }
> > >
> > > -static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
> > > +static __always_inline __attribute_const__ unsigned int variable__ffs(unsigned long word)
> >
> > There's a mismatch with the generic ffs() in asm-generic/bitops/ffs.h.
> >
> > The generic_ffs() returns int. There is another variable__ffs() defined
> > in arch/risk, also returning int.
> >
> > So I believe, the correct fix would be to switch x86 to int as well.
> > And anyways, I believe this deserves a separate series.
>
> It is a single patch, do you want me to resend the patch on its own?
> (With a different commit message)
The patch looks wrong to me. All the flavors of ffs(), ffz() and
others should have the same signature.
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int
2025-11-20 18:33 ` Yury Norov
@ 2025-11-20 21:18 ` David Laight
2025-11-24 14:58 ` Yury Norov
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 21:18 UTC (permalink / raw)
To: Yury Norov
Cc: linux-kernel, Borislav Petkov, Dave Hansen, Ingo Molnar,
Thomas Gleixner, x86
On Thu, 20 Nov 2025 13:33:11 -0500
Yury Norov <yury.norov@gmail.com> wrote:
> On Thu, Nov 20, 2025 at 06:29:09PM +0000, David Laight wrote:
> > On Thu, 20 Nov 2025 10:54:01 -0500
> > Yury Norov <yury.norov@gmail.com> wrote:
> >
> > > On Wed, Nov 19, 2025 at 10:40:57PM +0000, david.laight.linux@gmail.com wrote:
> > > > From: David Laight <david.laight.linux@gmail.com>
> > > >
> > > > The return type of variable__ffs() is currently 'unsigned long'.
> > > > This makes the x86 __ffs() be 'unsigned long' whereas the generic
> > > > version is 'unsigned int'.
> > > >
> > > > Similarly change variable_ffz() and ffz().
> > > >
> > > > This may save some REX prefix on 64bit.
> > > >
> > > > Detected by some extra checks added to min_t() to detect possible
> > > > truncation of large values.
> > > >
> > > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > > ---
> > > > arch/x86/include/asm/bitops.h | 18 +++++++-----------
> > > > 1 file changed, 7 insertions(+), 11 deletions(-)
> > > >
> > > > diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> > > > index c2ce213f2b9b..2e8a954d2e2d 100644
> > > > --- a/arch/x86/include/asm/bitops.h
> > > > +++ b/arch/x86/include/asm/bitops.h
> > > > @@ -240,7 +240,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
> > > > variable_test_bit(nr, addr);
> > > > }
> > > >
> > > > -static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
> > > > +static __always_inline __attribute_const__ unsigned int variable__ffs(unsigned long word)
> > >
> > > There's a mismatch with the generic ffs() in asm-generic/bitops/ffs.h.
> > >
> > > The generic_ffs() returns int. There is another variable__ffs() defined
> > > in arch/risk, also returning int.
> > >
> > > So I believe, the correct fix would be to switch x86 to int as well.
> > > And anyways, I believe this deserves a separate series.
> >
> > It is a single patch, do you want me to resend the patch on its own?
> > (With a different commit message)
>
> The patch looks wrong to me. All the flavors of ffs(), ffz() and
> others should have the same signature.
I only changed 'long' to 'int', all the generic (and builtin) ones are 'int'.
So I'm not sure which difference you are talking about.
IIRC the __attribute_const__ just lets the compiler do CSE.
David
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int
2025-11-20 21:18 ` David Laight
@ 2025-11-24 14:58 ` Yury Norov
2025-11-24 18:18 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Yury Norov @ 2025-11-24 14:58 UTC (permalink / raw)
To: David Laight
Cc: linux-kernel, Borislav Petkov, Dave Hansen, Ingo Molnar,
Thomas Gleixner, x86
On Thu, Nov 20, 2025 at 09:18:10PM +0000, David Laight wrote:
> On Thu, 20 Nov 2025 13:33:11 -0500
> Yury Norov <yury.norov@gmail.com> wrote:
>
> > On Thu, Nov 20, 2025 at 06:29:09PM +0000, David Laight wrote:
> > > On Thu, 20 Nov 2025 10:54:01 -0500
> > > Yury Norov <yury.norov@gmail.com> wrote:
> > >
> > > > On Wed, Nov 19, 2025 at 10:40:57PM +0000, david.laight.linux@gmail.com wrote:
> > > > > From: David Laight <david.laight.linux@gmail.com>
> > > > >
> > > > > The return type of variable__ffs() is currently 'unsigned long'.
> > > > > This makes the x86 __ffs() be 'unsigned long' whereas the generic
> > > > > version is 'unsigned int'.
> > > > >
> > > > > Similarly change variable_ffz() and ffz().
> > > > >
> > > > > This may save some REX prefix on 64bit.
> > > > >
> > > > > Detected by some extra checks added to min_t() to detect possible
> > > > > truncation of large values.
> > > > >
> > > > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > > > ---
> > > > > arch/x86/include/asm/bitops.h | 18 +++++++-----------
> > > > > 1 file changed, 7 insertions(+), 11 deletions(-)
> > > > >
> > > > > diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> > > > > index c2ce213f2b9b..2e8a954d2e2d 100644
> > > > > --- a/arch/x86/include/asm/bitops.h
> > > > > +++ b/arch/x86/include/asm/bitops.h
> > > > > @@ -240,7 +240,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
> > > > > variable_test_bit(nr, addr);
> > > > > }
> > > > >
> > > > > -static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
> > > > > +static __always_inline __attribute_const__ unsigned int variable__ffs(unsigned long word)
> > > >
> > > > There's a mismatch with the generic ffs() in asm-generic/bitops/ffs.h.
> > > >
> > > > The generic_ffs() returns int. There is another variable__ffs() defined
> > > > in arch/risk, also returning int.
> > > >
> > > > So I believe, the correct fix would be to switch x86 to int as well.
> > > > And anyways, I believe this deserves a separate series.
> > >
> > > It is a single patch, do you want me to resend the patch on its own?
> > > (With a different commit message)
> >
> > The patch looks wrong to me. All the flavors of ffs(), ffz() and
> > others should have the same signature.
>
> I only changed 'long' to 'int', all the generic (and builtin) ones are 'int'.
> So I'm not sure which difference you are talking about.
> IIRC the __attribute_const__ just lets the compiler do CSE.
All the versions of ffs(), ffz() and others should in the better world
have the same signatures. This is unfortunately not what we have now.
for __ffs() we've got signatures:
RISCV:
static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
x86:
static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
Generic:
static __always_inline __attribute_const__ unsigned int generic___ffs(unsigned long word)
You're changing x86 implementation to match the generic one, but don't
change RISCV, and this is wrong.
Can you make them all matching, and check the same for ffz() please?
This would require a small separate series, I guess.
Moving forward, it would be nice to make all that helpers looking more
unified across different arches and flavors. Although, out of scope of
your series.
Thanks,
Yury
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int
2025-11-24 14:58 ` Yury Norov
@ 2025-11-24 18:18 ` David Laight
0 siblings, 0 replies; 109+ messages in thread
From: David Laight @ 2025-11-24 18:18 UTC (permalink / raw)
To: Yury Norov
Cc: linux-kernel, Borislav Petkov, Dave Hansen, Ingo Molnar,
Thomas Gleixner, x86
On Mon, 24 Nov 2025 09:58:51 -0500
Yury Norov <yury.norov@gmail.com> wrote:
> On Thu, Nov 20, 2025 at 09:18:10PM +0000, David Laight wrote:
> > On Thu, 20 Nov 2025 13:33:11 -0500
> > Yury Norov <yury.norov@gmail.com> wrote:
> >
> > > On Thu, Nov 20, 2025 at 06:29:09PM +0000, David Laight wrote:
> > > > On Thu, 20 Nov 2025 10:54:01 -0500
> > > > Yury Norov <yury.norov@gmail.com> wrote:
> > > >
> > > > > On Wed, Nov 19, 2025 at 10:40:57PM +0000, david.laight.linux@gmail.com wrote:
> > > > > > From: David Laight <david.laight.linux@gmail.com>
> > > > > >
> > > > > > The return type of variable__ffs() is currently 'unsigned long'.
> > > > > > This makes the x86 __ffs() be 'unsigned long' whereas the generic
> > > > > > version is 'unsigned int'.
> > > > > >
> > > > > > Similarly change variable_ffz() and ffz().
> > > > > >
> > > > > > This may save some REX prefix on 64bit.
> > > > > >
> > > > > > Detected by some extra checks added to min_t() to detect possible
> > > > > > truncation of large values.
> > > > > >
> > > > > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > > > > ---
> > > > > > arch/x86/include/asm/bitops.h | 18 +++++++-----------
> > > > > > 1 file changed, 7 insertions(+), 11 deletions(-)
> > > > > >
> > > > > > diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> > > > > > index c2ce213f2b9b..2e8a954d2e2d 100644
> > > > > > --- a/arch/x86/include/asm/bitops.h
> > > > > > +++ b/arch/x86/include/asm/bitops.h
> > > > > > @@ -240,7 +240,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
> > > > > > variable_test_bit(nr, addr);
> > > > > > }
> > > > > >
> > > > > > -static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
> > > > > > +static __always_inline __attribute_const__ unsigned int variable__ffs(unsigned long word)
> > > > >
> > > > > There's a mismatch with the generic ffs() in asm-generic/bitops/ffs.h.
> > > > >
> > > > > The generic_ffs() returns int. There is another variable__ffs() defined
> > > > > in arch/risk, also returning int.
> > > > >
> > > > > So I believe, the correct fix would be to switch x86 to int as well.
> > > > > And anyways, I believe this deserves a separate series.
> > > >
> > > > It is a single patch, do you want me to resend the patch on its own?
> > > > (With a different commit message)
> > >
> > > The patch looks wrong to me. All the flavors of ffs(), ffz() and
> > > others should have the same signature.
> >
> > I only changed 'long' to 'int', all the generic (and builtin) ones are 'int'.
> > So I'm not sure which difference you are talking about.
> > IIRC the __attribute_const__ just lets the compiler do CSE.
>
> All the versions of ffs(), ffz() and others should in the better world
> have the same signatures. This is unfortunately not what we have now.
>
> for __ffs() we've got signatures:
>
> RISCV:
> static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
>
> x86:
> static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word)
>
> Generic:
> static __always_inline __attribute_const__ unsigned int generic___ffs(unsigned long word)
>
> You're changing x86 implementation to match the generic one, but don't
> change RISCV, and this is wrong.
More like 'incomplete'.
It looks like chunks of the RISCV file are a straight C&P of the x86 one.
> Can you make them all matching, and check the same for ffz() please?
> This would require a small separate series, I guess.
I can do a patch for RISCV - but I'm not setup to compile it.
But it should be just changing the function return types.
>
> Moving forward, it would be nice to make all that helpers looking more
> unified across different arches and flavors. Although, out of scope of
> your series.
I tripped up this one as part of my min_t() checks.
Basically if you do any maths with the result of the x86 'ffs' functions
the other operand (which is likely to be 32bits due to the domain of the
value) has to be promoted to 64bits.
This is likely to happen more often than the opposite.
David
>
> Thanks,
> Yury
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 02/44] ext4: Fix saturation of 64bit inode times for old filesystems
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
2025-11-19 22:40 ` [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int david.laight.linux
@ 2025-11-19 22:40 ` david.laight.linux
2025-11-19 22:40 ` [PATCH 03/44] perf: Fix branch stack callchain limit david.laight.linux
` (45 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:40 UTC (permalink / raw)
To: linux-kernel, linux-ext4; +Cc: Andreas Dilger, Theodore Ts'o, David Laight
From: David Laight <david.laight.linux@gmail.com>
If an inode only has space for 32bit seconds values the code tries
to saturate the times at the limit of the range (1901..2038).
However the 64bit values is cast to 32bits before the comparisons.
Fix by using clamp() instead of clamp_t(int32_t, ...).
Note that this is unlikely to cause any issues until 2038.
Fixes: 4881c4971df04 ("ext4: Initialize timestamps limits")
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
fs/ext4/ext4.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 57087da6c7be..d919cafcb521 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -909,7 +909,7 @@ do { \
(raw_inode)->xtime = cpu_to_le32((ts).tv_sec); \
(raw_inode)->xtime ## _extra = ext4_encode_extra_time(ts); \
} else \
- (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)); \
+ (raw_inode)->xtime = cpu_to_le32(clamp((ts).tv_sec, S32_MIN, S32_MAX)); \
} while (0)
#define EXT4_INODE_SET_ATIME(inode, raw_inode) \
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 03/44] perf: Fix branch stack callchain limit
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
2025-11-19 22:40 ` [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int david.laight.linux
2025-11-19 22:40 ` [PATCH 02/44] ext4: Fix saturation of 64bit inode times for old filesystems david.laight.linux
@ 2025-11-19 22:40 ` david.laight.linux
2025-11-26 5:25 ` Mi, Dapeng
2025-11-19 22:41 ` [PATCH 04/44] io_uring/net: Change some dubious min_t() david.laight.linux
` (44 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:40 UTC (permalink / raw)
To: linux-kernel, linux-perf-users
Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Namhyung Kim,
Peter Zijlstra, David Laight
From: David Laight <david.laight.linux@gmail.com>
The code that bounds the brs->nr to event->attr.sample_max_stack
incorrectly masks brs->nr with 65535 before the limit check.
Replace the min_t(u16, ...) with a plain min(...).
I guess there may be another limit on brs->nr (which is u64).
Fixes: c53e14f1ea4a8 ("perf: Extend per event callchain limit to branch stack")
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
include/linux/perf_event.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index fd1d91017b99..f91c875ea311 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1430,7 +1430,7 @@ static inline void perf_sample_save_brstack(struct perf_sample_data *data,
if (branch_sample_hw_index(event))
size += sizeof(u64);
- brs->nr = min_t(u16, event->attr.sample_max_stack, brs->nr);
+ brs->nr = min(event->attr.sample_max_stack, brs->nr);
size += brs->nr * sizeof(struct perf_branch_entry);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 03/44] perf: Fix branch stack callchain limit
2025-11-19 22:40 ` [PATCH 03/44] perf: Fix branch stack callchain limit david.laight.linux
@ 2025-11-26 5:25 ` Mi, Dapeng
0 siblings, 0 replies; 109+ messages in thread
From: Mi, Dapeng @ 2025-11-26 5:25 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, linux-perf-users
Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Namhyung Kim,
Peter Zijlstra
On 11/20/2025 6:40 AM, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> The code that bounds the brs->nr to event->attr.sample_max_stack
> incorrectly masks brs->nr with 65535 before the limit check.
> Replace the min_t(u16, ...) with a plain min(...).
>
> I guess there may be another limit on brs->nr (which is u64).
>
> Fixes: c53e14f1ea4a8 ("perf: Extend per event callchain limit to branch stack")
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> include/linux/perf_event.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index fd1d91017b99..f91c875ea311 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -1430,7 +1430,7 @@ static inline void perf_sample_save_brstack(struct perf_sample_data *data,
> if (branch_sample_hw_index(event))
> size += sizeof(u64);
>
> - brs->nr = min_t(u16, event->attr.sample_max_stack, brs->nr);
> + brs->nr = min(event->attr.sample_max_stack, brs->nr);
>
> size += brs->nr * sizeof(struct perf_branch_entry);
>
LGTM. Thanks.
Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 04/44] io_uring/net: Change some dubious min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (2 preceding siblings ...)
2025-11-19 22:40 ` [PATCH 03/44] perf: Fix branch stack callchain limit david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 14:48 ` Jens Axboe
2025-11-19 22:41 ` [PATCH 05/44] ipc/msg: Fix saturation of percpu counts in msgctl_info() david.laight.linux
` (43 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, io-uring; +Cc: Jens Axboe, David Laight
From: David Laight <david.laight.linux@gmail.com>
Since iov_len is 'unsigned long' it is possible that the cast
to 'int' will change the value of min_t(int, iov[nbufs].iov_len, ret).
Use a plain min() and change the loop bottom to while (ret > 0) so that
the compiler knows 'ret' is always positive.
Also change min_t(int, sel->val, sr->mshot_total_len) to a simple min()
since sel->val is also long and subject to possible trunctation.
It might be that other checks stop these being problems, but they are
picked up by some compile-time tests for min_t() truncating values.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
io_uring/net.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/io_uring/net.c b/io_uring/net.c
index a95cc9ca2a4d..5fcc3e9b094e 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -483,11 +483,11 @@ static int io_bundle_nbufs(struct io_async_msghdr *kmsg, int ret)
/* short transfer, count segments */
nbufs = 0;
do {
- int this_len = min_t(int, iov[nbufs].iov_len, ret);
+ int this_len = min(iov[nbufs].iov_len, ret);
nbufs++;
ret -= this_len;
- } while (ret);
+ } while (ret > 0);
return nbufs;
}
@@ -853,7 +853,7 @@ static inline bool io_recv_finish(struct io_kiocb *req,
* mshot as finished, and flag MSHOT_DONE as well to prevent
* a potential bundle from being retried.
*/
- sr->mshot_total_len -= min_t(int, sel->val, sr->mshot_total_len);
+ sr->mshot_total_len -= min(sel->val, sr->mshot_total_len);
if (!sr->mshot_total_len) {
sr->flags |= IORING_RECV_MSHOT_DONE;
mshot_finished = true;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 04/44] io_uring/net: Change some dubious min_t()
2025-11-19 22:41 ` [PATCH 04/44] io_uring/net: Change some dubious min_t() david.laight.linux
@ 2025-11-20 14:48 ` Jens Axboe
2025-11-20 15:48 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Jens Axboe @ 2025-11-20 14:48 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, io-uring
On 11/19/25 3:41 PM, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> Since iov_len is 'unsigned long' it is possible that the cast
> to 'int' will change the value of min_t(int, iov[nbufs].iov_len, ret).
> Use a plain min() and change the loop bottom to while (ret > 0) so that
> the compiler knows 'ret' is always positive.
>
> Also change min_t(int, sel->val, sr->mshot_total_len) to a simple min()
> since sel->val is also long and subject to possible trunctation.
>
> It might be that other checks stop these being problems, but they are
> picked up by some compile-time tests for min_t() truncating values.
Fails with clang-21:
io_uring/net.c:855:26: error: call to '__compiletime_assert_2006' declared with 'error' attribute: min(sel->val, sr->mshot_total_len) signedness error
855 | sr->mshot_total_len -= min(sel->val, sr->mshot_total_len);
| ^
./include/linux/minmax.h:105:19: note: expanded from macro 'min'
105 | #define min(x, y) __careful_cmp(min, x, y)
| ^
./include/linux/minmax.h:98:2: note: expanded from macro '__careful_cmp'
98 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
| ^
./include/linux/minmax.h:93:2: note: expanded from macro '__careful_cmp_once'
93 | BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \
| ^
note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
././include/linux/compiler_types.h:590:2: note: expanded from macro '_compiletime_assert'
590 | __compiletime_assert(condition, msg, prefix, suffix)
| ^
././include/linux/compiler_types.h:583:4: note: expanded from macro '__compiletime_assert'
583 | prefix ## suffix(); \
| ^
<scratch space>:319:1: note: expanded from here
319 | __compiletime_assert_2006
| ^
--
Jens Axboe
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 04/44] io_uring/net: Change some dubious min_t()
2025-11-20 14:48 ` Jens Axboe
@ 2025-11-20 15:48 ` David Laight
2025-11-20 15:53 ` Jens Axboe
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 15:48 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-kernel, io-uring
On Thu, 20 Nov 2025 07:48:58 -0700
Jens Axboe <axboe@kernel.dk> wrote:
> On 11/19/25 3:41 PM, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > Since iov_len is 'unsigned long' it is possible that the cast
> > to 'int' will change the value of min_t(int, iov[nbufs].iov_len, ret).
> > Use a plain min() and change the loop bottom to while (ret > 0) so that
> > the compiler knows 'ret' is always positive.
> >
> > Also change min_t(int, sel->val, sr->mshot_total_len) to a simple min()
> > since sel->val is also long and subject to possible trunctation.
> >
> > It might be that other checks stop these being problems, but they are
> > picked up by some compile-time tests for min_t() truncating values.
>
> Fails with clang-21:
>
> io_uring/net.c:855:26: error: call to '__compiletime_assert_2006' declared with 'error' attribute: min(sel->val, sr->mshot_total_len) signedness error
> 855 | sr->mshot_total_len -= min(sel->val, sr->mshot_total_len);
I'll take a look, I normally use gcc but there must be something subtle going on.
Actually which architecture?
I only tested x86-64.
David
> | ^
> ./include/linux/minmax.h:105:19: note: expanded from macro 'min'
> 105 | #define min(x, y) __careful_cmp(min, x, y)
> | ^
> ./include/linux/minmax.h:98:2: note: expanded from macro '__careful_cmp'
> 98 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
> | ^
> ./include/linux/minmax.h:93:2: note: expanded from macro '__careful_cmp_once'
> 93 | BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \
> | ^
> note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
> ././include/linux/compiler_types.h:590:2: note: expanded from macro '_compiletime_assert'
> 590 | __compiletime_assert(condition, msg, prefix, suffix)
> | ^
> ././include/linux/compiler_types.h:583:4: note: expanded from macro '__compiletime_assert'
> 583 | prefix ## suffix(); \
> | ^
> <scratch space>:319:1: note: expanded from here
> 319 | __compiletime_assert_2006
> | ^
>
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 04/44] io_uring/net: Change some dubious min_t()
2025-11-20 15:48 ` David Laight
@ 2025-11-20 15:53 ` Jens Axboe
2025-11-22 11:31 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Jens Axboe @ 2025-11-20 15:53 UTC (permalink / raw)
To: David Laight; +Cc: linux-kernel, io-uring
On 11/20/25 8:48 AM, David Laight wrote:
> On Thu, 20 Nov 2025 07:48:58 -0700
> Jens Axboe <axboe@kernel.dk> wrote:
>
>> On 11/19/25 3:41 PM, david.laight.linux@gmail.com wrote:
>>> From: David Laight <david.laight.linux@gmail.com>
>>>
>>> Since iov_len is 'unsigned long' it is possible that the cast
>>> to 'int' will change the value of min_t(int, iov[nbufs].iov_len, ret).
>>> Use a plain min() and change the loop bottom to while (ret > 0) so that
>>> the compiler knows 'ret' is always positive.
>>>
>>> Also change min_t(int, sel->val, sr->mshot_total_len) to a simple min()
>>> since sel->val is also long and subject to possible trunctation.
>>>
>>> It might be that other checks stop these being problems, but they are
>>> picked up by some compile-time tests for min_t() truncating values.
>>
>> Fails with clang-21:
>>
>> io_uring/net.c:855:26: error: call to '__compiletime_assert_2006' declared with 'error' attribute: min(sel->val, sr->mshot_total_len) signedness error
>> 855 | sr->mshot_total_len -= min(sel->val, sr->mshot_total_len);
>
> I'll take a look, I normally use gcc but there must be something
> subtle going on. Actually which architecture? I only tested x86-64.
This is x86-64.
--
Jens Axboe
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 04/44] io_uring/net: Change some dubious min_t()
2025-11-20 15:53 ` Jens Axboe
@ 2025-11-22 11:31 ` David Laight
0 siblings, 0 replies; 109+ messages in thread
From: David Laight @ 2025-11-22 11:31 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-kernel, io-uring
On Thu, 20 Nov 2025 08:53:56 -0700
Jens Axboe <axboe@kernel.dk> wrote:
> On 11/20/25 8:48 AM, David Laight wrote:
> > On Thu, 20 Nov 2025 07:48:58 -0700
> > Jens Axboe <axboe@kernel.dk> wrote:
> >
> >> On 11/19/25 3:41 PM, david.laight.linux@gmail.com wrote:
> >>> From: David Laight <david.laight.linux@gmail.com>
> >>>
> >>> Since iov_len is 'unsigned long' it is possible that the cast
> >>> to 'int' will change the value of min_t(int, iov[nbufs].iov_len, ret).
> >>> Use a plain min() and change the loop bottom to while (ret > 0) so that
> >>> the compiler knows 'ret' is always positive.
> >>>
> >>> Also change min_t(int, sel->val, sr->mshot_total_len) to a simple min()
> >>> since sel->val is also long and subject to possible trunctation.
> >>>
> >>> It might be that other checks stop these being problems, but they are
> >>> picked up by some compile-time tests for min_t() truncating values.
> >>
> >> Fails with clang-21:
> >>
> >> io_uring/net.c:855:26: error: call to '__compiletime_assert_2006' declared with 'error' attribute: min(sel->val, sr->mshot_total_len) signedness error
> >> 855 | sr->mshot_total_len -= min(sel->val, sr->mshot_total_len);
> >
> > I'll take a look, I normally use gcc but there must be something
> > subtle going on. Actually which architecture? I only tested x86-64.
>
> This is x86-64.
>
It is related to the test a few lines higher:
if (sel->val > 0 && sr->flags & IORING_RECV_MSHOT_LIM) {
'sel->val' is ssize_t, gcc is tracking that test so statically_true(sel->val >= 0)
is 'true' and the signed variable can be compared against the 'unsigned'
'sr->mshot_total_len'.
It seems clang isn't as clever.
Perhaps it reloads sel->val from memory - so loses the result of the comparison.
Even swapping the order of the two tests might fix it.
As might caching sel->val in a local (even a signed one).
The comment in the header file for io_br_sel.val doesn't seem to include
the case where 'val' is a length!
The simple fix is to use umin() since all the values are clearly non-negative.
David
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 05/44] ipc/msg: Fix saturation of percpu counts in msgctl_info()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (3 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 04/44] io_uring/net: Change some dubious min_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t() david.laight.linux
` (42 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel; +Cc: David Laight
From: David Laight <david.laight.linux@gmail.com>
While the percpu_counter_sum() values are unlikely to be large the code
tries to saturate them using min_t(int, percpu_counter_sum(), INT_MAX)
This just doesn't work since the high bits are all masked and then the
(possibly negative) value assigned.
Replace the min_t() with a plain min().
Fixes: 72d1e611082ed ("ipc/msg: mitigate the lock contention with percpu counter")
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
ipc/msg.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/ipc/msg.c b/ipc/msg.c
index ee6af4fe52bf..34e607add006 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -501,11 +501,9 @@ static int msgctl_info(struct ipc_namespace *ns, int msqid,
max_idx = ipc_get_maxidx(&msg_ids(ns));
up_read(&msg_ids(ns).rwsem);
if (cmd == MSG_INFO) {
- msginfo->msgmap = min_t(int,
- percpu_counter_sum(&ns->percpu_msg_hdrs),
+ msginfo->msgmap = min(percpu_counter_sum(&ns->percpu_msg_hdrs),
INT_MAX);
- msginfo->msgtql = min_t(int,
- percpu_counter_sum(&ns->percpu_msg_bytes),
+ msginfo->msgtql = min(percpu_counter_sum(&ns->percpu_msg_bytes),
INT_MAX);
} else {
msginfo->msgmap = MSGMAP;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (4 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 05/44] ipc/msg: Fix saturation of percpu counts in msgctl_info() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-21 21:40 ` Alexei Starovoitov
2025-11-19 22:41 ` [PATCH 07/44] net/core/flow_dissector: Fix cap of __skb_flow_dissect() return value david.laight.linux
` (41 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, bpf
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t() and max_t() are normally used to change the signedness
of a positive value to avoid a signed-v-unsigned compare warning.
However they are used here to convert an unsigned 64bit pattern
to a signed to a 32/64bit signed number.
To avoid any confusion use plain min()/max() and explicitely cast
the u64 expression to the correct signed value.
Use a simple max() for the max_pkt_offset calulation and delete the
comment about why the cast to u32 is safe.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
kernel/bpf/verifier.c | 29 +++++++++++------------------
1 file changed, 11 insertions(+), 18 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index ff40e5e65c43..22fa9769fbdb 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2319,12 +2319,12 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
struct tnum var32_off = tnum_subreg(reg->var_off);
/* min signed is max(sign bit) | min(other bits) */
- reg->s32_min_value = max_t(s32, reg->s32_min_value,
- var32_off.value | (var32_off.mask & S32_MIN));
+ reg->s32_min_value = max(reg->s32_min_value,
+ (s32)(var32_off.value | (var32_off.mask & S32_MIN)));
/* max signed is min(sign bit) | max(other bits) */
- reg->s32_max_value = min_t(s32, reg->s32_max_value,
- var32_off.value | (var32_off.mask & S32_MAX));
- reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)var32_off.value);
+ reg->s32_max_value = min(reg->s32_max_value,
+ (s32)(var32_off.value | (var32_off.mask & S32_MAX)));
+ reg->u32_min_value = max(reg->u32_min_value, (u32)var32_off.value);
reg->u32_max_value = min(reg->u32_max_value,
(u32)(var32_off.value | var32_off.mask));
}
@@ -2332,11 +2332,11 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
static void __update_reg64_bounds(struct bpf_reg_state *reg)
{
/* min signed is max(sign bit) | min(other bits) */
- reg->smin_value = max_t(s64, reg->smin_value,
- reg->var_off.value | (reg->var_off.mask & S64_MIN));
+ reg->smin_value = max(reg->smin_value,
+ (s64)(reg->var_off.value | (reg->var_off.mask & S64_MIN)));
/* max signed is min(sign bit) | max(other bits) */
- reg->smax_value = min_t(s64, reg->smax_value,
- reg->var_off.value | (reg->var_off.mask & S64_MAX));
+ reg->smax_value = min(reg->smax_value,
+ (s64)(reg->var_off.value | (reg->var_off.mask & S64_MAX)));
reg->umin_value = max(reg->umin_value, reg->var_off.value);
reg->umax_value = min(reg->umax_value,
reg->var_off.value | reg->var_off.mask);
@@ -6128,15 +6128,8 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
return err;
}
- /* __check_mem_access has made sure "off + size - 1" is within u16.
- * reg->umax_value can't be bigger than MAX_PACKET_OFF which is 0xffff,
- * otherwise find_good_pkt_pointers would have refused to set range info
- * that __check_mem_access would have rejected this pkt access.
- * Therefore, "off + reg->umax_value + size - 1" won't overflow u32.
- */
- env->prog->aux->max_pkt_offset =
- max_t(u32, env->prog->aux->max_pkt_offset,
- off + reg->umax_value + size - 1);
+ env->prog->aux->max_pkt_offset = max(env->prog->aux->max_pkt_offset,
+ off + reg->umax_value + size - 1);
return err;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t()
2025-11-19 22:41 ` [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t() david.laight.linux
@ 2025-11-21 21:40 ` Alexei Starovoitov
2025-11-21 22:21 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Alexei Starovoitov @ 2025-11-21 21:40 UTC (permalink / raw)
To: david.laight.linux
Cc: LKML, bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann
On Wed, Nov 19, 2025 at 2:42 PM <david.laight.linux@gmail.com> wrote:
>
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t() and max_t() are normally used to change the signedness
> of a positive value to avoid a signed-v-unsigned compare warning.
>
> However they are used here to convert an unsigned 64bit pattern
> to a signed to a 32/64bit signed number.
> To avoid any confusion use plain min()/max() and explicitely cast
> the u64 expression to the correct signed value.
>
> Use a simple max() for the max_pkt_offset calulation and delete the
> comment about why the cast to u32 is safe.
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> kernel/bpf/verifier.c | 29 +++++++++++------------------
> 1 file changed, 11 insertions(+), 18 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index ff40e5e65c43..22fa9769fbdb 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -2319,12 +2319,12 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
> struct tnum var32_off = tnum_subreg(reg->var_off);
>
> /* min signed is max(sign bit) | min(other bits) */
> - reg->s32_min_value = max_t(s32, reg->s32_min_value,
> - var32_off.value | (var32_off.mask & S32_MIN));
> + reg->s32_min_value = max(reg->s32_min_value,
> + (s32)(var32_off.value | (var32_off.mask & S32_MIN)));
> /* max signed is min(sign bit) | max(other bits) */
> - reg->s32_max_value = min_t(s32, reg->s32_max_value,
> - var32_off.value | (var32_off.mask & S32_MAX));
> - reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)var32_off.value);
> + reg->s32_max_value = min(reg->s32_max_value,
> + (s32)(var32_off.value | (var32_off.mask & S32_MAX)));
Nack.
This is plain ugly for no good reason.
Leave the code as-is.
pw-bot: cr
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t()
2025-11-21 21:40 ` Alexei Starovoitov
@ 2025-11-21 22:21 ` David Laight
2025-11-23 16:39 ` Alexei Starovoitov
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-21 22:21 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: LKML, bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann
On Fri, 21 Nov 2025 13:40:36 -0800
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> On Wed, Nov 19, 2025 at 2:42 PM <david.laight.linux@gmail.com> wrote:
> >
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t() and max_t() are normally used to change the signedness
> > of a positive value to avoid a signed-v-unsigned compare warning.
> >
> > However they are used here to convert an unsigned 64bit pattern
> > to a signed to a 32/64bit signed number.
> > To avoid any confusion use plain min()/max() and explicitely cast
> > the u64 expression to the correct signed value.
> >
> > Use a simple max() for the max_pkt_offset calulation and delete the
> > comment about why the cast to u32 is safe.
> >
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > ---
> > kernel/bpf/verifier.c | 29 +++++++++++------------------
> > 1 file changed, 11 insertions(+), 18 deletions(-)
> >
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index ff40e5e65c43..22fa9769fbdb 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -2319,12 +2319,12 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
> > struct tnum var32_off = tnum_subreg(reg->var_off);
> >
> > /* min signed is max(sign bit) | min(other bits) */
> > - reg->s32_min_value = max_t(s32, reg->s32_min_value,
> > - var32_off.value | (var32_off.mask & S32_MIN));
> > + reg->s32_min_value = max(reg->s32_min_value,
> > + (s32)(var32_off.value | (var32_off.mask & S32_MIN)));
> > /* max signed is min(sign bit) | max(other bits) */
> > - reg->s32_max_value = min_t(s32, reg->s32_max_value,
> > - var32_off.value | (var32_off.mask & S32_MAX));
> > - reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)var32_off.value);
> > + reg->s32_max_value = min(reg->s32_max_value,
> > + (s32)(var32_off.value | (var32_off.mask & S32_MAX)));
>
> Nack.
> This is plain ugly for no good reason.
> Leave the code as-is.
It is really horrid before.
From what i remember var32_off.value (and .mask) are both u64.
The pattern actually patches that used a few lines down the file.
I've been trying to build allmodconfig with the size test added to min_t()
and max_t().
The number of real (or potentially real) bugs I've found is stunning.
The only fix is to nuke min_t() and max_t() to they can't be used.
The basic problem is the people have used the type of the target not that
of the largest parameter.
The might be ok for ulong v uint (on 64bit), but there are plenty of places
where u16 and u8 are used - a lot are pretty much buggy.
Perhaps the worst ones I've found are with clamp_t(),
this is from 2/44:
- (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)); \
+ (raw_inode)->xtime = cpu_to_le32(clamp((ts).tv_sec, S32_MIN, S32_MAX)); \
If also found clamp_t(u8, xxx, 0, 255).
There are just so many broken examples.
David
>
> pw-bot: cr
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t()
2025-11-21 22:21 ` David Laight
@ 2025-11-23 16:39 ` Alexei Starovoitov
2025-11-23 18:07 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Alexei Starovoitov @ 2025-11-23 16:39 UTC (permalink / raw)
To: David Laight
Cc: LKML, bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann
On Fri, Nov 21, 2025 at 2:21 PM David Laight
<david.laight.linux@gmail.com> wrote:
>
> On Fri, 21 Nov 2025 13:40:36 -0800
> Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>
> > On Wed, Nov 19, 2025 at 2:42 PM <david.laight.linux@gmail.com> wrote:
> > >
> > > From: David Laight <david.laight.linux@gmail.com>
> > >
> > > min_t() and max_t() are normally used to change the signedness
> > > of a positive value to avoid a signed-v-unsigned compare warning.
> > >
> > > However they are used here to convert an unsigned 64bit pattern
> > > to a signed to a 32/64bit signed number.
> > > To avoid any confusion use plain min()/max() and explicitely cast
> > > the u64 expression to the correct signed value.
> > >
> > > Use a simple max() for the max_pkt_offset calulation and delete the
> > > comment about why the cast to u32 is safe.
> > >
> > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > ---
> > > kernel/bpf/verifier.c | 29 +++++++++++------------------
> > > 1 file changed, 11 insertions(+), 18 deletions(-)
> > >
> > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > index ff40e5e65c43..22fa9769fbdb 100644
> > > --- a/kernel/bpf/verifier.c
> > > +++ b/kernel/bpf/verifier.c
> > > @@ -2319,12 +2319,12 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
> > > struct tnum var32_off = tnum_subreg(reg->var_off);
> > >
> > > /* min signed is max(sign bit) | min(other bits) */
> > > - reg->s32_min_value = max_t(s32, reg->s32_min_value,
> > > - var32_off.value | (var32_off.mask & S32_MIN));
> > > + reg->s32_min_value = max(reg->s32_min_value,
> > > + (s32)(var32_off.value | (var32_off.mask & S32_MIN)));
> > > /* max signed is min(sign bit) | max(other bits) */
> > > - reg->s32_max_value = min_t(s32, reg->s32_max_value,
> > > - var32_off.value | (var32_off.mask & S32_MAX));
> > > - reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)var32_off.value);
> > > + reg->s32_max_value = min(reg->s32_max_value,
> > > + (s32)(var32_off.value | (var32_off.mask & S32_MAX)));
> >
> > Nack.
> > This is plain ugly for no good reason.
> > Leave the code as-is.
>
> It is really horrid before.
> From what i remember var32_off.value (and .mask) are both u64.
> The pattern actually patches that used a few lines down the file.
>
> I've been trying to build allmodconfig with the size test added to min_t()
> and max_t().
> The number of real (or potentially real) bugs I've found is stunning.
> The only fix is to nuke min_t() and max_t() to they can't be used.
No. min_t() is going to stay. It's not broken and
this crusade against it is inappropriate.
> The basic problem is the people have used the type of the target not that
> of the largest parameter.
> The might be ok for ulong v uint (on 64bit), but there are plenty of places
> where u16 and u8 are used - a lot are pretty much buggy.
>
> Perhaps the worst ones I've found are with clamp_t(),
> this is from 2/44:
> - (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)); \
> + (raw_inode)->xtime = cpu_to_le32(clamp((ts).tv_sec, S32_MIN, S32_MAX)); \
> If also found clamp_t(u8, xxx, 0, 255).
>
> There are just so many broken examples.
clamp_t(u8, xxx, 0, 255) is not wrong. It's silly, but
it's doing the right thing and one can argue and explicit
clamp values serve as a documentation.
clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)) is indeed incorrect,
but it's a bug in the implementation of __clamp_once().
Fix it, instead of spamming people with "_t" removal.
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t()
2025-11-23 16:39 ` Alexei Starovoitov
@ 2025-11-23 18:07 ` David Laight
2025-11-23 19:20 ` Alexei Starovoitov
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-23 18:07 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: LKML, bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann
On Sun, 23 Nov 2025 08:39:51 -0800
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> On Fri, Nov 21, 2025 at 2:21 PM David Laight
> <david.laight.linux@gmail.com> wrote:
> >
> > On Fri, 21 Nov 2025 13:40:36 -0800
> > Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> >
> > > On Wed, Nov 19, 2025 at 2:42 PM <david.laight.linux@gmail.com> wrote:
> > > >
> > > > From: David Laight <david.laight.linux@gmail.com>
> > > >
> > > > min_t() and max_t() are normally used to change the signedness
> > > > of a positive value to avoid a signed-v-unsigned compare warning.
> > > >
> > > > However they are used here to convert an unsigned 64bit pattern
> > > > to a signed to a 32/64bit signed number.
> > > > To avoid any confusion use plain min()/max() and explicitely cast
> > > > the u64 expression to the correct signed value.
> > > >
> > > > Use a simple max() for the max_pkt_offset calulation and delete the
> > > > comment about why the cast to u32 is safe.
> > > >
> > > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > > ---
> > > > kernel/bpf/verifier.c | 29 +++++++++++------------------
> > > > 1 file changed, 11 insertions(+), 18 deletions(-)
> > > >
> > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > > index ff40e5e65c43..22fa9769fbdb 100644
> > > > --- a/kernel/bpf/verifier.c
> > > > +++ b/kernel/bpf/verifier.c
> > > > @@ -2319,12 +2319,12 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
> > > > struct tnum var32_off = tnum_subreg(reg->var_off);
> > > >
> > > > /* min signed is max(sign bit) | min(other bits) */
> > > > - reg->s32_min_value = max_t(s32, reg->s32_min_value,
> > > > - var32_off.value | (var32_off.mask & S32_MIN));
> > > > + reg->s32_min_value = max(reg->s32_min_value,
> > > > + (s32)(var32_off.value | (var32_off.mask & S32_MIN)));
> > > > /* max signed is min(sign bit) | max(other bits) */
> > > > - reg->s32_max_value = min_t(s32, reg->s32_max_value,
> > > > - var32_off.value | (var32_off.mask & S32_MAX));
> > > > - reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)var32_off.value);
> > > > + reg->s32_max_value = min(reg->s32_max_value,
> > > > + (s32)(var32_off.value | (var32_off.mask & S32_MAX)));
> > >
> > > Nack.
> > > This is plain ugly for no good reason.
> > > Leave the code as-is.
> >
> > It is really horrid before.
> > From what i remember var32_off.value (and .mask) are both u64.
> > The pattern actually patches that used a few lines down the file.
> >
> > I've been trying to build allmodconfig with the size test added to min_t()
> > and max_t().
> > The number of real (or potentially real) bugs I've found is stunning.
> > The only fix is to nuke min_t() and max_t() to they can't be used.
>
> No. min_t() is going to stay. It's not broken and
> this crusade against it is inappropriate.
I bet to differ...
> > The basic problem is the people have used the type of the target not that
> > of the largest parameter.
> > The might be ok for ulong v uint (on 64bit), but there are plenty of places
> > where u16 and u8 are used - a lot are pretty much buggy.
> >
> > Perhaps the worst ones I've found are with clamp_t(),
> > this is from 2/44:
> > - (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)); \
> > + (raw_inode)->xtime = cpu_to_le32(clamp((ts).tv_sec, S32_MIN, S32_MAX)); \
> > If also found clamp_t(u8, xxx, 0, 255).
> >
> > There are just so many broken examples.
>
> clamp_t(u8, xxx, 0, 255) is not wrong. It's silly, but
> it's doing the right thing and one can argue and explicit
> clamp values serve as a documentation.
Not when you look at some of the code that uses it.
The clear intention is to saturate a large value - which isn't what it does.
> clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)) is indeed incorrect,
> but it's a bug in the implementation of __clamp_once().
> Fix it, instead of spamming people with "_t" removal.
It is too late by the time you get to clamp_once().
The 'type' for all the xxx_t() functions is an input cast, not the type
for the result.
clamp_t(type, v, lo, hi) has always been clamp((type)v, (type)lo, type(hi)).
From a code correctness point of view you pretty much never want those casts.
I've already fixed clamp() so it doesn't complain about comparing s64 against s32.
The next stage is to change pretty much all the xxx_t() to plain xxx().
If you've got some spare time try issuing read calls with a 4GB buffer to all
the subsystems you can find - and see how many loop for ever.
(I think you can do that with readv() and a single buffer.)
The issue there is that a lot use min_t(u32, max_frag_size, xfer_size) to split
operations - and xfer_size is size_t (so I'm pretty sure there are ways to get
4GB in there).
David
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t()
2025-11-23 18:07 ` David Laight
@ 2025-11-23 19:20 ` Alexei Starovoitov
2025-11-23 23:03 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Alexei Starovoitov @ 2025-11-23 19:20 UTC (permalink / raw)
To: David Laight
Cc: LKML, bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann
On Sun, Nov 23, 2025 at 10:07 AM David Laight
<david.laight.linux@gmail.com> wrote:
>
> On Sun, 23 Nov 2025 08:39:51 -0800
> Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>
> > On Fri, Nov 21, 2025 at 2:21 PM David Laight
> > <david.laight.linux@gmail.com> wrote:
> > >
> > > On Fri, 21 Nov 2025 13:40:36 -0800
> > > Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> > >
> > > > On Wed, Nov 19, 2025 at 2:42 PM <david.laight.linux@gmail.com> wrote:
> > > > >
> > > > > From: David Laight <david.laight.linux@gmail.com>
> > > > >
> > > > > min_t() and max_t() are normally used to change the signedness
> > > > > of a positive value to avoid a signed-v-unsigned compare warning.
> > > > >
> > > > > However they are used here to convert an unsigned 64bit pattern
> > > > > to a signed to a 32/64bit signed number.
> > > > > To avoid any confusion use plain min()/max() and explicitely cast
> > > > > the u64 expression to the correct signed value.
> > > > >
> > > > > Use a simple max() for the max_pkt_offset calulation and delete the
> > > > > comment about why the cast to u32 is safe.
> > > > >
> > > > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > > > ---
> > > > > kernel/bpf/verifier.c | 29 +++++++++++------------------
> > > > > 1 file changed, 11 insertions(+), 18 deletions(-)
> > > > >
> > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > > > index ff40e5e65c43..22fa9769fbdb 100644
> > > > > --- a/kernel/bpf/verifier.c
> > > > > +++ b/kernel/bpf/verifier.c
> > > > > @@ -2319,12 +2319,12 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
> > > > > struct tnum var32_off = tnum_subreg(reg->var_off);
> > > > >
> > > > > /* min signed is max(sign bit) | min(other bits) */
> > > > > - reg->s32_min_value = max_t(s32, reg->s32_min_value,
> > > > > - var32_off.value | (var32_off.mask & S32_MIN));
> > > > > + reg->s32_min_value = max(reg->s32_min_value,
> > > > > + (s32)(var32_off.value | (var32_off.mask & S32_MIN)));
> > > > > /* max signed is min(sign bit) | max(other bits) */
> > > > > - reg->s32_max_value = min_t(s32, reg->s32_max_value,
> > > > > - var32_off.value | (var32_off.mask & S32_MAX));
> > > > > - reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)var32_off.value);
> > > > > + reg->s32_max_value = min(reg->s32_max_value,
> > > > > + (s32)(var32_off.value | (var32_off.mask & S32_MAX)));
> > > >
> > > > Nack.
> > > > This is plain ugly for no good reason.
> > > > Leave the code as-is.
> > >
> > > It is really horrid before.
> > > From what i remember var32_off.value (and .mask) are both u64.
> > > The pattern actually patches that used a few lines down the file.
> > >
> > > I've been trying to build allmodconfig with the size test added to min_t()
> > > and max_t().
> > > The number of real (or potentially real) bugs I've found is stunning.
> > > The only fix is to nuke min_t() and max_t() to they can't be used.
> >
> > No. min_t() is going to stay. It's not broken and
> > this crusade against it is inappropriate.
>
> I bet to differ...
>
> > > The basic problem is the people have used the type of the target not that
> > > of the largest parameter.
> > > The might be ok for ulong v uint (on 64bit), but there are plenty of places
> > > where u16 and u8 are used - a lot are pretty much buggy.
> > >
> > > Perhaps the worst ones I've found are with clamp_t(),
> > > this is from 2/44:
> > > - (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)); \
> > > + (raw_inode)->xtime = cpu_to_le32(clamp((ts).tv_sec, S32_MIN, S32_MAX)); \
> > > If also found clamp_t(u8, xxx, 0, 255).
> > >
> > > There are just so many broken examples.
> >
> > clamp_t(u8, xxx, 0, 255) is not wrong. It's silly, but
> > it's doing the right thing and one can argue and explicit
> > clamp values serve as a documentation.
>
> Not when you look at some of the code that uses it.
> The clear intention is to saturate a large value - which isn't what it does.
>
> > clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)) is indeed incorrect,
> > but it's a bug in the implementation of __clamp_once().
> > Fix it, instead of spamming people with "_t" removal.
>
> It is too late by the time you get to clamp_once().
> The 'type' for all the xxx_t() functions is an input cast, not the type
> for the result.
> clamp_t(type, v, lo, hi) has always been clamp((type)v, (type)lo, type(hi)).
> From a code correctness point of view you pretty much never want those casts.
Historical behavior doesn't justify a footgun.
You definitely can make clampt_t() to behave like clamp_val() plus
the final cast.
Also note:
git grep -w clamp_val|wc -l
818
git grep -w clamp_t|wc -l
494
a safer macro is already used more often.
> I've already fixed clamp() so it doesn't complain about comparing s64 against s32.
> The next stage is to change pretty much all the xxx_t() to plain xxx().
Nack to that. Fix the problem. Not the symptom.
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t()
2025-11-23 19:20 ` Alexei Starovoitov
@ 2025-11-23 23:03 ` David Laight
0 siblings, 0 replies; 109+ messages in thread
From: David Laight @ 2025-11-23 23:03 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: LKML, bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann
On Sun, 23 Nov 2025 11:20:03 -0800
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> On Sun, Nov 23, 2025 at 10:07 AM David Laight
> <david.laight.linux@gmail.com> wrote:
> >
> > On Sun, 23 Nov 2025 08:39:51 -0800
> > Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> >
> > > On Fri, Nov 21, 2025 at 2:21 PM David Laight
> > > <david.laight.linux@gmail.com> wrote:
> > > >
> > > > On Fri, 21 Nov 2025 13:40:36 -0800
> > > > Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> > > >
> > > > > On Wed, Nov 19, 2025 at 2:42 PM <david.laight.linux@gmail.com> wrote:
> > > > > >
> > > > > > From: David Laight <david.laight.linux@gmail.com>
> > > > > >
> > > > > > min_t() and max_t() are normally used to change the signedness
> > > > > > of a positive value to avoid a signed-v-unsigned compare warning.
> > > > > >
> > > > > > However they are used here to convert an unsigned 64bit pattern
> > > > > > to a signed to a 32/64bit signed number.
> > > > > > To avoid any confusion use plain min()/max() and explicitely cast
> > > > > > the u64 expression to the correct signed value.
> > > > > >
> > > > > > Use a simple max() for the max_pkt_offset calulation and delete the
> > > > > > comment about why the cast to u32 is safe.
> > > > > >
> > > > > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > > > > ---
> > > > > > kernel/bpf/verifier.c | 29 +++++++++++------------------
> > > > > > 1 file changed, 11 insertions(+), 18 deletions(-)
> > > > > >
> > > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > > > > index ff40e5e65c43..22fa9769fbdb 100644
> > > > > > --- a/kernel/bpf/verifier.c
> > > > > > +++ b/kernel/bpf/verifier.c
> > > > > > @@ -2319,12 +2319,12 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
> > > > > > struct tnum var32_off = tnum_subreg(reg->var_off);
> > > > > >
> > > > > > /* min signed is max(sign bit) | min(other bits) */
> > > > > > - reg->s32_min_value = max_t(s32, reg->s32_min_value,
> > > > > > - var32_off.value | (var32_off.mask & S32_MIN));
> > > > > > + reg->s32_min_value = max(reg->s32_min_value,
> > > > > > + (s32)(var32_off.value | (var32_off.mask & S32_MIN)));
> > > > > > /* max signed is min(sign bit) | max(other bits) */
> > > > > > - reg->s32_max_value = min_t(s32, reg->s32_max_value,
> > > > > > - var32_off.value | (var32_off.mask & S32_MAX));
> > > > > > - reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)var32_off.value);
> > > > > > + reg->s32_max_value = min(reg->s32_max_value,
> > > > > > + (s32)(var32_off.value | (var32_off.mask & S32_MAX)));
> > > > >
> > > > > Nack.
> > > > > This is plain ugly for no good reason.
> > > > > Leave the code as-is.
> > > >
> > > > It is really horrid before.
> > > > From what i remember var32_off.value (and .mask) are both u64.
> > > > The pattern actually patches that used a few lines down the file.
> > > >
> > > > I've been trying to build allmodconfig with the size test added to min_t()
> > > > and max_t().
> > > > The number of real (or potentially real) bugs I've found is stunning.
> > > > The only fix is to nuke min_t() and max_t() to they can't be used.
> > >
> > > No. min_t() is going to stay. It's not broken and
> > > this crusade against it is inappropriate.
> >
> > I bet to differ...
> >
> > > > The basic problem is the people have used the type of the target not that
> > > > of the largest parameter.
> > > > The might be ok for ulong v uint (on 64bit), but there are plenty of places
> > > > where u16 and u8 are used - a lot are pretty much buggy.
> > > >
> > > > Perhaps the worst ones I've found are with clamp_t(),
> > > > this is from 2/44:
> > > > - (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)); \
> > > > + (raw_inode)->xtime = cpu_to_le32(clamp((ts).tv_sec, S32_MIN, S32_MAX)); \
> > > > If also found clamp_t(u8, xxx, 0, 255).
> > > >
> > > > There are just so many broken examples.
> > >
> > > clamp_t(u8, xxx, 0, 255) is not wrong. It's silly, but
> > > it's doing the right thing and one can argue and explicit
> > > clamp values serve as a documentation.
> >
> > Not when you look at some of the code that uses it.
> > The clear intention is to saturate a large value - which isn't what it does.
> >
> > > clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)) is indeed incorrect,
> > > but it's a bug in the implementation of __clamp_once().
> > > Fix it, instead of spamming people with "_t" removal.
> >
> > It is too late by the time you get to clamp_once().
> > The 'type' for all the xxx_t() functions is an input cast, not the type
> > for the result.
> > clamp_t(type, v, lo, hi) has always been clamp((type)v, (type)lo, type(hi)).
> > From a code correctness point of view you pretty much never want those casts.
>
> Historical behavior doesn't justify a footgun.
> You definitely can make clampt_t() to behave like clamp_val() plus
> the final cast.
clamp_val() is actually the worst of the lot.
> Also note:
> git grep -w clamp_val|wc -l
> 818
> git grep -w clamp_t|wc -l
> 494
>
> a safer macro is already used more often.
clamp_val() is worse than clamp_t() ...
Nope...
The problem is that clamp() requires all three parameters have the same type.
Coders are lazy and want to write clamp(variable, 1, 10).
This was fine if 'variable' had type 'int', but if it was 'unsigned int' you
had to write clamp(variable, 1u, 10u), worse if it is 'u8' you to either cast
both constants clamp(variable, (u8)1, (u8)10) or the variable
clamp((int)variable, 1, 10).
It the types/values aren't immediately obvious then any of those casts can
discard high bits.
A lot of the clamp_val() are actually for u8 structure members.
One thing to remember about C is it doesn't have any maths operators
for u8, the values are always promoted to 'int' before anything happens.
So if you write (foo->u8_member > 4 ? foo->u8_member : 4) the comparison
is done as an integer one.
Add some casts ((u8)f->m > (u8)x ? (u8)f->m : (u8)x) then the values are
all masked to 8 bits, promoted to 32 and then compared.
Even the ?: operator promotes its arguments and has a result type of 'int'.
Consider clamp_val(f->u8_m, LO, HI);
If HI is 255 it is fine, make HI 256 (perhaps it is sizeof() and something
got changed) and you suddenly have clamp(f->u8_m, LO, 0).
It is all just so fragile.
Maybe you are trying to find the 'chunk size' for a transfer of some kind.
If the transfer size is 'small' it might be in a 'u32', you want to limit it
to the size of the hardware's PCIe window - so do:
copy_size = min(transfer_size, hardware_window_size);
But the hardware_window_size is a size_t (so 64bit).
The old min() would complain about the type mismatch, since the
hardware_window_size might actually be 4GB (that is true) casting to u32
is broken - you have to use the larger type.
But it might be the other way around, transfer_size is u64 and
hardware_window_size is u32, you still have to cast to u64 - but this
time it is the size of the other parameter.
The trouble is people have a habit of using the type they want for the
result, u32 in both the above and wrong twice.
But it was only the type check in min() that caused a problem.
Without the casts the compiler generates the right code, the only problem
is when a signed variable might contain a negative value that gets promoted
to a large negative value.
The current implementations of min/max/clamp only generate an error if they
can't prove that negative values won't be promoted to large unsigned values.
This is all fine provided the variable/expressions have the correct type
for the value they contain - and they usually do.
But for this bpf code the type of 'var32_off.value | (var32_off.mask & S32_MIN)'
is actually u64, it really does need an explicit cast to s32.
David
>
> > I've already fixed clamp() so it doesn't complain about comparing s64 against s32.
> > The next stage is to change pretty much all the xxx_t() to plain xxx().
>
> Nack to that. Fix the problem. Not the symptom.
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 07/44] net/core/flow_dissector: Fix cap of __skb_flow_dissect() return value.
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (5 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 08/44] net: ethtool: Use min3() instead of nested min_t(u16,...) david.laight.linux
` (40 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
David Laight
From: David Laight <david.laight.linux@gmail.com>
There are some dodgy clamp_t(u16, ...) and min_t(u16, ...).
__skb_flow_dissect() tries to cap its return value with:
key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen);
however this casts skb->len to u16 before the comparison.
While both nboff and hlen are 'small', skb->len could be 0x10001 which
gets converted to 1 by the cast.
This gives an invalid (small) value for thoff for valid packets.
bpf_flow_dissect() used clamp_t(u16, ...) to set both flow_keys->nhoff
and flow_keys->thoff.
While I think these can't lose significant bits the casts are unnecessary
plain clamp(...) works fine.
Fixes: d0c081b49137c ("flow_dissector: properly cap thoff field")
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
net/core/flow_dissector.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 1b61bb25ba0e..e362160bb73d 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -1023,9 +1023,8 @@ u32 bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,
result = bpf_prog_run_pin_on_cpu(prog, ctx);
- flow_keys->nhoff = clamp_t(u16, flow_keys->nhoff, nhoff, hlen);
- flow_keys->thoff = clamp_t(u16, flow_keys->thoff,
- flow_keys->nhoff, hlen);
+ flow_keys->nhoff = clamp(flow_keys->nhoff, nhoff, hlen);
+ flow_keys->thoff = clamp(flow_keys->thoff, flow_keys->nhoff, hlen);
return result;
}
@@ -1687,7 +1686,7 @@ bool __skb_flow_dissect(const struct net *net,
ret = true;
out:
- key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen);
+ key_control->thoff = umin(nhoff, skb ? skb->len : hlen);
key_basic->n_proto = proto;
key_basic->ip_proto = ip_proto;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 08/44] net: ethtool: Use min3() instead of nested min_t(u16,...)
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (6 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 07/44] net/core/flow_dissector: Fix cap of __skb_flow_dissect() return value david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 09/44] ipv6: __ip6_append_data() don't abuse max_t() casts david.laight.linux
` (39 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, David Laight
From: David Laight <david.laight.linux@gmail.com>
In ethtool_cmis_cdb_execute_epl_cmd() change space_left and
bytes_to_write from u16 to u32.
Although the values may fit in 16 bits, 32bit variables will generate
better code.
Replace the nested min_t(u16, bytes_left, min_t(u16, space_left, x))
with a call to min3().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
net/ethtool/cmis_cdb.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/net/ethtool/cmis_cdb.c b/net/ethtool/cmis_cdb.c
index 3057576bc81e..1406205e047e 100644
--- a/net/ethtool/cmis_cdb.c
+++ b/net/ethtool/cmis_cdb.c
@@ -573,12 +573,11 @@ ethtool_cmis_cdb_execute_epl_cmd(struct net_device *dev,
while (offset <= CMIS_CDB_EPL_FW_BLOCK_OFFSET_END &&
bytes_written < epl_len) {
u32 bytes_left = epl_len - bytes_written;
- u16 space_left, bytes_to_write;
+ u32 space_left, bytes_to_write;
space_left = CMIS_CDB_EPL_FW_BLOCK_OFFSET_END - offset + 1;
- bytes_to_write = min_t(u16, bytes_left,
- min_t(u16, space_left,
- args->read_write_len_ext));
+ bytes_to_write = min3(bytes_left, space_left,
+ args->read_write_len_ext);
err = __ethtool_cmis_cdb_execute_cmd(dev, page_data,
page, offset,
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 09/44] ipv6: __ip6_append_data() don't abuse max_t() casts
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (7 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 08/44] net: ethtool: Use min3() instead of nested min_t(u16,...) david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 0:32 ` bot+bpf-ci
2025-11-19 22:41 ` [PATCH 10/44] x86/crypto: ctr_crypt() use min() instead of min_t() david.laight.linux
` (38 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: David Ahern, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, David Laight
From: David Laight <david.laight.linux@gmail.com>
The implicit casts done by max_t() should only really be used to
convert positive values to signed or unsigned types.
In the EMSGSIZE error path
pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
is being used to convert a large unsigned value to a signed negative one.
Rework using a signed temporary variable and max(pmtu, 0), as well as
casting sizeof() to (int) - which is where the unsignedness comes from.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
net/ipv6/ip6_output.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index f904739e99b9..6fecf2f2cc9a 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1440,7 +1440,7 @@ static int __ip6_append_data(struct sock *sk,
struct sk_buff *skb, *skb_prev = NULL;
struct inet_cork *cork = &cork_full->base;
struct flowi6 *fl6 = &cork_full->fl.u.ip6;
- unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu;
+ unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu;
struct ubuf_info *uarg = NULL;
int exthdrlen = 0;
int dst_exthdrlen = 0;
@@ -1504,9 +1504,10 @@ static int __ip6_append_data(struct sock *sk,
maxnonfragsize = mtu;
if (cork->length + length > maxnonfragsize - headersize) {
+ int pmtu;
emsgsize:
- pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
- ipv6_local_error(sk, EMSGSIZE, fl6, pmtu);
+ pmtu = mtu - headersize + (int)sizeof(struct ipv6hdr);
+ ipv6_local_error(sk, EMSGSIZE, fl6, max(pmtu, 0));
return -EMSGSIZE;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 09/44] ipv6: __ip6_append_data() don't abuse max_t() casts
2025-11-19 22:41 ` [PATCH 09/44] ipv6: __ip6_append_data() don't abuse max_t() casts david.laight.linux
@ 2025-11-20 0:32 ` bot+bpf-ci
2025-11-20 11:16 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: bot+bpf-ci @ 2025-11-20 0:32 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, netdev
Cc: dsahern, davem, edumazet, kuba, pabeni, david.laight.linux, ast,
andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1581 bytes --]
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index f904739e9..6fecf2f2c 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -1440,7 +1440,7 @@ static int __ip6_append_data(struct sock *sk,
> struct sk_buff *skb, *skb_prev = NULL;
> struct inet_cork *cork = &cork_full->base;
> struct flowi6 *fl6 = &cork_full->fl.u.ip6;
> - unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu;
> + unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu;
[ ... ]
> @@ -1504,9 +1504,10 @@ static int __ip6_append_data(struct sock *sk,
> maxnonfragsize = mtu;
>
> if (cork->length + length > maxnonfragsize - headersize) {
> + int pmtu;
> emsgsize:
> - pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
> - ipv6_local_error(sk, EMSGSIZE, fl6, pmtu);
> + pmtu = mtu - headersize + (int)sizeof(struct ipv6hdr);
> + ipv6_local_error(sk, EMSGSIZE, fl6, max(pmtu, 0));
> return -EMSGSIZE;
> }
Can the variable pmtu be used uninitialized here?
When reaching the emsgsize label via goto statements from earlier in
__ip6_append_data() (the checks at lines around mtu <= fragheaderlen,
headersize + transhdrlen > mtu, and the dontfrag check), the int pmtu
declaration is skipped. This leaves pmtu uninitialized when it's used
in the calculation that's passed to ipv6_local_error().
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/19519124312
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 09/44] ipv6: __ip6_append_data() don't abuse max_t() casts
2025-11-20 0:32 ` bot+bpf-ci
@ 2025-11-20 11:16 ` David Laight
2025-11-20 13:50 ` Chris Mason
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 11:16 UTC (permalink / raw)
To: bot+bpf-ci
Cc: linux-kernel, netdev, dsahern, davem, edumazet, kuba, pabeni, ast,
andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
On Thu, 20 Nov 2025 00:32:34 +0000 (UTC)
bot+bpf-ci@kernel.org wrote:
> > diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> > index f904739e9..6fecf2f2c 100644
> > --- a/net/ipv6/ip6_output.c
> > +++ b/net/ipv6/ip6_output.c
> > @@ -1440,7 +1440,7 @@ static int __ip6_append_data(struct sock *sk,
> > struct sk_buff *skb, *skb_prev = NULL;
> > struct inet_cork *cork = &cork_full->base;
> > struct flowi6 *fl6 = &cork_full->fl.u.ip6;
> > - unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu;
> > + unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu;
>
> [ ... ]
>
> > @@ -1504,9 +1504,10 @@ static int __ip6_append_data(struct sock *sk,
> > maxnonfragsize = mtu;
> >
> > if (cork->length + length > maxnonfragsize - headersize) {
> > + int pmtu;
> > emsgsize:
> > - pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
> > - ipv6_local_error(sk, EMSGSIZE, fl6, pmtu);
> > + pmtu = mtu - headersize + (int)sizeof(struct ipv6hdr);
> > + ipv6_local_error(sk, EMSGSIZE, fl6, max(pmtu, 0));
> > return -EMSGSIZE;
> > }
>
> Can the variable pmtu be used uninitialized here?
If your AI bot doesn't understand code don't run it.
David
>
> When reaching the emsgsize label via goto statements from earlier in
> __ip6_append_data() (the checks at lines around mtu <= fragheaderlen,
> headersize + transhdrlen > mtu, and the dontfrag check), the int pmtu
> declaration is skipped. This leaves pmtu uninitialized when it's used
> in the calculation that's passed to ipv6_local_error().
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/19519124312
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 09/44] ipv6: __ip6_append_data() don't abuse max_t() casts
2025-11-20 11:16 ` David Laight
@ 2025-11-20 13:50 ` Chris Mason
0 siblings, 0 replies; 109+ messages in thread
From: Chris Mason @ 2025-11-20 13:50 UTC (permalink / raw)
To: David Laight, bot+bpf-ci
Cc: linux-kernel, netdev, dsahern, davem, edumazet, kuba, pabeni, ast,
andrii, daniel, martin.lau, eddyz87, yonghong.song, ihor.solodrai
On 11/20/25 6:16 AM, David Laight wrote:
> On Thu, 20 Nov 2025 00:32:34 +0000 (UTC)
> bot+bpf-ci@kernel.org wrote:
>
>>> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
>>> index f904739e9..6fecf2f2c 100644
>>> --- a/net/ipv6/ip6_output.c
>>> +++ b/net/ipv6/ip6_output.c
>>> @@ -1440,7 +1440,7 @@ static int __ip6_append_data(struct sock *sk,
>>> struct sk_buff *skb, *skb_prev = NULL;
>>> struct inet_cork *cork = &cork_full->base;
>>> struct flowi6 *fl6 = &cork_full->fl.u.ip6;
>>> - unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu;
>>> + unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu;
>>
>> [ ... ]
>>
>>> @@ -1504,9 +1504,10 @@ static int __ip6_append_data(struct sock *sk,
>>> maxnonfragsize = mtu;
>>>
>>> if (cork->length + length > maxnonfragsize - headersize) {
>>> + int pmtu;
>>> emsgsize:
>>> - pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
>>> - ipv6_local_error(sk, EMSGSIZE, fl6, pmtu);
>>> + pmtu = mtu - headersize + (int)sizeof(struct ipv6hdr);
>>> + ipv6_local_error(sk, EMSGSIZE, fl6, max(pmtu, 0));
>>> return -EMSGSIZE;
>>> }
>>
>> Can the variable pmtu be used uninitialized here?
>
> If your AI bot doesn't understand code don't run it.
I ran this locally three more times and this false positive didn't
reproduce, but I'll see if the CI has enough logs to figure out where it
got confused.
Regardless, I'm doing periodic checks for patterns of false positives
and fine tuning the prompts.
-chris
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 10/44] x86/crypto: ctr_crypt() use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (8 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 09/44] ipv6: __ip6_append_data() don't abuse max_t() casts david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 11/44] arch/x96/kvm: " david.laight.linux
` (37 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-crypto
Cc: Borislav Petkov, Dave Hansen, David S. Miller, Herbert Xu,
Ingo Molnar, Thomas Gleixner, x86, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
arch/x86/crypto/aesni-intel_glue.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index d953ac470aae..f71db4f1c99c 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -693,8 +693,7 @@ ctr_crypt(struct skcipher_request *req,
* operation into two at the point where the overflow
* will occur. After the first part, add the carry bit.
*/
- p1_nbytes = min_t(unsigned int, nbytes,
- (nblocks - ctr64) * AES_BLOCK_SIZE);
+ p1_nbytes = min(nbytes, (nblocks - ctr64) * AES_BLOCK_SIZE);
(*ctr64_func)(key, walk.src.virt.addr,
walk.dst.virt.addr, p1_nbytes, le_ctr);
le_ctr[0] = 0;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 11/44] arch/x96/kvm: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (9 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 10/44] x86/crypto: ctr_crypt() use min() instead of min_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 12/44] block: " david.laight.linux
` (36 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, kvm
Cc: Borislav Petkov, Dave Hansen, Ingo Molnar, Paolo Bonzini,
Sean Christopherson, Thomas Gleixner, x86, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
(Similarly for max_t() and clamp_t().)
Use min3() in __do_insn_fetch_bytes().
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
arch/x86/kvm/emulate.c | 3 +--
arch/x86/kvm/lapic.c | 2 +-
arch/x86/kvm/mmu/mmu.c | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 4e3da5b497b8..9596969f4714 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -861,8 +861,7 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
if (unlikely(rc != X86EMUL_CONTINUE))
return rc;
- size = min_t(unsigned, 15UL ^ cur_size, max_size);
- size = min_t(unsigned, size, PAGE_SIZE - offset_in_page(linear));
+ size = min3(15U ^ cur_size, max_size, PAGE_SIZE - offset_in_page(linear));
/*
* One instruction can only straddle two pages,
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 0ae7f913d782..b6bdb76efe3a 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1894,7 +1894,7 @@ static inline void __wait_lapic_expire(struct kvm_vcpu *vcpu, u64 guest_cycles)
} else {
u64 delay_ns = guest_cycles * 1000000ULL;
do_div(delay_ns, vcpu->arch.virtual_tsc_khz);
- ndelay(min_t(u32, delay_ns, timer_advance_ns));
+ ndelay(min(delay_ns, timer_advance_ns));
}
}
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 667d66cf76d5..989d96f5ec23 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -5768,7 +5768,7 @@ static void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu,
root_role = cpu_role.base;
/* KVM uses PAE paging whenever the guest isn't using 64-bit paging. */
- root_role.level = max_t(u32, root_role.level, PT32E_ROOT_LEVEL);
+ root_role.level = max(root_role.level + 0, PT32E_ROOT_LEVEL);
/*
* KVM forces EFER.NX=1 when TDP is disabled, reflect it in the MMU role.
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 12/44] block: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (10 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 11/44] arch/x96/kvm: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 14:44 ` Jens Axboe
2025-11-19 22:41 ` [PATCH 13/44] drivers/acpi: " david.laight.linux
` (35 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, cgroups, linux-block, linux-efi
Cc: Davidlohr Bueso, Jens Axboe, Josef Bacik, Tejun Heo, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
(Similarly for max_t() and clamp_t().)
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
block/blk-iocost.c | 6 ++----
block/blk-settings.c | 2 +-
block/partitions/efi.c | 3 +--
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 5bfd70311359..a0416927d33d 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -2334,10 +2334,8 @@ static void ioc_timer_fn(struct timer_list *timer)
else
usage_dur = max_t(u64, now.now - ioc->period_at, 1);
- usage = clamp_t(u32,
- DIV64_U64_ROUND_UP(usage_us * WEIGHT_ONE,
- usage_dur),
- 1, WEIGHT_ONE);
+ usage = clamp(DIV64_U64_ROUND_UP(usage_us * WEIGHT_ONE, usage_dur),
+ 1, WEIGHT_ONE);
/*
* Already donating or accumulated enough to start.
diff --git a/block/blk-settings.c b/block/blk-settings.c
index d74b13ec8e54..4e0c23e68fac 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -472,7 +472,7 @@ int blk_validate_limits(struct queue_limits *lim)
seg_size = lim->max_segment_size;
else
seg_size = lim->seg_boundary_mask + 1;
- lim->min_segment_size = min_t(unsigned int, seg_size, PAGE_SIZE);
+ lim->min_segment_size = min(seg_size, PAGE_SIZE);
/*
* We require drivers to at least do logical block aligned I/O, but
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 7acba66eed48..638261e9f2fb 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -215,8 +215,7 @@ static int is_pmbr_valid(legacy_mbr *mbr, sector_t total_sectors)
sz = le32_to_cpu(mbr->partition_record[part].size_in_lba);
if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF)
pr_debug("GPT: mbr size in lba (%u) different than whole disk (%u).\n",
- sz, min_t(uint32_t,
- total_sectors - 1, 0xFFFFFFFF));
+ sz, (uint32_t)min(total_sectors - 1, 0xFFFFFFFF));
}
done:
return ret;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 12/44] block: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 12/44] block: " david.laight.linux
@ 2025-11-20 14:44 ` Jens Axboe
0 siblings, 0 replies; 109+ messages in thread
From: Jens Axboe @ 2025-11-20 14:44 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, cgroups, linux-block, linux-efi
Cc: Davidlohr Bueso, Josef Bacik, Tejun Heo
On 11/19/25 3:41 PM, david.laight.linux@gmail.com wrote:
> diff --git a/block/blk-settings.c b/block/blk-settings.c
> index d74b13ec8e54..4e0c23e68fac 100644
> --- a/block/blk-settings.c
> +++ b/block/blk-settings.c
> @@ -472,7 +472,7 @@ int blk_validate_limits(struct queue_limits *lim)
> seg_size = lim->max_segment_size;
> else
> seg_size = lim->seg_boundary_mask + 1;
> - lim->min_segment_size = min_t(unsigned int, seg_size, PAGE_SIZE);
> + lim->min_segment_size = min(seg_size, PAGE_SIZE);
>
> /*
> * We require drivers to at least do logical block aligned I/O, but
This doesn't exist in the 6.19 branch, dropped.
--
Jens Axboe
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 13/44] drivers/acpi: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (11 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 12/44] block: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-24 19:48 ` Rafael J. Wysocki
2025-11-19 22:41 ` [PATCH 14/44] drivers/char/hw_random: use min3() instead of nested min_t() david.laight.linux
` (34 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-acpi; +Cc: Rafael J. Wysocki, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/acpi/property.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 43d5e457814e..e427ab24cde7 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1280,7 +1280,7 @@ static int acpi_data_prop_read(const struct acpi_device_data *data,
ret = acpi_copy_property_array_uint(items, (u64 *)val, nval);
break;
case DEV_PROP_STRING:
- nval = min_t(u32, nval, obj->package.count);
+ nval = min(nval, obj->package.count);
if (nval == 0)
return -ENODATA;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 13/44] drivers/acpi: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 13/44] drivers/acpi: " david.laight.linux
@ 2025-11-24 19:48 ` Rafael J. Wysocki
0 siblings, 0 replies; 109+ messages in thread
From: Rafael J. Wysocki @ 2025-11-24 19:48 UTC (permalink / raw)
To: david.laight.linux; +Cc: linux-kernel, linux-acpi, Rafael J. Wysocki
On Wed, Nov 19, 2025 at 11:42 PM <david.laight.linux@gmail.com> wrote:
>
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
>
> In this case the 'unsigned long' value is small enough that the result
> is ok.
>
> Detected by an extra check added to min_t().
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> drivers/acpi/property.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> index 43d5e457814e..e427ab24cde7 100644
> --- a/drivers/acpi/property.c
> +++ b/drivers/acpi/property.c
> @@ -1280,7 +1280,7 @@ static int acpi_data_prop_read(const struct acpi_device_data *data,
> ret = acpi_copy_property_array_uint(items, (u64 *)val, nval);
> break;
> case DEV_PROP_STRING:
> - nval = min_t(u32, nval, obj->package.count);
> + nval = min(nval, obj->package.count);
> if (nval == 0)
> return -ENODATA;
>
> --
Applied as 6.19 material with adjusted subject, thanks!
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 14/44] drivers/char/hw_random: use min3() instead of nested min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (12 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 13/44] drivers/acpi: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 15/44] drivers/char/tpm: use min() instead of min_t() david.laight.linux
` (33 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-crypto; +Cc: Herbert Xu, Olivia Mackall, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(u16, a, b) is likely to discard significant bits.
Replace:
min_t(u16, min_t(u16, default_quality, 1024), rng->quality ?: 1024);
with:
min3(default_quality, 1024, rng->quality ?: 1024);
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/char/hw_random/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 018316f54621..74c8eb1d9048 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -542,7 +542,7 @@ int hwrng_register(struct hwrng *rng)
init_completion(&rng->dying);
/* Adjust quality field to always have a proper value */
- rng->quality = min_t(u16, min_t(u16, default_quality, 1024), rng->quality ?: 1024);
+ rng->quality = min3(default_quality, 1024, rng->quality ?: 1024);
if (!current_rng ||
(!cur_rng_set_by_user && rng->quality > current_rng->quality)) {
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 15/44] drivers/char/tpm: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (13 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 14/44] drivers/char/hw_random: use min3() instead of nested min_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-21 20:11 ` Jarkko Sakkinen
2025-11-19 22:41 ` [PATCH 16/44] drivers/crypto/ccp: " david.laight.linux
` (32 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-integrity; +Cc: Jarkko Sakkinen, Peter Huewe, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(int, a, b) casts an 'long' to 'int'.
Use min(a, b) instead as it promotes any 'int' to 'long'
and so cannot discard significant bits.
In this case the 'long' value is small enough that the result is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/char/tpm/tpm1-cmd.c | 2 +-
drivers/char/tpm/tpm_tis_core.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index cf64c7385105..11088bda4e68 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -530,7 +530,7 @@ struct tpm1_get_random_out {
int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
{
struct tpm1_get_random_out *out;
- u32 num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
+ u32 num_bytes = min(max, TPM_MAX_RNG_DATA);
struct tpm_buf buf;
u32 total = 0;
int retries = 5;
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 8954a8660ffc..2676e3a241b5 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -310,7 +310,7 @@ static int get_burstcount(struct tpm_chip *chip)
return -EBUSY;
}
-static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+static int recv_data(struct tpm_chip *chip, u8 *buf, u32 count)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
int size = 0, burstcnt, rc;
@@ -453,7 +453,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
rc = burstcnt;
goto out_err;
}
- burstcnt = min_t(int, burstcnt, len - count - 1);
+ burstcnt = min(burstcnt, len - count - 1);
rc = tpm_tis_write_bytes(priv, TPM_DATA_FIFO(priv->locality),
burstcnt, buf + count);
if (rc < 0)
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 15/44] drivers/char/tpm: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 15/44] drivers/char/tpm: use min() instead of min_t() david.laight.linux
@ 2025-11-21 20:11 ` Jarkko Sakkinen
0 siblings, 0 replies; 109+ messages in thread
From: Jarkko Sakkinen @ 2025-11-21 20:11 UTC (permalink / raw)
To: david.laight.linux; +Cc: linux-kernel, linux-integrity, Peter Huewe
On Wed, Nov 19, 2025 at 10:41:11PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(int, a, b) casts an 'long' to 'int'.
> Use min(a, b) instead as it promotes any 'int' to 'long'
> and so cannot discard significant bits.
>
> In this case the 'long' value is small enough that the result is ok.
>
> Detected by an extra check added to min_t().
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> drivers/char/tpm/tpm1-cmd.c | 2 +-
> drivers/char/tpm/tpm_tis_core.c | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
> index cf64c7385105..11088bda4e68 100644
> --- a/drivers/char/tpm/tpm1-cmd.c
> +++ b/drivers/char/tpm/tpm1-cmd.c
> @@ -530,7 +530,7 @@ struct tpm1_get_random_out {
> int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
> {
> struct tpm1_get_random_out *out;
> - u32 num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
> + u32 num_bytes = min(max, TPM_MAX_RNG_DATA);
> struct tpm_buf buf;
> u32 total = 0;
> int retries = 5;
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> index 8954a8660ffc..2676e3a241b5 100644
> --- a/drivers/char/tpm/tpm_tis_core.c
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -310,7 +310,7 @@ static int get_burstcount(struct tpm_chip *chip)
> return -EBUSY;
> }
>
> -static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
> +static int recv_data(struct tpm_chip *chip, u8 *buf, u32 count)
> {
> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> int size = 0, burstcnt, rc;
> @@ -453,7 +453,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
> rc = burstcnt;
> goto out_err;
> }
> - burstcnt = min_t(int, burstcnt, len - count - 1);
> + burstcnt = min(burstcnt, len - count - 1);
> rc = tpm_tis_write_bytes(priv, TPM_DATA_FIFO(priv->locality),
> burstcnt, buf + count);
> if (rc < 0)
> --
> 2.39.5
>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
BR, Jarkko
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 16/44] drivers/crypto/ccp: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (14 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 15/44] drivers/char/tpm: use min() instead of min_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 17/44] drivers/cxl: " david.laight.linux
` (31 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-crypto
Cc: David S. Miller, Herbert Xu, John Allen, Tom Lendacky,
David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/crypto/ccp/ccp-dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index c531d13d971f..246801912e1a 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -507,7 +507,7 @@ int ccp_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct ccp_device *ccp = container_of(rng, struct ccp_device, hwrng);
u32 trng_value;
- int len = min_t(int, sizeof(trng_value), max);
+ int len = min(sizeof(trng_value), max);
/* Locking is provided by the caller so we can update device
* hwrng-related fields safely
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 17/44] drivers/cxl: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (15 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 16/44] drivers/crypto/ccp: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 23:50 ` Dave Jiang
2025-11-19 22:41 ` [PATCH 18/44] drivers/gpio: " david.laight.linux
` (30 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-cxl
Cc: Alison Schofield, Dan Williams, Dave Jiang, Davidlohr Bueso,
Ira Weiny, Jonathan Cameron, Vishal Verma, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/cxl/core/mbox.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index fa6dd0c94656..17aec916e8cd 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -663,7 +663,7 @@ static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid,
u32 offset = 0;
while (remaining) {
- u32 xfer_size = min_t(u32, remaining, cxl_mbox->payload_size);
+ u32 xfer_size = min(remaining, cxl_mbox->payload_size);
struct cxl_mbox_cmd mbox_cmd;
struct cxl_mbox_get_log log;
int rc;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 17/44] drivers/cxl: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 17/44] drivers/cxl: " david.laight.linux
@ 2025-11-19 23:50 ` Dave Jiang
0 siblings, 0 replies; 109+ messages in thread
From: Dave Jiang @ 2025-11-19 23:50 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, linux-cxl
Cc: Alison Schofield, Dan Williams, Davidlohr Bueso, Ira Weiny,
Jonathan Cameron, Vishal Verma
On 11/19/25 3:41 PM, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
>
> In this case the 'unsigned long' value is small enough that the result
> is ok.
>
> Detected by an extra check added to min_t().
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
Acked-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/mbox.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
> index fa6dd0c94656..17aec916e8cd 100644
> --- a/drivers/cxl/core/mbox.c
> +++ b/drivers/cxl/core/mbox.c
> @@ -663,7 +663,7 @@ static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid,
> u32 offset = 0;
>
> while (remaining) {
> - u32 xfer_size = min_t(u32, remaining, cxl_mbox->payload_size);
> + u32 xfer_size = min(remaining, cxl_mbox->payload_size);
> struct cxl_mbox_cmd mbox_cmd;
> struct cxl_mbox_get_log log;
> int rc;
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 18/44] drivers/gpio: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (16 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 17/44] drivers/cxl: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 8:01 ` Andy Shevchenko
2025-11-19 22:41 ` [PATCH 19/44] drivers/gpu/drm/amd: " david.laight.linux
` (29 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-acpi, linux-gpio
Cc: Andy Shevchenko, Bartosz Golaszewski, Linus Walleij,
Mika Westerberg, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(u16, a, b) casts an 'unsigned long' to 'u16'.
Use min(a, b) instead as it promotes the both values to int
and so cannot discard significant bits.
In this case the values should be ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/gpio/gpiolib-acpi-core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-core.c
index d441c1236d8c..83dd227dbbec 100644
--- a/drivers/gpio/gpiolib-acpi-core.c
+++ b/drivers/gpio/gpiolib-acpi-core.c
@@ -1099,7 +1099,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
return AE_BAD_PARAMETER;
}
- length = min_t(u16, agpio->pin_table_length, pin_index + bits);
+ length = min(agpio->pin_table_length, pin_index + bits);
for (i = pin_index; i < length; ++i) {
unsigned int pin = agpio->pin_table[i];
struct acpi_gpio_connection *conn;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 18/44] drivers/gpio: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 18/44] drivers/gpio: " david.laight.linux
@ 2025-11-20 8:01 ` Andy Shevchenko
2025-11-20 9:37 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Andy Shevchenko @ 2025-11-20 8:01 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, linux-acpi, linux-gpio, Bartosz Golaszewski,
Linus Walleij, Mika Westerberg
On Wed, Nov 19, 2025 at 10:41:14PM +0000, david.laight.linux@gmail.com wrote:
>
> min_t(u16, a, b) casts an 'unsigned long' to 'u16'.
> Use min(a, b) instead as it promotes the both values to int
> and so cannot discard significant bits.
>
> In this case the values should be ok.
>
> Detected by an extra check added to min_t().
In most of the patches you need to follow the commonly used Subject prefix.
This can be done by doing
git log --oneline --no-merges -- $FILE(S)_OF_INTEREST
For example,
$ git log --no-decorate --oneline --no-merges -- drivers/gpio/gpiolib-acpi*
b1055678a016 gpiolib: acpi: Use %pe when passing an error pointer to dev_err()
e4a77f9c85a5 gpiolib: acpi: Make set debounce errors non fatal
19c839a98c73 gpiolib: acpi: initialize acpi_gpio_info struct
3712ce9fa501 gpiolib: acpi: Ignore touchpad wakeup on GPD G1619-05
16c07342b542 gpiolib: acpi: Program debounce when finding GPIO
23800ad1265f gpiolib: acpi: Add quirk for ASUS ProArt PX13
...
> acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
> - length = min_t(u16, agpio->pin_table_length, pin_index + bits);
> + length = min(agpio->pin_table_length, pin_index + bits);
Now, if you look closer at the code, the pin_index alone has the problem you
are targeting here. On top of that the iterator and 'length' are signed, while
the result of min_t(u16) is unsigned (however it has no difference in this case).
...
TL;DR: I apply this patch with subject changed, but I think more work needs to
be done if you want to fix it fully.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 18/44] drivers/gpio: use min() instead of min_t()
2025-11-20 8:01 ` Andy Shevchenko
@ 2025-11-20 9:37 ` David Laight
2025-11-25 9:55 ` Andy Shevchenko
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 9:37 UTC (permalink / raw)
To: Andy Shevchenko
Cc: linux-kernel, linux-acpi, linux-gpio, Bartosz Golaszewski,
Linus Walleij, Mika Westerberg
On Thu, 20 Nov 2025 10:01:29 +0200
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> On Wed, Nov 19, 2025 at 10:41:14PM +0000, david.laight.linux@gmail.com wrote:
> >
> > min_t(u16, a, b) casts an 'unsigned long' to 'u16'.
> > Use min(a, b) instead as it promotes the both values to int
> > and so cannot discard significant bits.
> >
> > In this case the values should be ok.
> >
> > Detected by an extra check added to min_t().
>
> In most of the patches you need to follow the commonly used Subject prefix.
> This can be done by doing
I did look up quite a few files to see what had been used previously.
But it is a bit tedious with 44 patches.
> git log --oneline --no-merges -- $FILE(S)_OF_INTEREST
I wasn't aware of that spell :-)
...
>
> > acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
>
> > - length = min_t(u16, agpio->pin_table_length, pin_index + bits);
> > + length = min(agpio->pin_table_length, pin_index + bits);
>
> Now, if you look closer at the code, the pin_index alone has the problem you
> are targeting here.
The compiler warning happens because 'pin_index + bits' is 'int' and the compiler
doesn't know the value fits in 16 bits.
It should fit, but only if the caller passes in valid data.
> On top of that the iterator and 'length' are signed, while
> the result of min_t(u16) is unsigned (however it has no difference in this case).
Actually the result type of min_t(u16) is 'int' (:? promotes char/short to int).
So the u16 cast does '(pin_index + bits) & 0xffff', everything is then promoted
to 'int' for all the comparisons (etc).
David
>
> ...
>
> TL;DR: I apply this patch with subject changed, but I think more work needs to
> be done if you want to fix it fully.
>
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 18/44] drivers/gpio: use min() instead of min_t()
2025-11-20 9:37 ` David Laight
@ 2025-11-25 9:55 ` Andy Shevchenko
0 siblings, 0 replies; 109+ messages in thread
From: Andy Shevchenko @ 2025-11-25 9:55 UTC (permalink / raw)
To: David Laight
Cc: linux-kernel, linux-acpi, linux-gpio, Bartosz Golaszewski,
Linus Walleij, Mika Westerberg
On Thu, Nov 20, 2025 at 09:37:43AM +0000, David Laight wrote:
> On Thu, 20 Nov 2025 10:01:29 +0200
> Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> > On Wed, Nov 19, 2025 at 10:41:14PM +0000, david.laight.linux@gmail.com wrote:
> > >
> > > min_t(u16, a, b) casts an 'unsigned long' to 'u16'.
> > > Use min(a, b) instead as it promotes the both values to int
> > > and so cannot discard significant bits.
> > >
> > > In this case the values should be ok.
> > >
> > > Detected by an extra check added to min_t().
...
> > > acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
> >
> > > - length = min_t(u16, agpio->pin_table_length, pin_index + bits);
> > > + length = min(agpio->pin_table_length, pin_index + bits);
> >
> > Now, if you look closer at the code, the pin_index alone has the problem you
> > are targeting here.
>
> The compiler warning happens because 'pin_index + bits' is 'int' and the compiler
> doesn't know the value fits in 16 bits.
> It should fit, but only if the caller passes in valid data.
I meant that assignment to pin_index already cuts the higher bits
from the input.
> > On top of that the iterator and 'length' are signed, while
> > the result of min_t(u16) is unsigned (however it has no difference in this case).
>
> Actually the result type of min_t(u16) is 'int' (:? promotes char/short to int).
> So the u16 cast does '(pin_index + bits) & 0xffff', everything is then promoted
> to 'int' for all the comparisons (etc).
Sure, but the value is positive even if int is signed. That's why I put
a remark in the parentheses that it has no difference in this case.
...
> > TL;DR: I apply this patch with subject changed, but I think more work needs to
> > be done if you want to fix it fully.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 19/44] drivers/gpu/drm/amd: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (17 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 18/44] drivers/gpio: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 20/44] drivers/i2c/busses: " david.laight.linux
` (28 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, amd-gfx, dri-devel
Cc: Alex Deucher, Christian König, David Airlie, Harry Wentland,
Leo Li, Simona Vetter, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
min_t(u8, a, b) is particularly likely to be problematic
In this case I think the values are small enough that the result is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c | 4 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c
index 3040437d99c2..1eb88327a18b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c
@@ -211,8 +211,8 @@ int amdgpu_doorbell_init(struct amdgpu_device *adev)
adev->doorbell.size = pci_resource_len(adev->pdev, 2);
adev->doorbell.num_kernel_doorbells =
- min_t(u32, adev->doorbell.size / sizeof(u32),
- adev->doorbell_index.max_assignment + 1);
+ min(adev->doorbell.size / sizeof(u32),
+ adev->doorbell_index.max_assignment + 1);
if (adev->doorbell.num_kernel_doorbells == 0)
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index c1a801203949..124ce3e7310e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2388,7 +2388,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
if (amdgpu_vm_block_size != -1)
tmp >>= amdgpu_vm_block_size - 9;
tmp = DIV_ROUND_UP(fls64(tmp) - 1, 9) - 1;
- adev->vm_manager.num_level = min_t(unsigned int, max_level, tmp);
+ adev->vm_manager.num_level = min(max_level, tmp);
switch (adev->vm_manager.num_level) {
case 3:
adev->vm_manager.root_level = AMDGPU_VM_PDB2;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 91c0188a29b2..0180675e76a4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6257,7 +6257,7 @@ convert_color_depth_from_display_info(const struct drm_connector *connector,
* or if this was called outside of atomic check, so it
* can't be used directly.
*/
- bpc = min_t(u8, bpc, requested_bpc);
+ bpc = umin(bpc, requested_bpc);
/* Round down to the nearest even number. */
bpc = bpc - (bpc & 1);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 20/44] drivers/i2c/busses: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (18 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 19/44] drivers/gpu/drm/amd: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2026-01-20 13:19 ` Andi Shyti
2025-11-19 22:41 ` [PATCH 21/44] drivers/net/ethernet/realtek: " david.laight.linux
` (27 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-i2c; +Cc: Andi Shyti, Mika Westerberg, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(u8, a, b) casts both its arguments to u8 potentially discarding
signifinact bits.
Use min(a, b) instead as it cannot discard significant bits.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/i2c/busses/i2c-designware-master.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index 41e9b5ecad20..8fc51d472a55 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -564,7 +564,7 @@ i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len)
* after receiving the first byte.
*/
len += (flags & I2C_CLIENT_PEC) ? 2 : 1;
- dev->tx_buf_len = len - min_t(u8, len, dev->rx_outstanding);
+ dev->tx_buf_len = len - min(len, dev->rx_outstanding);
msgs[dev->msg_read_idx].len = len;
msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 20/44] drivers/i2c/busses: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 20/44] drivers/i2c/busses: " david.laight.linux
@ 2026-01-20 13:19 ` Andi Shyti
0 siblings, 0 replies; 109+ messages in thread
From: Andi Shyti @ 2026-01-20 13:19 UTC (permalink / raw)
To: david.laight.linux; +Cc: linux-kernel, linux-i2c, Mika Westerberg
Hi David,
On Wed, Nov 19, 2025 at 10:41:16PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(u8, a, b) casts both its arguments to u8 potentially discarding
> signifinact bits.
> Use min(a, b) instead as it cannot discard significant bits.
>
> Detected by an extra check added to min_t().
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
merged to i2c/i2c-host.
Thanks,
Andi
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 21/44] drivers/net/ethernet/realtek: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (19 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 20/44] drivers/i2c/busses: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 22/44] drivers/nvme: " david.laight.linux
` (26 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Heiner Kallweit,
Jakub Kicinski, nic_swsd, Paolo Abeni, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/net/ethernet/realtek/r8169_main.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index d18734fe12e4..3e636983df4a 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -4238,8 +4238,7 @@ static unsigned int rtl8125_quirk_udp_padto(struct rtl8169_private *tp,
}
if (trans_data_len < sizeof(struct udphdr))
- padto = max_t(unsigned int, padto,
- len + sizeof(struct udphdr) - trans_data_len);
+ padto = max(padto, len + sizeof(struct udphdr) - trans_data_len);
}
return padto;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 22/44] drivers/nvme: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (20 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 21/44] drivers/net/ethernet/realtek: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 23/44] arch/x86/mm: " david.laight.linux
` (25 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-nvme
Cc: Christoph Hellwig, Jens Axboe, Keith Busch, Sagi Grimberg,
David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/nvme/host/pci.c | 3 +--
drivers/nvme/host/zns.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 72fb675a696f..c74be555a7e9 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -3412,8 +3412,7 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
* Limit the max command size to prevent iod->sg allocations going
* over a single page.
*/
- dev->ctrl.max_hw_sectors = min_t(u32,
- NVME_MAX_BYTES >> SECTOR_SHIFT,
+ dev->ctrl.max_hw_sectors = min(NVME_MAX_BYTES >> SECTOR_SHIFT,
dma_opt_mapping_size(&pdev->dev) >> 9);
dev->ctrl.max_segments = NVME_MAX_SEGS;
dev->ctrl.max_integrity_segments = 1;
diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c
index cce4c5b55aa9..c0b05a220f36 100644
--- a/drivers/nvme/host/zns.c
+++ b/drivers/nvme/host/zns.c
@@ -126,8 +126,7 @@ static void *nvme_zns_alloc_report_buffer(struct nvme_ns *ns,
const size_t min_bufsize = sizeof(struct nvme_zone_report) +
sizeof(struct nvme_zone_descriptor);
- nr_zones = min_t(unsigned int, nr_zones,
- get_capacity(ns->disk) >> ilog2(ns->head->zsze));
+ nr_zones = min(nr_zones, get_capacity(ns->disk) >> ilog2(ns->head->zsze));
bufsize = sizeof(struct nvme_zone_report) +
nr_zones * sizeof(struct nvme_zone_descriptor);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 23/44] arch/x86/mm: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (21 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 22/44] drivers/nvme: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 24/44] drivers/nvmem: " david.laight.linux
` (24 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel
Cc: Andy Lutomirski, Borislav Petkov, Dave Hansen, Ingo Molnar,
Peter Zijlstra, Thomas Gleixner, x86, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
arch/x86/mm/pat/set_memory.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index 970981893c9b..148c1880a823 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -1459,7 +1459,7 @@ static void unmap_pmd_range(pud_t *pud, unsigned long start, unsigned long end)
*/
if (start & (PMD_SIZE - 1)) {
unsigned long next_page = (start + PMD_SIZE) & PMD_MASK;
- unsigned long pre_end = min_t(unsigned long, end, next_page);
+ unsigned long pre_end = min(end, next_page);
__unmap_pmd_range(pud, pmd, start, pre_end);
@@ -1503,7 +1503,7 @@ static void unmap_pud_range(p4d_t *p4d, unsigned long start, unsigned long end)
*/
if (start & (PUD_SIZE - 1)) {
unsigned long next_page = (start + PUD_SIZE) & PUD_MASK;
- unsigned long pre_end = min_t(unsigned long, end, next_page);
+ unsigned long pre_end = min(end, next_page);
unmap_pmd_range(pud, start, pre_end);
@@ -1591,9 +1591,9 @@ static long populate_pmd(struct cpa_data *cpa,
unsigned long pre_end = start + (num_pages << PAGE_SHIFT);
unsigned long next_page = (start + PMD_SIZE) & PMD_MASK;
- pre_end = min_t(unsigned long, pre_end, next_page);
+ pre_end = min(pre_end, next_page);
cur_pages = (pre_end - start) >> PAGE_SHIFT;
- cur_pages = min_t(unsigned int, num_pages, cur_pages);
+ cur_pages = min(num_pages, cur_pages);
/*
* Need a PTE page?
@@ -1668,9 +1668,9 @@ static int populate_pud(struct cpa_data *cpa, unsigned long start, p4d_t *p4d,
unsigned long pre_end;
unsigned long next_page = (start + PUD_SIZE) & PUD_MASK;
- pre_end = min_t(unsigned long, end, next_page);
+ pre_end = min(end, next_page);
cur_pages = (pre_end - start) >> PAGE_SHIFT;
- cur_pages = min_t(int, (int)cpa->numpages, cur_pages);
+ cur_pages = min(cpa->numpages, cur_pages);
pud = pud_offset(p4d, start);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 24/44] drivers/nvmem: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (22 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 23/44] arch/x86/mm: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 25/44] drivers/pci: " david.laight.linux
` (23 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Srinivas Kandagatla, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/nvmem/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 387c88c55259..8d6e78343054 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -359,7 +359,7 @@ static ssize_t nvmem_cell_attr_read(struct file *filp, struct kobject *kobj,
goto destroy_cell;
}
- read_len = min_t(unsigned int, cell_sz - pos, count);
+ read_len = min(cell_sz - pos, count);
memcpy(buf, content + pos, read_len);
kfree(content);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 25/44] drivers/pci: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (23 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 24/44] drivers/nvmem: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-24 21:04 ` Bjorn Helgaas
2025-11-19 22:41 ` [PATCH 26/44] drivers/scsi: " david.laight.linux
` (22 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-pci; +Cc: Bjorn Helgaas, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case although pci_hotplug_bus_size is 'long' it is constrained
to be <= 255.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/pci/probe.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0ce98e18b5a8..0f0d1b44d8c2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -3163,8 +3163,7 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
* bus number if there is room.
*/
if (bus->self && bus->self->is_hotplug_bridge) {
- used_buses = max_t(unsigned int, available_buses,
- pci_hotplug_bus_size - 1);
+ used_buses = max(available_buses, pci_hotplug_bus_size - 1);
if (max - start < used_buses) {
max = start + used_buses;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 25/44] drivers/pci: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 25/44] drivers/pci: " david.laight.linux
@ 2025-11-24 21:04 ` Bjorn Helgaas
2025-11-24 21:42 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Bjorn Helgaas @ 2025-11-24 21:04 UTC (permalink / raw)
To: david.laight.linux; +Cc: linux-kernel, linux-pci, Bjorn Helgaas
On Wed, Nov 19, 2025 at 10:41:21PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
>
> In this case although pci_hotplug_bus_size is 'long' it is constrained
> to be <= 255.
>
> Detected by an extra check added to min_t().
I don't mind applying this, but it sure would be nice to have a hint
at the max() and max_t() definitions about when and why to prefer one
over the other.
Applied to pci/misc for v6.19 with the following commit log:
PCI: Use max() instead of max_t() to ease static analysis
In this code:
used_buses = max_t(unsigned int, available_buses,
pci_hotplug_bus_size - 1);
max_t() casts the 'unsigned long' pci_hotplug_bus_size (either 32 or 64
bits) to 'unsigned int' (32 bits) result type, so there's a potential of
discarding significant bits.
Instead, use max(a, b), which casts 'unsigned int' to 'unsigned long' and
cannot discard significant bits.
In this case, pci_hotplug_bus_size is constrained to <= 0xff by pci_setup()
so this doesn't fix a bug, but it makes static analysis easier.
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> drivers/pci/probe.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 0ce98e18b5a8..0f0d1b44d8c2 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -3163,8 +3163,7 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
> * bus number if there is room.
> */
> if (bus->self && bus->self->is_hotplug_bridge) {
> - used_buses = max_t(unsigned int, available_buses,
> - pci_hotplug_bus_size - 1);
> + used_buses = max(available_buses, pci_hotplug_bus_size - 1);
> if (max - start < used_buses) {
> max = start + used_buses;
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 25/44] drivers/pci: use min() instead of min_t()
2025-11-24 21:04 ` Bjorn Helgaas
@ 2025-11-24 21:42 ` David Laight
0 siblings, 0 replies; 109+ messages in thread
From: David Laight @ 2025-11-24 21:42 UTC (permalink / raw)
To: Bjorn Helgaas; +Cc: linux-kernel, linux-pci, Bjorn Helgaas
On Mon, 24 Nov 2025 15:04:10 -0600
Bjorn Helgaas <helgaas@kernel.org> wrote:
> On Wed, Nov 19, 2025 at 10:41:21PM +0000, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
> >
> > In this case although pci_hotplug_bus_size is 'long' it is constrained
> > to be <= 255.
> >
> > Detected by an extra check added to min_t().
>
> I don't mind applying this, but it sure would be nice to have a hint
> at the max() and max_t() definitions about when and why to prefer one
> over the other.
When I've sorted out local commits for all the other 400 files I've
had to change to get allmodconfig to build I'm going to look at
minmax.h and checkpatch.pl.
The current bit in checkpatch that suggests transforming
min(a, (type)b) => min_t(type, a, b)
isn't even a good idea.
The latter is min((type)a, (type)b) - which isn't the same.
at least in with min(a, (type)b)) the truncation is obvious.
I think I'll try to get checkpatch to reject min_t(u8|s8|u16|s16, ...
outright - remember the values get promoted the 'int'.
Unless the code is doing something really obscure they can all be
replaced with a plain min().
Then get minmax.h to reject u8 casts when one of the values is 255
(and u16 casts with 65535) - particularly for clamp_t().
That will error a small number of files - but only a handful.
I need to find the #if that is set for a W=1 build so that I can 'error'
more of the 'dodgy' cases.
That might include all the u8|s8|u16|s16 ones.
But I'll have to leave all the u32 casts of u64 values (on 64bit) for later
(they are typically u32 and size_t).
I've not yet looked for u32 casts of u64 values (long v long long) on 32bit.
I suspect there are some real bugs there.
Maybe I'll try to get them into the W=2 build no one does :-)
I'm retired, need to find something to do ...
(apart from getting to PoGo level 80)
David
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 26/44] drivers/scsi: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (24 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 25/44] drivers/pci: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 23:09 ` Bart Van Assche
2025-11-19 22:41 ` [PATCH 27/44] drivers/tty/vt: use umin() instead of min_t(u16, ...) for row/col limits david.laight.linux
` (21 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-scsi
Cc: James E.J. Bottomley, Martin K. Petersen, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/scsi/hosts.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 17173239301e..b15896560cf6 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -247,7 +247,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
shost->dma_dev = dma_dev;
if (dma_dev->dma_mask) {
- shost->max_sectors = min_t(unsigned int, shost->max_sectors,
+ shost->max_sectors = min(shost->max_sectors,
dma_max_mapping_size(dma_dev) >> SECTOR_SHIFT);
}
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 26/44] drivers/scsi: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 26/44] drivers/scsi: " david.laight.linux
@ 2025-11-19 23:09 ` Bart Van Assche
2025-11-20 18:44 ` David Laight
2025-11-22 21:50 ` David Laight
0 siblings, 2 replies; 109+ messages in thread
From: Bart Van Assche @ 2025-11-19 23:09 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, linux-scsi
Cc: James E.J. Bottomley, Martin K. Petersen
On 11/19/25 2:41 PM, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
>
> In this case the 'unsigned long' value is small enough that the result
> is ok.
>
> Detected by an extra check added to min_t().
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> drivers/scsi/hosts.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
> index 17173239301e..b15896560cf6 100644
> --- a/drivers/scsi/hosts.c
> +++ b/drivers/scsi/hosts.c
> @@ -247,7 +247,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
> shost->dma_dev = dma_dev;
>
> if (dma_dev->dma_mask) {
> - shost->max_sectors = min_t(unsigned int, shost->max_sectors,
> + shost->max_sectors = min(shost->max_sectors,
> dma_max_mapping_size(dma_dev) >> SECTOR_SHIFT);
> }
So instead of the type cast performed by min_t() potentially discarding
bits, the assignment potentially discards bits. I'm not sure this is an
improvement.
Thanks,
Bart.
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 26/44] drivers/scsi: use min() instead of min_t()
2025-11-19 23:09 ` Bart Van Assche
@ 2025-11-20 18:44 ` David Laight
2025-11-22 21:50 ` David Laight
1 sibling, 0 replies; 109+ messages in thread
From: David Laight @ 2025-11-20 18:44 UTC (permalink / raw)
To: Bart Van Assche
Cc: linux-kernel, linux-scsi, James E.J. Bottomley,
Martin K. Petersen
On Wed, 19 Nov 2025 15:09:02 -0800
Bart Van Assche <bvanassche@acm.org> wrote:
> On 11/19/25 2:41 PM, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
> >
> > In this case the 'unsigned long' value is small enough that the result
> > is ok.
> >
> > Detected by an extra check added to min_t().
> >
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > ---
> > drivers/scsi/hosts.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
> > index 17173239301e..b15896560cf6 100644
> > --- a/drivers/scsi/hosts.c
> > +++ b/drivers/scsi/hosts.c
> > @@ -247,7 +247,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
> > shost->dma_dev = dma_dev;
> >
> > if (dma_dev->dma_mask) {
> > - shost->max_sectors = min_t(unsigned int, shost->max_sectors,
> > + shost->max_sectors = min(shost->max_sectors,
> > dma_max_mapping_size(dma_dev) >> SECTOR_SHIFT);
> > }
>
> So instead of the type cast performed by min_t() potentially discarding
> bits, the assignment potentially discards bits. I'm not sure this is an
> improvement.
The assignment cant discard bits because shost->max_sectors is also on the RHS.
In any case you'd need a 2TB mapping size to get an error.
That probably cant happen for other reasons.
The patch is remove a false positive for a check added to min_t(T, a, b)
that sizeof (b) <= sizeof (T).
David
>
> Thanks,
>
> Bart.
>
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 26/44] drivers/scsi: use min() instead of min_t()
2025-11-19 23:09 ` Bart Van Assche
2025-11-20 18:44 ` David Laight
@ 2025-11-22 21:50 ` David Laight
1 sibling, 0 replies; 109+ messages in thread
From: David Laight @ 2025-11-22 21:50 UTC (permalink / raw)
To: Bart Van Assche
Cc: linux-kernel, linux-scsi, James E.J. Bottomley,
Martin K. Petersen
On Wed, 19 Nov 2025 15:09:02 -0800
Bart Van Assche <bvanassche@acm.org> wrote:
> On 11/19/25 2:41 PM, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
> >
> > In this case the 'unsigned long' value is small enough that the result
> > is ok.
> >
> > Detected by an extra check added to min_t().
> >
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > ---
> > drivers/scsi/hosts.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
> > index 17173239301e..b15896560cf6 100644
> > --- a/drivers/scsi/hosts.c
> > +++ b/drivers/scsi/hosts.c
> > @@ -247,7 +247,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
> > shost->dma_dev = dma_dev;
> >
> > if (dma_dev->dma_mask) {
> > - shost->max_sectors = min_t(unsigned int, shost->max_sectors,
> > + shost->max_sectors = min(shost->max_sectors,
> > dma_max_mapping_size(dma_dev) >> SECTOR_SHIFT);
> > }
>
> So instead of the type cast performed by min_t() potentially discarding
> bits, the assignment potentially discards bits. I'm not sure this is an
> improvement.
In this case the assignment is fine - shost->max_sectors is on both sides,
so the value can only go down.
The issue is that dma_max_mapping_size() returns a 64bit value.
So if you have some magic high speed interface with a 2TB 'dma map'
then 'dma_max_mapping_size(dma_dev) >> SECTOR_SHIFT' is '1u << 32' so
is zero when cast to 'unsigned int'.
At that point things start going horribly wrong.
I don't think there are any such interfaces - so the bug this fixes
can't happen.
OTOH the same test does pick up a lot (and I mean a lot [1]) of driver code
that contains code like:
ssize_t do_xxx(... size_t len)
{
unsigned int copied = 0, frag_len;
while (copied < len) {
frag_len = min_t(unsigned int, len, MAX_FRAG);
....
copied += frag_len;
len -= frag_len;
}
return copied;
}
If you manage to request a transfer for 4G (or more) then it doesn't work.
Now there might be a test earlier that stops that happening in a lot of places.
But from the perspective of the function it isn't true.
(I suspect readv() with a single iov[] can generate a big buffer.)
The compile-time test detects that (unsigned int)len may not equal len
and it can be fixed by changing to min(len, MAX_FRAG);
In this case it might be a real bug.
Note that a read can be truncated after a few bytes - it is only the
buffer size that needs to be massive.
David
[1] I've just built allmodconfig - 'only' 488 more files needed changing.
A fair number of 'real bugs', a few false positives because PAGE_SIZE and
sizeof() are 64bit, and a lot of dubious code.
By far the worst are all the min_t([u8|u16], ...) in many cases the code
uses the type of the destination - so you get (eg):
u8_var = min(u8, value_32 / 2, 255);
>
> Thanks,
>
> Bart.
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 27/44] drivers/tty/vt: use umin() instead of min_t(u16, ...) for row/col limits
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (25 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 26/44] drivers/scsi: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 7:23 ` Jiri Slaby
2025-11-19 22:41 ` [PATCH 28/44] drivers/usb/storage: use min() instead of min_t() david.laight.linux
` (20 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-serial; +Cc: Greg Kroah-Hartman, Jiri Slaby, David Laight
From: David Laight <david.laight.linux@gmail.com>
The row/column bounds (for a screen window box) are changed from
'offset one' to 'offset zero' and bound to the screen size using:
v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
This has the side effect of converting zero to the limit.
A check I'm adding to min_t() reports that (u16)(v->xs - 1) (etc)
discards signiticant bits (because v->xs is promoted to 'int' before
the addition).
If v->xs is zero (it comes from userspace) it converts -1 to 0xffff.
This is then bounded to 'vc->vc_cols - 1' which will be fine.
Replace with:
v->xs = umin(v->xs - 1, vc->vc_cols - 1);
which again converts a -1 to unsigned - this time to 0xffffffff,
with the same overall effect.
Whether zero is meant to mean the 'maximum size' is unknown.
I can't find any documentation for the ioctl and it pre-dates git.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/tty/vt/selection.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 07d3b93975d3..13f4e48b4142 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -348,10 +348,11 @@ static int vc_selection(struct vc_data *vc, struct tiocl_selection *v,
return 0;
}
- v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
- v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1);
- v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
- v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
+ /* Historically 0 => max value */
+ v->xs = umin(v->xs - 1, vc->vc_cols - 1);
+ v->ys = umin(v->ys - 1, vc->vc_rows - 1);
+ v->xe = umin(v->xe - 1, vc->vc_cols - 1);
+ v->ye = umin(v->ye - 1, vc->vc_rows - 1);
if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 27/44] drivers/tty/vt: use umin() instead of min_t(u16, ...) for row/col limits
2025-11-19 22:41 ` [PATCH 27/44] drivers/tty/vt: use umin() instead of min_t(u16, ...) for row/col limits david.laight.linux
@ 2025-11-20 7:23 ` Jiri Slaby
0 siblings, 0 replies; 109+ messages in thread
From: Jiri Slaby @ 2025-11-20 7:23 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, linux-serial; +Cc: Greg Kroah-Hartman
On 19. 11. 25, 23:41, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> The row/column bounds (for a screen window box) are changed from
> 'offset one' to 'offset zero' and bound to the screen size using:
> v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
> This has the side effect of converting zero to the limit.
>
> A check I'm adding to min_t() reports that (u16)(v->xs - 1) (etc)
> discards signiticant bits (because v->xs is promoted to 'int' before
> the addition).
> If v->xs is zero (it comes from userspace) it converts -1 to 0xffff.
> This is then bounded to 'vc->vc_cols - 1' which will be fine.
>
> Replace with:
> v->xs = umin(v->xs - 1, vc->vc_cols - 1);
> which again converts a -1 to unsigned - this time to 0xffffffff,
> with the same overall effect.
LGTM:
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
> Whether zero is meant to mean the 'maximum size' is unknown.
> I can't find any documentation for the ioctl and it pre-dates git.
Behavior of zero is unspecified AFAICT (the impl can do whatever is easy
:)).
thanks,
--
js
suse labs
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 28/44] drivers/usb/storage: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (26 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 27/44] drivers/tty/vt: use umin() instead of min_t(u16, ...) for row/col limits david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 2:59 ` Alan Stern
2025-11-19 22:41 ` [PATCH 29/44] drivers/xen: " david.laight.linux
` (19 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-usb, usb-storage
Cc: Alan Stern, Greg Kroah-Hartman, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/usb/storage/protocol.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index 9033e505db7f..0cff54ad90fa 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -139,8 +139,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
return cnt;
while (sg_miter_next(&miter) && cnt < buflen) {
- unsigned int len = min_t(unsigned int, miter.length,
- buflen - cnt);
+ unsigned int len = min(miter.length, buflen - cnt);
if (dir == FROM_XFER_BUF)
memcpy(buffer + cnt, miter.addr, len);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 28/44] drivers/usb/storage: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 28/44] drivers/usb/storage: use min() instead of min_t() david.laight.linux
@ 2025-11-20 2:59 ` Alan Stern
2025-11-20 9:18 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Alan Stern @ 2025-11-20 2:59 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, linux-usb, usb-storage, Greg Kroah-Hartman
On Wed, Nov 19, 2025 at 10:41:24PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
>
> In this case the 'unsigned long' value is small enough that the result
> is ok.
>
> Detected by an extra check added to min_t().
In fact, min_t(T, a, b) cannot go wrong as long as all the types are
unsigned and at least one of a, b has type T or smaller. Of course, in
this situation there's no reason not to simply use min(). (And if both
a and b have types larger than T, why would someone use min_t() like
this in the first place?)
Regardless, the patch is fine with me.
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Alan Stern
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> drivers/usb/storage/protocol.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
> index 9033e505db7f..0cff54ad90fa 100644
> --- a/drivers/usb/storage/protocol.c
> +++ b/drivers/usb/storage/protocol.c
> @@ -139,8 +139,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
> return cnt;
>
> while (sg_miter_next(&miter) && cnt < buflen) {
> - unsigned int len = min_t(unsigned int, miter.length,
> - buflen - cnt);
> + unsigned int len = min(miter.length, buflen - cnt);
>
> if (dir == FROM_XFER_BUF)
> memcpy(buffer + cnt, miter.addr, len);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 28/44] drivers/usb/storage: use min() instead of min_t()
2025-11-20 2:59 ` Alan Stern
@ 2025-11-20 9:18 ` David Laight
2025-11-20 14:39 ` [usb-storage] " Alan Stern
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 9:18 UTC (permalink / raw)
To: Alan Stern; +Cc: linux-kernel, linux-usb, usb-storage, Greg Kroah-Hartman
On Wed, 19 Nov 2025 21:59:42 -0500
Alan Stern <stern@rowland.harvard.edu> wrote:
> On Wed, Nov 19, 2025 at 10:41:24PM +0000, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
> >
> > In this case the 'unsigned long' value is small enough that the result
> > is ok.
> >
> > Detected by an extra check added to min_t().
>
> In fact, min_t(T, a, b) cannot go wrong as long as all the types are
> unsigned and at least one of a, b has type T or smaller.
That is backwards, both a and b have to have types at least as large
as T (or rather values that will fit in T).
- which is exactly what people keep getting wrong.
Consider:
u32 a = 4;
u64 b = 0x100000001ull;
then:
min_t(u32, a, b)
has value 1 not 4.
David
> Of course, in
> this situation there's no reason not to simply use min(). (And if both
> a and b have types larger than T, why would someone use min_t() like
> this in the first place?)
>
> Regardless, the patch is fine with me.
>
> Acked-by: Alan Stern <stern@rowland.harvard.edu>
>
> Alan Stern
>
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > ---
> > drivers/usb/storage/protocol.c | 3 +--
> > 1 file changed, 1 insertion(+), 2 deletions(-)
> >
> > diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
> > index 9033e505db7f..0cff54ad90fa 100644
> > --- a/drivers/usb/storage/protocol.c
> > +++ b/drivers/usb/storage/protocol.c
> > @@ -139,8 +139,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
> > return cnt;
> >
> > while (sg_miter_next(&miter) && cnt < buflen) {
> > - unsigned int len = min_t(unsigned int, miter.length,
> > - buflen - cnt);
> > + unsigned int len = min(miter.length, buflen - cnt);
> >
> > if (dir == FROM_XFER_BUF)
> > memcpy(buffer + cnt, miter.addr, len);
> > --
> > 2.39.5
> >
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [usb-storage] Re: [PATCH 28/44] drivers/usb/storage: use min() instead of min_t()
2025-11-20 9:18 ` David Laight
@ 2025-11-20 14:39 ` Alan Stern
0 siblings, 0 replies; 109+ messages in thread
From: Alan Stern @ 2025-11-20 14:39 UTC (permalink / raw)
To: David Laight; +Cc: linux-kernel, linux-usb, usb-storage, Greg Kroah-Hartman
On Thu, Nov 20, 2025 at 09:18:02AM +0000, David Laight wrote:
> On Wed, 19 Nov 2025 21:59:42 -0500
> Alan Stern <stern@rowland.harvard.edu> wrote:
>
> > On Wed, Nov 19, 2025 at 10:41:24PM +0000, david.laight.linux@gmail.com wrote:
> > > From: David Laight <david.laight.linux@gmail.com>
> > >
> > > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > > and so cannot discard significant bits.
> > >
> > > In this case the 'unsigned long' value is small enough that the result
> > > is ok.
> > >
> > > Detected by an extra check added to min_t().
> >
> > In fact, min_t(T, a, b) cannot go wrong as long as all the types are
> > unsigned and at least one of a, b has type T or smaller.
>
> That is backwards, both a and b have to have types at least as large
> as T (or rather values that will fit in T).
> - which is exactly what people keep getting wrong.
> Consider:
> u32 a = 4;
> u64 b = 0x100000001ull;
> then:
> min_t(u32, a, b)
> has value 1 not 4.
You are right. For some reason I was thinking that the comparison took
place before the casts, which doesn't make any sense.
Alan Stern
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 29/44] drivers/xen: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (27 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 28/44] drivers/usb/storage: use min() instead of min_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 8:13 ` Jürgen Groß
2025-11-19 22:41 ` [PATCH 30/44] fs: use min() or umin() " david.laight.linux
` (18 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Juergen Gross, Stefano Stabellini, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
drivers/xen/grant-table.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 478d2ad725ac..3e76e33f6e08 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -1204,7 +1204,7 @@ void gnttab_foreach_grant_in_range(struct page *page,
unsigned int glen;
unsigned long xen_pfn;
- len = min_t(unsigned int, PAGE_SIZE - offset, len);
+ len = min(PAGE_SIZE - offset, len);
goffset = xen_offset_in_page(offset);
xen_pfn = page_to_xen_pfn(page) + XEN_PFN_DOWN(offset);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 30/44] fs: use min() or umin() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (28 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 29/44] drivers/xen: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-25 9:06 ` Christian Brauner
` (2 more replies)
2025-11-19 22:41 ` [PATCH 31/44] block: bvec.h: use min() " david.laight.linux
` (17 subsequent siblings)
47 siblings, 3 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-ext4, linux-fsdevel, linux-mm
Cc: Alexander Viro, Andreas Dilger, Christian Brauner, Kees Cook,
Miklos Szeredi, OGAWA Hirofumi, Theodore Ts'o, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
A couple of places need umin() because of loops like:
nfolios = DIV_ROUND_UP(ret + start, PAGE_SIZE);
for (i = 0; i < nfolios; i++) {
struct folio *folio = page_folio(pages[i]);
...
unsigned int len = umin(ret, PAGE_SIZE - start);
...
ret -= len;
...
}
where the compiler doesn't track things well enough to know that
'ret' is never negative.
The alternate loop:
for (i = 0; ret > 0; i++) {
struct folio *folio = page_folio(pages[i]);
...
unsigned int len = min(ret, PAGE_SIZE - start);
...
ret -= len;
...
}
would be equivalent and doesn't need 'nfolios'.
Most of the 'unsigned long' actually come from PAGE_SIZE.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
fs/buffer.c | 2 +-
fs/exec.c | 2 +-
fs/ext4/mballoc.c | 3 +--
fs/ext4/resize.c | 2 +-
fs/ext4/super.c | 2 +-
fs/fat/dir.c | 4 ++--
fs/fat/file.c | 3 +--
fs/fuse/dev.c | 2 +-
fs/fuse/file.c | 8 +++-----
fs/splice.c | 2 +-
10 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 6a8752f7bbed..26c4c760b6c6 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2354,7 +2354,7 @@ bool block_is_partially_uptodate(struct folio *folio, size_t from, size_t count)
if (!head)
return false;
blocksize = head->b_size;
- to = min_t(unsigned, folio_size(folio) - from, count);
+ to = min(folio_size(folio) - from, count);
to = from + to;
if (from < blocksize && to > folio_size(folio) - blocksize)
return false;
diff --git a/fs/exec.c b/fs/exec.c
index 4298e7e08d5d..6d699e48df82 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -555,7 +555,7 @@ int copy_string_kernel(const char *arg, struct linux_binprm *bprm)
return -E2BIG;
while (len > 0) {
- unsigned int bytes_to_copy = min_t(unsigned int, len,
+ unsigned int bytes_to_copy = min(len,
min_not_zero(offset_in_page(pos), PAGE_SIZE));
struct page *page;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 9087183602e4..cb68ea974de6 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4254,8 +4254,7 @@ void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
* get the corresponding group metadata to work with.
* For this we have goto again loop.
*/
- thisgrp_len = min_t(unsigned int, (unsigned int)len,
- EXT4_BLOCKS_PER_GROUP(sb) - EXT4_C2B(sbi, blkoff));
+ thisgrp_len = min(len, EXT4_BLOCKS_PER_GROUP(sb) - EXT4_C2B(sbi, blkoff));
clen = EXT4_NUM_B2C(sbi, thisgrp_len);
if (!ext4_sb_block_valid(sb, NULL, block, thisgrp_len)) {
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 050f26168d97..76842f0957b5 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -1479,7 +1479,7 @@ static void ext4_update_super(struct super_block *sb,
/* Update the global fs size fields */
sbi->s_groups_count += flex_gd->count;
- sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
+ sbi->s_blockfile_groups = min(sbi->s_groups_count,
(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
/* Update the reserved block counts only once the new group is
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 33e7c08c9529..e116fe48ff43 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4830,7 +4830,7 @@ static int ext4_check_geometry(struct super_block *sb,
return -EINVAL;
}
sbi->s_groups_count = blocks_count;
- sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
+ sbi->s_blockfile_groups = min(sbi->s_groups_count,
(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
le32_to_cpu(es->s_inodes_count)) {
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 92b091783966..8375e7fbc1a5 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -1353,7 +1353,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
/* Fill the long name slots. */
for (i = 0; i < long_bhs; i++) {
- int copy = min_t(int, sb->s_blocksize - offset, size);
+ int copy = umin(sb->s_blocksize - offset, size);
memcpy(bhs[i]->b_data + offset, slots, copy);
mark_buffer_dirty_inode(bhs[i], dir);
offset = 0;
@@ -1364,7 +1364,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
err = fat_sync_bhs(bhs, long_bhs);
if (!err && i < nr_bhs) {
/* Fill the short name slot. */
- int copy = min_t(int, sb->s_blocksize - offset, size);
+ int copy = umin(sb->s_blocksize - offset, size);
memcpy(bhs[i]->b_data + offset, slots, copy);
mark_buffer_dirty_inode(bhs[i], dir);
if (IS_DIRSYNC(dir))
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 4fc49a614fb8..f48435e586c7 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -140,8 +140,7 @@ static int fat_ioctl_fitrim(struct inode *inode, unsigned long arg)
if (copy_from_user(&range, user_range, sizeof(range)))
return -EFAULT;
- range.minlen = max_t(unsigned int, range.minlen,
- bdev_discard_granularity(sb->s_bdev));
+ range.minlen = max(range.minlen, bdev_discard_granularity(sb->s_bdev));
err = fat_trim_fs(inode, &range);
if (err < 0)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 132f38619d70..0c9fb0db1de1 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1813,7 +1813,7 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
goto out_iput;
folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset;
- nr_bytes = min_t(unsigned, num, folio_size(folio) - folio_offset);
+ nr_bytes = min(num, folio_size(folio) - folio_offset);
nr_pages = (offset + nr_bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
err = fuse_copy_folio(cs, &folio, folio_offset, nr_bytes, 0);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index f1ef77a0be05..f4ffa559ad26 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1252,10 +1252,8 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
static inline unsigned int fuse_wr_pages(loff_t pos, size_t len,
unsigned int max_pages)
{
- return min_t(unsigned int,
- ((pos + len - 1) >> PAGE_SHIFT) -
- (pos >> PAGE_SHIFT) + 1,
- max_pages);
+ return min(((pos + len - 1) >> PAGE_SHIFT) - (pos >> PAGE_SHIFT) + 1,
+ max_pages);
}
static ssize_t fuse_perform_write(struct kiocb *iocb, struct iov_iter *ii)
@@ -1550,7 +1548,7 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
struct folio *folio = page_folio(pages[i]);
unsigned int offset = start +
(folio_page_idx(folio, pages[i]) << PAGE_SHIFT);
- unsigned int len = min_t(unsigned int, ret, PAGE_SIZE - start);
+ unsigned int len = umin(ret, PAGE_SIZE - start);
ap->descs[ap->num_folios].offset = offset;
ap->descs[ap->num_folios].length = len;
diff --git a/fs/splice.c b/fs/splice.c
index f5094b6d00a0..41ce3a4ef74f 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1467,7 +1467,7 @@ static ssize_t iter_to_pipe(struct iov_iter *from,
n = DIV_ROUND_UP(left + start, PAGE_SIZE);
for (i = 0; i < n; i++) {
- int size = min_t(int, left, PAGE_SIZE - start);
+ int size = umin(left, PAGE_SIZE - start);
buf.page = pages[i];
buf.offset = start;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 30/44] fs: use min() or umin() instead of min_t()
2025-11-19 22:41 ` [PATCH 30/44] fs: use min() or umin() " david.laight.linux
@ 2025-11-25 9:06 ` Christian Brauner
2026-01-12 21:51 ` Brian Masney
2026-01-13 16:56 ` Mark Brown
2 siblings, 0 replies; 109+ messages in thread
From: Christian Brauner @ 2025-11-25 9:06 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, linux-ext4, linux-fsdevel, linux-mm, Alexander Viro,
Andreas Dilger, Kees Cook, Miklos Szeredi, OGAWA Hirofumi,
Theodore Ts'o
On Wed, Nov 19, 2025 at 10:41:26PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
>
> A couple of places need umin() because of loops like:
> nfolios = DIV_ROUND_UP(ret + start, PAGE_SIZE);
>
> for (i = 0; i < nfolios; i++) {
> struct folio *folio = page_folio(pages[i]);
> ...
> unsigned int len = umin(ret, PAGE_SIZE - start);
> ...
> ret -= len;
> ...
> }
> where the compiler doesn't track things well enough to know that
> 'ret' is never negative.
>
> The alternate loop:
> for (i = 0; ret > 0; i++) {
> struct folio *folio = page_folio(pages[i]);
> ...
> unsigned int len = min(ret, PAGE_SIZE - start);
> ...
> ret -= len;
> ...
> }
> would be equivalent and doesn't need 'nfolios'.
>
> Most of the 'unsigned long' actually come from PAGE_SIZE.
>
> Detected by an extra check added to min_t().
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
Too late for this cycle but we will pick this up next cycle!
> fs/buffer.c | 2 +-
> fs/exec.c | 2 +-
> fs/ext4/mballoc.c | 3 +--
> fs/ext4/resize.c | 2 +-
> fs/ext4/super.c | 2 +-
> fs/fat/dir.c | 4 ++--
> fs/fat/file.c | 3 +--
> fs/fuse/dev.c | 2 +-
> fs/fuse/file.c | 8 +++-----
> fs/splice.c | 2 +-
> 10 files changed, 13 insertions(+), 17 deletions(-)
>
> diff --git a/fs/buffer.c b/fs/buffer.c
> index 6a8752f7bbed..26c4c760b6c6 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -2354,7 +2354,7 @@ bool block_is_partially_uptodate(struct folio *folio, size_t from, size_t count)
> if (!head)
> return false;
> blocksize = head->b_size;
> - to = min_t(unsigned, folio_size(folio) - from, count);
> + to = min(folio_size(folio) - from, count);
> to = from + to;
> if (from < blocksize && to > folio_size(folio) - blocksize)
> return false;
> diff --git a/fs/exec.c b/fs/exec.c
> index 4298e7e08d5d..6d699e48df82 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -555,7 +555,7 @@ int copy_string_kernel(const char *arg, struct linux_binprm *bprm)
> return -E2BIG;
>
> while (len > 0) {
> - unsigned int bytes_to_copy = min_t(unsigned int, len,
> + unsigned int bytes_to_copy = min(len,
> min_not_zero(offset_in_page(pos), PAGE_SIZE));
> struct page *page;
>
> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> index 9087183602e4..cb68ea974de6 100644
> --- a/fs/ext4/mballoc.c
> +++ b/fs/ext4/mballoc.c
> @@ -4254,8 +4254,7 @@ void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
> * get the corresponding group metadata to work with.
> * For this we have goto again loop.
> */
> - thisgrp_len = min_t(unsigned int, (unsigned int)len,
> - EXT4_BLOCKS_PER_GROUP(sb) - EXT4_C2B(sbi, blkoff));
> + thisgrp_len = min(len, EXT4_BLOCKS_PER_GROUP(sb) - EXT4_C2B(sbi, blkoff));
> clen = EXT4_NUM_B2C(sbi, thisgrp_len);
>
> if (!ext4_sb_block_valid(sb, NULL, block, thisgrp_len)) {
> diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
> index 050f26168d97..76842f0957b5 100644
> --- a/fs/ext4/resize.c
> +++ b/fs/ext4/resize.c
> @@ -1479,7 +1479,7 @@ static void ext4_update_super(struct super_block *sb,
>
> /* Update the global fs size fields */
> sbi->s_groups_count += flex_gd->count;
> - sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
> + sbi->s_blockfile_groups = min(sbi->s_groups_count,
> (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
>
> /* Update the reserved block counts only once the new group is
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 33e7c08c9529..e116fe48ff43 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -4830,7 +4830,7 @@ static int ext4_check_geometry(struct super_block *sb,
> return -EINVAL;
> }
> sbi->s_groups_count = blocks_count;
> - sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
> + sbi->s_blockfile_groups = min(sbi->s_groups_count,
> (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
> if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
> le32_to_cpu(es->s_inodes_count)) {
> diff --git a/fs/fat/dir.c b/fs/fat/dir.c
> index 92b091783966..8375e7fbc1a5 100644
> --- a/fs/fat/dir.c
> +++ b/fs/fat/dir.c
> @@ -1353,7 +1353,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
>
> /* Fill the long name slots. */
> for (i = 0; i < long_bhs; i++) {
> - int copy = min_t(int, sb->s_blocksize - offset, size);
> + int copy = umin(sb->s_blocksize - offset, size);
> memcpy(bhs[i]->b_data + offset, slots, copy);
> mark_buffer_dirty_inode(bhs[i], dir);
> offset = 0;
> @@ -1364,7 +1364,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
> err = fat_sync_bhs(bhs, long_bhs);
> if (!err && i < nr_bhs) {
> /* Fill the short name slot. */
> - int copy = min_t(int, sb->s_blocksize - offset, size);
> + int copy = umin(sb->s_blocksize - offset, size);
> memcpy(bhs[i]->b_data + offset, slots, copy);
> mark_buffer_dirty_inode(bhs[i], dir);
> if (IS_DIRSYNC(dir))
> diff --git a/fs/fat/file.c b/fs/fat/file.c
> index 4fc49a614fb8..f48435e586c7 100644
> --- a/fs/fat/file.c
> +++ b/fs/fat/file.c
> @@ -140,8 +140,7 @@ static int fat_ioctl_fitrim(struct inode *inode, unsigned long arg)
> if (copy_from_user(&range, user_range, sizeof(range)))
> return -EFAULT;
>
> - range.minlen = max_t(unsigned int, range.minlen,
> - bdev_discard_granularity(sb->s_bdev));
> + range.minlen = max(range.minlen, bdev_discard_granularity(sb->s_bdev));
>
> err = fat_trim_fs(inode, &range);
> if (err < 0)
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 132f38619d70..0c9fb0db1de1 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -1813,7 +1813,7 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
> goto out_iput;
>
> folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset;
> - nr_bytes = min_t(unsigned, num, folio_size(folio) - folio_offset);
> + nr_bytes = min(num, folio_size(folio) - folio_offset);
> nr_pages = (offset + nr_bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
>
> err = fuse_copy_folio(cs, &folio, folio_offset, nr_bytes, 0);
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index f1ef77a0be05..f4ffa559ad26 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -1252,10 +1252,8 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
> static inline unsigned int fuse_wr_pages(loff_t pos, size_t len,
> unsigned int max_pages)
> {
> - return min_t(unsigned int,
> - ((pos + len - 1) >> PAGE_SHIFT) -
> - (pos >> PAGE_SHIFT) + 1,
> - max_pages);
> + return min(((pos + len - 1) >> PAGE_SHIFT) - (pos >> PAGE_SHIFT) + 1,
> + max_pages);
> }
>
> static ssize_t fuse_perform_write(struct kiocb *iocb, struct iov_iter *ii)
> @@ -1550,7 +1548,7 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
> struct folio *folio = page_folio(pages[i]);
> unsigned int offset = start +
> (folio_page_idx(folio, pages[i]) << PAGE_SHIFT);
> - unsigned int len = min_t(unsigned int, ret, PAGE_SIZE - start);
> + unsigned int len = umin(ret, PAGE_SIZE - start);
>
> ap->descs[ap->num_folios].offset = offset;
> ap->descs[ap->num_folios].length = len;
> diff --git a/fs/splice.c b/fs/splice.c
> index f5094b6d00a0..41ce3a4ef74f 100644
> --- a/fs/splice.c
> +++ b/fs/splice.c
> @@ -1467,7 +1467,7 @@ static ssize_t iter_to_pipe(struct iov_iter *from,
>
> n = DIV_ROUND_UP(left + start, PAGE_SIZE);
> for (i = 0; i < n; i++) {
> - int size = min_t(int, left, PAGE_SIZE - start);
> + int size = umin(left, PAGE_SIZE - start);
>
> buf.page = pages[i];
> buf.offset = start;
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 30/44] fs: use min() or umin() instead of min_t()
2025-11-19 22:41 ` [PATCH 30/44] fs: use min() or umin() " david.laight.linux
2025-11-25 9:06 ` Christian Brauner
@ 2026-01-12 21:51 ` Brian Masney
2026-01-13 9:42 ` David Laight
2026-01-13 16:56 ` Mark Brown
2 siblings, 1 reply; 109+ messages in thread
From: Brian Masney @ 2026-01-12 21:51 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, linux-ext4, linux-fsdevel, linux-mm, Alexander Viro,
Andreas Dilger, Christian Brauner, Kees Cook, Miklos Szeredi,
OGAWA Hirofumi, Theodore Ts'o
Hi David,
On Wed, Nov 19, 2025 at 10:41:26PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
>
> A couple of places need umin() because of loops like:
> nfolios = DIV_ROUND_UP(ret + start, PAGE_SIZE);
>
> for (i = 0; i < nfolios; i++) {
> struct folio *folio = page_folio(pages[i]);
> ...
> unsigned int len = umin(ret, PAGE_SIZE - start);
> ...
> ret -= len;
> ...
> }
> where the compiler doesn't track things well enough to know that
> 'ret' is never negative.
>
> The alternate loop:
> for (i = 0; ret > 0; i++) {
> struct folio *folio = page_folio(pages[i]);
> ...
> unsigned int len = min(ret, PAGE_SIZE - start);
> ...
> ret -= len;
> ...
> }
> would be equivalent and doesn't need 'nfolios'.
>
> Most of the 'unsigned long' actually come from PAGE_SIZE.
>
> Detected by an extra check added to min_t().
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
When doing a mips cross compile from an arm64 host
(via ARCH=mips CROSS_COMPILE=mips64-linux-gnu- make), the following
build error occurs in linux-next and goes away when I revert this
commit.
In file included from <command-line>:
In function ‘fuse_wr_pages’,
inlined from ‘fuse_perform_write’ at fs/fuse/file.c:1347:27:
././include/linux/compiler_types.h:667:45: error: call to ‘__compiletime_assert_405’ declared with attribute error: min(((pos + len
- 1) >> 12) - (pos >> 12) + 1, max_pages) signedness error
667 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
././include/linux/compiler_types.h:648:25: note: in definition of macro ‘__compiletime_assert’
648 | prefix ## suffix(); \
| ^~~~~~
././include/linux/compiler_types.h:667:9: note: in expansion of macro ‘_compiletime_assert’
667 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
./include/linux/build_bug.h:39:37: note: in expansion of macro ‘compiletime_assert’
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
| ^~~~~~~~~~~~~~~~~~
./include/linux/minmax.h:93:9: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
93 | BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \
| ^~~~~~~~~~~~~~~~
./include/linux/minmax.h:98:9: note: in expansion of macro ‘__careful_cmp_once’
98 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
| ^~~~~~~~~~~~~~~~~~
./include/linux/minmax.h:105:25: note: in expansion of macro ‘__careful_cmp’
105 | #define min(x, y) __careful_cmp(min, x, y)
| ^~~~~~~~~~~~~
fs/fuse/file.c:1326:16: note: in expansion of macro ‘min’
1326 | return min(((pos + len - 1) >> PAGE_SHIFT) - (pos >> PAGE_SHIFT) + 1,
| ^~~
This is on a cento-stream-10 host running
gcc version 14.3.1 20250617 (Red Hat 14.3.1-2) (GCC). I didn't look into
this in detail, and I'm not entirely sure what the correct fix here
should be.
Brian
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 30/44] fs: use min() or umin() instead of min_t()
2026-01-12 21:51 ` Brian Masney
@ 2026-01-13 9:42 ` David Laight
0 siblings, 0 replies; 109+ messages in thread
From: David Laight @ 2026-01-13 9:42 UTC (permalink / raw)
To: Brian Masney
Cc: linux-kernel, linux-ext4, linux-fsdevel, linux-mm, Alexander Viro,
Andreas Dilger, Christian Brauner, Kees Cook, Miklos Szeredi,
OGAWA Hirofumi, Theodore Ts'o
On Mon, 12 Jan 2026 16:51:22 -0500
Brian Masney <bmasney@redhat.com> wrote:
> Hi David,
>
> On Wed, Nov 19, 2025 at 10:41:26PM +0000, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
> >
> > A couple of places need umin() because of loops like:
> > nfolios = DIV_ROUND_UP(ret + start, PAGE_SIZE);
> >
> > for (i = 0; i < nfolios; i++) {
> > struct folio *folio = page_folio(pages[i]);
> > ...
> > unsigned int len = umin(ret, PAGE_SIZE - start);
> > ...
> > ret -= len;
> > ...
> > }
> > where the compiler doesn't track things well enough to know that
> > 'ret' is never negative.
> >
> > The alternate loop:
> > for (i = 0; ret > 0; i++) {
> > struct folio *folio = page_folio(pages[i]);
> > ...
> > unsigned int len = min(ret, PAGE_SIZE - start);
> > ...
> > ret -= len;
> > ...
> > }
> > would be equivalent and doesn't need 'nfolios'.
> >
> > Most of the 'unsigned long' actually come from PAGE_SIZE.
> >
> > Detected by an extra check added to min_t().
> >
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
>
> When doing a mips cross compile from an arm64 host
> (via ARCH=mips CROSS_COMPILE=mips64-linux-gnu- make), the following
> build error occurs in linux-next and goes away when I revert this
> commit.
I've looked at this one before.
I think there is another patch lurking to fix it.
> In file included from <command-line>:
> In function ‘fuse_wr_pages’,
> inlined from ‘fuse_perform_write’ at fs/fuse/file.c:1347:27:
> ././include/linux/compiler_types.h:667:45: error: call to ‘__compiletime_assert_405’ declared with attribute error: min(((pos + len
> - 1) >> 12) - (pos >> 12) + 1, max_pages) signedness error
...
> fs/fuse/file.c:1326:16: note: in expansion of macro ‘min’
> 1326 | return min(((pos + len - 1) >> PAGE_SHIFT) - (pos >> PAGE_SHIFT) + 1,
max_pages);
'len' is 'unsigned long' and the expression is unsigned on 64bit.
But 'pos' is s64 so the expression is signed on 32bit.
IIRC the final version might have been (equivalent to):
len += pos & (PAGE_SIZE - 1);
return min(DIV_ROUND_UP(len, PAGE_SIZE), max_pages);
which generates much better code as well (no 64bit maths).
I don't think len can overflow, read/write are limited to INT_MAX - PAGE_SIZE
bytes in the syscall interface.
David
>
> This is on a cento-stream-10 host running
> gcc version 14.3.1 20250617 (Red Hat 14.3.1-2) (GCC). I didn't look into
> this in detail, and I'm not entirely sure what the correct fix here
> should be.
>
> Brian
>
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 30/44] fs: use min() or umin() instead of min_t()
2025-11-19 22:41 ` [PATCH 30/44] fs: use min() or umin() " david.laight.linux
2025-11-25 9:06 ` Christian Brauner
2026-01-12 21:51 ` Brian Masney
@ 2026-01-13 16:56 ` Mark Brown
2026-01-13 18:33 ` David Laight
2 siblings, 1 reply; 109+ messages in thread
From: Mark Brown @ 2026-01-13 16:56 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, linux-ext4, linux-fsdevel, linux-mm, Alexander Viro,
Andreas Dilger, Christian Brauner, Kees Cook, Miklos Szeredi,
OGAWA Hirofumi, Theodore Ts'o
[-- Attachment #1: Type: text/plain, Size: 2456 bytes --]
On Wed, Nov 19, 2025 at 10:41:26PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
This breaks an arm imx_v6_v7_defconfig build:
In file included from <command-line>:
In function 'fuse_wr_pages',
inlined from 'fuse_perform_write' at /home/broonie/git/bisect/fs/fuse/file.c:1347:27:
/home/broonie/git/bisect/include/linux/compiler_types.h:630:45: error: call to '__compiletime_assert_434' declared with attribute error: min(((pos + len - 1) >> 12) - (pos >> 12) + 1, max_pages) signedness error
630 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
/home/broonie/git/bisect/include/linux/compiler_types.h:611:25: note: in definition of macro '__compiletime_assert'
611 | prefix ## suffix(); \
| ^~~~~~
/home/broonie/git/bisect/include/linux/compiler_types.h:630:9: note: in expansion of macro '_compiletime_assert'
630 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
/home/broonie/git/bisect/include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
| ^~~~~~~~~~~~~~~~~~
/home/broonie/git/bisect/include/linux/minmax.h:93:9: note: in expansion of macro 'BUILD_BUG_ON_MSG'
93 | BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \
| ^~~~~~~~~~~~~~~~
/home/broonie/git/bisect/include/linux/minmax.h:98:9: note: in expansion of macro '__careful_cmp_once'
98 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
| ^~~~~~~~~~~~~~~~~~
/home/broonie/git/bisect/include/linux/minmax.h:105:25: note: in expansion of macro '__careful_cmp'
105 | #define min(x, y) __careful_cmp(min, x, y)
| ^~~~~~~~~~~~~
/home/broonie/git/bisect/fs/fuse/file.c:1326:16: note: in expansion of macro 'min'
1326 | return min(((pos + len - 1) >> PAGE_SHIFT) - (pos >> PAGE_SHIFT) + 1,
| ^~~
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 30/44] fs: use min() or umin() instead of min_t()
2026-01-13 16:56 ` Mark Brown
@ 2026-01-13 18:33 ` David Laight
2026-01-13 19:10 ` Mark Brown
2026-01-13 19:24 ` David Laight
0 siblings, 2 replies; 109+ messages in thread
From: David Laight @ 2026-01-13 18:33 UTC (permalink / raw)
To: Mark Brown
Cc: linux-kernel, linux-ext4, linux-fsdevel, linux-mm, Alexander Viro,
Andreas Dilger, Christian Brauner, Kees Cook, Miklos Szeredi,
OGAWA Hirofumi, Theodore Ts'o
On Tue, 13 Jan 2026 16:56:56 +0000
Mark Brown <broonie@kernel.org> wrote:
> On Wed, Nov 19, 2025 at 10:41:26PM +0000, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
>
> This breaks an arm imx_v6_v7_defconfig build:
I hadn't tested 32bit when I sent the patch.
It was noticed ages ago and I thought there was a patch (to fuse/file.c) that
changed the code to avoid the 64bit signed maths on 32bit.
David
>
> In file included from <command-line>:
> In function 'fuse_wr_pages',
> inlined from 'fuse_perform_write' at /home/broonie/git/bisect/fs/fuse/file.c:1347:27:
> /home/broonie/git/bisect/include/linux/compiler_types.h:630:45: error: call to '__compiletime_assert_434' declared with attribute error: min(((pos + len - 1) >> 12) - (pos >> 12) + 1, max_pages) signedness error
> 630 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
> | ^
> /home/broonie/git/bisect/include/linux/compiler_types.h:611:25: note: in definition of macro '__compiletime_assert'
> 611 | prefix ## suffix(); \
> | ^~~~~~
> /home/broonie/git/bisect/include/linux/compiler_types.h:630:9: note: in expansion of macro '_compiletime_assert'
> 630 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
> | ^~~~~~~~~~~~~~~~~~~
> /home/broonie/git/bisect/include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
> 39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
> | ^~~~~~~~~~~~~~~~~~
> /home/broonie/git/bisect/include/linux/minmax.h:93:9: note: in expansion of macro 'BUILD_BUG_ON_MSG'
> 93 | BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \
> | ^~~~~~~~~~~~~~~~
> /home/broonie/git/bisect/include/linux/minmax.h:98:9: note: in expansion of macro '__careful_cmp_once'
> 98 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
> | ^~~~~~~~~~~~~~~~~~
> /home/broonie/git/bisect/include/linux/minmax.h:105:25: note: in expansion of macro '__careful_cmp'
> 105 | #define min(x, y) __careful_cmp(min, x, y)
> | ^~~~~~~~~~~~~
> /home/broonie/git/bisect/fs/fuse/file.c:1326:16: note: in expansion of macro 'min'
> 1326 | return min(((pos + len - 1) >> PAGE_SHIFT) - (pos >> PAGE_SHIFT) + 1,
> | ^~~
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 30/44] fs: use min() or umin() instead of min_t()
2026-01-13 18:33 ` David Laight
@ 2026-01-13 19:10 ` Mark Brown
2026-01-13 19:24 ` David Laight
1 sibling, 0 replies; 109+ messages in thread
From: Mark Brown @ 2026-01-13 19:10 UTC (permalink / raw)
To: David Laight
Cc: linux-kernel, linux-ext4, linux-fsdevel, linux-mm, Alexander Viro,
Andreas Dilger, Christian Brauner, Kees Cook, Miklos Szeredi,
OGAWA Hirofumi, Theodore Ts'o
[-- Attachment #1: Type: text/plain, Size: 517 bytes --]
On Tue, Jan 13, 2026 at 06:33:46PM +0000, David Laight wrote:
> Mark Brown <broonie@kernel.org> wrote:
> > On Wed, Nov 19, 2025 at 10:41:26PM +0000, david.laight.linux@gmail.com wrote:
> > This breaks an arm imx_v6_v7_defconfig build:
> I hadn't tested 32bit when I sent the patch.
> It was noticed ages ago and I thought there was a patch (to fuse/file.c) that
> changed the code to avoid the 64bit signed maths on 32bit.
It's possible there's a patch out there somewhere but it's not present
in what's in -next.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 30/44] fs: use min() or umin() instead of min_t()
2026-01-13 18:33 ` David Laight
2026-01-13 19:10 ` Mark Brown
@ 2026-01-13 19:24 ` David Laight
1 sibling, 0 replies; 109+ messages in thread
From: David Laight @ 2026-01-13 19:24 UTC (permalink / raw)
To: Mark Brown
Cc: linux-kernel, linux-ext4, linux-fsdevel, linux-mm, Alexander Viro,
Andreas Dilger, Christian Brauner, Kees Cook, Miklos Szeredi,
OGAWA Hirofumi, Theodore Ts'o
On Tue, 13 Jan 2026 18:33:46 +0000
David Laight <david.laight.linux@gmail.com> wrote:
> On Tue, 13 Jan 2026 16:56:56 +0000
> Mark Brown <broonie@kernel.org> wrote:
>
> > On Wed, Nov 19, 2025 at 10:41:26PM +0000, david.laight.linux@gmail.com wrote:
> > > From: David Laight <david.laight.linux@gmail.com>
> > >
> > > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > > and so cannot discard significant bits.
> >
> > This breaks an arm imx_v6_v7_defconfig build:
>
> I hadn't tested 32bit when I sent the patch.
> It was noticed ages ago and I thought there was a patch (to fuse/file.c) that
> changed the code to avoid the 64bit signed maths on 32bit.
I've just sent in a patch to fix it, compile tested for 32bit x86.
David
> >
> > In file included from <command-line>:
> > In function 'fuse_wr_pages',
> > inlined from 'fuse_perform_write' at /home/broonie/git/bisect/fs/fuse/file.c:1347:27:
> > /home/broonie/git/bisect/include/linux/compiler_types.h:630:45: error: call to '__compiletime_assert_434' declared with attribute error: min(((pos + len - 1) >> 12) - (pos >> 12) + 1, max_pages) signedness error
... ^~~~~~~~~~~~~
> > /home/broonie/git/bisect/fs/fuse/file.c:1326:16: note: in expansion of macro 'min'
> > 1326 | return min(((pos + len - 1) >> PAGE_SHIFT) - (pos >> PAGE_SHIFT) + 1,
> > | ^~~
>
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 31/44] block: bvec.h: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (29 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 30/44] fs: use min() or umin() " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 32/44] nodemask: " david.laight.linux
` (16 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel; +Cc: David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
include/linux/bvec.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index 3fc0efa0825b..dbef99624bd5 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -219,8 +219,7 @@ static inline void bvec_advance(const struct bio_vec *bvec,
bv->bv_page = bvec->bv_page + (bvec->bv_offset >> PAGE_SHIFT);
bv->bv_offset = bvec->bv_offset & ~PAGE_MASK;
}
- bv->bv_len = min_t(unsigned int, PAGE_SIZE - bv->bv_offset,
- bvec->bv_len - iter_all->done);
+ bv->bv_len = min(PAGE_SIZE - bv->bv_offset, bvec->bv_len - iter_all->done);
iter_all->done += bv->bv_len;
if (iter_all->done == bvec->bv_len) {
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 32/44] nodemask: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (30 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 31/44] block: bvec.h: use min() " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 15:19 ` Yury Norov
2025-11-19 22:41 ` [PATCH 33/44] ipc: " david.laight.linux
` (15 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Yury Norov, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
include/linux/nodemask.h | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 7ad1f5c7407e..bd38648c998d 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -245,18 +245,18 @@ static __always_inline int __nodes_weight(const nodemask_t *srcp, unsigned int n
}
/* FIXME: better would be to fix all architectures to never return
- > MAX_NUMNODES, then the silly min_ts could be dropped. */
+ > MAX_NUMNODES, then the silly min()s could be dropped. */
#define first_node(src) __first_node(&(src))
static __always_inline unsigned int __first_node(const nodemask_t *srcp)
{
- return min_t(unsigned int, MAX_NUMNODES, find_first_bit(srcp->bits, MAX_NUMNODES));
+ return min(MAX_NUMNODES, find_first_bit(srcp->bits, MAX_NUMNODES));
}
#define next_node(n, src) __next_node((n), &(src))
static __always_inline unsigned int __next_node(int n, const nodemask_t *srcp)
{
- return min_t(unsigned int, MAX_NUMNODES, find_next_bit(srcp->bits, MAX_NUMNODES, n+1));
+ return min(MAX_NUMNODES, find_next_bit(srcp->bits, MAX_NUMNODES, n+1));
}
/*
@@ -293,8 +293,7 @@ static __always_inline void init_nodemask_of_node(nodemask_t *mask, int node)
#define first_unset_node(mask) __first_unset_node(&(mask))
static __always_inline unsigned int __first_unset_node(const nodemask_t *maskp)
{
- return min_t(unsigned int, MAX_NUMNODES,
- find_first_zero_bit(maskp->bits, MAX_NUMNODES));
+ return min(MAX_NUMNODES, find_first_zero_bit(maskp->bits, MAX_NUMNODES));
}
#define NODE_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(MAX_NUMNODES)
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 32/44] nodemask: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 32/44] nodemask: " david.laight.linux
@ 2025-11-20 15:19 ` Yury Norov
0 siblings, 0 replies; 109+ messages in thread
From: Yury Norov @ 2025-11-20 15:19 UTC (permalink / raw)
To: david.laight.linux; +Cc: linux-kernel
On Wed, Nov 19, 2025 at 10:41:28PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
>
> In this case the 'unsigned long' value is small enough that the result
> is ok.
>
> Detected by an extra check added to min_t().
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
Applied, thanks.
> ---
> include/linux/nodemask.h | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
> index 7ad1f5c7407e..bd38648c998d 100644
> --- a/include/linux/nodemask.h
> +++ b/include/linux/nodemask.h
> @@ -245,18 +245,18 @@ static __always_inline int __nodes_weight(const nodemask_t *srcp, unsigned int n
> }
>
> /* FIXME: better would be to fix all architectures to never return
> - > MAX_NUMNODES, then the silly min_ts could be dropped. */
> + > MAX_NUMNODES, then the silly min()s could be dropped. */
>
> #define first_node(src) __first_node(&(src))
> static __always_inline unsigned int __first_node(const nodemask_t *srcp)
> {
> - return min_t(unsigned int, MAX_NUMNODES, find_first_bit(srcp->bits, MAX_NUMNODES));
> + return min(MAX_NUMNODES, find_first_bit(srcp->bits, MAX_NUMNODES));
> }
>
> #define next_node(n, src) __next_node((n), &(src))
> static __always_inline unsigned int __next_node(int n, const nodemask_t *srcp)
> {
> - return min_t(unsigned int, MAX_NUMNODES, find_next_bit(srcp->bits, MAX_NUMNODES, n+1));
> + return min(MAX_NUMNODES, find_next_bit(srcp->bits, MAX_NUMNODES, n+1));
> }
>
> /*
> @@ -293,8 +293,7 @@ static __always_inline void init_nodemask_of_node(nodemask_t *mask, int node)
> #define first_unset_node(mask) __first_unset_node(&(mask))
> static __always_inline unsigned int __first_unset_node(const nodemask_t *maskp)
> {
> - return min_t(unsigned int, MAX_NUMNODES,
> - find_first_zero_bit(maskp->bits, MAX_NUMNODES));
> + return min(MAX_NUMNODES, find_first_zero_bit(maskp->bits, MAX_NUMNODES));
> }
>
> #define NODE_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(MAX_NUMNODES)
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 33/44] ipc: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (31 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 32/44] nodemask: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 34/44] bpf: " david.laight.linux
` (14 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel; +Cc: David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
ipc/mqueue.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 093551fe66a7..9384eb444b83 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -363,7 +363,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
if (info->attr.mq_msgsize > ULONG_MAX/info->attr.mq_maxmsg)
goto out_inode;
mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
- min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
+ min(info->attr.mq_maxmsg, MQ_PRIO_MAX) *
sizeof(struct posix_msg_tree_node);
mq_bytes = info->attr.mq_maxmsg * info->attr.mq_msgsize;
if (mq_bytes + mq_treesize < mq_bytes)
@@ -540,7 +540,7 @@ static void mqueue_evict_inode(struct inode *inode)
/* Total amount of bytes accounted for the mqueue */
mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
- min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
+ min(info->attr.mq_maxmsg, MQ_PRIO_MAX) *
sizeof(struct posix_msg_tree_node);
mq_bytes = mq_treesize + (info->attr.mq_maxmsg *
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 34/44] bpf: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (32 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 33/44] ipc: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 35/44] " david.laight.linux
` (13 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, bpf
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
kernel/bpf/core.c | 4 ++--
kernel/bpf/log.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index d595fe512498..4f9808ea51fb 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1081,7 +1081,7 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
bpf_fill_ill_insns(hdr, size);
hdr->size = size;
- hole = min_t(unsigned int, size - (proglen + sizeof(*hdr)),
+ hole = min(size - (proglen + sizeof(*hdr)),
PAGE_SIZE - sizeof(*hdr));
start = get_random_u32_below(hole) & ~(alignment - 1);
@@ -1142,7 +1142,7 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **image_ptr,
bpf_fill_ill_insns(*rw_header, size);
(*rw_header)->size = size;
- hole = min_t(unsigned int, size - (proglen + sizeof(*ro_header)),
+ hole = min(size - (proglen + sizeof(*ro_header)),
BPF_PROG_CHUNK_SIZE - sizeof(*ro_header));
start = get_random_u32_below(hole) & ~(alignment - 1);
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index f50533169cc3..01dc13aaa785 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -79,7 +79,7 @@ void bpf_verifier_vlog(struct bpf_verifier_log *log, const char *fmt,
/* check if we have at least something to put into user buf */
new_n = 0;
if (log->end_pos < log->len_total) {
- new_n = min_t(u32, log->len_total - log->end_pos, n);
+ new_n = min(log->len_total - log->end_pos, n);
log->kbuf[new_n - 1] = '\0';
}
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 35/44] bpf: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (33 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 34/44] bpf: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 36/44] lib/bucket_locks: " david.laight.linux
` (12 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, bpf, linux-trace-kernel
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann, KP Singh,
Masami Hiramatsu, Matt Bobrowski, Song Liu, Steven Rostedt,
David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
kernel/trace/bpf_trace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 4f87c16d915a..ee3152df767c 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1515,7 +1515,7 @@ BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx,
if (!buf || (size % br_entry_size != 0))
return -EINVAL;
- to_copy = min_t(u32, br_stack->nr * br_entry_size, size);
+ to_copy = min(br_stack->nr * br_entry_size, size);
memcpy(buf, br_stack->entries, to_copy);
return to_copy;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 36/44] lib/bucket_locks: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (34 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 35/44] " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 37/44] lib/crypto/mpi: " david.laight.linux
` (11 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Andrew Morton, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
lib/bucket_locks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/bucket_locks.c b/lib/bucket_locks.c
index 64b92e1dbace..6bad65501f2d 100644
--- a/lib/bucket_locks.c
+++ b/lib/bucket_locks.c
@@ -25,7 +25,7 @@ int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask,
if (cpu_mult) {
nr_pcpus = min_t(unsigned int, nr_pcpus, 64UL);
- size = min_t(unsigned int, nr_pcpus * cpu_mult, max_size);
+ size = min(nr_pcpus * cpu_mult, max_size);
} else {
size = max_size;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 37/44] lib/crypto/mpi: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (35 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 36/44] lib/bucket_locks: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 38/44] lib/dynamic_queue_limits: use max() instead of max_t() david.laight.linux
` (10 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-crypto
Cc: Ard Biesheuvel, Eric Biggers, Jason A. Donenfeld, David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
lib/crypto/mpi/mpicoder.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/crypto/mpi/mpicoder.c b/lib/crypto/mpi/mpicoder.c
index 47f6939599b3..bf716a03c704 100644
--- a/lib/crypto/mpi/mpicoder.c
+++ b/lib/crypto/mpi/mpicoder.c
@@ -398,7 +398,7 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
while (sg_miter_next(&miter)) {
buff = miter.addr;
- len = min_t(unsigned, miter.length, nbytes);
+ len = min(miter.length, nbytes);
nbytes -= len;
for (x = 0; x < len; x++) {
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 38/44] lib/dynamic_queue_limits: use max() instead of max_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (36 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 37/44] lib/crypto/mpi: " david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 39/44] mm: use min() instead of min_t() david.laight.linux
` (9 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Andrew Morton, David Laight
From: David Laight <david.laight.linux@gmail.com>
max_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use max(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to max_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
lib/dynamic_queue_limits.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/dynamic_queue_limits.c b/lib/dynamic_queue_limits.c
index f97a752e900a..8b9730b1d751 100644
--- a/lib/dynamic_queue_limits.c
+++ b/lib/dynamic_queue_limits.c
@@ -69,7 +69,7 @@ static void dql_check_stall(struct dql *dql, unsigned short stall_thrs)
goto dqs_again;
dql->stall_cnt++;
- dql->stall_max = max_t(unsigned short, dql->stall_max, now - t);
+ dql->stall_max = max(dql->stall_max, now - t);
trace_dql_stall_detected(dql->stall_thrs, now - t,
dql->last_reap, dql->history_head,
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 39/44] mm: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (37 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 38/44] lib/dynamic_queue_limits: use max() instead of max_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-20 9:20 ` David Hildenbrand (Red Hat)
2025-11-20 10:36 ` Lorenzo Stoakes
2025-11-19 22:41 ` [PATCH 40/44] net: Don't pass bitfields to max_t() david.laight.linux
` (8 subsequent siblings)
47 siblings, 2 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, linux-fsdevel, linux-mm
Cc: Andrew Morton, Axel Rasmussen, Christoph Lameter,
David Hildenbrand, Dennis Zhou, Johannes Weiner,
Matthew Wilcox (Oracle), Mike Rapoport, Tejun Heo, Yuanchu Xie,
David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' values are small enough that the result
is ok.
(Similarly for clamp_t().)
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
mm/gup.c | 4 ++--
mm/memblock.c | 2 +-
mm/memory.c | 2 +-
mm/percpu.c | 2 +-
mm/truncate.c | 3 +--
mm/vmscan.c | 2 +-
6 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/mm/gup.c b/mm/gup.c
index a8ba5112e4d0..55435b90dcc3 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -237,8 +237,8 @@ static inline struct folio *gup_folio_range_next(struct page *start,
unsigned int nr = 1;
if (folio_test_large(folio))
- nr = min_t(unsigned int, npages - i,
- folio_nr_pages(folio) - folio_page_idx(folio, next));
+ nr = min(npages - i,
+ folio_nr_pages(folio) - folio_page_idx(folio, next));
*ntails = nr;
return folio;
diff --git a/mm/memblock.c b/mm/memblock.c
index e23e16618e9b..19b491d39002 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -2208,7 +2208,7 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
* the case.
*/
if (start)
- order = min_t(int, MAX_PAGE_ORDER, __ffs(start));
+ order = min(MAX_PAGE_ORDER, __ffs(start));
else
order = MAX_PAGE_ORDER;
diff --git a/mm/memory.c b/mm/memory.c
index 74b45e258323..72f7bd71d65f 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2375,7 +2375,7 @@ static int insert_pages(struct vm_area_struct *vma, unsigned long addr,
while (pages_to_write_in_pmd) {
int pte_idx = 0;
- const int batch_size = min_t(int, pages_to_write_in_pmd, 8);
+ const int batch_size = min(pages_to_write_in_pmd, 8);
start_pte = pte_offset_map_lock(mm, pmd, addr, &pte_lock);
if (!start_pte) {
diff --git a/mm/percpu.c b/mm/percpu.c
index 81462ce5866e..cad59221d298 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1228,7 +1228,7 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
/*
* Search to find a fit.
*/
- end = min_t(int, start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
+ end = umin(start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
pcpu_chunk_map_bits(chunk));
bit_off = pcpu_find_zero_area(chunk->alloc_map, end, start, alloc_bits,
align_mask, &area_off, &area_bits);
diff --git a/mm/truncate.c b/mm/truncate.c
index 91eb92a5ce4f..7a56372d39a3 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -849,8 +849,7 @@ void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to)
unsigned int offset, end;
offset = from - folio_pos(folio);
- end = min_t(unsigned int, to - folio_pos(folio),
- folio_size(folio));
+ end = umin(to - folio_pos(folio), folio_size(folio));
folio_zero_segment(folio, offset, end);
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index b2fc8b626d3d..82cd99a5d843 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3489,7 +3489,7 @@ static struct folio *get_pfn_folio(unsigned long pfn, struct mem_cgroup *memcg,
static bool suitable_to_scan(int total, int young)
{
- int n = clamp_t(int, cache_line_size() / sizeof(pte_t), 2, 8);
+ int n = clamp(cache_line_size() / sizeof(pte_t), 2, 8);
/* suitable if the average number of young PTEs per cacheline is >=1 */
return young * n >= total;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 39/44] mm: use min() instead of min_t() david.laight.linux
@ 2025-11-20 9:20 ` David Hildenbrand (Red Hat)
2025-11-20 9:59 ` David Laight
2025-11-20 10:36 ` Lorenzo Stoakes
1 sibling, 1 reply; 109+ messages in thread
From: David Hildenbrand (Red Hat) @ 2025-11-20 9:20 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, linux-fsdevel, linux-mm
Cc: Andrew Morton, Axel Rasmussen, Christoph Lameter, Dennis Zhou,
Johannes Weiner, Matthew Wilcox (Oracle), Mike Rapoport,
Tejun Heo, Yuanchu Xie
On 11/19/25 23:41, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
I thought using min() was frowned upon and we were supposed to use
min_t() instead to make it clear which type we want to use.
Do I misremember or have things changed?
Wasn't there a checkpatch warning that states exactly that?
--
Cheers
David
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 9:20 ` David Hildenbrand (Red Hat)
@ 2025-11-20 9:59 ` David Laight
2025-11-20 23:45 ` Eric Biggers
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 9:59 UTC (permalink / raw)
To: David Hildenbrand (Red Hat)
Cc: linux-kernel, linux-fsdevel, linux-mm, Andrew Morton,
Axel Rasmussen, Christoph Lameter, Dennis Zhou, Johannes Weiner,
Matthew Wilcox (Oracle), Mike Rapoport, Tejun Heo, Yuanchu Xie
On Thu, 20 Nov 2025 10:20:41 +0100
"David Hildenbrand (Red Hat)" <david@kernel.org> wrote:
> On 11/19/25 23:41, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
>
> I thought using min() was frowned upon and we were supposed to use
> min_t() instead to make it clear which type we want to use.
I'm not sure that was ever true.
min_t() is just an accident waiting to happen.
(and I found a few of them, the worst are in sched/fair.c)
Most of the min_t() are there because of the rather overzealous type
check that used to be in min().
But even then it would really be better to explicitly cast one of the
parameters to min(), so min_t(T, a, b) => min(a, (T)b).
Then it becomes rather more obvious that min_t(u8, x->m_u8, expr)
is going mask off the high bits of 'expr'.
> Do I misremember or have things changed?
>
> Wasn't there a checkpatch warning that states exactly that?
There is one that suggests min_t() - it ought to be nuked.
The real fix is to backtrack the types so there isn't an error.
min_t() ought to be a 'last resort' and a single cast is better.
With the relaxed checks in min() most of the min_t() can just
be replaced by min(), even this is ok:
int len = fun();
if (len < 0)
return;
count = min(len, sizeof(T));
I did look at the history of min() and min_t().
IIRC some of the networking code had a real function min() with
'unsigned int' arguments.
This was moved to a common header, changed to a #define and had
a type added - so min(T, a, b).
Pretty much immediately that was renamed min_t() and min() added
that accepted any type - but checked the types of 'a' and 'b'
exactly matched.
Code was then changed (over the years) to use min(), but in many
cases the types didn't quite match - so min_t() was used a lot.
I keep spotting new commits that pass too small a type to min_t().
So this is the start of a '5 year' campaign to nuke min_t() (et al).
David
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 9:59 ` David Laight
@ 2025-11-20 23:45 ` Eric Biggers
2025-11-21 8:27 ` David Hildenbrand (Red Hat)
2025-11-21 9:15 ` David Laight
0 siblings, 2 replies; 109+ messages in thread
From: Eric Biggers @ 2025-11-20 23:45 UTC (permalink / raw)
To: David Laight
Cc: David Hildenbrand (Red Hat), linux-kernel, linux-fsdevel,
linux-mm, Andrew Morton, Axel Rasmussen, Christoph Lameter,
Dennis Zhou, Johannes Weiner, Matthew Wilcox (Oracle),
Mike Rapoport, Tejun Heo, Yuanchu Xie
On Thu, Nov 20, 2025 at 09:59:46AM +0000, David Laight wrote:
> On Thu, 20 Nov 2025 10:20:41 +0100
> "David Hildenbrand (Red Hat)" <david@kernel.org> wrote:
>
> > On 11/19/25 23:41, david.laight.linux@gmail.com wrote:
> > > From: David Laight <david.laight.linux@gmail.com>
> > >
> > > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > > and so cannot discard significant bits.
> >
> > I thought using min() was frowned upon and we were supposed to use
> > min_t() instead to make it clear which type we want to use.
>
> I'm not sure that was ever true.
> min_t() is just an accident waiting to happen.
> (and I found a few of them, the worst are in sched/fair.c)
>
> Most of the min_t() are there because of the rather overzealous type
> check that used to be in min().
> But even then it would really be better to explicitly cast one of the
> parameters to min(), so min_t(T, a, b) => min(a, (T)b).
> Then it becomes rather more obvious that min_t(u8, x->m_u8, expr)
> is going mask off the high bits of 'expr'.
>
> > Do I misremember or have things changed?
> >
> > Wasn't there a checkpatch warning that states exactly that?
>
> There is one that suggests min_t() - it ought to be nuked.
> The real fix is to backtrack the types so there isn't an error.
> min_t() ought to be a 'last resort' and a single cast is better.
>
> With the relaxed checks in min() most of the min_t() can just
> be replaced by min(), even this is ok:
> int len = fun();
> if (len < 0)
> return;
> count = min(len, sizeof(T));
>
> I did look at the history of min() and min_t().
> IIRC some of the networking code had a real function min() with
> 'unsigned int' arguments.
> This was moved to a common header, changed to a #define and had
> a type added - so min(T, a, b).
> Pretty much immediately that was renamed min_t() and min() added
> that accepted any type - but checked the types of 'a' and 'b'
> exactly matched.
> Code was then changed (over the years) to use min(), but in many
> cases the types didn't quite match - so min_t() was used a lot.
>
> I keep spotting new commits that pass too small a type to min_t().
> So this is the start of a '5 year' campaign to nuke min_t() (et al).
Yes, checkpatch suggests min_t() or max_t() if you cast an argument to
min() or max(). Grep for "typecasts on min/max could be min_t/max_t" in
scripts/checkpatch.pl.
And historically you could not pass different types to min() and max(),
which is why people use min_t() and max_t(). It looks like you fixed
that a couple years ago in
https://lore.kernel.org/all/b97faef60ad24922b530241c5d7c933c@AcuMS.aculab.com/,
which is great! It just takes some time for the whole community to get
the message. Also, it seems that checkpatch is in need of an update.
Doing these conversions looks good to me, but unfortunately this is
probably the type of thing that shouldn't be a single kernel-wide patch
series. They should be sent out per-subsystem.
I suggest also putting a sentence in the commit message that mentions
that min() and max() have been updated to accept arguments with
different types. (Seeing as historically that wasn't true.) I suggest
also being extra clear about when each change is a cleanup vs a fix.
- Eric
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 23:45 ` Eric Biggers
@ 2025-11-21 8:27 ` David Hildenbrand (Red Hat)
2025-11-21 9:15 ` David Laight
1 sibling, 0 replies; 109+ messages in thread
From: David Hildenbrand (Red Hat) @ 2025-11-21 8:27 UTC (permalink / raw)
To: Eric Biggers, David Laight
Cc: linux-kernel, linux-fsdevel, linux-mm, Andrew Morton,
Axel Rasmussen, Christoph Lameter, Dennis Zhou, Johannes Weiner,
Matthew Wilcox (Oracle), Mike Rapoport, Tejun Heo, Yuanchu Xie
On 11/21/25 00:45, Eric Biggers wrote:
> On Thu, Nov 20, 2025 at 09:59:46AM +0000, David Laight wrote:
>> On Thu, 20 Nov 2025 10:20:41 +0100
>> "David Hildenbrand (Red Hat)" <david@kernel.org> wrote:
>>
>>> On 11/19/25 23:41, david.laight.linux@gmail.com wrote:
>>>> From: David Laight <david.laight.linux@gmail.com>
>>>>
>>>> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
>>>> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
>>>> and so cannot discard significant bits.
>>>
>>> I thought using min() was frowned upon and we were supposed to use
>>> min_t() instead to make it clear which type we want to use.
>>
>> I'm not sure that was ever true.
>> min_t() is just an accident waiting to happen.
>> (and I found a few of them, the worst are in sched/fair.c)
>>
>> Most of the min_t() are there because of the rather overzealous type
>> check that used to be in min().
>> But even then it would really be better to explicitly cast one of the
>> parameters to min(), so min_t(T, a, b) => min(a, (T)b).
>> Then it becomes rather more obvious that min_t(u8, x->m_u8, expr)
>> is going mask off the high bits of 'expr'.
>>
>>> Do I misremember or have things changed?
>>>
>>> Wasn't there a checkpatch warning that states exactly that?
>>
>> There is one that suggests min_t() - it ought to be nuked.
>> The real fix is to backtrack the types so there isn't an error.
>> min_t() ought to be a 'last resort' and a single cast is better.
>>
>> With the relaxed checks in min() most of the min_t() can just
>> be replaced by min(), even this is ok:
>> int len = fun();
>> if (len < 0)
>> return;
>> count = min(len, sizeof(T));
>>
>> I did look at the history of min() and min_t().
>> IIRC some of the networking code had a real function min() with
>> 'unsigned int' arguments.
>> This was moved to a common header, changed to a #define and had
>> a type added - so min(T, a, b).
>> Pretty much immediately that was renamed min_t() and min() added
>> that accepted any type - but checked the types of 'a' and 'b'
>> exactly matched.
>> Code was then changed (over the years) to use min(), but in many
>> cases the types didn't quite match - so min_t() was used a lot.
>>
>> I keep spotting new commits that pass too small a type to min_t().
>> So this is the start of a '5 year' campaign to nuke min_t() (et al).
>
> Yes, checkpatch suggests min_t() or max_t() if you cast an argument to
> min() or max(). Grep for "typecasts on min/max could be min_t/max_t" in
> scripts/checkpatch.pl.
Right, that's the one I recalled.
>
> And historically you could not pass different types to min() and max(),
> which is why people use min_t() and max_t(). It looks like you fixed
> that a couple years ago in
> https://lore.kernel.org/all/b97faef60ad24922b530241c5d7c933c@AcuMS.aculab.com/,
> which is great! It just takes some time for the whole community to get
> the message. Also, it seems that checkpatch is in need of an update.
Exactly.
And whenever it comes to such things, I wonder if we want to clearly
spell them out somewhere (codying-style): especially, when to use
min/max and when to use min_t/max_t.
coding-style currently mentions:
"There are also min() and max() macros that do strict type checking ..."
is that also outdated or am I just confused at this point?
>
> Doing these conversions looks good to me, but unfortunately this is
> probably the type of thing that shouldn't be a single kernel-wide patch
> series. They should be sent out per-subsystem.
Agreed!
In particular as there is no need to rush and individual subsystems can
just pick it up separately.
>
> I suggest also putting a sentence in the commit message that mentions
> that min() and max() have been updated to accept arguments with
> different types. (Seeing as historically that wasn't true.) I suggest
> also being extra clear about when each change is a cleanup vs a fix.
+1
--
Cheers
David
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 23:45 ` Eric Biggers
2025-11-21 8:27 ` David Hildenbrand (Red Hat)
@ 2025-11-21 9:15 ` David Laight
1 sibling, 0 replies; 109+ messages in thread
From: David Laight @ 2025-11-21 9:15 UTC (permalink / raw)
To: Eric Biggers
Cc: David Hildenbrand (Red Hat), linux-kernel, linux-fsdevel,
linux-mm, Andrew Morton, Axel Rasmussen, Christoph Lameter,
Dennis Zhou, Johannes Weiner, Matthew Wilcox (Oracle),
Mike Rapoport, Tejun Heo, Yuanchu Xie
On Thu, 20 Nov 2025 23:45:22 +0000
Eric Biggers <ebiggers@kernel.org> wrote:
> On Thu, Nov 20, 2025 at 09:59:46AM +0000, David Laight wrote:
> > On Thu, 20 Nov 2025 10:20:41 +0100
> > "David Hildenbrand (Red Hat)" <david@kernel.org> wrote:
> >
> > > On 11/19/25 23:41, david.laight.linux@gmail.com wrote:
> > > > From: David Laight <david.laight.linux@gmail.com>
> > > >
> > > > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > > > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > > > and so cannot discard significant bits.
> > >
> > > I thought using min() was frowned upon and we were supposed to use
> > > min_t() instead to make it clear which type we want to use.
> >
> > I'm not sure that was ever true.
> > min_t() is just an accident waiting to happen.
> > (and I found a few of them, the worst are in sched/fair.c)
> >
> > Most of the min_t() are there because of the rather overzealous type
> > check that used to be in min().
> > But even then it would really be better to explicitly cast one of the
> > parameters to min(), so min_t(T, a, b) => min(a, (T)b).
> > Then it becomes rather more obvious that min_t(u8, x->m_u8, expr)
> > is going mask off the high bits of 'expr'.
> >
> > > Do I misremember or have things changed?
> > >
> > > Wasn't there a checkpatch warning that states exactly that?
> >
> > There is one that suggests min_t() - it ought to be nuked.
> > The real fix is to backtrack the types so there isn't an error.
> > min_t() ought to be a 'last resort' and a single cast is better.
> >
> > With the relaxed checks in min() most of the min_t() can just
> > be replaced by min(), even this is ok:
> > int len = fun();
> > if (len < 0)
> > return;
> > count = min(len, sizeof(T));
> >
> > I did look at the history of min() and min_t().
> > IIRC some of the networking code had a real function min() with
> > 'unsigned int' arguments.
> > This was moved to a common header, changed to a #define and had
> > a type added - so min(T, a, b).
> > Pretty much immediately that was renamed min_t() and min() added
> > that accepted any type - but checked the types of 'a' and 'b'
> > exactly matched.
> > Code was then changed (over the years) to use min(), but in many
> > cases the types didn't quite match - so min_t() was used a lot.
> >
> > I keep spotting new commits that pass too small a type to min_t().
> > So this is the start of a '5 year' campaign to nuke min_t() (et al).
>
> Yes, checkpatch suggests min_t() or max_t() if you cast an argument to
> min() or max(). Grep for "typecasts on min/max could be min_t/max_t" in
> scripts/checkpatch.pl.
IMHO that is a really bad suggestion (and always has been).
In reality min(a, (T)b) is less likely to be buggy than min_t(T, a, b).
Someone will notice that (u16)long_var is likely to be buggy but min_t()
is expected to 'do something magic'.
There are a log of examples of 'T_var = min_t(T, T_var, b)' which really
needed (typeof (b))T_var rather than (T)b
and T_var = min_t(T, a, b) which just doesn't need a cast at all.
>
> And historically you could not pass different types to min() and max(),
> which is why people use min_t() and max_t(). It looks like you fixed
> that a couple years ago in
> https://lore.kernel.org/all/b97faef60ad24922b530241c5d7c933c@AcuMS.aculab.com/,
> which is great!
I wrote that, and then Linus redid it to avoid some very long lines
from nested expansion (with some tree-wide patches that only he could do).
> It just takes some time for the whole community to get
> the message. Also, it seems that checkpatch is in need of an update.
>
> Doing these conversions looks good to me, but unfortunately this is
> probably the type of thing that shouldn't be a single kernel-wide patch
> series. They should be sent out per-subsystem.
In effect it is a list of separate patches, one per subsystem.
They just have a common 0/n wrapper.
I wanted to link them together, I guess I could have put a bit more
text in the common commit message I pasted into all the commits.
I didn't post the change to minmax.h (apart from a summary in 0/44)
because I hadn't even tried to build a 32bit kernel nevery mind
an allmodconfig or allyesconfig one.
I spent all yesterday trying to build allyesconfig...
David
>
> I suggest also putting a sentence in the commit message that mentions
> that min() and max() have been updated to accept arguments with
> different types. (Seeing as historically that wasn't true.) I suggest
> also being extra clear about when each change is a cleanup vs a fix.
>
> - Eric
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-19 22:41 ` [PATCH 39/44] mm: use min() instead of min_t() david.laight.linux
2025-11-20 9:20 ` David Hildenbrand (Red Hat)
@ 2025-11-20 10:36 ` Lorenzo Stoakes
2025-11-20 12:09 ` Lorenzo Stoakes
2025-11-20 12:55 ` David Laight
1 sibling, 2 replies; 109+ messages in thread
From: Lorenzo Stoakes @ 2025-11-20 10:36 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, linux-fsdevel, linux-mm, Andrew Morton,
Axel Rasmussen, Christoph Lameter, David Hildenbrand, Dennis Zhou,
Johannes Weiner, Matthew Wilcox (Oracle), Mike Rapoport,
Tejun Heo, Yuanchu Xie
I guess you decided to drop all reviewers for the series...?
I do wonder what the aversion to sending to more people is, email for review is
flawed but I don't think it's problematic to ensure that people signed up to
review everything for maintained files are cc'd...
On Wed, Nov 19, 2025 at 10:41:35PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> and so cannot discard significant bits.
you're changing min_t(int, ...) too? This commit message seems incomplete as a
result.
None of the changes you make here seem to have any bearing on reality, so I
think the commit message should reflect that this is an entirely pedantic change
for the sake of satisfying a check you feel will reveal actual bugs in the
future or something?
Commit messages should include actual motivation rather than a theoretical one.
>
> In this case the 'unsigned long' values are small enough that the result
> is ok.
>
> (Similarly for clamp_t().)
>
> Detected by an extra check added to min_t().
In general I really question the value of the check when basically every use
here is pointless...?
I guess idea is in future it'll catch some real cases right?
Is this check implemented in this series at all? Because presumably with the
cover letter saying you couldn't fix the CFS code etc. you aren't? So it's just
laying the groundwork for this?
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
> mm/gup.c | 4 ++--
> mm/memblock.c | 2 +-
> mm/memory.c | 2 +-
> mm/percpu.c | 2 +-
> mm/truncate.c | 3 +--
> mm/vmscan.c | 2 +-
> 6 files changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/mm/gup.c b/mm/gup.c
> index a8ba5112e4d0..55435b90dcc3 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -237,8 +237,8 @@ static inline struct folio *gup_folio_range_next(struct page *start,
> unsigned int nr = 1;
>
> if (folio_test_large(folio))
> - nr = min_t(unsigned int, npages - i,
> - folio_nr_pages(folio) - folio_page_idx(folio, next));
> + nr = min(npages - i,
> + folio_nr_pages(folio) - folio_page_idx(folio, next));
There's no cases where any of these would discard significant bits. But we
ultimately cast to unisnged int anyway (nr) so not sure this achieves anything.
But at the same time I guess no harm.
>
> *ntails = nr;
> return folio;
> diff --git a/mm/memblock.c b/mm/memblock.c
> index e23e16618e9b..19b491d39002 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -2208,7 +2208,7 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
> * the case.
> */
> if (start)
> - order = min_t(int, MAX_PAGE_ORDER, __ffs(start));
> + order = min(MAX_PAGE_ORDER, __ffs(start));
I guess this would already be defaulting to int anyway.
> else
> order = MAX_PAGE_ORDER;
>
> diff --git a/mm/memory.c b/mm/memory.c
> index 74b45e258323..72f7bd71d65f 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -2375,7 +2375,7 @@ static int insert_pages(struct vm_area_struct *vma, unsigned long addr,
>
> while (pages_to_write_in_pmd) {
> int pte_idx = 0;
> - const int batch_size = min_t(int, pages_to_write_in_pmd, 8);
> + const int batch_size = min(pages_to_write_in_pmd, 8);
Feels like there's just a mistake in pages_to_write_in_pmd being unsigned long?
Again I guess correct because we're not going to even come close to ulong64
issues with a count of pages to write.
>
> start_pte = pte_offset_map_lock(mm, pmd, addr, &pte_lock);
> if (!start_pte) {
> diff --git a/mm/percpu.c b/mm/percpu.c
> index 81462ce5866e..cad59221d298 100644
> --- a/mm/percpu.c
> +++ b/mm/percpu.c
> @@ -1228,7 +1228,7 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
> /*
> * Search to find a fit.
> */
> - end = min_t(int, start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
> + end = umin(start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
> pcpu_chunk_map_bits(chunk));
Is it really that useful to use umin() here? I mean in examples above all the
values would be positive too. Seems strange to use umin() when everything involves an int?
> bit_off = pcpu_find_zero_area(chunk->alloc_map, end, start, alloc_bits,
> align_mask, &area_off, &area_bits);
> diff --git a/mm/truncate.c b/mm/truncate.c
> index 91eb92a5ce4f..7a56372d39a3 100644
> --- a/mm/truncate.c
> +++ b/mm/truncate.c
> @@ -849,8 +849,7 @@ void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to)
> unsigned int offset, end;
>
> offset = from - folio_pos(folio);
> - end = min_t(unsigned int, to - folio_pos(folio),
> - folio_size(folio));
> + end = umin(to - folio_pos(folio), folio_size(folio));
Again confused about why we choose to use umin() here...
min(loff_t - loff_t, size_t)
so min(long long, unsigned long)
And I guess based on fact we don't expect delta between from and folio start to
be larger than a max folio size.
So probably fine.
> folio_zero_segment(folio, offset, end);
> }
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index b2fc8b626d3d..82cd99a5d843 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -3489,7 +3489,7 @@ static struct folio *get_pfn_folio(unsigned long pfn, struct mem_cgroup *memcg,
>
> static bool suitable_to_scan(int total, int young)
> {
> - int n = clamp_t(int, cache_line_size() / sizeof(pte_t), 2, 8);
> + int n = clamp(cache_line_size() / sizeof(pte_t), 2, 8);
int, size_t (but a size_t way < INT_MAX), int, int
So seems fine.
>
> /* suitable if the average number of young PTEs per cacheline is >=1 */
> return young * n >= total;
> --
> 2.39.5
>
Generally the changes look to be correct but pointless.
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 10:36 ` Lorenzo Stoakes
@ 2025-11-20 12:09 ` Lorenzo Stoakes
2025-11-20 12:55 ` David Laight
1 sibling, 0 replies; 109+ messages in thread
From: Lorenzo Stoakes @ 2025-11-20 12:09 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, linux-fsdevel, linux-mm, Andrew Morton,
Axel Rasmussen, Christoph Lameter, David Hildenbrand, Dennis Zhou,
Johannes Weiner, Matthew Wilcox (Oracle), Mike Rapoport,
Tejun Heo, Yuanchu Xie
On Thu, Nov 20, 2025 at 10:36:16AM +0000, Lorenzo Stoakes wrote:
> I guess you decided to drop all reviewers for the series...?
>
> I do wonder what the aversion to sending to more people is, email for review is
> flawed but I don't think it's problematic to ensure that people signed up to
> review everything for maintained files are cc'd...
>
> On Wed, Nov 19, 2025 at 10:41:35PM +0000, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
>
> you're changing min_t(int, ...) too? This commit message seems incomplete as a
> result.
>
> None of the changes you make here seem to have any bearing on reality, so I
> think the commit message should reflect that this is an entirely pedantic change
> for the sake of satisfying a check you feel will reveal actual bugs in the
> future or something?
>
> Commit messages should include actual motivation rather than a theoretical one.
>
> >
> > In this case the 'unsigned long' values are small enough that the result
> > is ok.
> >
> > (Similarly for clamp_t().)
> >
> > Detected by an extra check added to min_t().
>
> In general I really question the value of the check when basically every use
> here is pointless...?
>
> I guess idea is in future it'll catch some real cases right?
>
> Is this check implemented in this series at all? Because presumably with the
> cover letter saying you couldn't fix the CFS code etc. you aren't? So it's just
> laying the groundwork for this?
>
> >
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
I mean I don't see anything wrong here, and on the basis that this will be
useful in adding this upcoming check, with the nit about commit msg above, this
LGTM so:
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > ---
> > mm/gup.c | 4 ++--
> > mm/memblock.c | 2 +-
> > mm/memory.c | 2 +-
> > mm/percpu.c | 2 +-
> > mm/truncate.c | 3 +--
> > mm/vmscan.c | 2 +-
> > 6 files changed, 7 insertions(+), 8 deletions(-)
> >
> > diff --git a/mm/gup.c b/mm/gup.c
> > index a8ba5112e4d0..55435b90dcc3 100644
> > --- a/mm/gup.c
> > +++ b/mm/gup.c
> > @@ -237,8 +237,8 @@ static inline struct folio *gup_folio_range_next(struct page *start,
> > unsigned int nr = 1;
> >
> > if (folio_test_large(folio))
> > - nr = min_t(unsigned int, npages - i,
> > - folio_nr_pages(folio) - folio_page_idx(folio, next));
> > + nr = min(npages - i,
> > + folio_nr_pages(folio) - folio_page_idx(folio, next));
>
> There's no cases where any of these would discard significant bits. But we
> ultimately cast to unisnged int anyway (nr) so not sure this achieves anything.
>
> But at the same time I guess no harm.
>
> >
> > *ntails = nr;
> > return folio;
> > diff --git a/mm/memblock.c b/mm/memblock.c
> > index e23e16618e9b..19b491d39002 100644
> > --- a/mm/memblock.c
> > +++ b/mm/memblock.c
> > @@ -2208,7 +2208,7 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
> > * the case.
> > */
> > if (start)
> > - order = min_t(int, MAX_PAGE_ORDER, __ffs(start));
> > + order = min(MAX_PAGE_ORDER, __ffs(start));
>
> I guess this would already be defaulting to int anyway.
>
> > else
> > order = MAX_PAGE_ORDER;
> >
> > diff --git a/mm/memory.c b/mm/memory.c
> > index 74b45e258323..72f7bd71d65f 100644
> > --- a/mm/memory.c
> > +++ b/mm/memory.c
> > @@ -2375,7 +2375,7 @@ static int insert_pages(struct vm_area_struct *vma, unsigned long addr,
> >
> > while (pages_to_write_in_pmd) {
> > int pte_idx = 0;
> > - const int batch_size = min_t(int, pages_to_write_in_pmd, 8);
> > + const int batch_size = min(pages_to_write_in_pmd, 8);
>
> Feels like there's just a mistake in pages_to_write_in_pmd being unsigned long?
>
> Again I guess correct because we're not going to even come close to ulong64
> issues with a count of pages to write.
>
> >
> > start_pte = pte_offset_map_lock(mm, pmd, addr, &pte_lock);
> > if (!start_pte) {
> > diff --git a/mm/percpu.c b/mm/percpu.c
> > index 81462ce5866e..cad59221d298 100644
> > --- a/mm/percpu.c
> > +++ b/mm/percpu.c
> > @@ -1228,7 +1228,7 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
> > /*
> > * Search to find a fit.
> > */
> > - end = min_t(int, start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
> > + end = umin(start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
> > pcpu_chunk_map_bits(chunk));
>
> Is it really that useful to use umin() here? I mean in examples above all the
> values would be positive too. Seems strange to use umin() when everything involves an int?
>
> > bit_off = pcpu_find_zero_area(chunk->alloc_map, end, start, alloc_bits,
> > align_mask, &area_off, &area_bits);
> > diff --git a/mm/truncate.c b/mm/truncate.c
> > index 91eb92a5ce4f..7a56372d39a3 100644
> > --- a/mm/truncate.c
> > +++ b/mm/truncate.c
> > @@ -849,8 +849,7 @@ void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to)
> > unsigned int offset, end;
> >
> > offset = from - folio_pos(folio);
> > - end = min_t(unsigned int, to - folio_pos(folio),
> > - folio_size(folio));
> > + end = umin(to - folio_pos(folio), folio_size(folio));
>
> Again confused about why we choose to use umin() here...
>
> min(loff_t - loff_t, size_t)
>
> so min(long long, unsigned long)
>
> And I guess based on fact we don't expect delta between from and folio start to
> be larger than a max folio size.
>
> So probably fine.
>
> > folio_zero_segment(folio, offset, end);
> > }
> >
> > diff --git a/mm/vmscan.c b/mm/vmscan.c
> > index b2fc8b626d3d..82cd99a5d843 100644
> > --- a/mm/vmscan.c
> > +++ b/mm/vmscan.c
> > @@ -3489,7 +3489,7 @@ static struct folio *get_pfn_folio(unsigned long pfn, struct mem_cgroup *memcg,
> >
> > static bool suitable_to_scan(int total, int young)
> > {
> > - int n = clamp_t(int, cache_line_size() / sizeof(pte_t), 2, 8);
> > + int n = clamp(cache_line_size() / sizeof(pte_t), 2, 8);
>
> int, size_t (but a size_t way < INT_MAX), int, int
>
> So seems fine.
>
> >
> > /* suitable if the average number of young PTEs per cacheline is >=1 */
> > return young * n >= total;
> > --
> > 2.39.5
> >
>
> Generally the changes look to be correct but pointless.
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 10:36 ` Lorenzo Stoakes
2025-11-20 12:09 ` Lorenzo Stoakes
@ 2025-11-20 12:55 ` David Laight
2025-11-20 13:42 ` David Hildenbrand (Red Hat)
1 sibling, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 12:55 UTC (permalink / raw)
To: Lorenzo Stoakes
Cc: linux-kernel, linux-fsdevel, linux-mm, Andrew Morton,
Axel Rasmussen, Christoph Lameter, David Hildenbrand, Dennis Zhou,
Johannes Weiner, Matthew Wilcox (Oracle), Mike Rapoport,
Tejun Heo, Yuanchu Xie
On Thu, 20 Nov 2025 10:36:16 +0000
Lorenzo Stoakes <lorenzo.stoakes@oracle.com> wrote:
> I guess you decided to drop all reviewers for the series...?
>
> I do wonder what the aversion to sending to more people is, email for review is
> flawed but I don't think it's problematic to ensure that people signed up to
> review everything for maintained files are cc'd...
Even sending all 44 patches to all the mailing lists was over 5000 emails.
Sending to all 124 maintainers and lists is some 50000 emails.
And that is just the maintainers, not the reviewers etc.
I don't have access to a mail server that will let me send more than
500 messages/day (the gmail limit is 100).
So each patch was send to the maintainers for the files it contained,
that reduced it to just under 400 emails.
>
> On Wed, Nov 19, 2025 at 10:41:35PM +0000, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
> > Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
> > and so cannot discard significant bits.
>
> you're changing min_t(int, ...) too? This commit message seems incomplete as a
> result.
Ok, I used the same commit message for most of the 44 patches.
The large majority are 'unsigned int' ones.
>
> None of the changes you make here seem to have any bearing on reality, so I
> think the commit message should reflect that this is an entirely pedantic change
> for the sake of satisfying a check you feel will reveal actual bugs in the
> future or something?
>
> Commit messages should include actual motivation rather than a theoretical one.
>
> >
> > In this case the 'unsigned long' values are small enough that the result
> > is ok.
> >
> > (Similarly for clamp_t().)
> >
> > Detected by an extra check added to min_t().
>
> In general I really question the value of the check when basically every use
> here is pointless...?
>
> I guess idea is in future it'll catch some real cases right?
>
> Is this check implemented in this series at all? Because presumably with the
> cover letter saying you couldn't fix the CFS code etc. you aren't? So it's just
> laying the groundwork for this?
I could fix the CFS code, but not with a trivial patch.
I also wanted to put the 'fixes' in the first few patches, I didn't realise
how bad that code was until I looked again.
(I've also not fixed all the drivers I don't build.)
>
> >
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > ---
> > mm/gup.c | 4 ++--
> > mm/memblock.c | 2 +-
> > mm/memory.c | 2 +-
> > mm/percpu.c | 2 +-
> > mm/truncate.c | 3 +--
> > mm/vmscan.c | 2 +-
> > 6 files changed, 7 insertions(+), 8 deletions(-)
> >
> > diff --git a/mm/gup.c b/mm/gup.c
> > index a8ba5112e4d0..55435b90dcc3 100644
> > --- a/mm/gup.c
> > +++ b/mm/gup.c
> > @@ -237,8 +237,8 @@ static inline struct folio *gup_folio_range_next(struct page *start,
> > unsigned int nr = 1;
> >
> > if (folio_test_large(folio))
> > - nr = min_t(unsigned int, npages - i,
> > - folio_nr_pages(folio) - folio_page_idx(folio, next));
> > + nr = min(npages - i,
> > + folio_nr_pages(folio) - folio_page_idx(folio, next));
>
> There's no cases where any of these would discard significant bits. But we
> ultimately cast to unisnged int anyway (nr) so not sure this achieves anything.
The (implicit) cast to unsigned int is irrelevant - that happens after the min().
The issue is that 'npages' is 'unsigned long' so can (in theory) be larger than 4G.
Ok that would be a 16TB buffer, but someone must have decided that npages might
not fit in 32 bits otherwise they wouldn't have used 'unsigned long'.
>
> But at the same time I guess no harm.
>
> >
> > *ntails = nr;
> > return folio;
> > diff --git a/mm/memblock.c b/mm/memblock.c
> > index e23e16618e9b..19b491d39002 100644
> > --- a/mm/memblock.c
> > +++ b/mm/memblock.c
> > @@ -2208,7 +2208,7 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
> > * the case.
> > */
> > if (start)
> > - order = min_t(int, MAX_PAGE_ORDER, __ffs(start));
> > + order = min(MAX_PAGE_ORDER, __ffs(start));
>
> I guess this would already be defaulting to int anyway.
Actually that one is also fixed by patch 0001 - which changes the return
type of the x86-64 __ffs() to unsigned int.
Which will be why min_t() was used in the first place.
I probably did this edit first.
>
> > else
> > order = MAX_PAGE_ORDER;
> >
> > diff --git a/mm/memory.c b/mm/memory.c
> > index 74b45e258323..72f7bd71d65f 100644
> > --- a/mm/memory.c
> > +++ b/mm/memory.c
> > @@ -2375,7 +2375,7 @@ static int insert_pages(struct vm_area_struct *vma, unsigned long addr,
> >
> > while (pages_to_write_in_pmd) {
> > int pte_idx = 0;
> > - const int batch_size = min_t(int, pages_to_write_in_pmd, 8);
> > + const int batch_size = min(pages_to_write_in_pmd, 8);
>
> Feels like there's just a mistake in pages_to_write_in_pmd being unsigned long?
Changing that would be a different 'fix'.
> Again I guess correct because we're not going to even come close to ulong64
> issues with a count of pages to write.
That fact that the count of pages is small is why the existing code isn't wrong.
The patch can't make things worse.
>
> >
> > start_pte = pte_offset_map_lock(mm, pmd, addr, &pte_lock);
> > if (!start_pte) {
> > diff --git a/mm/percpu.c b/mm/percpu.c
> > index 81462ce5866e..cad59221d298 100644
> > --- a/mm/percpu.c
> > +++ b/mm/percpu.c
> > @@ -1228,7 +1228,7 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
> > /*
> > * Search to find a fit.
> > */
> > - end = min_t(int, start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
> > + end = umin(start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
> > pcpu_chunk_map_bits(chunk));
>
> Is it really that useful to use umin() here? I mean in examples above all the
> values would be positive too. Seems strange to use umin() when everything involves an int?
>
> > bit_off = pcpu_find_zero_area(chunk->alloc_map, end, start, alloc_bits,
> > align_mask, &area_off, &area_bits);
> > diff --git a/mm/truncate.c b/mm/truncate.c
> > index 91eb92a5ce4f..7a56372d39a3 100644
> > --- a/mm/truncate.c
> > +++ b/mm/truncate.c
> > @@ -849,8 +849,7 @@ void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to)
> > unsigned int offset, end;
> >
> > offset = from - folio_pos(folio);
> > - end = min_t(unsigned int, to - folio_pos(folio),
> > - folio_size(folio));
> > + end = umin(to - folio_pos(folio), folio_size(folio));
>
> Again confused about why we choose to use umin() here...
>
> min(loff_t - loff_t, size_t)
>
> so min(long long, unsigned long)
Which is a signedness error because both are 64bit.
min(s64, u32) also reports a signedness error even though u32 is promoted
to s64, allowing that would bloat min() somewhat (and it isn't common).
>
> And I guess based on fact we don't expect delta between from and folio start to
> be larger than a max folio size.
The problem arises if 'to - folio_pos(folio)' doesn't fit in 32 bits
(and its low 32bit are small).
I think that might be possible if truncating a large file.
So this might be a real bug.
>
> So probably fine.
>
> > folio_zero_segment(folio, offset, end);
> > }
> >
> > diff --git a/mm/vmscan.c b/mm/vmscan.c
> > index b2fc8b626d3d..82cd99a5d843 100644
> > --- a/mm/vmscan.c
> > +++ b/mm/vmscan.c
> > @@ -3489,7 +3489,7 @@ static struct folio *get_pfn_folio(unsigned long pfn, struct mem_cgroup *memcg,
> >
> > static bool suitable_to_scan(int total, int young)
> > {
> > - int n = clamp_t(int, cache_line_size() / sizeof(pte_t), 2, 8);
> > + int n = clamp(cache_line_size() / sizeof(pte_t), 2, 8);
>
> int, size_t (but a size_t way < INT_MAX), int, int
Unfortunately even if cache_line_size() is u32, the division makes the result
size_t and gcc doesn't detect the value as being 'smaller that it used to be'.
David
>
> So seems fine.
>
> >
> > /* suitable if the average number of young PTEs per cacheline is >=1 */
> > return young * n >= total;
> > --
> > 2.39.5
> >
>
> Generally the changes look to be correct but pointless.
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 12:55 ` David Laight
@ 2025-11-20 13:42 ` David Hildenbrand (Red Hat)
2025-11-20 15:44 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: David Hildenbrand (Red Hat) @ 2025-11-20 13:42 UTC (permalink / raw)
To: David Laight, Lorenzo Stoakes
Cc: linux-kernel, linux-fsdevel, linux-mm, Andrew Morton,
Axel Rasmussen, Christoph Lameter, Dennis Zhou, Johannes Weiner,
Matthew Wilcox (Oracle), Mike Rapoport, Tejun Heo, Yuanchu Xie
>>
>>>
>>> Signed-off-by: David Laight <david.laight.linux@gmail.com>
>>> ---
>>> mm/gup.c | 4 ++--
>>> mm/memblock.c | 2 +-
>>> mm/memory.c | 2 +-
>>> mm/percpu.c | 2 +-
>>> mm/truncate.c | 3 +--
>>> mm/vmscan.c | 2 +-
>>> 6 files changed, 7 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/mm/gup.c b/mm/gup.c
>>> index a8ba5112e4d0..55435b90dcc3 100644
>>> --- a/mm/gup.c
>>> +++ b/mm/gup.c
>>> @@ -237,8 +237,8 @@ static inline struct folio *gup_folio_range_next(struct page *start,
>>> unsigned int nr = 1;
>>>
>>> if (folio_test_large(folio))
>>> - nr = min_t(unsigned int, npages - i,
>>> - folio_nr_pages(folio) - folio_page_idx(folio, next));
>>> + nr = min(npages - i,
>>> + folio_nr_pages(folio) - folio_page_idx(folio, next));
>>
>> There's no cases where any of these would discard significant bits. But we
>> ultimately cast to unisnged int anyway (nr) so not sure this achieves anything.
>
> The (implicit) cast to unsigned int is irrelevant - that happens after the min().
> The issue is that 'npages' is 'unsigned long' so can (in theory) be larger than 4G.
> Ok that would be a 16TB buffer, but someone must have decided that npages might
> not fit in 32 bits otherwise they wouldn't have used 'unsigned long'.
See commit fa17bcd5f65e ("mm: make folio page count functions return
unsigned") why that function used to return "long" instead of "unsigned
int" and how we changed it to "unsigned long".
Until that function actually returns something that large might take a
while, so no need to worry about that right now.
--
Cheers
David
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 13:42 ` David Hildenbrand (Red Hat)
@ 2025-11-20 15:44 ` David Laight
2025-11-21 8:24 ` David Hildenbrand (Red Hat)
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-11-20 15:44 UTC (permalink / raw)
To: David Hildenbrand (Red Hat)
Cc: Lorenzo Stoakes, linux-kernel, linux-fsdevel, linux-mm,
Andrew Morton, Axel Rasmussen, Christoph Lameter, Dennis Zhou,
Johannes Weiner, Matthew Wilcox (Oracle), Mike Rapoport,
Tejun Heo, Yuanchu Xie
On Thu, 20 Nov 2025 14:42:24 +0100
"David Hildenbrand (Red Hat)" <david@kernel.org> wrote:
> >>
> >>>
> >>> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> >>> ---
> >>> mm/gup.c | 4 ++--
> >>> mm/memblock.c | 2 +-
> >>> mm/memory.c | 2 +-
> >>> mm/percpu.c | 2 +-
> >>> mm/truncate.c | 3 +--
> >>> mm/vmscan.c | 2 +-
> >>> 6 files changed, 7 insertions(+), 8 deletions(-)
> >>>
> >>> diff --git a/mm/gup.c b/mm/gup.c
> >>> index a8ba5112e4d0..55435b90dcc3 100644
> >>> --- a/mm/gup.c
> >>> +++ b/mm/gup.c
> >>> @@ -237,8 +237,8 @@ static inline struct folio *gup_folio_range_next(struct page *start,
> >>> unsigned int nr = 1;
> >>>
> >>> if (folio_test_large(folio))
> >>> - nr = min_t(unsigned int, npages - i,
> >>> - folio_nr_pages(folio) - folio_page_idx(folio, next));
> >>> + nr = min(npages - i,
> >>> + folio_nr_pages(folio) - folio_page_idx(folio, next));
> >>
> >> There's no cases where any of these would discard significant bits. But we
> >> ultimately cast to unisnged int anyway (nr) so not sure this achieves anything.
> >
> > The (implicit) cast to unsigned int is irrelevant - that happens after the min().
> > The issue is that 'npages' is 'unsigned long' so can (in theory) be larger than 4G.
> > Ok that would be a 16TB buffer, but someone must have decided that npages might
> > not fit in 32 bits otherwise they wouldn't have used 'unsigned long'.
>
> See commit fa17bcd5f65e ("mm: make folio page count functions return
> unsigned") why that function used to return "long" instead of "unsigned
> int" and how we changed it to "unsigned long".
>
> Until that function actually returns something that large might take a
> while, so no need to worry about that right now.
Except that it gives a false positive on a compile-time test that finds a
few real bugs.
I've been (slowly) fixing 'allmodconfig' and found 'goodies' like:
min_t(u32, MAX_UINT, expr)
and
min_t(u8, expr, 255)
Pretty much all the min_t(unsigned xxx) that compile when changed to min()
are safe changes and might fix an obscure bug.
Probably 99% make no difference.
So I'd like to get rid of the ones that make no difference.
David
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 39/44] mm: use min() instead of min_t()
2025-11-20 15:44 ` David Laight
@ 2025-11-21 8:24 ` David Hildenbrand (Red Hat)
0 siblings, 0 replies; 109+ messages in thread
From: David Hildenbrand (Red Hat) @ 2025-11-21 8:24 UTC (permalink / raw)
To: David Laight
Cc: Lorenzo Stoakes, linux-kernel, linux-fsdevel, linux-mm,
Andrew Morton, Axel Rasmussen, Christoph Lameter, Dennis Zhou,
Johannes Weiner, Matthew Wilcox (Oracle), Mike Rapoport,
Tejun Heo, Yuanchu Xie
On 11/20/25 16:44, David Laight wrote:
> On Thu, 20 Nov 2025 14:42:24 +0100
> "David Hildenbrand (Red Hat)" <david@kernel.org> wrote:
>
>>>>
>>>>>
>>>>> Signed-off-by: David Laight <david.laight.linux@gmail.com>
>>>>> ---
>>>>> mm/gup.c | 4 ++--
>>>>> mm/memblock.c | 2 +-
>>>>> mm/memory.c | 2 +-
>>>>> mm/percpu.c | 2 +-
>>>>> mm/truncate.c | 3 +--
>>>>> mm/vmscan.c | 2 +-
>>>>> 6 files changed, 7 insertions(+), 8 deletions(-)
>>>>>
>>>>> diff --git a/mm/gup.c b/mm/gup.c
>>>>> index a8ba5112e4d0..55435b90dcc3 100644
>>>>> --- a/mm/gup.c
>>>>> +++ b/mm/gup.c
>>>>> @@ -237,8 +237,8 @@ static inline struct folio *gup_folio_range_next(struct page *start,
>>>>> unsigned int nr = 1;
>>>>>
>>>>> if (folio_test_large(folio))
>>>>> - nr = min_t(unsigned int, npages - i,
>>>>> - folio_nr_pages(folio) - folio_page_idx(folio, next));
>>>>> + nr = min(npages - i,
>>>>> + folio_nr_pages(folio) - folio_page_idx(folio, next));
>>>>
>>>> There's no cases where any of these would discard significant bits. But we
>>>> ultimately cast to unisnged int anyway (nr) so not sure this achieves anything.
>>>
>>> The (implicit) cast to unsigned int is irrelevant - that happens after the min().
>>> The issue is that 'npages' is 'unsigned long' so can (in theory) be larger than 4G.
>>> Ok that would be a 16TB buffer, but someone must have decided that npages might
>>> not fit in 32 bits otherwise they wouldn't have used 'unsigned long'.
>>
>> See commit fa17bcd5f65e ("mm: make folio page count functions return
>> unsigned") why that function used to return "long" instead of "unsigned
>> int" and how we changed it to "unsigned long".
>>
>> Until that function actually returns something that large might take a
>> while, so no need to worry about that right now.
>
> Except that it gives a false positive on a compile-time test that finds a
> few real bugs.
>
> I've been (slowly) fixing 'allmodconfig' and found 'goodies' like:
> min_t(u32, MAX_UINT, expr)
> and
> min_t(u8, expr, 255)
>
:)
> Pretty much all the min_t(unsigned xxx) that compile when changed to min()
> are safe changes and might fix an obscure bug.
> Probably 99% make no difference.
>
> So I'd like to get rid of the ones that make no difference.
No objection from my side if using min() is the preferred way now and
introduces no observable changes.
--
Cheers
David
^ permalink raw reply [flat|nested] 109+ messages in thread
* [PATCH 40/44] net: Don't pass bitfields to max_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (38 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 39/44] mm: use min() instead of min_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 41/44] net/core: Change loop conditions so min() can be used david.laight.linux
` (7 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
David Laight
From: David Laight <david.laight.linux@gmail.com>
It is invalid to use sizeof() or typeof() in bitfields which stops
them being passed to max().
This has been fixed by using max_t().
I want to add some checks to max_t() to detect cases where the cast
discards non-zero high bits - which uses sizeof().
So add 0 to the bitfield (converting it to int) then use max().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
include/net/tcp_ecn.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index f13e5cd2b1ac..14c00404a95f 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -196,7 +196,7 @@ static inline void tcp_accecn_opt_demand_min(struct sock *sk,
struct tcp_sock *tp = tcp_sk(sk);
u8 opt_demand;
- opt_demand = max_t(u8, opt_demand_min, tp->accecn_opt_demand);
+ opt_demand = max(opt_demand_min, tp->accecn_opt_demand + 0);
tp->accecn_opt_demand = opt_demand;
}
@@ -303,8 +303,7 @@ static inline void tcp_ecn_received_counters(struct sock *sk,
u32 bytes_mask = GENMASK_U32(31, 22);
tp->received_ecn_bytes[ecnfield - 1] += len;
- tp->accecn_minlen = max_t(u8, tp->accecn_minlen,
- minlen);
+ tp->accecn_minlen = max(tp->accecn_minlen + 0, minlen);
/* Send AccECN option at least once per 2^22-byte
* increase in any ECN byte counter.
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 41/44] net/core: Change loop conditions so min() can be used
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (39 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 40/44] net: Don't pass bitfields to max_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 42/44] net: use min() instead of min_t() david.laight.linux
` (6 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, bpf, netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Jakub Sitnicki,
John Fastabend, Paolo Abeni, David Laight
From: David Laight <david.laight.linux@gmail.com>
Loops like:
int copied = ...;
...
while (copied) {
use = min_t(type, copied, PAGE_SIZE - offset);
...
copied -= 0;
}
can be converted to a plain min() if the comparison is changed to:
while (copied > 0) {
This removes any chance of high bits being discded by min_t().
(In the case above PAGE_SIZE is 64bits so the 'int' cast is safe,
but there are plenty of cases where the check shows up bugs.)
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
net/core/datagram.c | 6 +++---
net/core/skmsg.c | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/net/core/datagram.c b/net/core/datagram.c
index c285c6465923..555f38b89729 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -664,8 +664,8 @@ int zerocopy_fill_skb_from_iter(struct sk_buff *skb,
head = compound_head(pages[n]);
order = compound_order(head);
- for (refs = 0; copied != 0; start = 0) {
- int size = min_t(int, copied, PAGE_SIZE - start);
+ for (refs = 0; copied > 0; start = 0) {
+ int size = min(copied, PAGE_SIZE - start);
if (pages[n] - head > (1UL << order) - 1) {
head = compound_head(pages[n]);
@@ -783,7 +783,7 @@ EXPORT_SYMBOL(__zerocopy_sg_from_iter);
*/
int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
{
- int copy = min_t(int, skb_headlen(skb), iov_iter_count(from));
+ int copy = min(skb_headlen(skb), iov_iter_count(from));
/* copy up to skb headlen */
if (skb_copy_datagram_from_iter(skb, 0, from, copy))
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index 2ac7731e1e0a..b58e319f4e2e 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -335,8 +335,8 @@ int sk_msg_zerocopy_from_iter(struct sock *sk, struct iov_iter *from,
bytes -= copied;
msg->sg.size += copied;
- while (copied) {
- use = min_t(int, copied, PAGE_SIZE - offset);
+ while (copied > 0) {
+ use = min(copied, PAGE_SIZE - offset);
sg_set_page(&msg->sg.data[msg->sg.end],
pages[i], use, offset);
sg_unmark_end(&msg->sg.data[msg->sg.end]);
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 42/44] net: use min() instead of min_t()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (40 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 41/44] net/core: Change loop conditions so min() can be used david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 43/44] net/netlink: Use umin() to avoid min_t(int, ...) discarding high bits david.laight.linux
` (5 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: David Ahern, David S. Miller, Eric Dumazet, Jakub Kicinski,
Kuniyuki Iwashima, Neal Cardwell, Paolo Abeni, Willem de Bruijn,
David Laight
From: David Laight <david.laight.linux@gmail.com>
min_t(unsigned int, a, b) casts an 'unsigned long' to 'unsigned int'.
Use min(a, b) instead as it promotes any 'unsigned int' to 'unsigned long'
and so cannot discard significant bits.
In this case the 'unsigned long' value is small enough that the result
is ok.
Detected by an extra check added to min_t().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
net/core/net-sysfs.c | 3 +--
net/ipv4/fib_trie.c | 2 +-
net/ipv4/tcp_input.c | 4 ++--
net/ipv4/tcp_output.c | 5 ++---
net/ipv4/tcp_timer.c | 4 ++--
net/ipv6/addrconf.c | 8 ++++----
net/ipv6/ndisc.c | 5 ++---
net/packet/af_packet.c | 2 +-
net/unix/af_unix.c | 4 ++--
9 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index ca878525ad7c..8aaeed38be0b 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -985,8 +985,7 @@ static int netdev_rx_queue_set_rps_mask(struct netdev_rx_queue *queue,
struct rps_map *old_map, *map;
int cpu, i;
- map = kzalloc(max_t(unsigned int,
- RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES),
+ map = kzalloc(max(RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES),
GFP_KERNEL);
if (!map)
return -ENOMEM;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 59a6f0a9638f..e85441717222 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -710,7 +710,7 @@ static unsigned char update_suffix(struct key_vector *tn)
* tn->pos + tn->bits, the second highest node will have a suffix
* length at most of tn->pos + tn->bits - 1
*/
- slen_max = min_t(unsigned char, tn->pos + tn->bits - 1, tn->slen);
+ slen_max = min(tn->pos + tn->bits - 1, tn->slen);
/* search though the list of children looking for nodes that might
* have a suffix greater than the one we currently have. This is
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e4a979b75cc6..8c9eb91190ae 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2870,7 +2870,7 @@ static void tcp_mtup_probe_success(struct sock *sk)
val = (u64)tcp_snd_cwnd(tp) * tcp_mss_to_mtu(sk, tp->mss_cache);
do_div(val, icsk->icsk_mtup.probe_size);
DEBUG_NET_WARN_ON_ONCE((u32)val != val);
- tcp_snd_cwnd_set(tp, max_t(u32, 1U, val));
+ tcp_snd_cwnd_set(tp, max(1, val));
tp->snd_cwnd_cnt = 0;
tp->snd_cwnd_stamp = tcp_jiffies32;
@@ -3323,7 +3323,7 @@ void tcp_rearm_rto(struct sock *sk)
/* delta_us may not be positive if the socket is locked
* when the retrans timer fires and is rescheduled.
*/
- rto = usecs_to_jiffies(max_t(int, delta_us, 1));
+ rto = usecs_to_jiffies(max(delta_us, 1));
}
tcp_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto, true);
}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index b94efb3050d2..516ea138993d 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3076,7 +3076,7 @@ bool tcp_schedule_loss_probe(struct sock *sk, bool advancing_rto)
jiffies_to_usecs(inet_csk(sk)->icsk_rto) :
tcp_rto_delta_us(sk); /* How far in future is RTO? */
if (rto_delta_us > 0)
- timeout = min_t(u32, timeout, usecs_to_jiffies(rto_delta_us));
+ timeout = min(timeout, usecs_to_jiffies(rto_delta_us));
tcp_reset_xmit_timer(sk, ICSK_TIME_LOSS_PROBE, timeout, true);
return true;
@@ -4382,8 +4382,7 @@ void tcp_send_delayed_ack(struct sock *sk)
* directly.
*/
if (tp->srtt_us) {
- int rtt = max_t(int, usecs_to_jiffies(tp->srtt_us >> 3),
- TCP_DELACK_MIN);
+ int rtt = max(usecs_to_jiffies(tp->srtt_us >> 3), TCP_DELACK_MIN);
if (rtt < max_ato)
max_ato = rtt;
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 2dd73a4e8e51..9d5fc405e76a 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -43,7 +43,7 @@ static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
if (remaining <= 0)
return 1; /* user timeout has passed; fire ASAP */
- return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(remaining));
+ return min(icsk->icsk_rto, msecs_to_jiffies(remaining));
}
u32 tcp_clamp_probe0_to_user_timeout(const struct sock *sk, u32 when)
@@ -504,7 +504,7 @@ static bool tcp_rtx_probe0_timed_out(const struct sock *sk,
*/
if (rtx_delta > user_timeout)
return true;
- timeout = min_t(u32, timeout, msecs_to_jiffies(user_timeout));
+ timeout = umin(timeout, msecs_to_jiffies(user_timeout));
}
/* Note: timer interrupt might have been delayed by at least one jiffy,
* and tp->rcv_tstamp might very well have been written recently.
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 40e9c336f6c5..930e34af4331 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1422,11 +1422,11 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
if_public_preferred_lft = ifp->prefered_lft;
memset(&cfg, 0, sizeof(cfg));
- cfg.valid_lft = min_t(__u32, ifp->valid_lft,
- READ_ONCE(idev->cnf.temp_valid_lft) + age);
+ cfg.valid_lft = min(ifp->valid_lft,
+ READ_ONCE(idev->cnf.temp_valid_lft) + age);
cfg.preferred_lft = cnf_temp_preferred_lft + age - idev->desync_factor;
- cfg.preferred_lft = min_t(__u32, if_public_preferred_lft, cfg.preferred_lft);
- cfg.preferred_lft = min_t(__u32, cfg.valid_lft, cfg.preferred_lft);
+ cfg.preferred_lft = min(if_public_preferred_lft, cfg.preferred_lft);
+ cfg.preferred_lft = min(cfg.valid_lft, cfg.preferred_lft);
cfg.plen = ifp->prefix_len;
tmp_tstamp = ifp->tstamp;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index f427e41e9c49..b3bcbf0d864b 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1731,9 +1731,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
neigh_release(neigh);
}
- rd_len = min_t(unsigned int,
- IPV6_MIN_MTU - sizeof(struct ipv6hdr) - sizeof(*msg) - optlen,
- skb->len + 8);
+ rd_len = min(IPV6_MIN_MTU - sizeof(struct ipv6hdr) - sizeof(*msg) - optlen,
+ skb->len + 8);
rd_len &= ~0x7;
optlen += rd_len;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 173e6edda08f..af0c74f7b4d4 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3015,7 +3015,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
hlen = LL_RESERVED_SPACE(dev);
tlen = dev->needed_tailroom;
linear = __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len);
- linear = max(linear, min_t(int, len, dev->hard_header_len));
+ linear = max(linear, min(len, dev->hard_header_len));
skb = packet_alloc_skb(sk, hlen + tlen, hlen, len, linear,
msg->msg_flags & MSG_DONTWAIT, &err);
if (skb == NULL)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 768098dec231..e573fcb21a01 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2448,7 +2448,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
/* allow fallback to order-0 allocations */
size = min_t(int, size, SKB_MAX_HEAD(0) + UNIX_SKB_FRAGS_SZ);
- data_len = max_t(int, 0, size - SKB_MAX_HEAD(0));
+ data_len = max(0, size - (int)SKB_MAX_HEAD(0));
data_len = min_t(size_t, size, PAGE_ALIGN(data_len));
@@ -3054,7 +3054,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
sunaddr = NULL;
}
- chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size);
+ chunk = min(unix_skb_len(skb) - skip, size);
chunk = state->recv_actor(skb, skip, chunk, state);
if (chunk < 0) {
if (copied == 0)
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 43/44] net/netlink: Use umin() to avoid min_t(int, ...) discarding high bits
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (41 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 42/44] net: use min() instead of min_t() david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-11-19 22:41 ` [PATCH 44/44] net/mptcp: Change some dubious min_t(int, ...) to min() david.laight.linux
` (4 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
David Laight
From: David Laight <david.laight.linux@gmail.com>
The scan limit in genl_allocate_reserve_groups() is:
min_t(int, id + n_groups, mc_groups_longs * BITS_PER_LONG);
While 'id' and 'n_groups' are both 'int', 'mc_groups_longs' is
'unsigned long' (BITS_PER_LONG is 'int').
These inconsistent types (all the values are small and non-negative)
means that a simple min() fails.
When checks for masking high bits are added to min_t() that also fails.
Instead use umin() so safely convert all the values to unsigned.
Move the limit calculation outside the loop for efficiency and
readability.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
net/netlink/genetlink.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 978c129c6095..a802dd8ead2d 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -395,10 +395,11 @@ static unsigned int genl_op_iter_idx(struct genl_op_iter *iter)
return iter->cmd_idx;
}
-static int genl_allocate_reserve_groups(int n_groups, int *first_id)
+static noinline_for_stack int genl_allocate_reserve_groups(int n_groups, int *first_id)
{
unsigned long *new_groups;
int start = 0;
+ int limit;
int i;
int id;
bool fits;
@@ -414,10 +415,8 @@ static int genl_allocate_reserve_groups(int n_groups, int *first_id)
start);
fits = true;
- for (i = id;
- i < min_t(int, id + n_groups,
- mc_groups_longs * BITS_PER_LONG);
- i++) {
+ limit = umin(id + n_groups, mc_groups_longs * BITS_PER_LONG);
+ for (i = id; i < limit; i++) {
if (test_bit(i, mc_groups)) {
start = i;
fits = false;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* [PATCH 44/44] net/mptcp: Change some dubious min_t(int, ...) to min()
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (42 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 43/44] net/netlink: Use umin() to avoid min_t(int, ...) discarding high bits david.laight.linux
@ 2025-11-19 22:41 ` david.laight.linux
2025-12-18 17:33 ` Matthieu Baerts
2025-11-20 1:47 ` [PATCH 00/44] Change a lot of min_t() that might mask high bits Jakub Kicinski
` (3 subsequent siblings)
47 siblings, 1 reply; 109+ messages in thread
From: david.laight.linux @ 2025-11-19 22:41 UTC (permalink / raw)
To: linux-kernel, mptcp, netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Mat Martineau,
Matthieu Baerts, Paolo Abeni, David Laight
From: David Laight <david.laight.linux@gmail.com>
There are two:
min_t(int, xxx, mptcp_wnd_end(msk) - msk->snd_nxt);
Both mptcp_wnd_end(msk) and msk->snd_nxt are u64, their difference
(aka the window size) might be limited to 32 bits - but that isn't
knowable from this code.
So checks being added to min_t() detect the potential discard of
significant bits.
Provided the 'avail_size' and return of mptcp_check_allowed_size()
are changed to an unsigned type (size_t matches the type the caller
uses) both min_t() can be changed to min().
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
net/mptcp/protocol.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 2d6b8de35c44..d57c3659462f 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1123,8 +1123,8 @@ struct mptcp_sendmsg_info {
bool data_lock_held;
};
-static int mptcp_check_allowed_size(const struct mptcp_sock *msk, struct sock *ssk,
- u64 data_seq, int avail_size)
+static size_t mptcp_check_allowed_size(const struct mptcp_sock *msk, struct sock *ssk,
+ u64 data_seq, size_t avail_size)
{
u64 window_end = mptcp_wnd_end(msk);
u64 mptcp_snd_wnd;
@@ -1133,7 +1133,7 @@ static int mptcp_check_allowed_size(const struct mptcp_sock *msk, struct sock *s
return avail_size;
mptcp_snd_wnd = window_end - data_seq;
- avail_size = min_t(unsigned int, mptcp_snd_wnd, avail_size);
+ avail_size = min(mptcp_snd_wnd, avail_size);
if (unlikely(tcp_sk(ssk)->snd_wnd < mptcp_snd_wnd)) {
tcp_sk(ssk)->snd_wnd = min_t(u64, U32_MAX, mptcp_snd_wnd);
@@ -1477,7 +1477,7 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
if (!ssk || !sk_stream_memory_free(ssk))
return NULL;
- burst = min_t(int, MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - msk->snd_nxt);
+ burst = min(MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - msk->snd_nxt);
wmem = READ_ONCE(ssk->sk_wmem_queued);
if (!burst)
return ssk;
--
2.39.5
^ permalink raw reply related [flat|nested] 109+ messages in thread* Re: [PATCH 44/44] net/mptcp: Change some dubious min_t(int, ...) to min()
2025-11-19 22:41 ` [PATCH 44/44] net/mptcp: Change some dubious min_t(int, ...) to min() david.laight.linux
@ 2025-12-18 17:33 ` Matthieu Baerts
2025-12-18 20:15 ` David Laight
0 siblings, 1 reply; 109+ messages in thread
From: Matthieu Baerts @ 2025-12-18 17:33 UTC (permalink / raw)
To: david.laight.linux, linux-kernel, mptcp, netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Mat Martineau,
Paolo Abeni
Hi David,
On 19/11/2025 23:41, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> There are two:
> min_t(int, xxx, mptcp_wnd_end(msk) - msk->snd_nxt);
> Both mptcp_wnd_end(msk) and msk->snd_nxt are u64, their difference
> (aka the window size) might be limited to 32 bits - but that isn't
> knowable from this code.
> So checks being added to min_t() detect the potential discard of
> significant bits.
>
> Provided the 'avail_size' and return of mptcp_check_allowed_size()
> are changed to an unsigned type (size_t matches the type the caller
> uses) both min_t() can be changed to min().
Thank you for the patch!
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
I'm not sure what the status on your side: I don't know if you still
plan to send a specific series for all the modifications in the net, but
just in case, I just applied your patch in the MPTCP tree. I removed the
"net/" prefix from the subject. I will send this patch with others for
including in the net-next tree later on if you didn't do that in between.
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 44/44] net/mptcp: Change some dubious min_t(int, ...) to min()
2025-12-18 17:33 ` Matthieu Baerts
@ 2025-12-18 20:15 ` David Laight
2025-12-19 10:48 ` Matthieu Baerts
0 siblings, 1 reply; 109+ messages in thread
From: David Laight @ 2025-12-18 20:15 UTC (permalink / raw)
To: Matthieu Baerts
Cc: linux-kernel, mptcp, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Mat Martineau, Paolo Abeni
On Thu, 18 Dec 2025 18:33:26 +0100
Matthieu Baerts <matttbe@kernel.org> wrote:
> Hi David,
>
> On 19/11/2025 23:41, david.laight.linux@gmail.com wrote:
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > There are two:
> > min_t(int, xxx, mptcp_wnd_end(msk) - msk->snd_nxt);
> > Both mptcp_wnd_end(msk) and msk->snd_nxt are u64, their difference
> > (aka the window size) might be limited to 32 bits - but that isn't
> > knowable from this code.
> > So checks being added to min_t() detect the potential discard of
> > significant bits.
> >
> > Provided the 'avail_size' and return of mptcp_check_allowed_size()
> > are changed to an unsigned type (size_t matches the type the caller
> > uses) both min_t() can be changed to min().
>
> Thank you for the patch!
>
> Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
>
> I'm not sure what the status on your side: I don't know if you still
> plan to send a specific series for all the modifications in the net, but
> just in case, I just applied your patch in the MPTCP tree. I removed the
> "net/" prefix from the subject. I will send this patch with others for
> including in the net-next tree later on if you didn't do that in between.
I'll go through them again at some point.
I'll check against 'next' (but probably not net-next).
I actually need to look at the ones that seemed like real bugs when I
did an allmodconfig build - that got to over 200 patches to get 'clean'.
It would be nice to get rid of a lot of the min_t(), but I might try
to attack the dubious ones rather than the ones that appear to make
no difference.
I might propose some extra checks in minmax.h that would break W=1 builds.
Detecting things like min_t(u8, u32_value, 0xff) where the cast makes the
comparison always succeed.
In reality any calls with casts to u8 and u16 are 'dubious'.
That and changing checkpatch.pl to not suggest min_t() at all, and
to reject the more dubious uses.
After all with:
min(x, (int)y)
it is clear to the reader that 'y' is being possibly truncated and converted
to a signed value, but with:
min_t(int, x, y)
you don't know which value needed the cast (and the line isn't even shorter).
But what I've found all to often is actually:
a = min_t(typeof(a), x, y);
and the similar:
x = min_t(typeof(x), x, y);
where the type of the result is used and high bits get discarded.
I've just been trying to build with #define clamp_val clamp.
That requires a few minor changes and I'm pretty sure shows up
a real bug.
David
>
> Cheers,
> Matt
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 44/44] net/mptcp: Change some dubious min_t(int, ...) to min()
2025-12-18 20:15 ` David Laight
@ 2025-12-19 10:48 ` Matthieu Baerts
0 siblings, 0 replies; 109+ messages in thread
From: Matthieu Baerts @ 2025-12-19 10:48 UTC (permalink / raw)
To: David Laight
Cc: linux-kernel, mptcp, netdev, David S. Miller, Eric Dumazet,
Jakub Kicinski, Mat Martineau, Paolo Abeni
Hi David,
Thank you for your reply!
On 18/12/2025 21:15, David Laight wrote:
> On Thu, 18 Dec 2025 18:33:26 +0100
> Matthieu Baerts <matttbe@kernel.org> wrote:
>
>> Hi David,
>>
>> On 19/11/2025 23:41, david.laight.linux@gmail.com wrote:
>>> From: David Laight <david.laight.linux@gmail.com>
>>>
>>> There are two:
>>> min_t(int, xxx, mptcp_wnd_end(msk) - msk->snd_nxt);
>>> Both mptcp_wnd_end(msk) and msk->snd_nxt are u64, their difference
>>> (aka the window size) might be limited to 32 bits - but that isn't
>>> knowable from this code.
>>> So checks being added to min_t() detect the potential discard of
>>> significant bits.
>>>
>>> Provided the 'avail_size' and return of mptcp_check_allowed_size()
>>> are changed to an unsigned type (size_t matches the type the caller
>>> uses) both min_t() can be changed to min().
>>
>> Thank you for the patch!
>>
>> Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
>>
>> I'm not sure what the status on your side: I don't know if you still
>> plan to send a specific series for all the modifications in the net, but
>> just in case, I just applied your patch in the MPTCP tree. I removed the
>> "net/" prefix from the subject. I will send this patch with others for
>> including in the net-next tree later on if you didn't do that in between.
>
> I'll go through them again at some point.
Great, thank you!
> I'll check against 'next' (but probably not net-next).
net-next is in linux-next, so that should be fine.
> I actually need to look at the ones that seemed like real bugs when I
> did an allmodconfig build - that got to over 200 patches to get 'clean'.
>
> It would be nice to get rid of a lot of the min_t(), but I might try
> to attack the dubious ones rather than the ones that appear to make
> no difference.
>
> I might propose some extra checks in minmax.h that would break W=1 builds.
> Detecting things like min_t(u8, u32_value, 0xff) where the cast makes the
> comparison always succeed.
> In reality any calls with casts to u8 and u16 are 'dubious'.
>
> That and changing checkpatch.pl to not suggest min_t() at all, and
> to reject the more dubious uses.
> After all with:
> min(x, (int)y)
> it is clear to the reader that 'y' is being possibly truncated and converted
> to a signed value, but with:
> min_t(int, x, y)
> you don't know which value needed the cast (and the line isn't even shorter).
> But what I've found all to often is actually:
> a = min_t(typeof(a), x, y);
> and the similar:
> x = min_t(typeof(x), x, y);
> where the type of the result is used and high bits get discarded.
Good idea to add extra checks and prevent future issues!
> I've just been trying to build with #define clamp_val clamp.
> That requires a few minor changes and I'm pretty sure shows up
> a real bug.
Thank you for looking at that!
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
^ permalink raw reply [flat|nested] 109+ messages in thread
* Re: [PATCH 00/44] Change a lot of min_t() that might mask high bits
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (43 preceding siblings ...)
2025-11-19 22:41 ` [PATCH 44/44] net/mptcp: Change some dubious min_t(int, ...) to min() david.laight.linux
@ 2025-11-20 1:47 ` Jakub Kicinski
2025-11-20 9:38 ` Lorenzo Stoakes
` (2 subsequent siblings)
47 siblings, 0 replies; 109+ messages in thread
From: Jakub Kicinski @ 2025-11-20 1:47 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, Alan Stern, Alexander Viro, Alexei Starovoitov,
Andi Shyti, Andreas Dilger, Andrew Lunn, Andrew Morton,
Andrii Nakryiko, Andy Shevchenko, Ard Biesheuvel,
Arnaldo Carvalho de Melo, Bjorn Helgaas, Borislav Petkov,
Christian Brauner, Christian König, Christoph Hellwig,
Daniel Borkmann, Dan Williams, Dave Hansen, Dave Jiang,
David Ahern, David Hildenbrand, Davidlohr Bueso, David S. Miller,
Dennis Zhou, Eric Dumazet, Greg Kroah-Hartman, Herbert Xu,
Ingo Molnar, Jakub Sitnicki, James E.J. Bottomley,
Jarkko Sakkinen, Jason A. Donenfeld, Jens Axboe, Jiri Slaby,
Johannes Weiner, John Allen, Jonathan Cameron, Juergen Gross,
Kees Cook, KP Singh, Linus Walleij, Martin K. Petersen,
Matthew Wilcox (Oracle), Mika Westerberg, Mike Rapoport,
Miklos Szeredi, Namhyung Kim, Neal Cardwell, nic_swsd,
OGAWA Hirofumi, Olivia Mackall, Paolo Abeni, Paolo Bonzini,
Peter Huewe, Peter Zijlstra, Rafael J. Wysocki,
Sean Christopherson, Srinivas Kandagatla, Stefano Stabellini,
Steven Rostedt, Tejun Heo, Theodore Ts'o, Thomas Gleixner,
Tom Lendacky, Willem de Bruijn, x86, Yury Norov, amd-gfx, bpf,
cgroups, dri-devel, io-uring, kvm, linux-acpi, linux-block,
linux-crypto, linux-cxl, linux-efi, linux-ext4, linux-fsdevel,
linux-gpio, linux-i2c, linux-integrity, linux-mm, linux-nvme,
linux-pci, linux-perf-users, linux-scsi, linux-serial,
linux-trace-kernel, linux-usb, mptcp, netdev, usb-storage
On Wed, 19 Nov 2025 22:40:56 +0000 david.laight.linux@gmail.com wrote:
> I've had to trim the 124 maintainers/lists that get_maintainer.pl finds
> from 124 to under 100 to be able to send the cover letter.
> The individual patches only go to the addresses found for the associated files.
> That reduces the number of emails to a less unsane number.
Please split the networking (9?) patches out to a separate series.
It will help you with the CC list, and help us to get this applied..
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 00/44] Change a lot of min_t() that might mask high bits
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (44 preceding siblings ...)
2025-11-20 1:47 ` [PATCH 00/44] Change a lot of min_t() that might mask high bits Jakub Kicinski
@ 2025-11-20 9:38 ` Lorenzo Stoakes
2025-11-20 14:52 ` (subset) " Jens Axboe
2025-11-24 9:49 ` Herbert Xu
47 siblings, 0 replies; 109+ messages in thread
From: Lorenzo Stoakes @ 2025-11-20 9:38 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, Alan Stern, Alexander Viro, Alexei Starovoitov,
Andi Shyti, Andreas Dilger, Andrew Lunn, Andrew Morton,
Andrii Nakryiko, Andy Shevchenko, Ard Biesheuvel,
Arnaldo Carvalho de Melo, Bjorn Helgaas, Borislav Petkov,
Christian Brauner, Christian König, Christoph Hellwig,
Daniel Borkmann, Dan Williams, Dave Hansen, Dave Jiang,
David Ahern, David Hildenbrand, Davidlohr Bueso, David S. Miller,
Dennis Zhou, Eric Dumazet, Greg Kroah-Hartman, Herbert Xu,
Ingo Molnar, Jakub Kicinski, Jakub Sitnicki, James E.J. Bottomley,
Jarkko Sakkinen, Jason A. Donenfeld, Jens Axboe, Jiri Slaby,
Johannes Weiner, John Allen, Jonathan Cameron, Juergen Gross,
Kees Cook, KP Singh, Linus Walleij, Martin K. Petersen,
Matthew Wilcox (Oracle), Mika Westerberg, Mike Rapoport,
Miklos Szeredi, Namhyung Kim, Neal Cardwell, nic_swsd,
OGAWA Hirofumi, Olivia Mackall, Paolo Abeni, Paolo Bonzini,
Peter Huewe, Peter Zijlstra, Rafael J. Wysocki,
Sean Christopherson, Srinivas Kandagatla, Stefano Stabellini,
Steven Rostedt, Tejun Heo, Theodore Ts'o, Thomas Gleixner,
Tom Lendacky, Willem de Bruijn, x86, Yury Norov, amd-gfx, bpf,
cgroups, dri-devel, io-uring, kvm, linux-acpi, linux-block,
linux-crypto, linux-cxl, linux-efi, linux-ext4, linux-fsdevel,
linux-gpio, linux-i2c, linux-integrity, linux-mm, linux-nvme,
linux-pci, linux-perf-users, linux-scsi, linux-serial,
linux-trace-kernel, linux-usb, mptcp, netdev, usb-storage
On Wed, Nov 19, 2025 at 10:40:56PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> It in not uncommon for code to use min_t(uint, a, b) when one of a or b
> is 64bit and can have a value that is larger than 2^32;
> This is particularly prevelant with:
> uint_var = min_t(uint, uint_var, uint64_expression);
>
> Casts to u8 and u16 are very likely to discard significant bits.
>
> These can be detected at compile time by changing min_t(), for example:
> #define CHECK_SIZE(fn, type, val) \
> BUILD_BUG_ON_MSG(sizeof (val) > sizeof (type) && \
> !statically_true(((val) >> 8 * (sizeof (type) - 1)) < 256), \
> fn "() significant bits of '" #val "' may be discarded")
>
> #define min_t(type, x, y) ({ \
> CHECK_SIZE("min_t", type, x); \
> CHECK_SIZE("min_t", type, y); \
> __cmp_once(min, type, x, y); })
>
> (and similar changes to max_t() and clamp_t().)
Have we made sure that the introduction of these don't cause a combinatorial
explosion like previous min()/max() changes did?
>
> This shows up some real bugs, some unlikely bugs and some false positives.
> In most cases both arguments are unsigned type (just different ones)
> and min_t() can just be replaced by min().
>
> The patches are all independant and are most of the ones needed to
> get the x86-64 kernel I build to compile.
> I've not tried building an allyesconfig or allmodconfig kernel.
Well I have a beefy box at my disposal so tried thiese for you :)
Both allyesconfig & allmodconfig works fine for x86-64 (I tried both for good
measure)
> I've also not included the patch to minmax.h itself.
>
> I've tried to put the patches that actually fix things first.
> The last one is 0009.
>
> I gave up on fixing sched/fair.c - it is too broken for a single patch!
> The patch for net/ipv4/tcp.c is also absent because do_tcp_getsockopt()
> needs multiple/larger changes to make it 'sane'.
I guess this isn't broken per se there just retain min_t()/max_t() right?
>
> I've had to trim the 124 maintainers/lists that get_maintainer.pl finds
> from 124 to under 100 to be able to send the cover letter.
> The individual patches only go to the addresses found for the associated files.
> That reduces the number of emails to a less unsane number.
>
> David Laight (44):
> x86/asm/bitops: Change the return type of variable__ffs() to unsigned
> int
> ext4: Fix saturation of 64bit inode times for old filesystems
> perf: Fix branch stack callchain limit
> io_uring/net: Change some dubious min_t()
> ipc/msg: Fix saturation of percpu counts in msgctl_info()
> bpf: Verifier, remove some unusual uses of min_t() and max_t()
> net/core/flow_dissector: Fix cap of __skb_flow_dissect() return value.
> net: ethtool: Use min3() instead of nested min_t(u16,...)
> ipv6: __ip6_append_data() don't abuse max_t() casts
> x86/crypto: ctr_crypt() use min() instead of min_t()
> arch/x96/kvm: use min() instead of min_t()
> block: use min() instead of min_t()
> drivers/acpi: use min() instead of min_t()
> drivers/char/hw_random: use min3() instead of nested min_t()
> drivers/char/tpm: use min() instead of min_t()
> drivers/crypto/ccp: use min() instead of min_t()
> drivers/cxl: use min() instead of min_t()
> drivers/gpio: use min() instead of min_t()
> drivers/gpu/drm/amd: use min() instead of min_t()
> drivers/i2c/busses: use min() instead of min_t()
> drivers/net/ethernet/realtek: use min() instead of min_t()
> drivers/nvme: use min() instead of min_t()
> arch/x86/mm: use min() instead of min_t()
> drivers/nvmem: use min() instead of min_t()
> drivers/pci: use min() instead of min_t()
> drivers/scsi: use min() instead of min_t()
> drivers/tty/vt: use umin() instead of min_t(u16, ...) for row/col
> limits
> drivers/usb/storage: use min() instead of min_t()
> drivers/xen: use min() instead of min_t()
> fs: use min() or umin() instead of min_t()
> block: bvec.h: use min() instead of min_t()
> nodemask: use min() instead of min_t()
> ipc: use min() instead of min_t()
> bpf: use min() instead of min_t()
> bpf_trace: use min() instead of min_t()
> lib/bucket_locks: use min() instead of min_t()
> lib/crypto/mpi: use min() instead of min_t()
> lib/dynamic_queue_limits: use max() instead of max_t()
> mm: use min() instead of min_t()
> net: Don't pass bitfields to max_t()
> net/core: Change loop conditions so min() can be used
> net: use min() instead of min_t()
> net/netlink: Use umin() to avoid min_t(int, ...) discarding high bits
> net/mptcp: Change some dubious min_t(int, ...) to min()
>
> arch/x86/crypto/aesni-intel_glue.c | 3 +-
> arch/x86/include/asm/bitops.h | 18 +++++-------
> arch/x86/kvm/emulate.c | 3 +-
> arch/x86/kvm/lapic.c | 2 +-
> arch/x86/kvm/mmu/mmu.c | 2 +-
> arch/x86/mm/pat/set_memory.c | 12 ++++----
> block/blk-iocost.c | 6 ++--
> block/blk-settings.c | 2 +-
> block/partitions/efi.c | 3 +-
> drivers/acpi/property.c | 2 +-
> drivers/char/hw_random/core.c | 2 +-
> drivers/char/tpm/tpm1-cmd.c | 2 +-
> drivers/char/tpm/tpm_tis_core.c | 4 +--
> drivers/crypto/ccp/ccp-dev.c | 2 +-
> drivers/cxl/core/mbox.c | 2 +-
> drivers/gpio/gpiolib-acpi-core.c | 2 +-
> .../gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c | 4 +--
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +-
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
> drivers/i2c/busses/i2c-designware-master.c | 2 +-
> drivers/net/ethernet/realtek/r8169_main.c | 3 +-
> drivers/nvme/host/pci.c | 3 +-
> drivers/nvme/host/zns.c | 3 +-
> drivers/nvmem/core.c | 2 +-
> drivers/pci/probe.c | 3 +-
> drivers/scsi/hosts.c | 2 +-
> drivers/tty/vt/selection.c | 9 +++---
> drivers/usb/storage/protocol.c | 3 +-
> drivers/xen/grant-table.c | 2 +-
> fs/buffer.c | 2 +-
> fs/exec.c | 2 +-
> fs/ext4/ext4.h | 2 +-
> fs/ext4/mballoc.c | 3 +-
> fs/ext4/resize.c | 2 +-
> fs/ext4/super.c | 2 +-
> fs/fat/dir.c | 4 +--
> fs/fat/file.c | 3 +-
> fs/fuse/dev.c | 2 +-
> fs/fuse/file.c | 8 ++---
> fs/splice.c | 2 +-
> include/linux/bvec.h | 3 +-
> include/linux/nodemask.h | 9 +++---
> include/linux/perf_event.h | 2 +-
> include/net/tcp_ecn.h | 5 ++--
> io_uring/net.c | 6 ++--
> ipc/mqueue.c | 4 +--
> ipc/msg.c | 6 ++--
> kernel/bpf/core.c | 4 +--
> kernel/bpf/log.c | 2 +-
> kernel/bpf/verifier.c | 29 +++++++------------
> kernel/trace/bpf_trace.c | 2 +-
> lib/bucket_locks.c | 2 +-
> lib/crypto/mpi/mpicoder.c | 2 +-
> lib/dynamic_queue_limits.c | 2 +-
> mm/gup.c | 4 +--
> mm/memblock.c | 2 +-
> mm/memory.c | 2 +-
> mm/percpu.c | 2 +-
> mm/truncate.c | 3 +-
> mm/vmscan.c | 2 +-
> net/core/datagram.c | 6 ++--
> net/core/flow_dissector.c | 7 ++---
> net/core/net-sysfs.c | 3 +-
> net/core/skmsg.c | 4 +--
> net/ethtool/cmis_cdb.c | 7 ++---
> net/ipv4/fib_trie.c | 2 +-
> net/ipv4/tcp_input.c | 4 +--
> net/ipv4/tcp_output.c | 5 ++--
> net/ipv4/tcp_timer.c | 4 +--
> net/ipv6/addrconf.c | 8 ++---
> net/ipv6/ip6_output.c | 7 +++--
> net/ipv6/ndisc.c | 5 ++--
> net/mptcp/protocol.c | 8 ++---
> net/netlink/genetlink.c | 9 +++---
> net/packet/af_packet.c | 2 +-
> net/unix/af_unix.c | 4 +--
> 76 files changed, 141 insertions(+), 176 deletions(-)
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: (subset) [PATCH 00/44] Change a lot of min_t() that might mask high bits
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (45 preceding siblings ...)
2025-11-20 9:38 ` Lorenzo Stoakes
@ 2025-11-20 14:52 ` Jens Axboe
2025-11-24 9:49 ` Herbert Xu
47 siblings, 0 replies; 109+ messages in thread
From: Jens Axboe @ 2025-11-20 14:52 UTC (permalink / raw)
To: linux-kernel, david.laight.linux
Cc: Alan Stern, Alexander Viro, Alexei Starovoitov, Andi Shyti,
Andreas Dilger, Andrew Lunn, Andrew Morton, Andrii Nakryiko,
Andy Shevchenko, Ard Biesheuvel, Arnaldo Carvalho de Melo,
Bjorn Helgaas, Borislav Petkov, Christian Brauner,
Christian König, Christoph Hellwig, Daniel Borkmann,
Dan Williams, Dave Hansen, Dave Jiang, David Ahern,
Davidlohr Bueso, David S. Miller, Dennis Zhou, Eric Dumazet,
Greg Kroah-Hartman, Herbert Xu, Ingo Molnar, Jakub Kicinski,
Jakub Sitnicki, James E.J. Bottomley, Jarkko Sakkinen,
Jason A. Donenfeld, Jiri Slaby, Johannes Weiner, John Allen,
Jonathan Cameron, Juergen Gross, Kees Cook, KP Singh,
Linus Walleij, Martin K. Petersen, Matthew Wilcox (Oracle),
Mika Westerberg, Mike Rapoport, Miklos Szeredi, Namhyung Kim,
Neal Cardwell, nic_swsd, OGAWA Hirofumi, Olivia Mackall,
Paolo Abeni, Paolo Bonzini, Peter Huewe, Peter Zijlstra,
Rafael J. Wysocki, Sean Christopherson, Srinivas Kandagatla,
Stefano Stabellini, Steven Rostedt, Tejun Heo, Theodore Ts'o,
Thomas Gleixner, Tom Lendacky, Willem de Bruijn, x86, Yury Norov,
amd-gfx, bpf, cgroups, dri-devel, io-uring, kvm, linux-acpi,
linux-block, linux-crypto, linux-cxl, linux-efi, linux-ext4,
linux-fsdevel, linux-gpio, linux-i2c, linux-integrity, linux-mm,
linux-nvme, linux-pci, linux-perf-users, linux-scsi, linux-serial,
linux-trace-kernel, linux-usb, mptcp, netdev, usb-storage,
David Hildenbrand
On Wed, 19 Nov 2025 22:40:56 +0000, david.laight.linux@gmail.com wrote:
> It in not uncommon for code to use min_t(uint, a, b) when one of a or b
> is 64bit and can have a value that is larger than 2^32;
> This is particularly prevelant with:
> uint_var = min_t(uint, uint_var, uint64_expression);
>
> Casts to u8 and u16 are very likely to discard significant bits.
>
> [...]
Applied, thanks!
[12/44] block: use min() instead of min_t()
commit: 9420e720ad192c53c8d2803c5a2313b2d586adbd
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 109+ messages in thread* Re: [PATCH 00/44] Change a lot of min_t() that might mask high bits
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
` (46 preceding siblings ...)
2025-11-20 14:52 ` (subset) " Jens Axboe
@ 2025-11-24 9:49 ` Herbert Xu
47 siblings, 0 replies; 109+ messages in thread
From: Herbert Xu @ 2025-11-24 9:49 UTC (permalink / raw)
To: david.laight.linux
Cc: linux-kernel, Alan Stern, Alexander Viro, Alexei Starovoitov,
Andi Shyti, Andreas Dilger, Andrew Lunn, Andrew Morton,
Andrii Nakryiko, Andy Shevchenko, Ard Biesheuvel,
Arnaldo Carvalho de Melo, Bjorn Helgaas, Borislav Petkov,
Christian Brauner, Christian König, Christoph Hellwig,
Daniel Borkmann, Dan Williams, Dave Hansen, Dave Jiang,
David Ahern, David Hildenbrand, Davidlohr Bueso, David S. Miller,
Dennis Zhou, Eric Dumazet, Greg Kroah-Hartman, Ingo Molnar,
Jakub Kicinski, Jakub Sitnicki, James E.J. Bottomley,
Jarkko Sakkinen, Jason A. Donenfeld, Jens Axboe, Jiri Slaby,
Johannes Weiner, John Allen, Jonathan Cameron, Juergen Gross,
Kees Cook, KP Singh, Linus Walleij, Martin K. Petersen,
Matthew Wilcox (Oracle), Mika Westerberg, Mike Rapoport,
Miklos Szeredi, Namhyung Kim, Neal Cardwell, nic_swsd,
OGAWA Hirofumi, Olivia Mackall, Paolo Abeni, Paolo Bonzini,
Peter Huewe, Peter Zijlstra, Rafael J. Wysocki,
Sean Christopherson, Srinivas Kandagatla, Stefano Stabellini,
Steven Rostedt, Tejun Heo, Theodore Ts'o, Thomas Gleixner,
Tom Lendacky, Willem de Bruijn, x86, Yury Norov, amd-gfx, bpf,
cgroups, dri-devel, io-uring, kvm, linux-acpi, linux-block,
linux-crypto, linux-cxl, linux-efi, linux-ext4, linux-fsdevel,
linux-gpio, linux-i2c, linux-integrity, linux-mm, linux-nvme,
linux-pci, linux-perf-users, linux-scsi, linux-serial,
linux-trace-kernel, linux-usb, mptcp, netdev, usb-storage
On Wed, Nov 19, 2025 at 10:40:56PM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
>
> It in not uncommon for code to use min_t(uint, a, b) when one of a or b
> is 64bit and can have a value that is larger than 2^32;
> This is particularly prevelant with:
> uint_var = min_t(uint, uint_var, uint64_expression);
>
> Casts to u8 and u16 are very likely to discard significant bits.
>
> These can be detected at compile time by changing min_t(), for example:
> #define CHECK_SIZE(fn, type, val) \
> BUILD_BUG_ON_MSG(sizeof (val) > sizeof (type) && \
> !statically_true(((val) >> 8 * (sizeof (type) - 1)) < 256), \
> fn "() significant bits of '" #val "' may be discarded")
>
> #define min_t(type, x, y) ({ \
> CHECK_SIZE("min_t", type, x); \
> CHECK_SIZE("min_t", type, y); \
> __cmp_once(min, type, x, y); })
>
> (and similar changes to max_t() and clamp_t().)
>
> This shows up some real bugs, some unlikely bugs and some false positives.
> In most cases both arguments are unsigned type (just different ones)
> and min_t() can just be replaced by min().
>
> The patches are all independant and are most of the ones needed to
> get the x86-64 kernel I build to compile.
> I've not tried building an allyesconfig or allmodconfig kernel.
> I've also not included the patch to minmax.h itself.
>
> I've tried to put the patches that actually fix things first.
> The last one is 0009.
>
> I gave up on fixing sched/fair.c - it is too broken for a single patch!
> The patch for net/ipv4/tcp.c is also absent because do_tcp_getsockopt()
> needs multiple/larger changes to make it 'sane'.
>
> I've had to trim the 124 maintainers/lists that get_maintainer.pl finds
> from 124 to under 100 to be able to send the cover letter.
> The individual patches only go to the addresses found for the associated files.
> That reduces the number of emails to a less unsane number.
>
> David Laight (44):
> x86/asm/bitops: Change the return type of variable__ffs() to unsigned
> int
> ext4: Fix saturation of 64bit inode times for old filesystems
> perf: Fix branch stack callchain limit
> io_uring/net: Change some dubious min_t()
> ipc/msg: Fix saturation of percpu counts in msgctl_info()
> bpf: Verifier, remove some unusual uses of min_t() and max_t()
> net/core/flow_dissector: Fix cap of __skb_flow_dissect() return value.
> net: ethtool: Use min3() instead of nested min_t(u16,...)
> ipv6: __ip6_append_data() don't abuse max_t() casts
> x86/crypto: ctr_crypt() use min() instead of min_t()
> arch/x96/kvm: use min() instead of min_t()
> block: use min() instead of min_t()
> drivers/acpi: use min() instead of min_t()
> drivers/char/hw_random: use min3() instead of nested min_t()
> drivers/char/tpm: use min() instead of min_t()
> drivers/crypto/ccp: use min() instead of min_t()
> drivers/cxl: use min() instead of min_t()
> drivers/gpio: use min() instead of min_t()
> drivers/gpu/drm/amd: use min() instead of min_t()
> drivers/i2c/busses: use min() instead of min_t()
> drivers/net/ethernet/realtek: use min() instead of min_t()
> drivers/nvme: use min() instead of min_t()
> arch/x86/mm: use min() instead of min_t()
> drivers/nvmem: use min() instead of min_t()
> drivers/pci: use min() instead of min_t()
> drivers/scsi: use min() instead of min_t()
> drivers/tty/vt: use umin() instead of min_t(u16, ...) for row/col
> limits
> drivers/usb/storage: use min() instead of min_t()
> drivers/xen: use min() instead of min_t()
> fs: use min() or umin() instead of min_t()
> block: bvec.h: use min() instead of min_t()
> nodemask: use min() instead of min_t()
> ipc: use min() instead of min_t()
> bpf: use min() instead of min_t()
> bpf_trace: use min() instead of min_t()
> lib/bucket_locks: use min() instead of min_t()
> lib/crypto/mpi: use min() instead of min_t()
> lib/dynamic_queue_limits: use max() instead of max_t()
> mm: use min() instead of min_t()
> net: Don't pass bitfields to max_t()
> net/core: Change loop conditions so min() can be used
> net: use min() instead of min_t()
> net/netlink: Use umin() to avoid min_t(int, ...) discarding high bits
> net/mptcp: Change some dubious min_t(int, ...) to min()
>
> arch/x86/crypto/aesni-intel_glue.c | 3 +-
> arch/x86/include/asm/bitops.h | 18 +++++-------
> arch/x86/kvm/emulate.c | 3 +-
> arch/x86/kvm/lapic.c | 2 +-
> arch/x86/kvm/mmu/mmu.c | 2 +-
> arch/x86/mm/pat/set_memory.c | 12 ++++----
> block/blk-iocost.c | 6 ++--
> block/blk-settings.c | 2 +-
> block/partitions/efi.c | 3 +-
> drivers/acpi/property.c | 2 +-
> drivers/char/hw_random/core.c | 2 +-
> drivers/char/tpm/tpm1-cmd.c | 2 +-
> drivers/char/tpm/tpm_tis_core.c | 4 +--
> drivers/crypto/ccp/ccp-dev.c | 2 +-
> drivers/cxl/core/mbox.c | 2 +-
> drivers/gpio/gpiolib-acpi-core.c | 2 +-
> .../gpu/drm/amd/amdgpu/amdgpu_doorbell_mgr.c | 4 +--
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +-
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
> drivers/i2c/busses/i2c-designware-master.c | 2 +-
> drivers/net/ethernet/realtek/r8169_main.c | 3 +-
> drivers/nvme/host/pci.c | 3 +-
> drivers/nvme/host/zns.c | 3 +-
> drivers/nvmem/core.c | 2 +-
> drivers/pci/probe.c | 3 +-
> drivers/scsi/hosts.c | 2 +-
> drivers/tty/vt/selection.c | 9 +++---
> drivers/usb/storage/protocol.c | 3 +-
> drivers/xen/grant-table.c | 2 +-
> fs/buffer.c | 2 +-
> fs/exec.c | 2 +-
> fs/ext4/ext4.h | 2 +-
> fs/ext4/mballoc.c | 3 +-
> fs/ext4/resize.c | 2 +-
> fs/ext4/super.c | 2 +-
> fs/fat/dir.c | 4 +--
> fs/fat/file.c | 3 +-
> fs/fuse/dev.c | 2 +-
> fs/fuse/file.c | 8 ++---
> fs/splice.c | 2 +-
> include/linux/bvec.h | 3 +-
> include/linux/nodemask.h | 9 +++---
> include/linux/perf_event.h | 2 +-
> include/net/tcp_ecn.h | 5 ++--
> io_uring/net.c | 6 ++--
> ipc/mqueue.c | 4 +--
> ipc/msg.c | 6 ++--
> kernel/bpf/core.c | 4 +--
> kernel/bpf/log.c | 2 +-
> kernel/bpf/verifier.c | 29 +++++++------------
> kernel/trace/bpf_trace.c | 2 +-
> lib/bucket_locks.c | 2 +-
> lib/crypto/mpi/mpicoder.c | 2 +-
> lib/dynamic_queue_limits.c | 2 +-
> mm/gup.c | 4 +--
> mm/memblock.c | 2 +-
> mm/memory.c | 2 +-
> mm/percpu.c | 2 +-
> mm/truncate.c | 3 +-
> mm/vmscan.c | 2 +-
> net/core/datagram.c | 6 ++--
> net/core/flow_dissector.c | 7 ++---
> net/core/net-sysfs.c | 3 +-
> net/core/skmsg.c | 4 +--
> net/ethtool/cmis_cdb.c | 7 ++---
> net/ipv4/fib_trie.c | 2 +-
> net/ipv4/tcp_input.c | 4 +--
> net/ipv4/tcp_output.c | 5 ++--
> net/ipv4/tcp_timer.c | 4 +--
> net/ipv6/addrconf.c | 8 ++---
> net/ipv6/ip6_output.c | 7 +++--
> net/ipv6/ndisc.c | 5 ++--
> net/mptcp/protocol.c | 8 ++---
> net/netlink/genetlink.c | 9 +++---
> net/packet/af_packet.c | 2 +-
> net/unix/af_unix.c | 4 +--
> 76 files changed, 141 insertions(+), 176 deletions(-)
Patches 10,14,16,37 applied. Thanks.
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 109+ messages in thread