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
This commit is contained in:
David van Moolenbroek 2013-09-18 13:41:56 +02:00 committed by Lionel Sambuc
parent d266a94fea
commit 38f7b96048
5 changed files with 133 additions and 82 deletions

View file

@ -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

View file

@ -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

View file

@ -16,6 +16,8 @@ LDADD+= -lm -lcompat_minix
.include <bsd.own.mk>
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 <bsd.prog.mk>
.include <bsd.subdir.mk>

View file

@ -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 <minix.service.mk>

View file

@ -1,10 +1,12 @@
/* Block Device Driver Test driver, by D.C. van Moolenbroek */
#include <stdlib.h>
#include <stdarg.h>
#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#include <minix/ds.h>
#include <minix/optset.h>
#include <sys/ioc_disk.h>
#include <sys/mman.h>
#include <assert.h>
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;
}