Add "blocktest" test, for testing block drivers
The test is located in test/blocktest. It requires hand-editing of its configuration, and is not part of any automated test set.
This commit is contained in:
		
							parent
							
								
									ff542f0b27
								
							
						
					
					
						commit
						fc34180cca
					
				
							
								
								
									
										13
									
								
								test/blocktest/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/blocktest/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					# Makefile for the Block Device Driver Test driver (blocktest)
 | 
				
			||||||
 | 
					PROG=	blocktest
 | 
				
			||||||
 | 
					SRCS=	blocktest.c optset.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DPADD+=	${LIBSYS}
 | 
				
			||||||
 | 
					LDADD+=	-lsys
 | 
				
			||||||
 | 
					CPPFLAGS+=-I${MINIXSRCDIR}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MAN=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BINDIR?= /usr/sbin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.include <bsd.prog.mk>
 | 
				
			||||||
							
								
								
									
										10
									
								
								test/blocktest/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								test/blocktest/README
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					Instructions on how to use blocktest:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1) compile it by running 'make'
 | 
				
			||||||
 | 
					2) read test.sh
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
							
								
								
									
										2722
									
								
								test/blocktest/blocktest.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2722
									
								
								test/blocktest/blocktest.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										128
									
								
								test/blocktest/optset.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								test/blocktest/optset.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					/* This file provides functionality to parse strings of comma-separated
 | 
				
			||||||
 | 
					 * options, each being either a single key name or a key=value pair, where the
 | 
				
			||||||
 | 
					 * value may be enclosed in quotes. A table of optset entries is provided to
 | 
				
			||||||
 | 
					 * determine which options are recognized, how to parse their values, and where
 | 
				
			||||||
 | 
					 * to store those. Unrecognized options are silently ignored; improperly
 | 
				
			||||||
 | 
					 * formatted options are silently set to reasonably acceptable values.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The entry points into this file are:
 | 
				
			||||||
 | 
					 *   optset_parse	parse the given options string using the given table
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Created:
 | 
				
			||||||
 | 
					 *   May 2009 (D.C. van Moolenbroek)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define _MINIX 1
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <minix/config.h>
 | 
				
			||||||
 | 
					#include <minix/const.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "optset.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FORWARD _PROTOTYPE( void optset_parse_entry, (struct optset *entry,
 | 
				
			||||||
 | 
											char *ptr, int len)	);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*===========================================================================*
 | 
				
			||||||
 | 
					 *				optset_parse_entry			     *
 | 
				
			||||||
 | 
					 *===========================================================================*/
 | 
				
			||||||
 | 
					PRIVATE void optset_parse_entry(entry, ptr, len)
 | 
				
			||||||
 | 
					struct optset *entry;
 | 
				
			||||||
 | 
					char *ptr;
 | 
				
			||||||
 | 
					int len;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					/* Parse and store the value of a single option.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					  char *dst;
 | 
				
			||||||
 | 
					  int val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  switch (entry->os_type) {
 | 
				
			||||||
 | 
					  case OPT_BOOL:
 | 
				
			||||||
 | 
						*((int *) entry->os_ptr) = entry->os_val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case OPT_STRING:
 | 
				
			||||||
 | 
						if (len >= entry->os_val)
 | 
				
			||||||
 | 
							len = entry->os_val - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dst = (char *) entry->os_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (len > 0)
 | 
				
			||||||
 | 
							memcpy(dst, ptr, len);
 | 
				
			||||||
 | 
						dst[len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case OPT_INT:
 | 
				
			||||||
 | 
						if (len > 0)
 | 
				
			||||||
 | 
							val = strtol(ptr, NULL, entry->os_val);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							val = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*((int *) entry->os_ptr) = val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*===========================================================================*
 | 
				
			||||||
 | 
					 *				optset_parse				     *
 | 
				
			||||||
 | 
					 *===========================================================================*/
 | 
				
			||||||
 | 
					PUBLIC void optset_parse(table, string)
 | 
				
			||||||
 | 
					struct optset *table;
 | 
				
			||||||
 | 
					char *string;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					/* Parse a string of options, using the provided table of optset entries.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					  char *p, *kptr, *vptr;
 | 
				
			||||||
 | 
					  int i, klen, vlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (p = string; *p; ) {
 | 
				
			||||||
 | 
						/* Get the key name for the field. */
 | 
				
			||||||
 | 
						for (kptr = p, klen = 0; *p && *p != '=' && *p != ','; p++, klen++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*p == '=') {
 | 
				
			||||||
 | 
							/* The field has an associated value. */
 | 
				
			||||||
 | 
							vptr = ++p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* If the first character after the '=' is a quote character,
 | 
				
			||||||
 | 
							 * find a matching quote character followed by either a comma
 | 
				
			||||||
 | 
							 * or the terminating null character, and use the string in
 | 
				
			||||||
 | 
							 * between. Otherwise, use the string up to the next comma or
 | 
				
			||||||
 | 
							 * the terminating null character.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (*p == '\'' || *p == '"') {
 | 
				
			||||||
 | 
								p++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (vlen = 0; *p && (*p != *vptr ||
 | 
				
			||||||
 | 
									(p[1] && p[1] != ',')); p++, vlen++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (*p) p++;
 | 
				
			||||||
 | 
								vptr++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								for (vlen = 0; *p && *p != ','; p++, vlen++);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							vptr = NULL;
 | 
				
			||||||
 | 
							vlen = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*p == ',') p++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Find a matching entry for this key in the given table. If found,
 | 
				
			||||||
 | 
						 * call optset_parse_entry() on it. Silently ignore the option
 | 
				
			||||||
 | 
						 * otherwise.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						for (i = 0; table[i].os_name != NULL; i++) {
 | 
				
			||||||
 | 
							if ((int) strlen(table[i].os_name) == klen &&
 | 
				
			||||||
 | 
								!strncasecmp(table[i].os_name, kptr, klen)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								optset_parse_entry(&table[i], vptr, vlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								test/blocktest/optset.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								test/blocktest/optset.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					#ifndef _OPTSET_H
 | 
				
			||||||
 | 
					#define _OPTSET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					  OPT_BOOL,
 | 
				
			||||||
 | 
					  OPT_STRING,
 | 
				
			||||||
 | 
					  OPT_INT
 | 
				
			||||||
 | 
					} opt_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* An entry for the parser of an options set. The 'os_name' field must point
 | 
				
			||||||
 | 
					 * to a string, which is treated case-insensitively; the last entry of a table
 | 
				
			||||||
 | 
					 * must have NULL name. The 'os_type' field must be set to one of the OPT_
 | 
				
			||||||
 | 
					 * values defined above. The 'os_ptr' field must point to the field that is to
 | 
				
			||||||
 | 
					 * receive the value of a recognized option. For OPT_STRING, it must point to a
 | 
				
			||||||
 | 
					 * string of a size set in 'os_val'; the resulting string may be truncated, but
 | 
				
			||||||
 | 
					 * will always be null-terminated. For OPT_BOOL, it must point to an int which
 | 
				
			||||||
 | 
					 * will be set to the value in 'os_val' if the option is present. For OPT_INT,
 | 
				
			||||||
 | 
					 * it must point to an int which will be set to the provided option value;
 | 
				
			||||||
 | 
					 * 'os_val' is then a base passed to strtol().
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct optset {
 | 
				
			||||||
 | 
					  char *os_name;
 | 
				
			||||||
 | 
					  opt_type os_type;
 | 
				
			||||||
 | 
					  void *os_ptr;
 | 
				
			||||||
 | 
					  int os_val;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_PROTOTYPE( void optset_parse, (struct optset *table, char *string)	);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _OPTSET_H */
 | 
				
			||||||
							
								
								
									
										56
									
								
								test/blocktest/test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										56
									
								
								test/blocktest/test.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The blocktest driver expects the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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,
 | 
				
			||||||
 | 
					#              on other partitions and possibly other disks) WILL BE DESTROYED.
 | 
				
			||||||
 | 
					#              Use "ro" for read-only mediums, such as CD-ROMs.
 | 
				
			||||||
 | 
					# sector       Sector size, in bytes. This should be 512 for ATA devices, and
 | 
				
			||||||
 | 
					#              2048 for ATAPI devices.
 | 
				
			||||||
 | 
					# min_read     Minimum size of a read request. This must be at least 2 and at
 | 
				
			||||||
 | 
					#              most the sector size, and the sector size must be divisible by
 | 
				
			||||||
 | 
					#              it. A value other than the sector size allows blocktest to test
 | 
				
			||||||
 | 
					#              sub-sector reads. Sub-sector writes are currently not supported
 | 
				
			||||||
 | 
					#              by any driver and hence not by blocktest, so there is no
 | 
				
			||||||
 | 
					#              matching "min_write" (yet).
 | 
				
			||||||
 | 
					# element      Minimum size of a vector element within a larger I/O request.
 | 
				
			||||||
 | 
					#              This must be at least 2 and at most min_read, and min_read must
 | 
				
			||||||
 | 
					#              be divisible by this value. The idea is that several small
 | 
				
			||||||
 | 
					#              elements may add up to the minimum read size.
 | 
				
			||||||
 | 
					# max          Maximum size of any request. This should be a multiple of the
 | 
				
			||||||
 | 
					#              sector size. Blocktest will not test what happens when this
 | 
				
			||||||
 | 
					#              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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user