LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 0/7] lib: rework bitmap_parse
@ 2019-05-01  1:06 Yury Norov
  2019-05-01  1:06 ` [PATCH 1/7] lib/string: add strnchrnul() Yury Norov
                   ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Yury Norov @ 2019-05-01  1:06 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Yury Norov, Jens Axboe, Steffen Klassert

On top of next-20190418.

Similarly to recently revisited bitmap_parselist() [1],
bitmap_parse() is ineffective and overcomplicated.  This
series reworks it, aligns its interface with bitmap_parselist()
and makes usage simpler.

The series also adds a test for the function and fixes usage of it
in cpumask_parse() according to new design - drops the calculating
of length of an input string.

The following users would also consider to drop the length argument,
if possible:
drivers/block/drbd/drbd_main.c:2608
kernel/padata.c:924
net/core/net-sysfs.c:726
net/core/net-sysfs.c:1309
net/core/net-sysfs.c:1391

bitmap_parse() takes the array of numbers to be put into the map in
the BE order which is reversed to the natural LE order for bitmaps.
For example, to construct bitmap containing a bit on the position 42,
we have to put a line '400,0'. Current implementation reads chunk
one by one from the beginning ('400' before '0') and makes bitmap
shift after each successful parse. It makes the complexity of the
whole process as O(n^2). We can do it in reverse direction ('0'
before '400') and avoid shifting, but it requires reverse parsing
helpers.

Tested on arm64 and BE mips.

v1: https://lkml.org/lkml/2019/4/27/597
v2:
 - strnchrnul() signature and description changed, ifdeffery and
   exporting removed;
 - test split for better demonstration of before/after changes;
 - minor naming and formatting issues fixed.

[1] https://lkml.org/lkml/2019/4/16/66

Yury Norov (7):
  lib/string: add strnchrnul()
  bitops: more BITS_TO_* macros
  lib: add test for bitmap_parse()
  lib: make bitmap_parse_user a wrapper on bitmap_parse
  lib: rework bitmap_parse()
  lib: new testcases for bitmap_parse{_user}
  cpumask: don't calculate length of the input string

 include/linux/bitmap.h       |   8 +-
 include/linux/bitops.h       |   5 +-
 include/linux/cpumask.h      |   4 +-
 include/linux/string.h       |   1 +
 lib/bitmap.c                 | 197 +++++++++++++++++------------------
 lib/string.c                 |  17 +++
 lib/test_bitmap.c            | 102 +++++++++++++++++-
 tools/include/linux/bitops.h |   9 +-
 8 files changed, 226 insertions(+), 117 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/7] lib/string: add strnchrnul()
  2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
@ 2019-05-01  1:06 ` Yury Norov
  2019-05-08  8:47   ` Andy Shevchenko
  2019-05-01  1:06 ` [PATCH 2/7] bitops: more BITS_TO_* macros Yury Norov
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Yury Norov @ 2019-05-01  1:06 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Yury Norov, Jens Axboe, Steffen Klassert

New function works like strchrnul() with a length limited strings.

Signed-off-by: Yury Norov <ynorov@marvell.com>
---
 include/linux/string.h |  1 +
 lib/string.c           | 17 +++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index 4deb11f7976b..ae934d6c50bf 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -62,6 +62,7 @@ extern char * strchr(const char *,int);
 #ifndef __HAVE_ARCH_STRCHRNUL
 extern char * strchrnul(const char *,int);
 #endif
+extern char * strnchrnul(const char *, size_t, int);
 #ifndef __HAVE_ARCH_STRNCHR
 extern char * strnchr(const char *, size_t, int);
 #endif
diff --git a/lib/string.c b/lib/string.c
index 6016eb3ac73d..eee521ad1f40 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -429,6 +429,23 @@ char *strchrnul(const char *s, int c)
 EXPORT_SYMBOL(strchrnul);
 #endif
 
