[PATCH] string: use min in sized_strscpy

Thorsten Blum posted 1 patch 4 weeks ago
lib/string.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
[PATCH] string: use min in sized_strscpy
Posted by Thorsten Blum 4 weeks ago
Use min() and drop the limit variable to simplify sized_strscpy().

Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
 lib/string.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/lib/string.c b/lib/string.c
index b632c71df1a5..1f9297e9776a 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/limits.h>
 #include <linux/linkage.h>
+#include <linux/minmax.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -125,11 +126,8 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
 	 * If src is unaligned, don't cross a page boundary,
 	 * since we don't know if the next page is mapped.
 	 */
-	if ((long)src & (sizeof(long) - 1)) {
-		size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
-		if (limit < max)
-			max = limit;
-	}
+	if ((long)src & (sizeof(long) - 1))
+		max = min(PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)), max);
 #else
 	/* If src or dest is unaligned, don't do word-at-a-time. */
 	if (((long) dest | (long) src) & (sizeof(long) - 1))
Re: [PATCH] string: use min in sized_strscpy
Posted by Andrew Morton 3 weeks, 2 days ago
On Thu, 14 May 2026 18:56:03 +0200 Thorsten Blum <thorsten.blum@linux.dev> wrote:

> Use min() and drop the limit variable to simplify sized_strscpy().

Why is this code so messy.   Never seen so many typecasts per inch.

> @@ -125,11 +126,8 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
>  	 * If src is unaligned, don't cross a page boundary,
>  	 * since we don't know if the next page is mapped.
>  	 */
> -	if ((long)src & (sizeof(long) - 1)) {
> -		size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
> -		if (limit < max)
> -			max = limit;
> -	}
> +	if ((long)src & (sizeof(long) - 1))

That looks like IS_ALIGNED()?

> +		max = min(PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)), max);

That looks like a dog's breakfast.

And a bit like ALIGN_DOWN.  Not quite, but I'm sure we have helpers for
whatever this is doing.

>  #else
>  	/* If src or dest is unaligned, don't do word-at-a-time. */
>  	if (((long) dest | (long) src) & (sizeof(long) - 1))

gargh.


Oh well, not your fault.  I'll grab the patch, thanks.
Re: [PATCH] string: use min in sized_strscpy
Posted by Andy Shevchenko 4 weeks ago
On Thu, May 14, 2026 at 7:56 PM Thorsten Blum <thorsten.blum@linux.dev> wrote:
>
> Use min() and drop the limit variable to simplify sized_strscpy().

...

> -       if ((long)src & (sizeof(long) - 1)) {
> -               size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
> -               if (limit < max)
> -                       max = limit;
> -       }
> +       if ((long)src & (sizeof(long) - 1))
> +               max = min(PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)), max);

Side note: Isn't simply
               max = min(PAGE_SIZE - offset_in_page(src), max);

? (One will need to include linux/mm.h for this, though.)

Moreover there are plenty of duplications to count the size in the
first page and even the similar min() as in
  fs/iomap/buffered-io.c:869
  arch/s390/kvm/gaccess.c:976
and many more...

Perhaps a new macro with a good (famous last words!) naming?

-- 
With Best Regards,
Andy Shevchenko
Re: [PATCH] string: use min in sized_strscpy
Posted by Thorsten Blum 3 weeks, 6 days ago
On Fri, May 15, 2026 at 09:45:08AM +0300, Andy Shevchenko wrote:
> On Thu, May 14, 2026 at 7:56 PM Thorsten Blum <thorsten.blum@linux.dev> wrote:
> >
> > Use min() and drop the limit variable to simplify sized_strscpy().
> 
> ...
> 
> > -       if ((long)src & (sizeof(long) - 1)) {
> > -               size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
> > -               if (limit < max)
> > -                       max = limit;
> > -       }
> > +       if ((long)src & (sizeof(long) - 1))
> > +               max = min(PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)), max);
> 
> Side note: Isn't simply
>                max = min(PAGE_SIZE - offset_in_page(src), max);
> 
> ? (One will need to include linux/mm.h for this, though.)

I thought about it, but wasn't sure if pulling in all of linux/mm.h into
lib/string.c is worth it.

> Moreover there are plenty of duplications to count the size in the
> first page and even the similar min() as in
>   fs/iomap/buffered-io.c:869
>   arch/s390/kvm/gaccess.c:976
> and many more...
> 
> Perhaps a new macro with a good (famous last words!) naming?

How about adding

#define offset_in_page(p)	((unsigned long)(p) & ~PAGE_MASK)
#define bytes_to_page_end(p)	(PAGE_SIZE - offset_in_page(p))

to a new header, e.g. include/linux/page_helpers.h? There are about 50+
direct replacements and possibly more.
Re: [PATCH] string: use min in sized_strscpy
Posted by David Laight 3 weeks, 4 days ago
On Fri, 15 May 2026 17:09:02 +0200
Thorsten Blum <thorsten.blum@linux.dev> wrote:

> On Fri, May 15, 2026 at 09:45:08AM +0300, Andy Shevchenko wrote:
.
> How about adding
> 
> #define offset_in_page(p)	((unsigned long)(p) & ~PAGE_MASK)
> #define bytes_to_page_end(p)	(PAGE_SIZE - offset_in_page(p))
> 
> to a new header, e.g. include/linux/page_helpers.h? There are about 50+
> direct replacements and possibly more.
> 

Why not put them in vdso/page.h just after PAGE_MASK.

-- David
Re: [PATCH] string: use min in sized_strscpy
Posted by Andy Shevchenko 3 weeks, 5 days ago
On Fri, May 15, 2026 at 05:09:02PM +0200, Thorsten Blum wrote:
> On Fri, May 15, 2026 at 09:45:08AM +0300, Andy Shevchenko wrote:
> > On Thu, May 14, 2026 at 7:56 PM Thorsten Blum <thorsten.blum@linux.dev> wrote:

...

> > > -       if ((long)src & (sizeof(long) - 1)) {
> > > -               size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
> > > -               if (limit < max)
> > > -                       max = limit;
> > > -       }
> > > +       if ((long)src & (sizeof(long) - 1))
> > > +               max = min(PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)), max);
> > 
> > Side note: Isn't simply
> >                max = min(PAGE_SIZE - offset_in_page(src), max);
> > 
> > ? (One will need to include linux/mm.h for this, though.)
> 
> I thought about it, but wasn't sure if pulling in all of linux/mm.h into
> lib/string.c is worth it.
> 
> > Moreover there are plenty of duplications to count the size in the
> > first page and even the similar min() as in
> >   fs/iomap/buffered-io.c:869
> >   arch/s390/kvm/gaccess.c:976
> > and many more...
> > 
> > Perhaps a new macro with a good (famous last words!) naming?
> 
> How about adding
> 
> #define offset_in_page(p)	((unsigned long)(p) & ~PAGE_MASK)
> #define bytes_to_page_end(p)	(PAGE_SIZE - offset_in_page(p))
> 
> to a new header, e.g. include/linux/page_helpers.h? There are about 50+
> direct replacements and possibly more.

I checked existing linux/page*.h and have no better naming, so all looks
like a good idea to me. Because there are more (existing!) users of mm.h
just for offset_in_page().


-- 
With Best Regards,
Andy Shevchenko