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

#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);