+/**
+ * strnchrnul - Find and return a character in a length limited string,
+ * or end of string
+ * @s: The string to be searched
+ * @count: The number of characters to be searched
+ * @c: The character to search for
+ *
+ * Returns pointer to the first occurrence of 'c' in s. If c is not found,
+ * then return a pointer to the last character of the string.
+ */
+char *strnchrnul(const char *s, size_t count, int c)
+{
+	while (count-- && *s && *s != (char)c)
+		s++;
+	return (char *)s;
+}
+
 #ifndef __HAVE_ARCH_STRRCHR
 /**
  * strrchr - Find the last occurrence of a character in a string
-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 2/7] bitops: more BITS_TO_* macros
  2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
  2019-05-01  1:06 ` [PATCH 1/7] lib/string: add strnchrnul() Yury Norov
@ 2019-05-01  1:06 ` Yury Norov
  2019-05-08  8:47   ` Andy Shevchenko
  2019-05-01  1:06 ` [PATCH 3/7] lib: add test for bitmap_parse() Yury Norov
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Yury Norov @ 2019-05-01  1:06 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Yury Norov, Jens Axboe, Steffen Klassert

Introduce BITS_TO_U64, BITS_TO_U32 and BITS_TO_BYTES as they are handy
in the following patches (BITS_TO_U32 specifically). Reimplement tools/
version of the macros according to the kernel implementation.

Also fix indentation for BITS_PER_TYPE definition.

Signed-off-by: Yury Norov <ynorov@marvell.com>
---
 include/linux/bitops.h       | 5 ++++-
 tools/include/linux/bitops.h | 9 +++++----
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index cf074bce3eb3..e61c4e614264 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -4,8 +4,11 @@
 #include <asm/types.h>
 #include <linux/bits.h>
 
-#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
 #define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
+#define BITS_TO_U64(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
+#define BITS_TO_U32(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
+#define BITS_TO_BYTES(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
 
 extern unsigned int __sw_hweight8(unsigned int w);
 extern unsigned int __sw_hweight16(unsigned int w);
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
index 0b0ef3abc966..a8ba37a50d08 100644
--- a/tools/include/linux/bitops.h
+++ b/tools/include/linux/bitops.h
@@ -13,10 +13,11 @@
 #include <linux/bits.h>
 #include <linux/compiler.h>
 
-#define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
-#define BITS_TO_U64(nr)		DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
-#define BITS_TO_U32(nr)		DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
-#define BITS_TO_BYTES(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE)
+#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
+#define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
+#define BITS_TO_U64(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
+#define BITS_TO_U32(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
+#define BITS_TO_BYTES(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
 
 extern unsigned int __sw_hweight8(unsigned int w);
 extern unsigned int __sw_hweight16(unsigned int w);
-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 3/7] lib: add test for bitmap_parse()
  2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
  2019-05-01  1:06 ` [PATCH 1/7] lib/string: add strnchrnul() Yury Norov
  2019-05-01  1:06 ` [PATCH 2/7] bitops: more BITS_TO_* macros Yury Norov
@ 2019-05-01  1:06 ` Yury Norov
  2019-05-08  8:47   ` Andy Shevchenko
  2019-05-01  1:06 ` [PATCH 4/7] lib: make bitmap_parse_user a wrapper on bitmap_parse Yury Norov
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Yury Norov @ 2019-05-01  1:06 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Yury Norov, Jens Axboe, Steffen Klassert

The test is derived from bitmap_parselist()
NO_LEN is reserved for use in following patches.

Signed-off-by: Yury Norov <ynorov@marvell.com>
---
 lib/test_bitmap.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 1 deletion(-)

diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c
index d3a501f2a81a..731e107d811a 100644
--- a/lib/test_bitmap.c
+++ b/lib/test_bitmap.c
@@ -205,7 +205,8 @@ static void __init test_copy(void)
 	expect_eq_pbl("0-108,128-1023", bmap2, 1024);
 }
 
-#define PARSE_TIME 0x1
+#define PARSE_TIME	0x1
+#define NO_LEN		0x2
 
 struct test_bitmap_parselist{
 	const int errno;
@@ -328,6 +329,85 @@ static void __init __test_bitmap_parselist(int is_user)
 	}
 }
 
+static const unsigned long parse_test[] __initconst = {
+	BITMAP_FROM_U64(0),
+	BITMAP_FROM_U64(1),
+	BITMAP_FROM_U64(0xdeadbeef),
+	BITMAP_FROM_U64(0x100000000ULL),
+};
+
+static const unsigned long parse_test2[] __initconst = {
+	BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xdeadbeef),
+	BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xbaadf00ddeadbeef),
+	BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0x0badf00ddeadbeef),
+};
+
+static const struct test_bitmap_parselist parse_tests[] __initconst = {
+	{0, "0",			&parse_test[0 * step], 32, 0},
+	{0, "1",			&parse_test[1 * step], 32, 0},
+	{0, "deadbeef",			&parse_test[2 * step], 32, 0},
+	{0, "1,0",			&parse_test[3 * step], 33, 0},
+
+	{0, "deadbeef,1,0",		&parse_test2[0 * 2 * step], 96, 0},
+	{0, "baadf00d,deadbeef,1,0",	&parse_test2[1 * 2 * step], 128, 0},
+	{0, "badf00d,deadbeef,1,0",	&parse_test2[2 * 2 * step], 124, 0},
+
+	{-EINVAL,    "goodfood,deadbeef,1,0",	NULL, 128, 0},
+	{-EOVERFLOW, "3,0",			NULL, 33, 0},
+	{-EOVERFLOW, "123badf00d,deadbeef,1,0",	NULL, 128, 0},
+	{-EOVERFLOW, "badf00d,deadbeef,1,0",	NULL, 90, 0},
+	{-EOVERFLOW, "fbadf00d,deadbeef,1,0",	NULL, 95, 0},
+	{-EOVERFLOW, "badf00d,deadbeef,1,0",	NULL, 100, 0},
+};
+
+static void __init __test_bitmap_parse(int is_user)
+{
+	int i;
+	int err;
+	ktime_t time;
+	DECLARE_BITMAP(bmap, 2048);
+	char *mode = is_user ? "_user"  : "";
+
+	for (i = 0; i < ARRAY_SIZE(parse_tests); i++) {
+		struct test_bitmap_parselist test = parse_tests[i];
+
+		if (is_user) {
+			size_t len = strlen(test.in);
+			mm_segment_t orig_fs = get_fs();
+
+			set_fs(KERNEL_DS);
+			time = ktime_get();
+			err = bitmap_parse_user(test.in, len, bmap, test.nbits);
+			time = ktime_get() - time;
+			set_fs(orig_fs);
+		} else {
+			size_t len = test.flags & NO_LEN ?
+				UINT_MAX : strlen(test.in);
+			time = ktime_get();
+			err = bitmap_parse(test.in, len, bmap, test.nbits);
+			time = ktime_get() - time;
+		}
+
+		if (err != test.errno) {
+			pr_err("parse%s: %d: input is %s, errno is %d, expected %d\n",
+					mode, i, test.in, err, test.errno);
+			continue;
+		}
+
+		if (!err && test.expected
+			 && !__bitmap_equal(bmap, test.expected, test.nbits)) {
+			pr_err("parse%s: %d: input is %s, result is 0x%lx, expected 0x%lx\n",
+					mode, i, test.in, bmap[0],
+					*test.expected);
+			continue;
+		}
+
+		if (test.flags & PARSE_TIME)
+			pr_err("parse%s: %d: input is '%s' OK, Time: %llu\n",
+					mode, i, test.in, time);
+	}
+}
+
 static void __init test_bitmap_parselist(void)
 {
 	__test_bitmap_parselist(0);
@@ -338,6 +418,16 @@ static void __init test_bitmap_parselist_user(void)
 	__test_bitmap_parselist(1);
 }
 
+static void __init test_bitmap_parse(void)
+{
+	__test_bitmap_parse(0);
+}
+
+static void __init test_bitmap_parse_user(void)
+{
+	__test_bitmap_parse(1);
+}
+
 #define EXP_BYTES	(sizeof(exp) * 8)
 
 static void __init test_bitmap_arr32(void)
@@ -409,6 +499,8 @@ static void __init selftest(void)
 	test_fill_set();
 	test_copy();
 	test_bitmap_arr32();
+	test_bitmap_parse();
+	test_bitmap_parse_user();
 	test_bitmap_parselist();
 	test_bitmap_parselist_user();
 	test_mem_optimisations();
-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 4/7] lib: make bitmap_parse_user a wrapper on bitmap_parse
  2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
                   ` (2 preceding siblings ...)
  2019-05-01  1:06 ` [PATCH 3/7] lib: add test for bitmap_parse() Yury Norov
@ 2019-05-01  1:06 ` Yury Norov
  2019-05-08  8:47   ` Andy Shevchenko
  2019-05-01  1:06 ` [PATCH 5/7] lib: rework bitmap_parse() Yury Norov
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Yury Norov @ 2019-05-01  1:06 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Yury Norov, Jens Axboe, Steffen Klassert

Currently we parse user data byte after byte which leads to
overcomplicating of parsing algorithm. There are no performance
critical users of bitmap_parse_user(), and so we can duplicate
user data to kernel buffer and simply call bitmap_parselist().
This rework lets us unify and simplify bitmap_parse() and
bitmap_parse_user(), which is done in the following patch.

Signed-off-by: Yury Norov <ynorov@marvell.com>
---
 lib/bitmap.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/lib/bitmap.c b/lib/bitmap.c
index f235434df87b..300732031fad 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -434,22 +434,22 @@ EXPORT_SYMBOL(__bitmap_parse);
  *    then it must be terminated with a \0.
  * @maskp: pointer to bitmap array that will contain result.
  * @nmaskbits: size of bitmap, in bits.
- *
- * Wrapper for __bitmap_parse(), providing it with user buffer.
- *
- * We cannot have this as an inline function in bitmap.h because it needs
- * linux/uaccess.h to get the access_ok() declaration and this causes
- * cyclic dependencies.
  */
 int bitmap_parse_user(const char __user *ubuf,
 			unsigned int ulen, unsigned long *maskp,
 			int nmaskbits)
 {
-	if (!access_ok(ubuf, ulen))
-		return -EFAULT;
-	return __bitmap_parse((const char __force *)ubuf,
-				ulen, 1, maskp, nmaskbits);
+	char *buf;
+	int ret;
 
+	buf = memdup_user_nul(ubuf, ulen);
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
+
+	ret = bitmap_parse(buf, ulen, maskp, nmaskbits);
+
+	kfree(buf);
+	return ret;
 }
 EXPORT_SYMBOL(bitmap_parse_user);
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 5/7] lib: rework bitmap_parse()
  2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
                   ` (3 preceding siblings ...)
  2019-05-01  1:06 ` [PATCH 4/7] lib: make bitmap_parse_user a wrapper on bitmap_parse Yury Norov
