On fre, sep 05, 2025 at 18:50, Ahmad Fatoum <[email protected]> wrote: > On 8/28/25 5:05 PM, Tobias Waldekranz wrote: >> Verify that the 'linear' target works as expected. >> >> Do this by (1) creating a dm device with a couple of linear mappings >> to two underlying ramdisks, and then (2) verify that data is returned >> in the expected order when reading it through the dm device. > > Thanks for writing a test! :) > >> Signed-off-by: Tobias Waldekranz <[email protected]> >> --- >> test/self/Kconfig | 7 ++ >> test/self/Makefile | 1 + >> test/self/dm.c | 159 +++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 167 insertions(+) > > Please add to common/boards/configs/enable_self_test.config, so CI also > tests this.
Ah right, tests are more useful if you execute them :) I have told SELFTEST_ENABLE_ALL to select SELFTEST_DM and all checks pass (https://github.com/wkz/barebox/actions/runs/17545487677), but I'm not exactly sure which job is running the selftests, and how I can see whether the dm tests are included. >> create mode 100644 test/self/dm.c >> >> diff --git a/test/self/Kconfig b/test/self/Kconfig >> index 4c43dfe394..a6dfd5f9ae 100644 >> --- a/test/self/Kconfig >> +++ b/test/self/Kconfig >> @@ -125,4 +125,11 @@ config SELFTEST_TLV >> select BASE64 >> select BOARD_LXA >> >> +config SELFTEST_DM >> + bool "Device mapper selftest" >> + depends on DM_BLK >> + select RAMDISK_BLK >> + help >> + Tests the available device mapper targets >> + >> endif >> diff --git a/test/self/Makefile b/test/self/Makefile >> index 9aa8aab78b..3d74bf9e98 100644 >> --- a/test/self/Makefile >> +++ b/test/self/Makefile >> @@ -20,6 +20,7 @@ obj-$(CONFIG_SELFTEST_REGULATOR) += regulator.o >> test_regulator.dtbo.o >> obj-$(CONFIG_SELFTEST_TEST_COMMAND) += test_command.o >> obj-$(CONFIG_SELFTEST_IDR) += idr.o >> obj-$(CONFIG_SELFTEST_TLV) += tlv.o tlv.dtb.o >> +obj-$(CONFIG_SELFTEST_DM) += dm.o >> >> ifdef REGENERATE_KEYTOC >> >> diff --git a/test/self/dm.c b/test/self/dm.c >> new file mode 100644 >> index 0000000000..e2add03a48 >> --- /dev/null >> +++ b/test/self/dm.c >> @@ -0,0 +1,159 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> + >> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt >> + >> +#include <common.h> >> +#include <fcntl.h> >> +#include <fs.h> >> +#include <disks.h> >> +#include <dirent.h> >> +#include <libfile.h> >> +#include <sys/stat.h> >> +#include <unistd.h> >> +#include <bselftest.h> >> +#include <linux/sizes.h> >> +#include <ramdisk.h> >> +#include <dm.h> >> +#include <driver.h> >> +#include <block.h> >> + >> +BSELFTEST_GLOBALS(); >> + >> +struct rdctx { >> + char mem[16][SECTOR_SIZE]; >> + struct ramdisk *rd; >> + const char *name; >> +}; >> + >> +static struct rdctx rdctx[2]; >> + >> +static int rd_create(void) >> +{ >> + struct block_device *blk; >> + struct rdctx *ctx; >> + char base; >> + int i, s; >> + >> + >> + for (i = 0, ctx = rdctx; i < 2; i++, ctx++) { >> + /* In case tests are run multiple times */ >> + memset(ctx->mem, '\0', sizeof(ctx->mem)); >> + >> + /* Add an identifying mark ('a'-'p' and 'A'-'P') at >> + * the start and end of every sector in both disks, so >> + * that we have something to compare against when we >> + * read them back through the DM device. >> + */ >> + base = i ? 'A' : 'a'; >> + for (s = 0; s < 16; s++) { >> + ctx->mem[s][0] = base + s; >> + ctx->mem[s][SECTOR_SIZE - 1] = base + s; >> + } >> + >> + ctx->rd = ramdisk_init(SECTOR_SIZE); >> + if (!ctx->rd) { >> + failed_tests++; >> + pr_err("Could not create ramdisk\n"); >> + return 1; >> + } >> + >> + ramdisk_setup_rw(ctx->rd, ctx->mem, sizeof(ctx->mem)); >> + blk = ramdisk_get_block_device(ctx->rd); >> + ctx->name = cdev_name(&blk->cdev); >> + } >> + >> + return 0; >> +} >> + >> +static void rd_destroy(void) >> +{ >> + ramdisk_free(rdctx[0].rd); >> + ramdisk_free(rdctx[1].rd); >> +} >> + >> +static void verify_read(const char *pattern, const char *buf) >> +{ >> + off_t first, last; >> + int s, len; >> + >> + for (s = 0, len = strlen(pattern); s < len; s++) { >> + first = s << SECTOR_SHIFT; >> + last = first + SECTOR_SIZE - 1; >> + >> + if (buf[first] != pattern[s]) { >> + failed_tests++; >> + pr_err("Expected '%c' at beginning of sector %d, read >> '%c'\n", >> + pattern[s], s, buf[first]); >> + return; >> + } >> + >> + if (buf[last] != pattern[s]) { >> + failed_tests++; >> + pr_err("Expected '%c' at end of sector %d, read '%c'\n", >> + pattern[s], s, buf[last]); >> + return; >> + } >> + } >> +} >> + >> +static void test_dm_linear(void) >> +{ >> + static const char pattern[] = "DEFaghijklmnopNOP"; >> + const size_t dmsize = (sizeof(pattern) - 1) * SECTOR_SIZE; >> + struct dm_device *dm; >> + struct cdev *cdev; >> + char *buf, *table; >> + >> + total_tests++; >> + >> + if (!IS_ENABLED(CONFIG_DM_BLK_LINEAR)) { >> + pr_info("skipping dm-linear test: disabled in config\n"); >> + skipped_tests++; >> + return; >> + } >> + >> + if (rd_create()) >> + return; >> + >> + table = xasprintf(" 0 3 linear /dev/%s 3\n" /* "DEF" */ >> + " 3 1 linear /dev/%s 0\n" /* "a" */ >> + " 4 10 linear /dev/%s 6\n" /* "ghijklmnop" */ >> + "14 3 linear /dev/%s 13\n" /* "NOP" */, >> + rdctx[1].name, >> + rdctx[0].name, >> + rdctx[0].name, >> + rdctx[1].name); >> + >> + dm = dm_create("dmtest", table); >> + free(table); >> + >> + if (IS_ERR_OR_NULL(dm)) { >> + failed_tests++; >> + pr_err("Could not create dm device\n"); >> + goto out_destroy; >> + } >> + >> + cdev = cdev_by_name("dmtest"); >> + if (!cdev) { >> + failed_tests++; >> + pr_err("Could not find dm device\n"); >> + goto out_destroy; >> + } >> + >> + buf = xmalloc(dmsize); >> + >> + if (cdev_read(cdev, buf, dmsize, 0, 0) < dmsize) { >> + failed_tests++; >> + pr_err("Could not read dm device\n"); >> + goto out_free_buf; >> + } >> + >> + verify_read(pattern, buf); >> + >> +out_free_buf: >> + free(buf); >> +out_destroy: >> + dm_destroy(dm); >> + rd_destroy(); >> +} >> +bselftest(core, test_dm_linear); > > -- > Pengutronix e.K. | | > Steuerwalder Str. 21 | http://www.pengutronix.de/ | > 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | > Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
