You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
3.8 KiB
C
131 lines
3.8 KiB
C
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/bitmap.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/errno.h>
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_DESCRIPTION("Test cpumask sizes and bitmap_parse behaviour");
|
|
|
|
static int __init cpumask_test_init(void)
|
|
{
|
|
int ret;
|
|
cpumask_var_t mask = NULL;
|
|
unsigned int nbits;
|
|
size_t buf_len;
|
|
char *buf;
|
|
int i;
|
|
int rc;
|
|
|
|
pr_info("cpumask_test: module init\n");
|
|
|
|
/* basic sizes */
|
|
pr_info("cpumask_test: sizeof(long) = %zu\n", sizeof(long));
|
|
pr_info("cpumask_test: cpumask_size() = %u\n", cpumask_size());
|
|
pr_info("cpumask_test: nr_cpumask_bits = %u\n", nr_cpumask_bits);
|
|
|
|
/* allocate a cpumask_var */
|
|
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
|
|
pr_err("cpumask_test: alloc_cpumask_var() failed\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
nbits = nr_cpumask_bits; /* number of bits we'll give to bitmap_parse */
|
|
pr_info("cpumask_test: will use nbits=%u for bitmap_parse tests\n", nbits);
|
|
|
|
/* 1) Test simple single-hex-chunk inputs with increasing hex-digit count.
|
|
* The kernel's bitmap_parse returns -EOVERFLOW when an individual
|
|
* hex chunk encodes more than 32 bits (i.e. > 8 hex digits).
|
|
*/
|
|
for (i = 1; i <= 40; ++i) {
|
|
/* build buffer: string of i 'f' hex digits (no commas) */
|
|
buf_len = i + 1;
|
|
buf = kmalloc(buf_len, GFP_KERNEL);
|
|
if (!buf) {
|
|
pr_err("cpumask_test: kmalloc failed\n");
|
|
rc = -ENOMEM;
|
|
goto out_free;
|
|
}
|
|
memset(buf, 'f', i);
|
|
buf[i] = '\0';
|
|
|
|
rc = bitmap_parse(buf, (unsigned int)i, cpumask_bits(mask), nbits);
|
|
if (rc == -EOVERFLOW)
|
|
pr_info("cpumask_test: single-chunk hex len=%2d -> bitmap_parse => -EOVERFLOW\n", i);
|
|
else if (rc == 0)
|
|
pr_info("cpumask_test: single-chunk hex len=%2d -> OK (0)\n", i);
|
|
else
|
|
pr_info("cpumask_test: single-chunk hex len=%2d -> bitmap_parse => %d\n", i, rc);
|
|
|
|
kfree(buf);
|
|
}
|
|
|
|
/* 2) Test grouping by 32-bit chunks separated by commas.
|
|
* We create input like "ffffffff,ffffffff,...". This should allow
|
|
* arbitrarily many bits (up to nbits) as long as each chunk <=32 bits.
|
|
*/
|
|
for (i = 1; i <= 16; ++i) {
|
|
/* i chunks, each "ffffffff", separated by commas */
|
|
int j;
|
|
/* each chunk 8 chars + comma except last, plus NUL */
|
|
buf_len = i * 8 + (i - 1) + 1;
|
|
buf = kmalloc(buf_len, GFP_KERNEL);
|
|
if (!buf) {
|
|
pr_err("cpumask_test: kmalloc failed\n");
|
|
rc = -ENOMEM;
|
|
goto out_free;
|
|
}
|
|
buf[0] = '\0';
|
|
for (j = 0; j < i; ++j) {
|
|
strcat(buf, "ffffffff");
|
|
if (j != i - 1)
|
|
strcat(buf, ",");
|
|
}
|
|
|
|
rc = bitmap_parse(buf, (unsigned int)strlen(buf), cpumask_bits(mask), nbits);
|
|
if (rc == -EOVERFLOW)
|
|
pr_info("cpumask_test: %2d chunks (8hex each, commas) -> -EOVERFLOW\n", i);
|
|
else if (rc == 0)
|
|
pr_info("cpumask_test: %2d chunks (8hex each, commas) -> OK (0)\n", i);
|
|
else
|
|
pr_info("cpumask_test: %2d chunks (8hex each, commas) -> %d\n", i, rc);
|
|
|
|
kfree(buf);
|
|
}
|
|
|
|
/* 3) Test constructing a string that asks for bits beyond nbits (-> -ERANGE expected) */
|
|
{
|
|
/* Example: "999999999" is a large hex chunk (9 digits) -> EOVERFLOW
|
|
* We'll also try a list format that attempts to set a very large bit number:
|
|
* e.g., a decimal list "999999" will likely give -ERANGE if > nbits.
|
|
*/
|
|
buf = kmalloc(64, GFP_KERNEL);
|
|
if (!buf) {
|
|
pr_err("cpumask_test: kmalloc failed\n");
|
|
rc = -ENOMEM;
|
|
goto out_free;
|
|
}
|
|
snprintf(buf, 64, "%u", nbits + 1000); /* decimal token > nbits */
|
|
rc = bitmap_parselist(buf, cpumask_bits(mask), nbits);
|
|
pr_info("cpumask_test: parselist token '>%u' => %d (0 ok, -ERANGE if too big)\n", nbits, rc);
|
|
kfree(buf);
|
|
}
|
|
|
|
rc = 0;
|
|
|
|
out_free:
|
|
free_cpumask_var(mask);
|
|
pr_info("cpumask_test: module init done\n");
|
|
return rc;
|
|
}
|
|
|
|
static void __exit cpumask_test_exit(void)
|
|
{
|
|
pr_info("cpumask_test: module exit\n");
|
|
}
|
|
|
|
module_init(cpumask_test_init);
|
|
module_exit(cpumask_test_exit);
|