@ 2019-05-01  1:06 ` Yury Norov
  2019-05-08  8:46   ` Andy Shevchenko
  2019-05-01  1:06 ` [PATCH 6/7] lib: new testcases for bitmap_parse{_user} Yury Norov
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Yury Norov @ 2019-05-01  1:06 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Yury Norov, Jens Axboe, Steffen Klassert

bitmap_parse() is ineffective and full of opaque variables and opencoded
parts. It leads to hard understanding and usage of it. This rework
includes:
 - remove bitmap_shift_left() call from the cycle. Now it makes the
   complexity of the algorithm as O(nbits^2). In the suggested approach
   the input string is parsed in reverse direction, so no shifts needed;
 - relax requirement on a single comma and no white spaces between chunks.
   It is considered useful in scripting, and it aligns with
   bitmap_parselist();
 - split bitmap_parse() to small readable helpers;
 - make an explicit calculation of the end of input line at the
   beginning, so users of the bitmap_parse() won't bother doing this.

Signed-off-by: Yury Norov <ynorov@marvell.com>
---
 include/linux/bitmap.h |   8 +-
 lib/bitmap.c           | 179 ++++++++++++++++++++---------------------
 2 files changed, 88 insertions(+), 99 deletions(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index f58e97446abc..c3e84864cc33 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -172,7 +172,7 @@ bitmap_find_next_zero_area(unsigned long *map,
 					      align_mask, 0);
 }
 
-extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
+extern int bitmap_parse(const char *buf, unsigned int buflen,
 			unsigned long *dst, int nbits);
 extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
 			unsigned long *dst, int nbits);
@@ -408,12 +408,6 @@ static inline void bitmap_shift_left(unsigned long *dst, const unsigned long *sr
 		__bitmap_shift_left(dst, src, shift, nbits);
 }
 
-static inline int bitmap_parse(const char *buf, unsigned int buflen,
-			unsigned long *maskp, int nmaskbits)
-{
-	return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
-}
-
 /**
  * BITMAP_FROM_U64() - Represent u64 value in the format suitable for bitmap.
  * @n: u64 value
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 300732031fad..ebcf4700ebed 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -335,97 +335,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area_off);
  * second version by Paul Jackson, third by Joe Korty.
  */
 
-#define CHUNKSZ				32
-#define nbits_to_hold_value(val)	fls(val)
-#define BASEDEC 10		/* fancier cpuset lists input in decimal */
-
-/**
- * __bitmap_parse - convert an ASCII hex string into a bitmap.
- * @buf: pointer to buffer containing string.
- * @buflen: buffer size in bytes.  If string is smaller than this
- *    then it must be terminated with a \0.
- * @is_user: location of buffer, 0 indicates kernel space
- * @maskp: pointer to bitmap array that will contain result.
- * @nmaskbits: size of bitmap, in bits.
- *
- * Commas group hex digits into chunks.  Each chunk defines exactly 32
- * bits of the resultant bitmask.  No chunk may specify a value larger
- * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value
- * then leading 0-bits are prepended.  %-EINVAL is returned for illegal
- * characters and for grouping errors such as "1,,5", ",44", "," and "".
- * Leading and trailing whitespace accepted, but not embedded whitespace.
- */
-int __bitmap_parse(const char *buf, unsigned int buflen,
-		int is_user, unsigned long *maskp,
-		int nmaskbits)
-{
-	int c, old_c, totaldigits, ndigits, nchunks, nbits;
-	u32 chunk;
-	const char __user __force *ubuf = (const char __user __force *)buf;
-
-	bitmap_zero(maskp, nmaskbits);
-
-	nchunks = nbits = totaldigits = c = 0;
-	do {
-		chunk = 0;
-		ndigits = totaldigits;
-
-		/* Get the next chunk of the bitmap */
-		while (buflen) {
-			old_c = c;
-			if (is_user) {
-				if (__get_user(c, ubuf++))
-					return -EFAULT;
-			}
-			else
-				c = *buf++;
-			buflen--;
-			if (isspace(c))
-				continue;
-
-			/*
-			 * If the last character was a space and the current
-			 * character isn't '\0', we've got embedded whitespace.
-			 * This is a no-no, so throw an error.
-			 */
-			if (totaldigits && c && isspace(old_c))
-				return -EINVAL;
-
-			/* A '\0' or a ',' signal the end of the chunk */
-			if (c == '\0' || c == ',')
-				break;
-
-			if (!isxdigit(c))
-				return -EINVAL;
-
-			/*
-			 * Make sure there are at least 4 free bits in 'chunk'.
-			 * If not, this hexdigit will overflow 'chunk', so
-			 * throw an error.
-			 */
-			if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
-				return -EOVERFLOW;
-
-			chunk = (chunk << 4) | hex_to_bin(c);
-			totaldigits++;
-		}
-		if (ndigits == totaldigits)
-			return -EINVAL;
-		if (nchunks == 0 && chunk == 0)
-			continue;
-
-		__bitmap_shift_left(maskp, maskp, CHUNKSZ, nmaskbits);
-		*maskp |= chunk;
-		nchunks++;
-		nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
-		if (nbits > nmaskbits)
-			return -EOVERFLOW;
-	} while (buflen && c == ',');
-
-	return 0;
-}
-EXPORT_SYMBOL(__bitmap_parse);
-
 /**
  * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap
  *
@@ -446,7 +355,7 @@ int bitmap_parse_user(const char __user *ubuf,
 	if (IS_ERR(buf))
 		return PTR_ERR(buf);
 
-	ret = bitmap_parse(buf, ulen, maskp, nmaskbits);
+	ret = bitmap_parse(buf, UINT_MAX, maskp, nmaskbits);
 
 	kfree(buf);
 	return ret;
@@ -545,6 +454,11 @@ static inline bool end_of_region(char c)
 	return __end_of_region(c) || end_of_str(c);
 }
 
+static inline bool in_str(const char *start, const char *ptr)
+{
+	return start <= ptr;
+}
+
 /*
  * The format allows commas and whitespases at the beginning
  * of the region.
@@ -557,6 +471,14 @@ static const char *bitmap_find_region(const char *str)
 	return end_of_str(*str) ? NULL : str;
 }
 
+static const char *bitmap_find_region_reverse(const char *start, const char *end)
+{
+	while (in_str(start, end) && __end_of_region(*end))
+		end--;
+
+	return end;
+}
+
 static const char *bitmap_parse_region(const char *str, struct region *r)
 {
 	str = bitmap_getnum(str, &r->start);
@@ -680,6 +602,79 @@ int bitmap_parselist_user(const char __user *ubuf,
 }
 EXPORT_SYMBOL(bitmap_parselist_user);
 
+static const char *bitmap_get_x32_reverse(const char *start,
+					const char *end, u32 *num)
+{
+	u32 ret = 0;
+	int c, i;
+
+	if (hex_to_bin(*end) < 0)
+		return ERR_PTR(-EINVAL);
+
+	for (i = 0; i < 32; i += 4) {
+		c = hex_to_bin(*end--);
+		if (c < 0)
+			return ERR_PTR(-EINVAL);
+
+		ret |= c << i;
+
+		if (!in_str(start, end) || __end_of_region(*end))
+			goto out;
+	}
+
+	if (hex_to_bin(*end) >= 0)
+		return ERR_PTR(-EOVERFLOW);
+out:
+	*num = ret;
+	return end;
+}
+
+/**
+ * bitmap_parse - convert an ASCII hex string into a bitmap.
+ * @start: pointer to buffer containing string.
+ * @buflen: buffer size in bytes.  If string is smaller than this
+ *    then it must be terminated with a \0 or \n. In that case,
+ *    UINT_MAX may be provided instead of string length.
+ * @maskp: pointer to bitmap array that will contain result.
+ * @nmaskbits: size of bitmap, in bits.
+ *
+ * Commas group hex digits into chunks.  Each chunk defines exactly 32
+ * bits of the resultant bitmask.  No chunk may specify a value larger
+ * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value
+ * then leading 0-bits are prepended.  %-EINVAL is returned for illegal
+ * characters. Grouping such as "1,,5", ",44", "," or "" is allowed.
+ * Leading, embedded and trailing whitespace accepted.
+ */
+int bitmap_parse(const char *start, unsigned int buflen,
+		unsigned long *maskp, int nmaskbits)
+{
+	const char *end = strnchrnul(start, buflen, '\n') - 1;
+	int chunks = BITS_TO_U32(nmaskbits);
+	u32 *bitmap = (u32 *)maskp;
+	int unset_bit;
+
+	while (in_str(start, (end = bitmap_find_region_reverse(start, end)))) {
+		if (!chunks--)
+			return -EOVERFLOW;
+
+		end = bitmap_get_x32_reverse(start, end, bitmap++);
+		if (IS_ERR(end))
+			return PTR_ERR(end);
+	}
+
+	unset_bit = (BITS_TO_U32(nmaskbits) - chunks) * 32;
+	if (unset_bit < nmaskbits) {
+		bitmap_clear(maskp, unset_bit, nmaskbits);
+		return 0;
+	}
+
+	if (find_next_bit(maskp, unset_bit, nmaskbits) != unset_bit)
+		return -EOVERFLOW;
+
+	return 0;
+}
+EXPORT_SYMBOL(bitmap_parse);
+
 
 #ifdef CONFIG_NUMA
 /**
-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 6/7] lib: new testcases for bitmap_parse{_user}
  2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
                   ` (4 preceding siblings ...)
  2019-05-01  1:06 ` [PATCH 5/7] lib: rework bitmap_parse() Yury Norov
@ 2019-05-01  1:06 ` Yury Norov
  2019-05-08  8:47   ` Andy Shevchenko
  2019-05-01  1:06 ` [PATCH 7/7] cpumask: don't calculate length of the input string Yury Norov
  2019-05-07 21:04 ` [PATCH 0/7] lib: rework bitmap_parse Yury Norov
  7 siblings, 1 reply; 18+ messages in thread
From: Yury Norov @ 2019-05-01  1:06 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Yury Norov, Jens Axboe, Steffen Klassert

New version of bitmap_parse() is unified with bitmap_parse_list(),
and therefore:
 - weakens rules on whitespaces and commas between hex chunks;
 - in addition to \0 allows using \n as the line ending symbol;
 - allows passing UINT_MAX or any other big number as the length
   of input string instead of actual string length.

The patch covers the cases.

Signed-off-by: Yury Norov <ynorov@marvell.com>
---
 lib/test_bitmap.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c
index 731e107d811a..9e6b87895108 100644
--- a/lib/test_bitmap.c
+++ b/lib/test_bitmap.c
@@ -343,14 +343,22 @@ static const unsigned long parse_test2[] __initconst = {
 };
 
 static const struct test_bitmap_parselist parse_tests[] __initconst = {
+	{0, "",				&parse_test[0 * step], 32, 0},
+	{0, " ",			&parse_test[0 * step], 32, 0},
 	{0, "0",			&parse_test[0 * step], 32, 0},
+	{0, "0\n",			&parse_test[0 * step], 32, 0},
 	{0, "1",			&parse_test[1 * step], 32, 0},
 	{0, "deadbeef",			&parse_test[2 * step], 32, 0},
 	{0, "1,0",			&parse_test[3 * step], 33, 0},
+	{0, "deadbeef,\n,0,1",		&parse_test[2 * step], 96, 0},
 
 	{0, "deadbeef,1,0",		&parse_test2[0 * 2 * step], 96, 0},
 	{0, "baadf00d,deadbeef,1,0",	&parse_test2[1 * 2 * step], 128, 0},
 	{0, "badf00d,deadbeef,1,0",	&parse_test2[2 * 2 * step], 124, 0},
+	{0, "badf00d,deadbeef,1,0",	&parse_test2[2 * 2 * step], 124, NO_LEN},
+	{0, "  badf00d,deadbeef,1,0  ",	&parse_test2[2 * 2 * step], 124, 0},
+	{0, " , badf00d,deadbeef,1,0 , ",	&parse_test2[2 * 2 * step], 124, 0},
+	{0, " , badf00d, ,, ,,deadbeef,1,0 , ",	&parse_test2[2 * 2 * step], 124, 0},
 
 	{-EINVAL,    "goodfood,deadbeef,1,0",	NULL, 128, 0},
 	{-EOVERFLOW, "3,0",			NULL, 33, 0},
-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 7/7] cpumask: don't calculate length of the input string
  2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
                   ` (5 preceding siblings ...)
  2019-05-01  1:06 ` [PATCH 6/7] lib: new testcases for bitmap_parse{_user} Yury Norov
@ 2019-05-01  1:06 ` Yury Norov
  2019-05-08  8:48   ` Andy Shevchenko
  2019-05-07 21:04 ` [PATCH 0/7] lib: rework bitmap_parse Yury Norov
  7 siblings, 1 reply; 18+ messages in thread
