1567 lines · 46.3 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * Test cases for bitmap API. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/bitmap.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/printk.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/uaccess.h> #include "../tools/testing/selftests/kselftest_module.h" #define EXP1_IN_BITS	(sizeof(exp1) * 8) KSTM_MODULE_GLOBALS(); static char pbl_buffer[PAGE_SIZE] __initdata;static char print_buf[PAGE_SIZE * 2] __initdata; static const unsigned long exp1[] __initconst = {	BITMAP_FROM_U64(1),	BITMAP_FROM_U64(2),	BITMAP_FROM_U64(0x0000ffff),	BITMAP_FROM_U64(0xffff0000),	BITMAP_FROM_U64(0x55555555),	BITMAP_FROM_U64(0xaaaaaaaa),	BITMAP_FROM_U64(0x11111111),	BITMAP_FROM_U64(0x22222222),	BITMAP_FROM_U64(0xffffffff),	BITMAP_FROM_U64(0xfffffffe),	BITMAP_FROM_U64(0x3333333311111111ULL),	BITMAP_FROM_U64(0xffffffff77777777ULL),	BITMAP_FROM_U64(0),	BITMAP_FROM_U64(0x00008000),	BITMAP_FROM_U64(0x80000000),}; static const unsigned long exp2[] __initconst = {	BITMAP_FROM_U64(0x3333333311111111ULL),	BITMAP_FROM_U64(0xffffffff77777777ULL),}; /* Fibonacci sequence */static const unsigned long exp2_to_exp3_mask[] __initconst = {	BITMAP_FROM_U64(0x008000020020212eULL),};/* exp3_0_1 = (exp2[0] & ~exp2_to_exp3_mask) | (exp2[1] & exp2_to_exp3_mask) */static const unsigned long exp3_0_1[] __initconst = {	BITMAP_FROM_U64(0x33b3333311313137ULL),};/* exp3_1_0 = (exp2[1] & ~exp2_to_exp3_mask) | (exp2[0] & exp2_to_exp3_mask) */static const unsigned long exp3_1_0[] __initconst = {	BITMAP_FROM_U64(0xff7fffff77575751ULL),}; static bool __init__check_eq_ulong(const char *srcfile, unsigned int line,		 const unsigned long exp_ulong, unsigned long x){	if (exp_ulong != x) {		pr_err("[%s:%u] expected %lu, got %lu\n",			srcfile, line, exp_ulong, x);		return false;	}	return true;} static bool __init__check_eq_bitmap(const char *srcfile, unsigned int line,		  const unsigned long *exp_bmap, const unsigned long *bmap,		  unsigned int nbits){	if (!bitmap_equal(exp_bmap, bmap, nbits)) {		pr_warn("[%s:%u] bitmaps contents differ: expected \"%*pbl\", got \"%*pbl\"\n",			srcfile, line,			nbits, exp_bmap, nbits, bmap);		return false;	}	return true;} static bool __init__check_eq_pbl(const char *srcfile, unsigned int line,	       const char *expected_pbl,	       const unsigned long *bitmap, unsigned int nbits){	snprintf(pbl_buffer, sizeof(pbl_buffer), "%*pbl", nbits, bitmap);	if (strcmp(expected_pbl, pbl_buffer)) {		pr_warn("[%s:%u] expected \"%s\", got \"%s\"\n",			srcfile, line,			expected_pbl, pbl_buffer);		return false;	}	return true;} static bool __init __check_eq_clump8(const char *srcfile, unsigned int line,				    const unsigned int offset,				    const unsigned int size,				    const unsigned char *const clump_exp,				    const unsigned long *const clump){	unsigned long exp; 	if (offset >= size) {		pr_warn("[%s:%u] bit offset for clump out-of-bounds: expected less than %u, got %u\n",			srcfile, line, size, offset);		return false;	} 	exp = clump_exp[offset / 8];	if (!exp) {		pr_warn("[%s:%u] bit offset for zero clump: expected nonzero clump, got bit offset %u with clump value 0",			srcfile, line, offset);		return false;	} 	if (*clump != exp) {		pr_warn("[%s:%u] expected clump value of 0x%lX, got clump value of 0x%lX",			srcfile, line, exp, *clump);		return false;	} 	return true;} static bool __init__check_eq_str(const char *srcfile, unsigned int line,		const char *exp_str, const char *str,		unsigned int len){	bool eq; 	eq = strncmp(exp_str, str, len) == 0;	if (!eq)		pr_err("[%s:%u] expected %s, got %s\n", srcfile, line, exp_str, str); 	return eq;} #define __expect_eq(suffix, ...)					\	({								\		int result = 0;						\		total_tests++;						\		if (!__check_eq_ ## suffix(__FILE__, __LINE__,		\					   ##__VA_ARGS__)) {		\			failed_tests++;					\			result = 1;					\		}							\		result;							\	}) #define expect_eq_ulong(...)		__expect_eq(ulong, ##__VA_ARGS__)#define expect_eq_uint(x, y)		expect_eq_ulong((unsigned int)(x), (unsigned int)(y))#define expect_eq_bitmap(...)		__expect_eq(bitmap, ##__VA_ARGS__)#define expect_eq_pbl(...)		__expect_eq(pbl, ##__VA_ARGS__)#define expect_eq_u32_array(...)	__expect_eq(u32_array, ##__VA_ARGS__)#define expect_eq_clump8(...)		__expect_eq(clump8, ##__VA_ARGS__)#define expect_eq_str(...)		__expect_eq(str, ##__VA_ARGS__) static void __init test_zero_clear(void){	DECLARE_BITMAP(bmap, 1024); 	/* Known way to set all bits */	memset(bmap, 0xff, 128); 	expect_eq_pbl("0-22", bmap, 23);	expect_eq_pbl("0-1023", bmap, 1024); 	/* single-word bitmaps */	bitmap_clear(bmap, 0, 9);	expect_eq_pbl("9-1023", bmap, 1024); 	bitmap_zero(bmap, 35);	expect_eq_pbl("64-1023", bmap, 1024); 	/* cross boundaries operations */	bitmap_clear(bmap, 79, 19);	expect_eq_pbl("64-78,98-1023", bmap, 1024); 	bitmap_zero(bmap, 115);	expect_eq_pbl("128-1023", bmap, 1024); 	/* Zeroing entire area */	bitmap_zero(bmap, 1024);	expect_eq_pbl("", bmap, 1024);} static void __init test_find_nth_bit(void){	unsigned long b, bit, cnt = 0;	DECLARE_BITMAP(bmap, 64 * 3); 	bitmap_zero(bmap, 64 * 3);	__set_bit(10, bmap);	__set_bit(20, bmap);	__set_bit(30, bmap);	__set_bit(40, bmap);	__set_bit(50, bmap);	__set_bit(60, bmap);	__set_bit(80, bmap);	__set_bit(123, bmap); 	expect_eq_uint(10,  find_nth_bit(bmap, 64 * 3, 0));	expect_eq_uint(20,  find_nth_bit(bmap, 64 * 3, 1));	expect_eq_uint(30,  find_nth_bit(bmap, 64 * 3, 2));	expect_eq_uint(40,  find_nth_bit(bmap, 64 * 3, 3));	expect_eq_uint(50,  find_nth_bit(bmap, 64 * 3, 4));	expect_eq_uint(60,  find_nth_bit(bmap, 64 * 3, 5));	expect_eq_uint(80,  find_nth_bit(bmap, 64 * 3, 6));	expect_eq_uint(123, find_nth_bit(bmap, 64 * 3, 7));	expect_eq_uint(0,   !!(find_nth_bit(bmap, 64 * 3, 8) < 64 * 3)); 	expect_eq_uint(10,  find_nth_bit(bmap, 64 * 3 - 1, 0));	expect_eq_uint(20,  find_nth_bit(bmap, 64 * 3 - 1, 1));	expect_eq_uint(30,  find_nth_bit(bmap, 64 * 3 - 1, 2));	expect_eq_uint(40,  find_nth_bit(bmap, 64 * 3 - 1, 3));	expect_eq_uint(50,  find_nth_bit(bmap, 64 * 3 - 1, 4));	expect_eq_uint(60,  find_nth_bit(bmap, 64 * 3 - 1, 5));	expect_eq_uint(80,  find_nth_bit(bmap, 64 * 3 - 1, 6));	expect_eq_uint(123, find_nth_bit(bmap, 64 * 3 - 1, 7));	expect_eq_uint(0,   !!(find_nth_bit(bmap, 64 * 3 - 1, 8) < 64 * 3 - 1)); 	for_each_set_bit(bit, exp1, EXP1_IN_BITS) {		b = find_nth_bit(exp1, EXP1_IN_BITS, cnt++);		expect_eq_uint(b, bit);	}} static void __init test_fill_set(void){	DECLARE_BITMAP(bmap, 1024); 	/* Known way to clear all bits */	memset(bmap, 0x00, 128); 	expect_eq_pbl("", bmap, 23);	expect_eq_pbl("", bmap, 1024); 	/* single-word bitmaps */	bitmap_set(bmap, 0, 9);	expect_eq_pbl("0-8", bmap, 1024); 	bitmap_fill(bmap, 35);	expect_eq_pbl("0-63", bmap, 1024); 	/* cross boundaries operations */	bitmap_set(bmap, 79, 19);	expect_eq_pbl("0-63,79-97", bmap, 1024); 	bitmap_fill(bmap, 115);	expect_eq_pbl("0-127", bmap, 1024); 	/* Zeroing entire area */	bitmap_fill(bmap, 1024);	expect_eq_pbl("0-1023", bmap, 1024);} static void __init test_copy(void){	DECLARE_BITMAP(bmap1, 1024);	DECLARE_BITMAP(bmap2, 1024); 	bitmap_zero(bmap1, 1024);	bitmap_zero(bmap2, 1024); 	/* single-word bitmaps */	bitmap_set(bmap1, 0, 19);	bitmap_copy(bmap2, bmap1, 23);	expect_eq_pbl("0-18", bmap2, 1024); 	bitmap_set(bmap2, 0, 23);	bitmap_copy(bmap2, bmap1, 23);	expect_eq_pbl("0-18", bmap2, 1024); 	/* multi-word bitmaps */	bitmap_set(bmap1, 0, 109);	bitmap_copy(bmap2, bmap1, 1024);	expect_eq_pbl("0-108", bmap2, 1024); 	bitmap_fill(bmap2, 1024);	bitmap_copy(bmap2, bmap1, 1024);	expect_eq_pbl("0-108", bmap2, 1024); 	/* the following tests assume a 32- or 64-bit arch (even 128b	 * if we care)	 */ 	bitmap_fill(bmap2, 1024);	bitmap_copy(bmap2, bmap1, 109);  /* ... but 0-padded til word length */	expect_eq_pbl("0-108,128-1023", bmap2, 1024); 	bitmap_fill(bmap2, 1024);	bitmap_copy(bmap2, bmap1, 97);  /* ... but aligned on word length */	expect_eq_pbl("0-108,128-1023", bmap2, 1024);} static void __init test_bitmap_region(void){	int pos, order; 	DECLARE_BITMAP(bmap, 1000); 	bitmap_zero(bmap, 1000); 	for (order = 0; order < 10; order++) {		pos = bitmap_find_free_region(bmap, 1000, order);		if (order == 0)			expect_eq_uint(pos, 0);		else			expect_eq_uint(pos, order < 9 ? BIT(order) : -ENOMEM);	} 	bitmap_release_region(bmap, 0, 0);	for (order = 1; order < 9; order++)		bitmap_release_region(bmap, BIT(order), order); 	expect_eq_uint(bitmap_weight(bmap, 1000), 0);} #define EXP2_IN_BITS	(sizeof(exp2) * 8) static void __init test_replace(void){	unsigned int nbits = 64;	unsigned int nlongs = DIV_ROUND_UP(nbits, BITS_PER_LONG);	DECLARE_BITMAP(bmap, 1024); 	BUILD_BUG_ON(EXP2_IN_BITS < nbits * 2); 	bitmap_zero(bmap, 1024);	bitmap_replace(bmap, &exp2[0 * nlongs], &exp2[1 * nlongs], exp2_to_exp3_mask, nbits);	expect_eq_bitmap(bmap, exp3_0_1, nbits); 	bitmap_zero(bmap, 1024);	bitmap_replace(bmap, &exp2[1 * nlongs], &exp2[0 * nlongs], exp2_to_exp3_mask, nbits);	expect_eq_bitmap(bmap, exp3_1_0, nbits); 	bitmap_fill(bmap, 1024);	bitmap_replace(bmap, &exp2[0 * nlongs], &exp2[1 * nlongs], exp2_to_exp3_mask, nbits);	expect_eq_bitmap(bmap, exp3_0_1, nbits); 	bitmap_fill(bmap, 1024);	bitmap_replace(bmap, &exp2[1 * nlongs], &exp2[0 * nlongs], exp2_to_exp3_mask, nbits);	expect_eq_bitmap(bmap, exp3_1_0, nbits);} static const unsigned long sg_mask[] __initconst = {	BITMAP_FROM_U64(0x000000000000035aULL),	BITMAP_FROM_U64(0x0000000000000000ULL),}; static const unsigned long sg_src[] __initconst = {	BITMAP_FROM_U64(0x0000000000000667ULL),	BITMAP_FROM_U64(0x0000000000000000ULL),}; static const unsigned long sg_gather_exp[] __initconst = {	BITMAP_FROM_U64(0x0000000000000029ULL),	BITMAP_FROM_U64(0x0000000000000000ULL),}; static const unsigned long sg_scatter_exp[] __initconst = {	BITMAP_FROM_U64(0x000000000000021aULL),	BITMAP_FROM_U64(0x0000000000000000ULL),}; static void __init test_bitmap_sg(void){	unsigned int nbits = 64;	DECLARE_BITMAP(bmap_gather, 100);	DECLARE_BITMAP(bmap_scatter, 100);	DECLARE_BITMAP(bmap_tmp, 100);	DECLARE_BITMAP(bmap_res, 100); 	/* Simple gather call */	bitmap_zero(bmap_gather, 100);	bitmap_gather(bmap_gather, sg_src, sg_mask, nbits);	expect_eq_bitmap(sg_gather_exp, bmap_gather, 100); 	/* Simple scatter call */	bitmap_zero(bmap_scatter, 100);	bitmap_scatter(bmap_scatter, sg_src, sg_mask, nbits);	expect_eq_bitmap(sg_scatter_exp, bmap_scatter, 100); 	/* Scatter/gather relationship */	bitmap_zero(bmap_tmp, 100);	bitmap_gather(bmap_tmp, bmap_scatter, sg_mask, nbits);	bitmap_scatter(bmap_res, bmap_tmp, sg_mask, nbits);	expect_eq_bitmap(bmap_scatter, bmap_res, 100);} #define PARSE_TIME	0x1#define NO_LEN		0x2 struct test_bitmap_parselist{	const int errno;	const char *in;	const unsigned long *expected;	const int nbits;	const int flags;}; static const struct test_bitmap_parselist parselist_tests[] __initconst = {#define step (sizeof(u64) / sizeof(unsigned long)) 	{0, "0",			&exp1[0], 8, 0},	{0, "1",			&exp1[1 * step], 8, 0},	{0, "0-15",			&exp1[2 * step], 32, 0},	{0, "16-31",			&exp1[3 * step], 32, 0},	{0, "0-31:1/2",			&exp1[4 * step], 32, 0},	{0, "1-31:1/2",			&exp1[5 * step], 32, 0},	{0, "0-31:1/4",			&exp1[6 * step], 32, 0},	{0, "1-31:1/4",			&exp1[7 * step], 32, 0},	{0, "0-31:4/4",			&exp1[8 * step], 32, 0},	{0, "1-31:4/4",			&exp1[9 * step], 32, 0},	{0, "0-31:1/4,32-63:2/4",	&exp1[10 * step], 64, 0},	{0, "0-31:3/4,32-63:4/4",	&exp1[11 * step], 64, 0},	{0, "  ,,  0-31:3/4  ,, 32-63:4/4  ,,  ",	&exp1[11 * step], 64, 0}, 	{0, "0-31:1/4,32-63:2/4,64-95:3/4,96-127:4/4",	exp2, 128, 0}, 	{0, "0-2047:128/256", NULL, 2048, PARSE_TIME}, 	{0, "",				&exp1[12 * step], 8, 0},	{0, "\n",			&exp1[12 * step], 8, 0},	{0, ",,  ,,  , ,  ,",		&exp1[12 * step], 8, 0},	{0, " ,  ,,  , ,   ",		&exp1[12 * step], 8, 0},	{0, " ,  ,,  , ,   \n",		&exp1[12 * step], 8, 0}, 	{0, "0-0",			&exp1[0], 32, 0},	{0, "1-1",			&exp1[1 * step], 32, 0},	{0, "15-15",			&exp1[13 * step], 32, 0},	{0, "31-31",			&exp1[14 * step], 32, 0}, 	{0, "0-0:0/1",			&exp1[12 * step], 32, 0},	{0, "0-0:1/1",			&exp1[0], 32, 0},	{0, "0-0:1/31",			&exp1[0], 32, 0},	{0, "0-0:31/31",		&exp1[0], 32, 0},	{0, "1-1:1/1",			&exp1[1 * step], 32, 0},	{0, "0-15:16/31",		&exp1[2 * step], 32, 0},	{0, "15-15:1/2",		&exp1[13 * step], 32, 0},	{0, "15-15:31/31",		&exp1[13 * step], 32, 0},	{0, "15-31:1/31",		&exp1[13 * step], 32, 0},	{0, "16-31:16/31",		&exp1[3 * step], 32, 0},	{0, "31-31:31/31",		&exp1[14 * step], 32, 0}, 	{0, "N-N",			&exp1[14 * step], 32, 0},	{0, "0-0:1/N",			&exp1[0], 32, 0},	{0, "0-0:N/N",			&exp1[0], 32, 0},	{0, "0-15:16/N",		&exp1[2 * step], 32, 0},	{0, "15-15:N/N",		&exp1[13 * step], 32, 0},	{0, "15-N:1/N",			&exp1[13 * step], 32, 0},	{0, "16-N:16/N",		&exp1[3 * step], 32, 0},	{0, "N-N:N/N",			&exp1[14 * step], 32, 0}, 	{0, "0-N:1/3,1-N:1/3,2-N:1/3",		&exp1[8 * step], 32, 0},	{0, "0-31:1/3,1-31:1/3,2-31:1/3",	&exp1[8 * step], 32, 0},	{0, "1-10:8/12,8-31:24/29,0-31:0/3",	&exp1[9 * step], 32, 0}, 	{0,	  "all",		&exp1[8 * step], 32, 0},	{0,	  "0, 1, all,  ",	&exp1[8 * step], 32, 0},	{0,	  "all:1/2",		&exp1[4 * step], 32, 0},	{0,	  "ALL:1/2",		&exp1[4 * step], 32, 0},	{-EINVAL, "al", NULL, 8, 0},	{-EINVAL, "alll", NULL, 8, 0}, 	{-EINVAL, "-1",	NULL, 8, 0},	{-EINVAL, "-0",	NULL, 8, 0},	{-EINVAL, "10-1", NULL, 8, 0},	{-ERANGE, "8-8", NULL, 8, 0},	{-ERANGE, "0-31", NULL, 8, 0},	{-EINVAL, "0-31:", NULL, 32, 0},	{-EINVAL, "0-31:0", NULL, 32, 0},	{-EINVAL, "0-31:0/", NULL, 32, 0},	{-EINVAL, "0-31:0/0", NULL, 32, 0},	{-EINVAL, "0-31:1/0", NULL, 32, 0},	{-EINVAL, "0-31:10/1", NULL, 32, 0},	{-EOVERFLOW, "0-98765432123456789:10/1", NULL, 8, 0}, 	{-EINVAL, "a-31", NULL, 8, 0},	{-EINVAL, "0-a1", NULL, 8, 0},	{-EINVAL, "a-31:10/1", NULL, 8, 0},	{-EINVAL, "0-31:a/1", NULL, 8, 0},	{-EINVAL, "0-\n", NULL, 8, 0}, }; static void __init test_bitmap_parselist(void){	int i;	int err;	ktime_t time;

Lines 1–500 of 1567.