blocktest: resolve label/minor in userland

The test script now resolves the device node into a <label,minor>
pair, so that the blocktest driver itself no longer has to. This
removes blocktest's dependency on VFS' internal data structures.

Also allow blocktest to be linked using with gcc/clang.
This commit is contained in:
David van Moolenbroek 2011-12-11 15:37:35 +01:00
parent 35cf8beb33
commit 95d1f25b28
6 changed files with 66 additions and 73 deletions

View file

@ -4,10 +4,10 @@ SRCS= blocktest.c
DPADD+= ${LIBSYS}
LDADD+= -lsys
CPPFLAGS+=-I${MINIXSRCDIR}
MAN=
BINDIR?= /usr/sbin
.include <bsd.prog.mk>
.include "Makefile.inc"
.include <minix.service.mk>

View file

@ -0,0 +1,9 @@
# Copied from drivers/Makefile.inc, and slightly edited.
.if ${COMPILER_TYPE} == "gnu"
CPPFLAGS+= -D_MINIX -D_NETBSD_SOURCE
LDADD+= -lminlib -lcompat_minix -lc
DPADD+= ${LIBMINLIB} ${LIBCOMPAT_MINIX}
.else
CPPFLAGS+= -D_MINIX -D_POSIX_SOURCE
.endif
BINDIR?=/usr/sbin

View file

@ -5,6 +5,3 @@ Instructions on how to use blocktest:
3) edit and uncomment one line from test.sh
4) run './test.sh'
5) read the output in /var/log/messages
WARNING: while this tool works with both VFS and AVFS, it has been configured
to use AVFS's headers. Either use with AVFS, or edit blocktest.c first.

View file