From: Yury Norov @ 2019-05-01  1:06 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Yury Norov, Jens Axboe, Steffen Klassert

New design of inner bitmap_parse() allows to avoid
calculating the size of a null-terminated string.

Signed-off-by: Yury Norov <ynorov@marvell.com>
---
 include/linux/cpumask.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 21755471b1c3..d55d015edc58 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -633,9 +633,7 @@ static inline int cpumask_parselist_user(const char __user *buf, int len,
  */
 static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
 {
-	unsigned int len = strchrnul(buf, '\n') - buf;
-
-	return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
+	return bitmap_parse(buf, UINT_MAX, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 0/7] lib: rework bitmap_parse
  2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
                   ` (6 preceding siblings ...)
  2019-05-01  1:06 ` [PATCH 7/7] cpumask: don't calculate length of the input string Yury Norov
@ 2019-05-07 21:04 ` Yury Norov
  7 siblings, 0 replies; 18+ messages in thread
From: Yury Norov @ 2019-05-07 21:04 UTC (permalink / raw)
  To: Andrew Morton, Andy Shevchenko, Rasmus Villemoes,
	Dmitry Torokhov, David S . Miller, Stephen Rothwell,
	Amritha Nambiar, Willem de Bruijn, Kees Cook, Matthew Wilcox,
	Tobin C . Harding, Will Deacon, Miklos Szeredi, Vineet Gupta,
	Chris Wilson, Arnaldo Carvalho de Melo, linux-kernel
  Cc: Yury Norov, Jens Axboe, Steffen Klassert

On Tue, Apr 30, 2019 at 06:06:29PM -0700, Yury Norov wrote:
> On top of next-20190418.
> 
> Similarly to recently revisited bitmap_parselist() [1],
> bitmap_parse() is ineffective and overcomplicated.  This
> series reworks it, aligns its interface with bitmap_parselist()
> and makes usage simpler.
> 
> The series also adds a test for the function and fixes usage of it
> in cpumask_parse() according to new design - drops the calculating
> of length of an input string.
> 
> The following users would also consider to drop the length argument,
> if possible:
> drivers/block/drbd/drbd_main.c:2608
> kernel/padata.c:924
> net/core/net-sysfs.c:726
> net/core/net-sysfs.c:1309
> net/core/net-sysfs.c:1391
> 
> bitmap_parse() takes the array of numbers to be put into the map in
> the BE order which is reversed to the natural LE order for bitmaps.
> For example, to construct bitmap containing a bit on the position 42,
> we have to put a line '400,0'. Current implementation reads chunk
> one by one from the beginning ('400' before '0') and makes bitmap
> shift after each successful parse. It makes the complexity of the
> whole process as O(n^2). We can do it in reverse direction ('0'
> before '400') and avoid shifting, but it requires reverse parsing
> helpers.
> 
> Tested on arm64 and BE mips.

Any comments?

> v1: https://lkml.org/lkml/2019/4/27/597
> v2:
>  - strnchrnul() signature and description changed, ifdeffery and
>    exporting removed;
>  - test split for better demonstration of before/after changes;
>  - minor naming and formatting issues fixed.
> 
> [1] https://lkml.org/lkml/2019/4/16/66
> 
> Yury Norov (7):
>   lib/string: add strnchrnul()
>   bitops: more BITS_TO_* macros
>   lib: add test for bitmap_parse()
>   lib: make bitmap_parse_user a wrapper on bitmap_parse
>   lib: rework bitmap_parse()
>   lib: new testcases for bitmap_parse{_user}
>   cpumask: don't calculate length of the input string
> 
>  include/linux/bitmap.h       |   8 +-
>  include/linux/bitops.h       |   5 +-
>  include/linux/cpumask.h      |   4 +-
>  include/linux/string.h       |   1 +
>  lib/bitmap.c                 | 197 +++++++++++++++++------------------
>  lib/string.c                 |  17 +++
>  lib/test_bitmap.c            | 102 +++++++++++++++++-
>  tools/include/linux/bitops.h |   9 +-
>  8 files changed, 226 insertions(+), 117 deletions(-)
> 
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/7] lib: rework bitmap_parse()
  2019-05-01  1:06 ` [PATCH 5/7] lib: rework bitmap_parse() Yury Norov
@ 2019-05-08  8:46   ` Andy Shevchenko
  2019-05-10  2:26     ` Yury Norov
  0 siblings, 1 reply; 18+ messages in thread
From: Andy Shevchenko @ 2019-05-08  8:46 UTC (permalink / raw)
  To: Yury Norov
  Cc: Andrew Morton, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

On Tue, Apr 30, 2019 at 06:06:34PM -0700, Yury Norov wrote:
> bitmap_parse() is ineffective and full of opaque variables and opencoded
> parts. It leads to hard understanding and usage of it. This rework
> includes:
>  - remove bitmap_shift_left() call from the cycle. Now it makes the
>    complexity of the algorithm as O(nbits^2). In the suggested approach
>    the input string is parsed in reverse direction, so no shifts needed;
>  - relax requirement on a single comma and no white spaces between chunks.
>    It is considered useful in scripting, and it aligns with
>    bitmap_parselist();
>  - split bitmap_parse() to small readable helpers;
>  - make an explicit calculation of the end of input line at the
>    beginning, so users of the bitmap_parse() won't bother doing this.

> +static inline bool in_str(const char *start, const char *ptr)
> +{
> +	return start <= ptr;
> +}
> +

The explicit use of the conditional is better.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/7] lib/string: add strnchrnul()
  2019-05-01  1:06 ` [PATCH 1/7] lib/string: add strnchrnul() Yury Norov
@ 2019-05-08  8:47   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2019-05-08  8:47 UTC (permalink / raw)
  To: Yury Norov
  Cc: Andrew Morton, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

On Tue, Apr 30, 2019 at 06:06:30PM -0700, Yury Norov wrote:
> New function works like strchrnul() with a length limited strings.
> 

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Yury Norov <ynorov@marvell.com>
> ---
>  include/linux/string.h |  1 +
>  lib/string.c           | 17 +++++++++++++++++
>  2 files changed, 18 insertions(+)
> 
> diff --git a/include/linux/string.h b/include/linux/string.h
> index 4deb11f7976b..ae934d6c50bf 100644
> --- a/include/linux/string.h
> +++ b/include/linux/string.h
> @@ -62,6 +62,7 @@ extern char * strchr(const char *,int);
>  #ifndef __HAVE_ARCH_STRCHRNUL
>  extern char * strchrnul(const char *,int);
>  #endif
> +extern char * strnchrnul(const char *, size_t, int);
>  #ifndef __HAVE_ARCH_STRNCHR
>  extern char * strnchr(const char *, size_t, int);
>  #endif
> diff --git a/lib/string.c b/lib/string.c
> index 6016eb3ac73d..eee521ad1f40 100644
> --- a/lib/string.c
> +++ b/lib/string.c
> @@ -429,6 +429,23 @@ char *strchrnul(const char *s, int c)
>  EXPORT_SYMBOL(strchrnul);
>  #endif
>  
> +/**
> + * strnchrnul - Find and return a character in a length limited string,
> + * or end of string
> + * @s: The string to be searched
> + * @count: The number of characters to be searched
> + * @c: The character to search for
> + *
> + * Returns pointer to the first occurrence of 'c' in s. If c is not found,
> + * then return a pointer to the last character of the string.
> + */
> +char *strnchrnul(const char *s, size_t count, int c)
> +{
> +	while (count-- && *s && *s != (char)c)
> +		s++;
> +	return (char *)s;
> +}
> +
>  #ifndef __HAVE_ARCH_STRRCHR
>  /**
>   * strrchr - Find the last occurrence of a character in a string
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/7] bitops: more BITS_TO_* macros
  2019-05-01  1:06 ` [PATCH 2/7] bitops: more BITS_TO_* macros Yury Norov
@ 2019-05-08  8:47   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2019-05-08  8:47 UTC (permalink / raw)
  To: Yury Norov
  Cc: Andrew Morton, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

On Tue, Apr 30, 2019 at 06:06:31PM -0700, Yury Norov wrote:
> Introduce BITS_TO_U64, BITS_TO_U32 and BITS_TO_BYTES as they are handy
> in the following patches (BITS_TO_U32 specifically). Reimplement tools/
> version of the macros according to the kernel implementation.
> 
> Also fix indentation for BITS_PER_TYPE definition.
> 

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Yury Norov <ynorov@marvell.com>
> ---
>  include/linux/bitops.h       | 5 ++++-
>  tools/include/linux/bitops.h | 9 +++++----
>  2 files changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/bitops.h b/include/linux/bitops.h
> index cf074bce3eb3..e61c4e614264 100644
> --- a/include/linux/bitops.h
> +++ b/include/linux/bitops.h
> @@ -4,8 +4,11 @@
>  #include <asm/types.h>
>  #include <linux/bits.h>
>  
> -#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
> +#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
>  #define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
> +#define BITS_TO_U64(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
> +#define BITS_TO_U32(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
> +#define BITS_TO_BYTES(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
>  
>  extern unsigned int __sw_hweight8(unsigned int w);
>  extern unsigned int __sw_hweight16(unsigned int w);
> diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
> index 0b0ef3abc966..a8ba37a50d08 100644
> --- a/tools/include/linux/bitops.h
> +++ b/tools/include/linux/bitops.h
> @@ -13,10 +13,11 @@
>  #include <linux/bits.h>
>  #include <linux/compiler.h>
>  
> -#define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
> -#define BITS_TO_U64(nr)		DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
> -#define BITS_TO_U32(nr)		DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
> -#define BITS_TO_BYTES(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE)
> +#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
> +#define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
> +#define BITS_TO_U64(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
> +#define BITS_TO_U32(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
> +#define BITS_TO_BYTES(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
>  
>  extern unsigned int __sw_hweight8(unsigned int w);
>  extern unsigned int __sw_hweight16(unsigned int w);
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/7] lib: add test for bitmap_parse()
  2019-05-01  1:06 ` [PATCH 3/7] lib: add test for bitmap_parse() Yury Norov
@ 2019-05-08  8:47   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2019-05-08  8:47 UTC (permalink / raw)
  To: Yury Norov
  Cc: Andrew Morton, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

On Tue, Apr 30, 2019 at 06:06:32PM -0700, Yury Norov wrote:
> The test is derived from bitmap_parselist()
> NO_LEN is reserved for use in following patches.
> 

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Yury Norov <ynorov@marvell.com>
> ---
>  lib/test_bitmap.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 93 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c
> index d3a501f2a81a..731e107d811a 100644
> --- a/lib/test_bitmap.c
> +++ b/lib/test_bitmap.c
> @@ -205,7 +205,8 @@ static void __init test_copy(void)
>  	expect_eq_pbl("0-108,128-1023", bmap2, 1024);
>  }
>  
> -#define PARSE_TIME 0x1
> +#define PARSE_TIME	0x1
> +#define NO_LEN		0x2
>  
>  struct test_bitmap_parselist{
>  	const int errno;
> @@ -328,6 +329,85 @@ static void __init __test_bitmap_parselist(int is_user)
>  	}
>  }
>  
> +static const unsigned long parse_test[] __initconst = {
> +	BITMAP_FROM_U64(0),
> +	BITMAP_FROM_U64(1),
> +	BITMAP_FROM_U64(0xdeadbeef),
> +	BITMAP_FROM_U64(0x100000000ULL),
> +};
> +
> +static const unsigned long parse_test2[] __initconst = {
> +	BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xdeadbeef),
> +	BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xbaadf00ddeadbeef),
> +	BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0x0badf00ddeadbeef),
> +};
> +
> +static const struct test_bitmap_parselist parse_tests[] __initconst = {
> +	{0, "0",			&parse_test[0 * step], 32, 0},
> +	{0, "1",			&parse_test[1 * step], 32, 0},
> +	{0, "deadbeef",			&parse_test[2 * step], 32, 0},
> +	{0, "1,0",			&parse_test[3 * step], 33, 0},
> +
> +	{0, "deadbeef,1,0",		&parse_test2[0 * 2 * step], 96, 0},
> +	{0, "baadf00d,deadbeef,1,0",	&parse_test2[1 * 2 * step], 128, 0},
> +	{0, "badf00d,deadbeef,1,0",	&parse_test2[2 * 2 * step], 124, 0},
> +
> +	{-EINVAL,    "goodfood,deadbeef,1,0",	NULL, 128, 0},
> +	{-EOVERFLOW, "3,0",			NULL, 33, 0},
> +	{-EOVERFLOW, "123badf00d,deadbeef,1,0",	NULL, 128, 0},
> +	{-EOVERFLOW, "badf00d,deadbeef,1,0",	NULL, 90, 0},
> +	{-EOVERFLOW, "fbadf00d,deadbeef,1,0",	NULL, 95, 0},
> +	{-EOVERFLOW, "badf00d,deadbeef,1,0",	NULL, 100, 0},
> +};
> +
> +static void __init __test_bitmap_parse(int is_user)
> +{
> +	int i;
> +	int err;
> +	ktime_t time;
> +	DECLARE_BITMAP(bmap, 2048);
> +	char *mode = is_user ? "_user"  : "";
> +
> +	for (i = 0; i < ARRAY_SIZE(parse_tests); i++) {
> +		struct test_bitmap_parselist test = parse_tests[i];
> +
> +		if (is_user) {
> +			size_t len = strlen(test.in);
> +			mm_segment_t orig_fs = get_fs();
> +
> +			set_fs(KERNEL_DS);
> +			time = ktime_get();
> +			err = bitmap_parse_user(test.in, len, bmap, test.nbits);
> +			time = ktime_get() - time;
> +			set_fs(orig_fs);
> +		} else {
> +			size_t len = test.flags & NO_LEN ?
> +				UINT_MAX : strlen(test.in);
> +			time = ktime_get();
> +			err = bitmap_parse(test.in, len, bmap, test.nbits);
> +			time = ktime_get() - time;
> +		}
> +
> +		if (err != test.errno) {
> +			pr_err("parse%s: %d: input is %s, errno is %d, expected %d\n",
> +					mode, i, test.in, err, test.errno);
> +			continue;
> +		}
> +
> +		if (!err && test.expected
> +			 && !__bitmap_equal(bmap, test.expected, test.nbits)) {
> +			pr_err("parse%s: %d: input is %s, result is 0x%lx, expected 0x%lx\n",
> +					mode, i, test.in, bmap[0],
> +					*test.expected);
> +			continue;
> +		}
> +
> +		if (test.flags & PARSE_TIME)
> +			pr_err("parse%s: %d: input is '%s' OK, Time: %llu\n",
> +					mode, i, test.in, time);
> +	}
> +}
> +
>  static void __init test_bitmap_parselist(void)
>  {
>  	__test_bitmap_parselist(0);
> @@ -338,6 +418,16 @@ static void __init test_bitmap_parselist_user(void)
>  	__test_bitmap_parselist(1);
>  }
>  
> +static void __init test_bitmap_parse(void)
> +{
> +	__test_bitmap_parse(0);
> +}
> +
> +static void __init test_bitmap_parse_user(void)
> +{
> +	__test_bitmap_parse(1);
> +}
> +
>  #define EXP_BYTES	(sizeof(exp) * 8)
>  
>  static void __init test_bitmap_arr32(void)
> @@ -409,6 +499,8 @@ static void __init selftest(void)
>  	test_fill_set();
>  	test_copy();
>  	test_bitmap_arr32();
> +	test_bitmap_parse();
> +	test_bitmap_parse_user();
>  	test_bitmap_parselist();
>  	test_bitmap_parselist_user();
>  	test_mem_optimisations();
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/7] lib: make bitmap_parse_user a wrapper on bitmap_parse
  2019-05-01  1:06 ` [PATCH 4/7] lib: make bitmap_parse_user a wrapper on bitmap_parse Yury Norov
