From 38f7b96048272531a3253c7dd40648e48bdbd220 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Wed, 18 Sep 2013 13:41:56 +0200 Subject: [PATCH] blocktest: prepare to be run as part of tests - fail SEF initialization if any of the subtests failed, so that the party invoking the "service up" can tell whether the test succeeded; - add "nocontig" option, because VM isn't particularly good at allocating contiguous memory; - add "silent" option, because it floods the console otherwise; - allow the device size to be smaller than the maximum transfer size; - install files to installed test directory. Change-Id: I45c818f817c11d90c5f94ae26a2fc49e36e6761e --- distrib/sets/lists/minix/mi | 6 ++ etc/mtree/NetBSD.dist.base | 1 + test/Makefile | 3 + test/blocktest/Makefile | 4 +- test/blocktest/blocktest.c | 201 +++++++++++++++++++++--------------- 5 files changed, 133 insertions(+), 82 deletions(-) diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index ad6db8feb..17b3d94f1 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -5668,6 +5668,12 @@ ./usr/tests/minix-posix/testsh2 minix-sys ./usr/tests/minix-posix/testvm minix-sys ./usr/tests/minix-posix/testvm.conf minix-sys +./usr/tests/minix-posix/blocktest minix-sys +./usr/tests/minix-posix/blocktest/README minix-sys +./usr/tests/minix-posix/blocktest/blocktest minix-sys +./usr/tests/minix-posix/blocktest/support.sh minix-sys +./usr/tests/minix-posix/blocktest/system.conf minix-sys +./usr/tests/minix-posix/blocktest/test.sh minix-sys ./usr/tests/usr.bin/jot/Atffile minix-sys atf ./usr/tests/usr.bin/jot/d_basic.out minix-sys atf ./usr/tests/usr.bin/jot/t_jot minix-sys atf diff --git a/etc/mtree/NetBSD.dist.base b/etc/mtree/NetBSD.dist.base index 5cb3df985..d41b00655 100644 --- a/etc/mtree/NetBSD.dist.base +++ b/etc/mtree/NetBSD.dist.base @@ -161,6 +161,7 @@ /set type=dir uid=2 gid=0 mode=755 ./usr/tests/minix-posix +./usr/tests/minix-posix/blocktest # this one is for term(1) /set type=dir uid=0 gid=5 mode=775 diff --git a/test/Makefile b/test/Makefile index 331cb3b3e..945b56e67 100644 --- a/test/Makefile +++ b/test/Makefile @@ -16,6 +16,8 @@ LDADD+= -lm -lcompat_minix .include +SUBDIR= blocktest + # Some have special flags compiling .if ${MACHINE_ARCH} == "i386" # LSC FIXME: Compilation error for now on ARM with that! @@ -110,3 +112,4 @@ clean: .PHONY .MAKE @rm -rf DIR* .include +.include diff --git a/test/blocktest/Makefile b/test/blocktest/Makefile index fdd4d7811..b13ba095c 100644 --- a/test/blocktest/Makefile +++ b/test/blocktest/Makefile @@ -1,13 +1,15 @@ # Makefile for the Block Device Driver Test driver (blocktest) PROG= blocktest SRCS= blocktest.c +FILES= system.conf support.sh test.sh README DPADD+= ${LIBSYS} LDADD+= -lsys MAN= -BINDIR?= /usr/sbin +BINDIR?= /usr/tests/minix-posix/blocktest +FILESDIR?= /usr/tests/minix-posix/blocktest .include "Makefile.inc" .include diff --git a/test/blocktest/blocktest.c b/test/blocktest/blocktest.c index 15723310e..7d7526cb3 100644 --- a/test/blocktest/blocktest.c +++ b/test/blocktest/blocktest.c @@ -1,10 +1,12 @@ /* Block Device Driver Test driver, by D.C. van Moolenbroek */ #include +#include #include #include #include #include #include +#include #include enum { @@ -40,6 +42,10 @@ static int max_size = 131072; /* maximum total size of any req */ * it to a value lower than the driver supports. */ +/* These settings are used for automated test runs. */ +static int contig = TRUE; /* allocate contiguous DMA memory? */ +static int silent = FALSE; /* do not produce console output? */ + static struct part_geom part; /* base and size of target partition */ #define NR_OPENED 10 /* maximum number of opened devices */ @@ -63,9 +69,58 @@ static struct optset optset_table[] = { { "min_read", OPT_INT, &min_read, 10 }, { "min_write", OPT_INT, &min_write, 10 }, { "max", OPT_INT, &max_size, 10 }, + { "nocontig", OPT_BOOL, &contig, FALSE }, + { "silent", OPT_BOOL, &silent, TRUE }, { NULL, 0, NULL, 0 } }; +static void output(char *fmt, ...) +{ + /* Print debugging information, unless configured to be silent. + */ + va_list argp; + + if (silent) + return; + + va_start(argp, fmt); + + vprintf(fmt, argp); + + va_end(argp); +} + +static void *alloc_dma_memory(size_t size) +{ + /* Allocate memory that may be used for direct DMA. For most drivers, + * this means that the memory has to be physically contiguous. For some + * drivers (e.g. VND) we allow non-contiguous allocation, because VM is + * currently flaky and does not always manage to provide contiguous + * memory even when it should, thus causing needless test failures. + */ + void *ptr; + + if (contig) + ptr = alloc_contig(size, 0, NULL); + else + ptr = minix_mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_PREALLOC | MAP_ANON, -1, 0); + + if (ptr == MAP_FAILED) + panic("unable to allocate %d bytes of memory", size); + + return ptr; +} + +static void free_dma_memory(void *ptr, size_t size) +{ + /* Free memory previously allocated for direct DMA. */ + if (contig) + free_contig(ptr, size); + else + minix_munmap(ptr, size); +} + static int set_result(result_t *res, int type, ssize_t value) { /* Set the result to the given result type and with the given optional @@ -109,42 +164,42 @@ static void got_result(result_t *res, char *desc) } } - printf("#%02d: %-38s\t[%s]\n", ++i, desc, + output("#%02d: %-38s\t[%s]\n", ++i, desc, (res->type == RESULT_OK) ? "PASS" : "FAIL"); switch (res->type) { case RESULT_DEATH: - printf("- driver died\n"); + output("- driver died\n"); break; case RESULT_COMMFAIL: - printf("- communication failed; sendrec returned %d\n", + output("- communication failed; sendrec returned %d\n", res->value); break; case RESULT_BADTYPE: - printf("- bad type %d in reply message\n", res->value); + output("- bad type %d in reply message\n", res->value); break; case RESULT_BADID: - printf("- mismatched ID %d in reply message\n", res->value); + output("- mismatched ID %d in reply message\n", res->value); break; case RESULT_BADSTATUS: - printf("- bad or unexpected status %d in reply message\n", + output("- bad or unexpected status %d in reply message\n", res->value); break; case RESULT_TRUNC: - printf("- result size not as expected (%u bytes left)\n", + output("- result size not as expected (%u bytes left)\n", res->value); break; case RESULT_CORRUPT: - printf("- buffer has been modified erroneously\n"); + output("- buffer has been modified erroneously\n"); break; case RESULT_MISSING: - printf("- buffer has been left untouched erroneously\n"); + output("- buffer has been left untouched erroneously\n"); break; case RESULT_OVERFLOW: - printf("- area around target buffer modified\n"); + output("- area around target buffer modified\n"); break; case RESULT_BADVALUE: - printf("- bad or unexpected return value %d from call\n", + output("- bad or unexpected return value %d from call\n", res->value); break; } @@ -155,7 +210,7 @@ static void test_group(char *name, int exec) /* Start a new group of tests. */ - printf("Test group: %s%s\n", name, exec ? "" : " (skipping)"); + output("Test group: %s%s\n", name, exec ? "" : " (skipping)"); group_failure = FALSE; } @@ -196,7 +251,7 @@ static int sendrec_driver(message *m_ptr, ssize_t exp, result_t *res) /* The driver has died. Find its new endpoint, and reopen all * devices that we opened earlier. Then return failure. */ - printf("WARNING: driver has died, attempting to proceed\n"); + output("WARNING: driver has died, attempting to proceed\n"); driver_deaths++; @@ -325,9 +380,7 @@ static void alloc_buf_and_grant(u8_t **ptr, cp_grant_id_t *grant, * grant for it with the requested CPF_* grant permissions. */ - *ptr = alloc_contig(size, 0, NULL); - if (*ptr == NULL) - panic("unable to allocate memory"); + *ptr = alloc_dma_memory(size); if ((*grant = cpf_grant_direct(driver_endpt, (vir_bytes) *ptr, size, perms)) == GRANT_INVALID) @@ -341,7 +394,7 @@ static void free_buf_and_grant(u8_t *ptr, cp_grant_id_t grant, size_t size) cpf_revoke(grant); - free_contig(ptr, size); + free_dma_memory(ptr, size); } static void bad_read1(void) @@ -895,10 +948,8 @@ static void vector_and_large_sub(size_t small_size) buf_size = large_size + sizeof(u32_t) * 2; buf2_size = large_size + sizeof(u32_t) * (NR_IOREQS + 1); - buf_ptr = alloc_contig(buf_size, 0, NULL); - buf2_ptr = alloc_contig(buf2_size, 0, NULL); - if (buf_ptr == NULL || buf2_ptr == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); + buf2_ptr = alloc_dma_memory(buf2_size); /* The first buffer has one large chunk with dword-sized guards on each * side. LPTR(n) points to the start of the nth small data chunk within @@ -1002,8 +1053,8 @@ static void vector_and_large_sub(size_t small_size) #undef SPTR /* Clean up. */ - free_contig(buf2_ptr, buf2_size); - free_contig(buf_ptr, buf_size); + free_dma_memory(buf2_ptr, buf2_size); + free_dma_memory(buf_ptr, buf_size); } static void vector_and_large(void) @@ -1015,6 +1066,12 @@ static void vector_and_large(void) */ size_t max_block; + /* Make sure that the maximum size does not exceed the target device + * size, minus the margins we need for testing here and there. + */ + if (max_size > part.size - sector_size * 4) + max_size = part.size - sector_size * 4; + /* Compute the largest sector multiple which, when multiplied by * NR_IOREQS, is no more than the maximum transfer size. Note that if * max_size is not a multiple of sector_size, we're not going up to the @@ -1141,7 +1198,7 @@ static void misc_ioctl(void) /* The other tests do not check whether there is sufficient room. */ if (res.type == RESULT_OK && part.size < (u64_t)max_size * 2) - printf("WARNING: small partition, some tests may fail\n"); + output("WARNING: small partition, some tests may fail\n"); /* Test retrieving global driver open count. */ openct = 0x0badcafe; @@ -1197,9 +1254,7 @@ static void read_limits(dev_t sub0_minor, dev_t sub1_minor, size_t sub_size) test_group("read around subpartition limits", TRUE); buf_size = sector_size * 3; - - if ((buf_ptr = alloc_contig(buf_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); /* Read one sector up to the partition limit. */ fill_rand(buf_ptr, buf_size); @@ -1295,7 +1350,7 @@ static void read_limits(dev_t sub0_minor, dev_t sub1_minor, size_t sub_size) got_result(&res, "read with negative offset"); /* Clean up. */ - free_contig(buf_ptr, buf_size); + free_dma_memory(buf_ptr, buf_size); } static void write_limits(dev_t sub0_minor, dev_t sub1_minor, size_t sub_size) @@ -1317,9 +1372,7 @@ static void write_limits(dev_t sub0_minor, dev_t sub1_minor, size_t sub_size) return; buf_size = sector_size * 3; - - if ((buf_ptr = alloc_contig(buf_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); /* Write to the start of the second subpartition, so that we can * reliably check whether the contents have changed later. @@ -1436,7 +1489,7 @@ static void write_limits(dev_t sub0_minor, dev_t sub1_minor, size_t sub_size) got_result(&res, "read up to partition end"); /* Clean up. */ - free_contig(buf_ptr, buf_size); + free_dma_memory(buf_ptr, buf_size); } static void vir_limits(dev_t sub0_minor, dev_t sub1_minor, int part_secs) @@ -1531,9 +1584,7 @@ static void real_limits(dev_t sub0_minor, dev_t sub1_minor, int part_secs) * anyway. */ buf_size = sector_size; - - if ((buf_ptr = alloc_contig(buf_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); memset(buf_ptr, 0, buf_size); @@ -1642,7 +1693,7 @@ static void real_limits(dev_t sub0_minor, dev_t sub1_minor, int part_secs) close_device(sub0_minor); close_device(sub1_minor); - free_contig(buf_ptr, buf_size); + free_dma_memory(buf_ptr, buf_size); } static void part_limits(void) @@ -1658,7 +1709,7 @@ static void part_limits(void) * cannot conduct this test. */ if (driver_minor >= MINOR_d0p0s0) { - printf("WARNING: operating on subpartition, " + output("WARNING: operating on subpartition, " "skipping partition tests\n"); return; } @@ -1879,14 +1930,9 @@ static void unaligned_size(void) base_pos = (u64_t)sector_size * 2; - if ((buf_ptr = alloc_contig(buf_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); - - if ((sec_ptr[0] = alloc_contig(sector_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); - - if ((sec_ptr[1] = alloc_contig(sector_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); + sec_ptr[0] = alloc_dma_memory(sector_size); + sec_ptr[1] = alloc_dma_memory(sector_size); if (may_write) { sum = fill_rand(buf_ptr, buf_size); @@ -1947,9 +1993,9 @@ static void unaligned_size(void) } /* Clean up. */ - free_contig(sec_ptr[1], sector_size); - free_contig(sec_ptr[0], sector_size); - free_contig(buf_ptr, buf_size); + free_dma_memory(sec_ptr[1], sector_size); + free_dma_memory(sec_ptr[0], sector_size); + free_dma_memory(buf_ptr, buf_size); } static void unaligned_pos1(void) @@ -1983,11 +2029,8 @@ static void unaligned_pos1(void) base_pos = (u64_t)sector_size * 3; - if ((buf_ptr = alloc_contig(buf_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); - - if ((buf2_ptr = alloc_contig(buf2_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); + buf2_ptr = alloc_dma_memory(buf2_size); if (may_write) { sum = fill_rand(buf_ptr, buf_size); @@ -2100,8 +2143,8 @@ static void unaligned_pos1(void) got_result(&res, "multisector read with lead and trail"); /* Clean up. */ - free_contig(buf2_ptr, buf2_size); - free_contig(buf_ptr, buf_size); + free_dma_memory(buf2_ptr, buf2_size); + free_dma_memory(buf_ptr, buf_size); } static void unaligned_pos2(void) @@ -2131,11 +2174,8 @@ static void unaligned_pos2(void) base_pos = (u64_t)sector_size * 3; - if ((buf_ptr = alloc_contig(buf_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); - - if ((buf2_ptr = alloc_contig(buf2_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); + buf2_ptr = alloc_dma_memory(buf2_size); /* First establish a baseline. We need two requests for this, as the * total area intentionally exceeds the max request size. @@ -2244,8 +2284,8 @@ static void unaligned_pos2(void) got_result(&res, "large fully unaligned filled vector"); /* Clean up. */ - free_contig(buf2_ptr, buf2_size); - free_contig(buf_ptr, buf_size); + free_dma_memory(buf2_ptr, buf2_size); + free_dma_memory(buf_ptr, buf_size); } static void sweep_area(u64_t base_pos) @@ -2261,9 +2301,7 @@ static void sweep_area(u64_t base_pos) int i, j; buf_size = sector_size * 8; - - if ((buf_ptr = alloc_contig(buf_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); /* First (write to, if allowed, and) read from the entire area in one * go, so that we know the (initial) contents of the area. @@ -2336,7 +2374,7 @@ static void sweep_area(u64_t base_pos) } /* Clean up. */ - free_contig(buf_ptr, buf_size); + free_dma_memory(buf_ptr, buf_size); } static void sweep_and_check(u64_t pos, int check_integ) @@ -2353,9 +2391,7 @@ static void sweep_and_check(u64_t pos, int check_integ) if (check_integ) { buf_size = sector_size * 3; - - if ((buf_ptr = alloc_contig(buf_size, 0, NULL)) == NULL) - panic("unable to allocate memory"); + buf_ptr = alloc_dma_memory(buf_size); if (may_write) { sum = fill_rand(buf_ptr, buf_size); @@ -2391,7 +2427,7 @@ static void sweep_and_check(u64_t pos, int check_integ) got_result(&res, "check integrity zone"); - free_contig(buf_ptr, buf_size); + free_dma_memory(buf_ptr, buf_size); } } @@ -2653,7 +2689,20 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) srand48(now); - return OK; + output("BLOCKTEST: driver label '%s' (endpt %d), minor %d\n", + driver_label, driver_endpt, driver_minor); + + do_tests(); + + output("BLOCKTEST: summary: %d out of %d tests failed " + "across %d group%s; %d driver deaths\n", + failed_tests, total_tests, failed_groups, + failed_groups == 1 ? "" : "s", driver_deaths); + + /* The returned code will determine the outcome of the RS call, and + * thus the entire test. The actual error code does not matter. + */ + return (failed_tests) ? EINVAL : OK; } static void sef_local_startup(void) @@ -2674,15 +2723,5 @@ int main(int argc, char **argv) env_setargs(argc, argv); sef_local_startup(); - printf("BLOCKTEST: driver label '%s' (endpt %d), minor %d\n", - driver_label, driver_endpt, driver_minor); - - do_tests(); - - printf("BLOCKTEST: summary: %d out of %d tests failed " - "across %d group%s; %d driver deaths\n", - failed_tests, total_tests, failed_groups, - failed_groups == 1 ? "" : "s", driver_deaths); - return 0; } -- 2.44.0