@ -1,19 +1,12 @@
/* Block Device Driver Test driver, by D.C. van Moolenbroek */
#include <stdlib.h>
#include <sys/stat.h>
#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#include <minix/dmap.h>
#include <minix/sysinfo.h>
#include <minix/ds.h>
#include <minix/optset.h>
#include <sys/ioc_disk.h>
#include <assert.h>
/* FIXME: use servers/vfs/.. with VFS */
#include "servers/avfs/const.h"
#include "servers/avfs/dmap.h"
enum {
RESULT_OK, /* exactly as expected */
RESULT_COMMFAIL, /* communication failed */
@ -32,9 +25,8 @@ typedef struct {
ssize_t value;
} result_t;
PRIVATE char device_path[PATH_MAX]; /* path to device node to use */
PRIVATE char driver_label[LABEL_MAX]; /* driver DS label */
PRIVATE dev_t driver_minor; /* driver's partition minor to use */
PRIVATE char driver_label[32] = ""; /* driver DS label */
PRIVATE dev_t driver_minor = -1; /* driver's partition minor to use */
PRIVATE endpoint_t driver_endpt; /* driver endpoint */
PRIVATE int may_write = FALSE; /* may we write to the device? */
@ -60,7 +52,8 @@ PRIVATE int driver_deaths = 0; /* number of restarts that we saw */
/* Options supported by this driver. */
PRIVATE struct optset optset_table[] = {
{ "device", OPT_STRING, device_path, sizeof(device_path) },
{ "label", OPT_STRING, driver_label, sizeof(driver_label) },
{ "minor", OPT_INT, &driver_minor, 10 },
{ "rw", OPT_BOOL, &may_write, TRUE },
{ "ro", OPT_BOOL, &may_write, FALSE },
{ "sector", OPT_INT, &sector_size, 10 },
@ -2569,41 +2562,6 @@ PRIVATE void do_tests(void)
close_primary();
}
PRIVATE void map_device(char *path)
{
/* Map a device node to a label, endpoint, and minor device number.
* This should be replaced with something better some day. For now,
* it seems this is the only working approach.
*/
static struct dmap dmap[NR_DEVICES];
struct stat statbuf;
dev_t major;
int r;
if ((r = stat(path, &statbuf)) != OK)
panic("unable to stat '%s'", path);
if (!S_ISBLK(statbuf.st_mode) || major(statbuf.st_rdev) >= NR_DEVICES)
panic("'%s' is not a block device", path);
major = major(statbuf.st_rdev);
driver_minor = minor(statbuf.st_rdev);
if ((r = getsysinfo(VFS_PROC_NR, SI_DMAP_TAB, dmap)) != OK)
panic("unable to get dmap table from VFS: %d", r);
if (driver_endpt == NONE || !dmap[major].dmap_label[0])
panic("no driver present for given device");
strcpy(driver_label, dmap[major].dmap_label);
if (ds_retrieve_label_endpt(driver_label, &driver_endpt))
panic("unable to resolve label");
if (driver_endpt != dmap[major].dmap_driver)
panic("endpoint mismatch between VFS and DS");
}
PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
{
/* Initialize.
@ -2614,10 +2572,14 @@ PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
if (env_argc > 1)
optset_parse(optset_table, env_argv[1]);
if (device_path[0] == '\0')
panic("no device path given");
if (driver_label[0] == '\0')
panic("no driver label given");
map_device(device_path);
if (ds_retrieve_label_endpt(driver_label, &driver_endpt))
panic("unable to resolve driver label");
if (driver_minor > 255)
panic("invalid or no driver minor given");
if ((r = getuptime(&now)) != OK)
panic("unable to get uptime: %d", r);

19
test/blocktest/support.sh Normal file
View file

@ -0,0 +1,19 @@
# Supporting routines for blocktest. Do not run directly.
# usage: devtopair /dev/cXdY..
# returns a label, minor pair in the form "label=at_wini_N,minor=M"
devtopair() {
label=`awk "/^$(stat -f '%Hr' $1) / "'{print $2}' /proc/dmap`
if [ ! -z "$label" ]; then echo "label=$label,minor=`stat -f '%Lr' $1`"; fi
}
# usage: blocktest /dev/cXdY.. "params,for,blocktest"
# runs the blocktest driver on the given device with the given parameters
blocktest() {
if [ ! -x blocktest ]; then echo "compile blocktest first!" >&2; exit 1; fi
if [ ! -b "$1" ]; then echo "$1 is not a block device" >&2; exit 1; fi
pair=$(devtopair $1)
if [ -z "$pair" ]; then echo "driver not found for $1" >&2; exit 1; fi
service up `pwd`/blocktest -args "$pair,$2" -config system.conf \
-script /etc/rs.single -label blocktest_$(stat -f '%r' $1)
}

View file

@ -1,13 +1,21 @@
#!/bin/sh
# The blocktest driver expects the following parameters:
. support.sh
# The following commented-out examples of how to run blocktest for certain
# driver and device pairs. The syntax of the calls is:
#
# blocktest <device> <parameters>
#
# <device> is the path to a device to run blocktest on. This may be a full
# disk, a partition, or a subpartition. If possible, give blocktest the whole
# disk; otherwise preferably the first partition with a size of slightly over
# 8GB (for ATA) (better yet: slightly over 128GB); even fewer tests can be done
# if you give it only a subpartition.
#
# <parameters> is a comma-separated list of parameters for blocktest. The
# following parameters are supported and in fact expected:
#
# device Path to the device node to perform the test on. This may be a
# full disk, a partition, or a subpartition. If possible, give
# blocktest the whole disk; otherwise preferably the first
# partition with a size of slightly over 8GB (for ATA) (better
# yet: slightly over 128GB); even fewer tests can be done if you
# give it only a subpartition.
# rw (or) ro Specifying "rw" will let blocktest write to the target
# partition. This allows for a lot more tests, but keep in mind
# that any data on the partition (and, if the driver misbehaves,
@ -30,27 +38,25 @@
# value is exceeded, but it will generate large requests up to
# this value. For drivers that do not have a maximum request size,
# simply use some large value (typically several megabytes).
# The following are examples of how to configure blocktest for certain driver
# and device pairs. Before commenting out any entry, you MUST edit the "device"
# option for that entry, or you WILL risk losing arbitrary data. You may run
# multiple tests in parallel (on different devices), but you will then have to
# give them different labels. Note that at_wini has no maximum request size, so
# an arbitray size is used. Finally, a disclaimer: a buggy device driver may
# destroy any data it has access to, so use at your own risk.
#
# Before commenting out any entry, you MUST edit the device name for that
# entry, or you WILL risk losing arbitrary data. You may run multiple tests in
# parallel, on different devices. Note that at_wini has no maximum request
# size, so an arbitray size is used. Finally, a disclaimer: a buggy device
# driver may destroy any data it has access to, so use at your own risk.
# AT_WINI ATA TEST (for IDE disk devices)
#service up `pwd`/blocktest -script /etc/rs.single -args "device=/dev/c0d1,rw,sector=512,min_read=512,element=2,max=16777216" -config system.conf -label blocktest_0
#blocktest /dev/c0d1 "rw,sector=512,min_read=512,element=2,max=16777216"
# AT_WINI ATAPI TEST (for IDE CD-ROM devices)
#service up `pwd`/blocktest -script /etc/rs.single -args "device=/dev/c0d2,ro,sector=2048,min_read=2,element=2,max=16777216" -config system.conf -label blocktest_0
#blocktest /dev/c0d2 "ro,sector=2048,min_read=2,element=2,max=16777216"
# AHCI ATA TEST (for SATA disk devices)
#service up `pwd`/blocktest -script /etc/rs.single -args "device=/dev/c2d0,rw,sector=512,min_read=2,element=2,max=4194304" -config system.conf -label blocktest_0
#blocktest /dev/c2d0 "rw,sector=512,min_read=2,element=2,max=4194304"
# AHCI ATAPI TEST (for SATA CD-ROM devices)
#service up `pwd`/blocktest -script /etc/rs.single -args "device=/dev/c2d1,ro,sector=2048,min_read=2,element=2,max=4194304" -config system.conf -label blocktest_0
#blocktest /dev/c2d1 "ro,sector=2048,min_read=2,element=2,max=4194304"