@ 2019-05-08  8:47   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2019-05-08  8:47 UTC (permalink / raw)
  To: Yury Norov
  Cc: Andrew Morton, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

On Tue, Apr 30, 2019 at 06:06:33PM -0700, Yury Norov wrote:
> Currently we parse user data byte after byte which leads to
> overcomplicating of parsing algorithm. There are no performance
> critical users of bitmap_parse_user(), and so we can duplicate
> user data to kernel buffer and simply call bitmap_parselist().
> This rework lets us unify and simplify bitmap_parse() and
> bitmap_parse_user(), which is done in the following patch.
> 

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Yury Norov <ynorov@marvell.com>
> ---
>  lib/bitmap.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/lib/bitmap.c b/lib/bitmap.c
> index f235434df87b..300732031fad 100644
> --- a/lib/bitmap.c
> +++ b/lib/bitmap.c
> @@ -434,22 +434,22 @@ EXPORT_SYMBOL(__bitmap_parse);
>   *    then it must be terminated with a \0.
>   * @maskp: pointer to bitmap array that will contain result.
>   * @nmaskbits: size of bitmap, in bits.
> - *
> - * Wrapper for __bitmap_parse(), providing it with user buffer.
> - *
> - * We cannot have this as an inline function in bitmap.h because it needs
> - * linux/uaccess.h to get the access_ok() declaration and this causes
> - * cyclic dependencies.
>   */
>  int bitmap_parse_user(const char __user *ubuf,
>  			unsigned int ulen, unsigned long *maskp,
>  			int nmaskbits)
>  {
> -	if (!access_ok(ubuf, ulen))
> -		return -EFAULT;
> -	return __bitmap_parse((const char __force *)ubuf,
> -				ulen, 1, maskp, nmaskbits);
> +	char *buf;
> +	int ret;
>  
> +	buf = memdup_user_nul(ubuf, ulen);
> +	if (IS_ERR(buf))
> +		return PTR_ERR(buf);
> +
> +	ret = bitmap_parse(buf, ulen, maskp, nmaskbits);
> +
> +	kfree(buf);
> +	return ret;
>  }
>  EXPORT_SYMBOL(bitmap_parse_user);
>  
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 6/7] lib: new testcases for bitmap_parse{_user}
  2019-05-01  1:06 ` [PATCH 6/7] lib: new testcases for bitmap_parse{_user} Yury Norov
@ 2019-05-08  8:47   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2019-05-08  8:47 UTC (permalink / raw)
  To: Yury Norov
  Cc: Andrew Morton, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

On Tue, Apr 30, 2019 at 06:06:35PM -0700, Yury Norov wrote:
> New version of bitmap_parse() is unified with bitmap_parse_list(),
> and therefore:
>  - weakens rules on whitespaces and commas between hex chunks;
>  - in addition to \0 allows using \n as the line ending symbol;
>  - allows passing UINT_MAX or any other big number as the length
>    of input string instead of actual string length.
> 
> The patch covers the cases.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> 
> Signed-off-by: Yury Norov <ynorov@marvell.com>
> ---
>  lib/test_bitmap.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c
> index 731e107d811a..9e6b87895108 100644
> --- a/lib/test_bitmap.c
> +++ b/lib/test_bitmap.c
> @@ -343,14 +343,22 @@ static const unsigned long parse_test2[] __initconst = {
>  };
>  
>  static const struct test_bitmap_parselist parse_tests[] __initconst = {
> +	{0, "",				&parse_test[0 * step], 32, 0},
> +	{0, " ",			&parse_test[0 * step], 32, 0},
>  	{0, "0",			&parse_test[0 * step], 32, 0},
> +	{0, "0\n",			&parse_test[0 * step], 32, 0},
>  	{0, "1",			&parse_test[1 * step], 32, 0},
>  	{0, "deadbeef",			&parse_test[2 * step], 32, 0},
>  	{0, "1,0",			&parse_test[3 * step], 33, 0},
> +	{0, "deadbeef,\n,0,1",		&parse_test[2 * step], 96, 0},
>  
>  	{0, "deadbeef,1,0",		&parse_test2[0 * 2 * step], 96, 0},
>  	{0, "baadf00d,deadbeef,1,0",	&parse_test2[1 * 2 * step], 128, 0},
>  	{0, "badf00d,deadbeef,1,0",	&parse_test2[2 * 2 * step], 124, 0},
> +	{0, "badf00d,deadbeef,1,0",	&parse_test2[2 * 2 * step], 124, NO_LEN},
> +	{0, "  badf00d,deadbeef,1,0  ",	&parse_test2[2 * 2 * step], 124, 0},
> +	{0, " , badf00d,deadbeef,1,0 , ",	&parse_test2[2 * 2 * step], 124, 0},
> +	{0, " , badf00d, ,, ,,deadbeef,1,0 , ",	&parse_test2[2 * 2 * step], 124, 0},
>  
>  	{-EINVAL,    "goodfood,deadbeef,1,0",	NULL, 128, 0},
>  	{-EOVERFLOW, "3,0",			NULL, 33, 0},
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 7/7] cpumask: don't calculate length of the input string
  2019-05-01  1:06 ` [PATCH 7/7] cpumask: don't calculate length of the input string Yury Norov
