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