Blame SOURCES/irqbalance-1.0.8-import-__bitmap_parselist-from-Linux-kernel.patch

5f346f
From 976e741c59b64d51fec0b8c4f5c1c8d3cf8ed3be Mon Sep 17 00:00:00 2001
5f346f
From: Rik van Riel <riel@redhat.com>
5f346f
Date: Thu, 12 Mar 2015 17:47:00 -0400
5f346f
Subject: [PATCH 1/3] import __bitmap_parselist from Linux kernel
5f346f
5f346f
Import __bitmap_parselist from the Linux kernel, in order to parse
5f346f
CPU ranges as used in eg. the kernel isolcpus= commandline argument.
5f346f
5f346f
This code appears to have been in the Linux kernel since the initial
5f346f
git import in 2005, so I do not have attribution of which changeset(s)
5f346f
introduced it into the kernel.
5f346f
5f346f
Signed-off-by: Rik van Riel <riel@redhat.com>
5f346f
---
5f346f
 bitmap.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5f346f
 bitmap.h | 10 ++++++--
5f346f
 2 files changed, 92 insertions(+), 2 deletions(-)
5f346f
5f346f
diff --git a/bitmap.c b/bitmap.c
5f346f
index 2f44660..6a7421a 100644
5f346f
--- a/bitmap.c
5f346f
+++ b/bitmap.c
5f346f
@@ -377,3 +377,87 @@ int __bitmap_parse(const char *buf, unsigned int buflen,
5f346f
 
5f346f
 	return 0;
5f346f
 }
5f346f
+
5f346f
+/**
5f346f
+ * __bitmap_parselist - convert list format ASCII string to bitmap
5f346f
+ * @buf: read nul-terminated user string from this buffer
5f346f
+ * @buflen: buffer size in bytes.  If string is smaller than this
5f346f
+ *    then it must be terminated with a \0.
5f346f
+ * @is_user: location of buffer, 0 indicates kernel space
5f346f
+ * @maskp: write resulting mask here
5f346f
+ * @nmaskbits: number of bits in mask to be written
5f346f
+ *
5f346f
+ * Input format is a comma-separated list of decimal numbers and
5f346f
+ * ranges.  Consecutively set bits are shown as two hyphen-separated
5f346f
+ * decimal numbers, the smallest and largest bit numbers set in
5f346f
+ * the range.
5f346f
+ *
5f346f
+ * Returns 0 on success, -errno on invalid input strings.
5f346f
+ * Error values:
5f346f
+ *    %-EINVAL: second number in range smaller than first
5f346f
+ *    %-EINVAL: invalid character in string
5f346f
+ *    %-ERANGE: bit number specified too large for mask
5f346f
+ */
5f346f
+int __bitmap_parselist(const char *buf, unsigned int buflen,
5f346f
+		int is_user __attribute((unused)), unsigned long *maskp,
5f346f
+		int nmaskbits)
5f346f
+{
5f346f
+	int a, b, c, old_c, totaldigits;
5f346f
+	int exp_digit, in_range;
5f346f
+
5f346f
+	totaldigits = c = 0;
5f346f
+	bitmap_zero(maskp, nmaskbits);
5f346f
+	do {
5f346f
+		exp_digit = 1;
5f346f
+		in_range = 0;
5f346f
+		a = b = 0;
5f346f
+
5f346f
+		/* Get the next cpu# or a range of cpu#'s */
5f346f
+		while (buflen) {
5f346f
+			old_c = c;
5f346f
+			c = *buf++;
5f346f
+			buflen--;
5f346f
+			if (isspace(c))
5f346f
+				continue;
5f346f
+
5f346f
+			/*
5f346f
+			 * If the last character was a space and the current
5f346f
+			 * character isn't '\0', we've got embedded whitespace.
5f346f
+			 * This is a no-no, so throw an error.
5f346f
+			 */
5f346f
+			if (totaldigits && c && isspace(old_c))
5f346f
+				return -EINVAL;
5f346f
+
5f346f
+			/* A '\0' or a ',' signal the end of a cpu# or range */
5f346f
+			if (c == '\0' || c == ',')
5f346f
+				break;
5f346f
+
5f346f
+			if (c == '-') {
5f346f
+				if (exp_digit || in_range)
5f346f
+					return -EINVAL;
5f346f
+				b = 0;
5f346f
+				in_range = 1;
5f346f
+				exp_digit = 1;
5f346f
+				continue;
5f346f
+			}
5f346f
+
5f346f
+			if (!isdigit(c))
5f346f
+				return -EINVAL;
5f346f
+
5f346f
+			b = b * 10 + (c - '0');
5f346f
+			if (!in_range)
5f346f
+				a = b;
5f346f
+			exp_digit = 0;
5f346f
+			totaldigits++;
5f346f
+		}
5f346f
+		if (!(a <= b))
5f346f
+			return -EINVAL;
5f346f
+		if (b >= nmaskbits)
5f346f
+			return -ERANGE;
5f346f
+		while (a <= b) {
5f346f
+			set_bit(a, maskp);
5f346f
+			a++;
5f346f
+		}
5f346f
+	} while (buflen && c == ',');
5f346f
+	return 0;
5f346f
+}
5f346f
diff --git a/bitmap.h b/bitmap.h
5f346f
index 91ed499..7afce59 100644
5f346f
--- a/bitmap.h
5f346f
+++ b/bitmap.h
5f346f
@@ -185,8 +185,8 @@ extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
5f346f
 			unsigned long *dst, int nbits);
5f346f
 extern int bitmap_scnlistprintf(char *buf, unsigned int len,
5f346f
 			const unsigned long *src, int nbits);
5f346f
-extern int bitmap_parselist(const char *buf, unsigned long *maskp,
5f346f
-			int nmaskbits);
5f346f
+extern int __bitmap_parselist(const char *buf, unsigned int buflen, int is_user,
5f346f
+			unsigned long *dst, int nbits);
5f346f
 extern void bitmap_remap(unsigned long *dst, const unsigned long *src,
5f346f
 		const unsigned long *old, const unsigned long *new, int bits);
5f346f
 extern int bitmap_bitremap(int oldbit,
5f346f
@@ -351,6 +351,12 @@ static inline int bitmap_parse(const char *buf, unsigned int buflen,
5f346f
 	return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
5f346f
 }
5f346f
 
5f346f
+static inline int bitmap_parselist(const char *buf, unsigned int buflen,
5f346f
+			unsigned long *maskp, int nmaskbits)
5f346f
+{
5f346f
+	return __bitmap_parselist(buf, buflen, 0, maskp, nmaskbits);
5f346f
+}
5f346f
+
5f346f
 #endif /* __ASSEMBLY__ */
5f346f
 
5f346f
 #endif /* __LINUX_BITMAP_H */
5f346f
-- 
5f346f
2.1.0
5f346f