@ 2019-05-08  8:48   ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2019-05-08  8:48 UTC (permalink / raw)
  To: Yury Norov
  Cc: Andrew Morton, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

On Tue, Apr 30, 2019 at 06:06:36PM -0700, Yury Norov wrote:
> New design of inner bitmap_parse() allows to avoid
> calculating the size of a null-terminated string.
> 

FWIW,
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Yury Norov <ynorov@marvell.com>
> ---
>  include/linux/cpumask.h | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
> index 21755471b1c3..d55d015edc58 100644
> --- a/include/linux/cpumask.h
> +++ b/include/linux/cpumask.h
> @@ -633,9 +633,7 @@ static inline int cpumask_parselist_user(const char __user *buf, int len,
>   */
>  static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
>  {
> -	unsigned int len = strchrnul(buf, '\n') - buf;
> -
> -	return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
> +	return bitmap_parse(buf, UINT_MAX, cpumask_bits(dstp), nr_cpumask_bits);
>  }
>  
>  /**
> -- 
> 2.17.1
> 

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/7] lib: rework bitmap_parse()
  2019-05-08  8:46   ` Andy Shevchenko
@ 2019-05-10  2:26     ` Yury Norov
  2019-05-24  2:51       ` Andrew Morton
  0 siblings, 1 reply; 18+ messages in thread
From: Yury Norov @ 2019-05-10  2:26 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Andrew Morton, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

Hi Andy,

Thanks for thorough review.

On Wed, May 08, 2019 at 11:46:32AM +0300, Andy Shevchenko wrote:
> On Tue, Apr 30, 2019 at 06:06:34PM -0700, Yury Norov wrote:
> > bitmap_parse() is ineffective and full of opaque variables and opencoded
> > parts. It leads to hard understanding and usage of it. This rework
> > includes:
> >  - remove bitmap_shift_left() call from the cycle. Now it makes the
> >    complexity of the algorithm as O(nbits^2). In the suggested approach
> >    the input string is parsed in reverse direction, so no shifts needed;
> >  - relax requirement on a single comma and no white spaces between chunks.
> >    It is considered useful in scripting, and it aligns with
> >    bitmap_parselist();
> >  - split bitmap_parse() to small readable helpers;
> >  - make an explicit calculation of the end of input line at the
> >    beginning, so users of the bitmap_parse() won't bother doing this.
> 
> > +static inline bool in_str(const char *start, const char *ptr)
> > +{
> > +	return start <= ptr;
> > +}
> > +
> 
> The explicit use of the conditional is better.
> 
> -- 
> With Best Regards,
> Andy Shevchenko

I still think that is_str() is more verbose, but it's minor issue
anyways, so I obey. Below is the patch that removes the function.
It's up to Andrew finally, either apply it or not.

Thanks,
Yury

From 7438c15a0b165032a3e5a6d87daabe877dc8cbc8 Mon Sep 17 00:00:00 2001
From: Yury Norov <ynorov@marvell.com>
Date: Thu, 9 May 2019 17:54:23 -0700
Subject: [PATCH] lib: opencode in_str()

Signed-off-by: Yury Norov <ynorov@marvell.com>
---
 lib/bitmap.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/lib/bitmap.c b/lib/bitmap.c
index ebcf4700ebed..ecf93d2982a5 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -454,11 +454,6 @@ static inline bool end_of_region(char c)
 	return __end_of_region(c) || end_of_str(c);
 }
 
-static inline bool in_str(const char *start, const char *ptr)
-{
-	return start <= ptr;
-}
-
 /*
  * The format allows commas and whitespases at the beginning
  * of the region.
@@ -473,7 +468,7 @@ static const char *bitmap_find_region(const char *str)
 
 static const char *bitmap_find_region_reverse(const char *start, const char *end)
 {
-	while (in_str(start, end) && __end_of_region(*end))
+	while (start <= end && __end_of_region(*end))
 		end--;
 
 	return end;
@@ -618,7 +613,7 @@ static const char *bitmap_get_x32_reverse(const char *start,
 
 		ret |= c << i;
 
-		if (!in_str(start, end) || __end_of_region(*end))
+		if (start > end || __end_of_region(*end))
 			goto out;
 	}
 
@@ -653,7 +648,7 @@ int bitmap_parse(const char *start, unsigned int buflen,
 	u32 *bitmap = (u32 *)maskp;
 	int unset_bit;
 
-	while (in_str(start, (end = bitmap_find_region_reverse(start, end)))) {
+	while (start <= (end = bitmap_find_region_reverse(start, end))) {
 		if (!chunks--)
 			return -EOVERFLOW;
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/7] lib: rework bitmap_parse()
  2019-05-10  2:26     ` Yury Norov
@ 2019-05-24  2:51       ` Andrew Morton
  0 siblings, 0 replies; 18+ messages in thread
From: Andrew Morton @ 2019-05-24  2:51 UTC (permalink / raw)
  To: Yury Norov
  Cc: Andy Shevchenko, Rasmus Villemoes, Dmitry Torokhov,
	David S . Miller, Stephen Rothwell, Amritha Nambiar,
	Willem de Bruijn, Kees Cook, Matthew Wilcox, Tobin C . Harding,
	Will Deacon, Miklos Szeredi, Vineet Gupta, Chris Wilson,
	Arnaldo Carvalho de Melo, linux-kernel, Yury Norov, Jens Axboe,
	Steffen Klassert

On Thu, 9 May 2019 19:26:33 -0700 Yury Norov <yury.norov@gmail.com> wrote:

> Hi Andy,
> 
> Thanks for thorough review.
> 
> On Wed, May 08, 2019 at 11:46:32AM +0300, Andy Shevchenko wrote:
> > On Tue, Apr 30, 2019 at 06:06:34PM -0700, Yury Norov wrote:
> > > bitmap_parse() is ineffective and full of opaque variables and opencoded
> > > parts. It leads to hard understanding and usage of it. This rework
> > > includes:
> > >  - remove bitmap_shift_left() call from the cycle. Now it makes the
> > >    complexity of the algorithm as O(nbits^2). In the suggested approach
> > >    the input string is parsed in reverse direction, so no shifts needed;
> > >  - relax requirement on a single comma and no white spaces between chunks.
> > >    It is considered useful in scripting, and it aligns with
> > >    bitmap_parselist();
> > >  - split bitmap_parse() to small readable helpers;
> > >  - make an explicit calculation of the end of input line at the
> > >    beginning, so users of the bitmap_parse() won't bother doing this.
> > 
> > > +static inline bool in_str(const char *start, const char *ptr)
> > > +{
> > > +	return start <= ptr;
> > > +}
> > > +
> > 
> > The explicit use of the conditional is better.
> > 
> > -- 
> > With Best Regards,
> > Andy Shevchenko
> 
> I still think that is_str() is more verbose, but it's minor issue
> anyways, so I obey. Below is the patch that removes the function.
> It's up to Andrew finally, either apply it or not.

I agree with Andy - open-coding the comparisons makes it easier to
understand the varoius in_str() callsites, IMO.

> @@ -653,7 +648,7 @@ int bitmap_parse(const char *start, unsigned int buflen,
>  	u32 *bitmap = (u32 *)maskp;
>  	int unset_bit;
>  
> -	while (in_str(start, (end = bitmap_find_region_reverse(start, end)))) {
> +	while (start <= (end = bitmap_find_region_reverse(start, end))) {

This statement hurts my little brain.  Can it be broken into easier to digest
chunks?

>  		if (!chunks--)
>  			return -EOVERFLOW;
>  

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2019-05-24  2:51 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-01  1:06 [PATCH 0/7] lib: rework bitmap_parse Yury Norov
2019-05-01  1:06 ` [PATCH 1/7] lib/string: add strnchrnul() Yury Norov
2019-05-08  8:47   ` Andy Shevchenko
2019-05-01  1:06 ` [PATCH 2/7] bitops: more BITS_TO_* macros Yury Norov
2019-05-08  8:47   ` Andy Shevchenko
2019-05-01  1:06 ` [PATCH 3/7] lib: add test for bitmap_parse() Yury Norov
2019-05-08  8:47   ` Andy Shevchenko
2019-05-01  1:06 ` [PATCH 4/7] lib: make bitmap_parse_user a wrapper on bitmap_parse Yury Norov
2019-05-08  8:47   ` Andy Shevchenko
2019-05-01  1:06 ` [PATCH 5/7] lib: rework bitmap_parse() Yury Norov
2019-05-08  8:46   ` Andy Shevchenko
2019-05-10  2:26     ` Yury Norov
2019-05-24  2:51       ` Andrew Morton
2019-05-01  1:06 ` [PATCH 6/7] lib: new testcases for bitmap_parse{_user} Yury Norov
2019-05-08  8:47   ` Andy Shevchenko
2019-05-01  1:06 ` [PATCH 7/7] cpumask: don't calculate length of the input string Yury Norov
2019-05-08  8:48   ` Andy Shevchenko
2019-05-07 21:04 ` [PATCH 0/7] lib: rework bitmap_parse Yury Norov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).