code: mafs

Download patch

ref: e245d319b6771cc672b5a39bfa2c065c27cea4b1
parent: 322ee5ed143f7655d4c3282bf4cf16d5b6c812e3
author: 9ferno <gophone2015@gmail.com>
date: Wed Nov 9 05:22:17 EST 2022

working mfs tests

--- a/9p.c
+++ b/9p.c
@@ -1,6 +1,7 @@
 #include "all.h"
 
 extern int mpstarted;
+extern u8 synchronouswrites;
 
 s32 readfile(u64 dblkno, u64 qpath, char *rbuf, s32 rbufsize, u64 offset);
 s32 writefile(u64 dblkno, u64 qpath, s16 uid, char *wbuf, s32 wbufsize, u64 offset);
@@ -900,18 +901,22 @@
 		rwakeupall(&buf.isempty);
 		qunlock(&buf.lck);
 	}
-	while((n=pendingwrites())>0){
-		if(chatty9p > 1)
-		dprint("shutdown: pendingwrites %llud of write queue\n", n);
-		sleep(1000);
+	if(synchronouswrites == 0){
+		while((n=pendingwrites())>0){
+			if(chatty9p > 1)
+			dprint("shutdown: pendingwrites %llud of write queue\n", n);
+			sleep(1000);
+		}
 	}
 	savefrees(Bdfrees);
-	while((n=pendingwrites())>0){
-		if(chatty9p > 1)
-		dprint("shutdown: pendingwrites %llud of frees\n", n);
-		sleep(1000);
+	if(synchronouswrites == 0){
+		while((n=pendingwrites())>0){
+			if(chatty9p > 1)
+			dprint("shutdown: pendingwrites %llud of frees\n", n);
+			sleep(1000);
+		}
+		stopwriter();
 	}
-	stopwriter();
 
 	/* free users, why bother? leave it alone */
 /*	u = t->users;
--- a/all.h
+++ b/all.h
@@ -78,6 +78,8 @@
 	};
 
 	/*
+		only used by mafs.
+
 		Using Ref to avoid using a wlock() in dowrite.
 		wlock() in dowrite() causes a deadlock with putwrite()
 
--- a/dat.h
+++ b/dat.h
@@ -448,7 +448,6 @@
 extern	u8 noauth;
 
 /* used by panic() */
-extern	char	*progname;
 extern	char	*procname;
 
 extern Config config;
--- a/docs/mafs.ms
+++ b/docs/mafs.ms
@@ -8,17 +8,21 @@
 .RT
 .ft B
 .ce
-Mafs - Plan 9 userspace file system
+M[a]fs - Plan 9 userspace file systems
 .ft R
 .sp
-Mafs wants you to be able to understand it, so you can be self-sufficient and fix a crash at two in the morning or satisfy your need for speed or a feature. This empowerment is priceless for those with skin in the game.
+Mfs and Mafs wants you to be able to understand it, so you can be self-sufficient and fix a crash at two in the morning or satisfy your need for speed or a feature. This empowerment is priceless for those with skin in the game.
 .sp
-Mafs is a user space file system to provide system stability and security. It is based on kfs.
+Mfs and Mafs are user space file systems to provide system stability and security. They are based on kfs.
 .sp
 As this document aims to also provide working knowledge, it gratuitously uses the actual commands and the relevant C data structure definitions to convey information.
 .sp
+Mfs writes synchronously to the disk. It ensures that what has been said to be written has been passed along to the disk driver. Mafs writes asynchronously to the disk. It stores the writes in memory for a writer process to write to the disk at leisure.
+.sp
+This document uses the word M[a]fs to refer to both mfs and mafs.
+.sp
 .ft B
-Workflow
+Mfs Workflow
 .ft R
 .sp
 .PS
@@ -45,6 +49,50 @@
 	Buffercache: box invis "Buffer cache" "used blocks" with .sw at Datastructures.ne + 0.5i,0
 	Extents: box invis "Extents" "free blocks" with .nw at Datastructures.se + 0.5i,0
 	move 0.5*boxwid
+	Inmemory: box invis "In-memory" "block contents" with .sw at Buffercache.n + 0.5i,0
+	down
+	move 0.5*boxwid
+	Disk: box "Disk" "blocks" height 1.5*boxht with .sw at Extents.se + 0.4i,0
+}
+	line <-> from Multiple.e to Abstractions.w - 0.1i,0
+	line <-> from Abstractions.e + 0.1i,0 to Datastructures.w - 0.2i,0
+	line <-> from Datastructures.e + 0,0.1i to Buffercache.w - 0.1i,0
+	line <-> from Datastructures.e - 0,0.1i to Extents.w
+	line <-> from Buffercache.se + 0.1i,0 to Disk.w
+	line <-> from Extents.e to Disk.w
+	line <-> from Buffercache.s to Extents.n
+	line <-> from Buffercache.ne - 0,0.1i to Inmemory.sw + 0,0.1i
+.PE
+.sp
+.ne 14
+.ft B
+Mafs Workflow
+.ft R
+.sp
+.PS
+right;
+{
+	Client: box invis height 4*boxht wid 2*boxwid "" "" "" "Chan.aux has" "file offset, etc.";
+	"Client" at Client.n
+	line from Client.ne to Client.se
+}
+move 2*boxwid
+{
+	Multiple: box invis
+	{
+		" multiple" at Multiple.nw - 0,0.1 ljust
+		" workers" at Multiple.sw + 0,0.1 ljust
+		line <-> from Client to Multiple.w "9p" above
+	}
+	move 0.5*boxwid
+	Abstractions: box invis "Abstractions"
+	{ "Directory" "File" at Abstractions.s }
+	move 0.75*boxwid
+	Datastructures: box invis "Data Structures"
+	{ "Dentry" at Datastructures.s }
+	Buffercache: box invis "Buffer cache" "used blocks" with .sw at Datastructures.ne + 0.5i,0
+	Extents: box invis "Extents" "free blocks" with .nw at Datastructures.se + 0.5i,0
+	move 0.5*boxwid
 	Writer: box invis "writer" with .nw at Buffercache.ne + 0.4i,0
 	Inmemory: box invis "In-memory" "block contents" with .sw at Buffercache.n + 0.5i,0
 	down
@@ -69,7 +117,7 @@
 Disk Contents
 .ft R
 .sp
-Mafs organizes and saves content on a disk as directories and files, just like any other filesystem.
+M[a]fs organizes and saves content on a disk as directories and files, just like any other filesystem.
 .sp
 The unit of storage is a logical block (not physical sector) of data. Disk space is split into 512 byte logical blocks.
 .sp
@@ -119,13 +167,13 @@
 .sp
 A file stores its contents in blocks with a Tag.type of Tdata. A directory holds the directory entries of it's children in blocks with a Tag.type of Tdentry.
 .sp
-The blocks used by a file or directory entry are listed in their directory entry. As it is not possible to represent big files using a list of blocks, the blocks are structured to use multiple levels of indirection as file size increases.
+The blocks used by a file or directory entry are listed in their directory entry. As it is not possible to represent big files using the list of blocks available in the directory entry, the blocks are structured to use multiple levels of indirection as the file size increases.
 .sp
-A file's data blocks are identified by a tag of Tdata and that file's Qid.path. A directory's data blocks are identified by a tag of Tdentry and Qid.path of the child directory entry. (Is this quirky? Should the child's directory entry have a tag o the parent's Qid.path?)
+A file's data blocks are identified by a tag of Tdata and that file's Qid.path. A directory's data blocks are identified by a tag of Tdentry and Qid.path of the child directory entry. (Is this quirky? Should the child's directory entry have a tag with the parent's Qid.path?)
 .sp
 A block number of zero represents the end of the file's contents. If a file is truncated, the data and indirect blocks are given up and the dentry.dblocks[0] = 0.
 .sp
-Mafs does not store the last access time of a file or directory.
+M[a]fs does not store the last access time of a file or directory.
 .ne 20
 .sp
 .nf
@@ -234,7 +282,7 @@
 .fi
 .ne 30
 .sp
-On an empty mafs filesystem mounted at /n/mafs, the disk contents added by the below commands are:
+On an empty m[a]fs filesystem mounted at /n/mafs, the disk contents added by the below commands are:
 .nf
 mkdir /n/mafs/dir1
 echo test > /n/mafs/dir1/file1
@@ -643,10 +691,10 @@
 .TE
 .ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n
 .sp
-Mafs needs atleast Nminblocks=17 blocks (8.5 KB). The middle block number is Nminblocks + ((nblocks - Nminblocks)/2), where nblocks = total number of blocks.
+M[a]fs needs atleast Nminblocks=17 blocks (8.5 KB). The middle block number is Nminblocks + ((nblocks - Nminblocks)/2), where nblocks = total number of blocks.
 .fi
 .sp
-kfs and cwfs use 8192 byte blocks. Hence, they store multiple directory entries (Dentry) per block. They use slot numbers to identify a particular directory entry in a block of directory entries. Mafs avoids that be using 512 byte blocks thus having only one directory entry per block. This avoids locking up other sibling directory entries on access.
+kfs and cwfs use 8192 byte blocks. Hence, they store multiple directory entries (Dentry) per block. They use slot numbers to identify a particular directory entry in a block of directory entries. M[a]fs avoids that be using 512 byte blocks thus having only one directory entry per block. This avoids locking up other sibling directory entries on access.
 .sp
 .sp
 .ft B
@@ -682,6 +730,19 @@
 		u8	*xiobuf;	/* "real" buffer pointer */
 		Content *io;	/* cast'able to contents */
 	};
+	/*
+		only used by mafs.
+
+		Using Ref to avoid using a wlock() in dowrite.
+		wlock() in dowrite() causes a deadlock with putwrite()
+
+		dirties is decremented without a wlock() on the buffer in dowrite().
+		Using a wlock() in dowrite() deadlocks with putwrite().
+		getbuf() guarantees that even a free'ed block cannot be
+		stolen until the dirties == 0. This avoids dirty blocks
+		being stolen by other block numbers.
+		incref(dirties) only happens with a wlock() in putwrite().
+	 */
 	Ref	dirties;	/* number of versions of this block yet to be written by the writer */
 };
 .fi
@@ -746,7 +807,7 @@
 .sp
 .ne 10
 .ft B
-Asynchronous writes
+Asynchronous writes of Mafs
 .ft R
 .sp
 The blocks to be written to a disk are stored to a linked list represented by:
@@ -780,7 +841,7 @@
 .sp
 The writer throttles input when there are more than Npendingwrites waiting to be written. This can be adjusted with the -w parameter.
 .sp
-The alternative to having a single writer process is to have each worker write to the disk too, synchronous writes. Synchronous writes makes writes happen at disk write speed. With asynchronous writes, memory is used to hold the data until written to the disk. This shows increased write throughput until we fill up memory. After filling up memory, writes happen at disk speed. Asynchronous writes have the side effect of a single disk write queue.
+The alternative to having a single writer process is to have each worker write to the disk, as mfs does. Synchronous writes throttles writes to disk write speed. With asynchronous writes, memory is used to hold the data until written to the disk. This shows increased write throughput until we fill up memory. After filling up memory, writes happen at disk speed. Asynchronous writes have the side effect of a single disk write queue.
 .sp
 .sp
 .ne 4
@@ -790,7 +851,7 @@
 .sp
 Free blocks are managed using Extents. The list of free blocks is stored to the disk when shutting down. If this state is not written, then the file system needs to be checked and the list of free blocks should be updated.
 .sp
-When shutting down, the Extents are written to free blocks. This information can be accessed from /adm/frees. Also, fsok in the super block is set to 1. Mafs does not start until fsok is 1. When fsok = 0, run the sanity check that the unused blocks and the free blocks in /adm/frees match up. disk/reconcile identifies any missing blocks or blocks that are marked as both used and free.
+When shutting down, the Extents are written to free blocks. This information can be accessed from /adm/frees. Also, fsok in the super block is set to 1. M[a]fs does not start until fsok is 1. When fsok = 0, run the sanity check that the unused blocks and the free blocks in /adm/frees match up. disk/reconcile identifies any missing blocks or blocks that are marked as both used and free.
 .sp
 This process of fixing issues and setting fsok to 1 is manual. There is no automatic file system checker as in other file systems. This document aims to empower you with the knowledge to fix your file system issues instead of entrusting your precious data to an arbitrary decision maker such as the file system checker.
 .sp
@@ -1087,7 +1148,7 @@
 Kfs stores the list of free blocks in a Tfrees block and the Superblock. Instead we use block management routines, similar to pool.h, to allocate and monitor free blocks. On shutdown(), the block management routines (extents.[ch]) store state into the free blocks. This can be read from /adm/frees. On startup, this is read back by the block management routines. On a crash, the fsck can walk the directory structure to identify the free blocks and recreate /adm/frees.
 .sp
 .sp
-.ne 4
+.ne 12
 .ft B
 Code details
 .ft R
@@ -1094,10 +1155,11 @@
 .sp
 .TS
 allbox;
-c l
+c c
 l a .
 Program	Description
 _
+disk/mfs	Start mfs on a disk.
 disk/mafs	Start mafs on a disk.
 disk/free	List the free blocks. It reads the contents of /adm/frees.
 disk/used	List the used blocks by traversing all directory entries.
@@ -1108,7 +1170,7 @@
 .sp
 .TS
 allbox;
-c l r
+c c r
 l a r .
 File	Description	chatty9p
 _
@@ -1136,8 +1198,10 @@
 Useful commands:
 .ft R
 .sp
-Ream and start single process Mafs on a disk and also mount it for use.
+disk/mfs and disk/mafs have the same arguments. The following commands use disk/mafs to avoid duplicating them for disk/mfs.
 .sp
+Ream and start single process M[a]fs on a disk and also mount it for use.
+.sp
 .nf
 	mount -c <{disk/mafs -s -r mafs_myservice -h 10  mydisk  <[0=1]} /n/mafs_myservice
 .in 3n
@@ -1145,7 +1209,7 @@
 	-s: use stdin and stdout for communication
 	-r mafs_myservice: ream the disk using mafs_myservice as the service name
 	-h 10: use 10 hash buckets
-	 mydisk: running Mafs on the mydisk
+	 mydisk: running mafs on the disk, mydisk
 .in 0
 .fi
 .sp
@@ -1201,11 +1265,11 @@
 	mount -c /srv/mafs_ramfs_file /n/mafs_ramfs_file
 .fi
 .sp
-Sync Mafs. This command does not return until all the writes are written to the disk. So, could take a long time if you have a long writer queue.
+Sync M[a]fs. This command does not return until all the writes are written to the disk. So, could take a long time if you have a long writer queue.
 .sp
 	echo sync >> /n/mafs_myservice/adm/ctl
 .sp
-Stop Mafs. This command does not return until all the writes are written to the disk. So, could take a long time if you have a long writer queue.
+Stop M[a]fs. This command does not return until all the writes are written to the disk. So, could take a long time if you have a long writer queue.
 .sp
 	echo halt >> /n/mafs_myservice/adm/ctl
 .sp
@@ -1263,7 +1327,67 @@
 	diff <{disk/unused -l <{disk/used $disk} $nblocks}} <{disk/free $disk}
 .fi
 .sp
+Changing the service name without a ream.
 .sp
+.nf
+	disk/block /dev/sdF1/fs 1 | wc
+	Tdata 2
+	size 6001172505088
+	nblocks 11721040049
+	backup config 1 to 11721040048 5860520032
+	backup super 2 to 11721040047 5860520031
+	backup root 3 to 11721040046 5860520030
+	service mafs_ddf_1
+
+	dd -if /dev/sdF1/fs -count 10 -skip 682 -bs 1
+	mafs_ddf_110+0 records in
+	10+0 records out
+
+	dd -if <{echo m_ddf_1; cat /dev/zero} -of /dev/sdF1/fs -count 11 -oseek 682 -bs 1
+	7+0 records in
+	7+0 records out
+
+	disk/block /dev/sdF1/fs 1
+	Tdata 2
+	size 6001172505088
+	nblocks 11721040049
+	backup config 1 to 11721040048 5860520032
+	backup super 2 to 11721040047 5860520031
+	backup root 3 to 11721040046 5860520030
+	service m_ddf_1
+.fi
+.sp
+Changing the magic phrase in the magic block.
+.sp
+.nf
+	disk/block /dev/sdF1/fs 0
+	Tmagic 1
+	mafs device
+	512
+
+	dd -if /dev/sdF1/fs -count 16 -iseek 256 -bs 1
+	mafs device
+	512
+	20+0 records in
+	20+0 records out
+
+	dd -if <{echo m[a]fs device; echo 512; cat /dev/zero} -of /dev/sdF1/fs -count 18 -oseek 256 -bs 1
+	18+0 records in
+	18+0 records out
+
+	dd -if /dev/sdF1/fs -count 18 -iseek 256 -bs 1
+	m[a]fs device
+	512
+	18+0 records in
+	18+0 records out
+
+	disk/block /dev/sdF1/fs 0
+	Tmagic 1
+	m[a]fs device
+	512
+.fi
+.sp
+.sp
 .ne 20
 .ft B
 Tests
@@ -1292,13 +1416,13 @@
 1. Initializes a disk for mafs.
 .br
 .ti 0
-2. Run mafs on that dsk.
+2. Run mfs and mafs on that dsk.
 .br
 .ti 0
-3. Stop mafs.
+3. Stop mfs or mafs.
 .br
 .ti 0
-4. Compares the contents with the expected contents (tests/test.0/blocks/*).
+4. Compare the contents with the expected contents (tests/test.0/blocks/*).
 .in 0
 .sp
 .TS
@@ -1347,14 +1471,21 @@
 tests/extents/mergenext	Figure 5 of the Extents section
 tests/extents/mergeprevious	Figure 6 of the Extents section
 .TE
+.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n
+.in 0
 .sp
 .ne 3
+To run all the regression tests:
+.br
 .nf
+	cd tests/; ./regress.rc
+.fi
+.sp
+.ne 3
 To loop through all the blocks of a test:
-.in 3n
 .br
-for(t in tests/test.2/blocks/^`{seq 0 39}*){ echo $t; echo '---------'; cat $t; echo }
-.in 0
+.nf
+	for(t in tests/test.2/blocks/^`{seq 0 39}*){ echo $t; echo '---------'; cat $t; echo }
 .fi
 .sp
 .sp
@@ -1363,7 +1494,7 @@
 Limitations
 .ft R
 .sp
-As we use packed structs to store data to the disk, a disk with mafs is not portable to a machine using a different endian system.
+As we use packed structs to store data to the disk, a disk with m[a]fs is not portable to a machine using a different endian system.
 .sp
 .sp
 .ft B
@@ -1372,7 +1503,7 @@
 .sp
 Why are you not using a checksum to verify the contents?
 .br
-Checksums are probabilistic and can be implemented as a bespoke application instead of complicating the filesystem.
+Checksums are probabilistic and can be implemented as a bespoke application instead of complicating the file system implementation.
 .sp
 .sp
 .ft B
--- a/mafs.c
+++ b/mafs.c
@@ -11,7 +11,6 @@
 short*	gidspace;
 RWLock	mainlock;
 Tlock	*tlocks;
-char	*progname;
 char	*procname;
 
 char *devfile = nil;	/* device file path */
@@ -47,7 +46,6 @@
 	int pid, ctl;
 	u64 nmemunits, size;
 
-	progname = "mafs";
 	procname = "init";
 
 	/* mainmem->flags |= POOL_PARANOIA|POOL_LOGGING; */
--- a/man/mafs.4
+++ b/man/mafs.4
@@ -25,9 +25,31 @@
 .I announce-string
 ]
 .B file
+.B mfs
+[
+.B -Ds
+] [
+.B -n
+.I service
+] [
+.B -r
+.I service
+] [
+.B -m
+.I nmemunits
+] [
+.B -h
+.I nbuckets
+] [
+.B -a
+.I announce-string
+]
+.B file
 .SH DESCRIPTION
+.I Mfs
+and
 .I Mafs
-is a user space file server on a single partition.
+are user space file servers that run on a single partition.
 .PP
 The options are:
 .TF "n name"
@@ -72,6 +94,7 @@
 .PD
 .SH SOURCE
 .B /sys/src/cmd/mafs
+.B /sys/src/cmd/mfs
 .SH "SEE ALSO"
 .IR mafs (8),
 .IR prep (8),
--- a/man/mafs.8
+++ b/man/mafs.8
@@ -87,7 +87,7 @@
 Check disk usage (traditional df) of a mafs mounted at /n/mafs_myservice.
 .IP
 .EX
-% cat /n/mafs_myservice/adm/ctl
+% cat /n/myservice/adm/ctl
 .EE
 .SH SEE ALSO
 .IR mafs (4)
--- a/mfs.c
+++ b/mfs.c
@@ -11,7 +11,6 @@
 short*	gidspace;
 RWLock	mainlock;
 Tlock	*tlocks;
-char	*progname;
 char	*procname;
 
 char *devfile = nil;	/* device file path */
@@ -46,7 +45,6 @@
 	int pid, ctl;
 	u64 nmemunits, size;
 
-	progname = "mafs";
 	procname = "init";
 
 	/* mainmem->flags |= POOL_PARANOIA|POOL_LOGGING; */
@@ -67,11 +65,13 @@
 	fprint(ctl, "noswap\n");
 	close(ctl);
 
+	/* ignoring -w argument, but keeping it here to stay compatible with mafs */
 	ARGBEGIN{
 	default:	usage();
 	case 'D':	chatty9p++; break;
 	case 'f':	devfile = ARGF(); break;
 	case 'h':	nbuckets = atoll(EARGF(usage())); break;
+	case 'w':	atoll(EARGF(usage())); break;
 	case 'm':	nmemunits = atoll(EARGF(usage())); break;
 	case 'r':
 		doream = 1;
--- a/sub.c
+++ b/sub.c
@@ -436,7 +436,7 @@
 	fsok(0);
 }
 
-char magic[] = "mafs device\n";
+char magic[] = "m[a]fs device\n";
 /* TODO open the dev file OEXCL? */
 void
 ream(u64 size)
--- a/tests/regress.rc
+++ b/tests/regress.rc
@@ -8,80 +8,84 @@
 # regress.rc test.2 -DDDDD # for running mafs with debug flags
 
 fn rununi {
-	test=$1
-	debug=$"2
-	echo 'service='^$test
-	service=$test
-	echo 'disk='^$service^/disk
-	disk=$service^/disk
+	cmd=$1
+	test=$2
+	debug=$"3
+	echo 'cmd='^$cmd
+	echo 'service='^$cmd^'_'^$test
+	service=$cmd^'_'^$test
+	echo 'disk='^$test^/disk
+	disk=$test^/disk
 	echo 'debug='^$debug
 
 	nblocks=()
-	. $service^/params
+	. $test^/params
 
 	# setup the service
-	test -f $service^/setup.rc && $service^/setup.rc $disk $nblocks
+	test -f $test^/setup.rc && $test^/setup.rc $disk $nblocks
 
 	# start service
 	if(~ $"debug '')
-		mount -c <{disk/mafs -s -r mafs_^$service -h 10 $disk <[0=1]} /n/mafs_^$service
-	if not # TODO below breaks auth negotiation. Something is writing to fd 1.
-		mount -c <{disk/mafs $"debug -s -r mafs_^$service -h 10 $disk <[0=1]} /n/mafs_^$service
+		mount -c <{disk/^$cmd -s -r $test -h 10 $disk <[0=1]} /n/^$service
+	if not # if auth negotiation breaks, something is writing to fd 1.
+		mount -c <{disk/^$cmd $"debug -s -r $test -h 10 $disk <[0=1]} /n/^$service
 	echo service status: $status
 
 	sleep 1
-	test -f $service^/action.rc && $service^/action.rc
+	test -f $test^/action.rc && $test^/action.rc $service
 
 	# tear it down
-	test -f /n/mafs_^$service^/adm/ctl && {
-		echo halt >> /n/mafs_^$service^/adm/ctl
+	test -f /n/^$service^/adm/ctl && {
+		echo halt >> /n/^$service^/adm/ctl
 	}
-	unmount /n/mafs_^$service
-	test -f /srv/mafs_^$service && rm /srv/mafs_^$service
+	unmount /n/^$service
+	test -f /srv/^$test && rm /srv/^$test
 
 	sleep 1
-	test -f $service^/check.rc &&
-		$service^/check.rc $test $disk $nblocks ||
+	test -f $test^/check.rc &&
+		$test^/check.rc $test $disk $nblocks ||
 		check.rc $test $disk $nblocks
 }
 
 fn runmp {
-	test=$1
-	debug=$"2
-	echo 'service='^$test
-	service=$test
-	echo 'disk='^$service^/disk
-	disk=$service^/disk
+	cmd=$1
+	test=$2
+	debug=$"3
+	echo 'cmd='^$cmd
+	echo 'service='^$cmd^'_'^$test
+	service=$cmd^'_'^$test
+	echo 'disk='^$test^/disk
+	disk=$test^/disk
 	echo 'debug='^$debug
 
 	nblocks=()
-	. $service^/params
+	. $test^/params
 
 	# setup the service
-	test -f $service^/setup.rc && $service^/setup.rc $disk $nblocks
+	test -f $test^/setup.rc && $test^/setup.rc $disk $nblocks
 
 	# start service
 	if(~ $"debug '')
-		disk/mafs -r mafs_^$service -h 10 $disk
+		disk/^$cmd -r $test -h 10 $disk
 	if not
-		disk/mafs $"debug -r mafs_^$service -h 10 $disk
+		disk/^$cmd $"debug -r $test -h 10 $disk
 	echo service status: $status
 
-	mount -c /srv/mafs_^$service /n/mafs_^$service
+	mount -c /srv/^$test /n/^$service
 
 	sleep 1
-	test -f $service^/action.rc && $service^/action.rc
+	test -f $test^/action.rc && $test^/action.rc $service
 
 	# tear it down
-	test -f /n/mafs_^$service^/adm/ctl && {
-		echo halt >> /n/mafs_^$service^/adm/ctl
+	test -f /n/^$service^/adm/ctl && {
+		echo halt >> /n/^$service^/adm/ctl
 	}
-	unmount /n/mafs_^$service
-	test -f /srv/mafs_^$service && rm /srv/mafs_^$service
+	unmount /n/^$service
+	test -f /srv/^$test && rm /srv/^$test
 
 	sleep 1
-	test -f $service^/check.rc &&
-		$service^/check.rc $test $disk $nblocks ||
+	test -f $test^/check.rc &&
+		$test^/check.rc $test $disk $nblocks ||
 		check.rc $test $disk $nblocks
 }
 
@@ -89,8 +93,10 @@
 	chkreli.rc
 	chkextents.rc
 	for (t in test.*){
-		rununi $t
-		runmp $t
+		rununi mfs $t
+		rununi mafs $t
+		runmp mfs $t
+		runmp mafs $t
 	}
 }
 if not {
@@ -101,7 +107,9 @@
 		chkextents.rc
 	}
 	if not {
-		rununi $*
-		runmp $*
+		rununi mfs $*
+		rununi mafs $*
+		runmp mfs $*
+		runmp mafs $*
 	}
 }
--- a/tests/test.0/blocks/1
+++ b/tests/test.0/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.0
+service test.0
--- a/tests/test.0/blocks/24
+++ b/tests/test.0/blocks/24
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.0
+service test.0
--- a/tests/test.0/blocks/31
+++ b/tests/test.0/blocks/31
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.0
+service test.0
--- a/tests/test.1/action.rc
+++ b/tests/test.1/action.rc
@@ -1,8 +1,10 @@
 #!/bin/rc
 
-# du -a /n/mafs_test.1/
-mkdir /n/mafs_test.1/dir1
-touch /n/mafs_test.1/dir1/file1
-echo test >> /n/mafs_test.1/dir1/file1
+service=$1
 
-cat /n/mafs_test.1/adm/ctl
+# du -a /n/^$service^/
+mkdir /n/^$service^/dir1
+touch /n/^$service^/dir1/file1
+echo test >> /n/^$service^/dir1/file1
+
+cat /n/^$service^/adm/ctl
--- a/tests/test.1/blocks/1
+++ b/tests/test.1/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.1
+service test.1
--- a/tests/test.1/blocks/24
+++ b/tests/test.1/blocks/24
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.1
+service test.1
--- a/tests/test.1/blocks/31
+++ b/tests/test.1/blocks/31
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.1
+service test.1
--- a/tests/test.2/action.rc
+++ b/tests/test.2/action.rc
@@ -1,24 +1,26 @@
 #!/bin/rc
 
-# du -a /n/mafs_test.2/
+service=$1
 
+# du -a /n/^$service^/
+
 for(t in 0 1 01 2 3 4 5 7){
-	touch /n/mafs_test.2/file1
-	echo ./6.offsets -s test.2/^$t^.start -o `{cat test.2/^$t^.offset} -a test.2/^$t^.add /n/mafs_test.2/file1
-	./6.offsets -s test.2/^$t^.start -o `{cat test.2/^$t^.offset} -a test.2/^$t^.add /n/mafs_test.2/file1
-	diff /n/mafs_test.2/file1 test.2/^$t^.end
+	touch /n/^$service^/file1
+	echo ./6.offsets -s test.2/^$t^.start -o `{cat test.2/^$t^.offset} -a test.2/^$t^.add /n/^$service^/file1
+	./6.offsets -s test.2/^$t^.start -o `{cat test.2/^$t^.offset} -a test.2/^$t^.add /n/^$service^/file1
+	diff /n/^$service^/file1 test.2/^$t^.end
 #	{
-#		ls -l /n/mafs_test.2/file1 test.2/^$t^.end
-#		echo cat /n/mafs_test.2/file1
-#		cat /n/mafs_test.2/file1
+#		ls -l /n/^$service^/file1 test.2/^$t^.end
+#		echo cat /n/^$service^/file1
+#		cat /n/^$service^/file1
 #		echo cat test.2/^$t^.end
 #		cat test.2/^$t^.end
 #	}
-	rm /n/mafs_test.2/file1
+	rm /n/^$service^/file1
 }
-# 	touch /n/mafs_test.2/file1
-# ./6.offsets -s test.2/6.start -o 1124 -a test.2/6.add /n/mafs_test.2/file1 > test.2/6.end
-# 	ls -l /n/mafs_test.2/file1
-#	xd -c -b /n/mafs_test.2/file1
-# 	cp /n/mafs_test.2/file1 test.2/6.end
-#	rm /n/mafs_test.2/file1
+# 	touch /n/^$service^/file1
+# ./6.offsets -s test.2/6.start -o 1124 -a test.2/6.add /n/^$service^/file1 > test.2/6.end
+# 	ls -l /n/^$service^/file1
+#	xd -c -b /n/^$service^/file1
+# 	cp /n/^$service^/file1 test.2/6.end
+#	rm /n/^$service^/file1
--- a/tests/test.2/blocks/1
+++ b/tests/test.2/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 39 28
 backup super 2 to 38 27
 backup root 3 to 37 26
-service mafs_test.2
+service test.2
--- a/tests/test.2/blocks/28
+++ b/tests/test.2/blocks/28
@@ -4,4 +4,4 @@
 backup config 1 to 39 28
 backup super 2 to 38 27
 backup root 3 to 37 26
-service mafs_test.2
+service test.2
--- a/tests/test.2/blocks/39
+++ b/tests/test.2/blocks/39
@@ -4,4 +4,4 @@
 backup config 1 to 39 28
 backup super 2 to 38 27
 backup root 3 to 37 26
-service mafs_test.2
+service test.2
--- a/tests/test.3/action.rc
+++ b/tests/test.3/action.rc
@@ -1,14 +1,16 @@
 #!/bin/rc
 
+service=$1
+
 # ls -l /srv/ /n/
 fn dofile {
 	file=$"*
 	echo $file
-	time fcp -x test.3/^$file /n/mafs_test.3/
-	ls -ltr test.3/^$file /n/mafs_test.3/^$file
-	diff test.3/^$file /n/mafs_test.3/^$file # > /mnt/term/tmp/test.out
+	time fcp -x test.3/^$file /n/^$service^/
+	ls -ltr test.3/^$file /n/^$service^/^$file
+	diff test.3/^$file /n/^$service^/^$file # > /mnt/term/tmp/test.out
 	# tail /mnt/term/tmp/test.out
-	rm /n/mafs_test.3/^$file
+	rm /n/^$service^/^$file
 }
 
 # to build these files
@@ -26,4 +28,4 @@
 dofile 16384_blocks.file
 # dofile big.file # cannot do this, not enough space for this.
 
-cat /n/mafs_test.3/adm/ctl
+cat /n/^$service^/adm/ctl
--- a/tests/test.3/blocks/1
+++ b/tests/test.3/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 40959 20488
 backup super 2 to 40958 20487
 backup root 3 to 40957 20486
-service mafs_test.3
+service test.3
--- a/tests/test.3/blocks/20488
+++ b/tests/test.3/blocks/20488
@@ -4,4 +4,4 @@
 backup config 1 to 40959 20488
 backup super 2 to 40958 20487
 backup root 3 to 40957 20486
-service mafs_test.3
+service test.3
--- a/tests/test.3/blocks/40959
+++ b/tests/test.3/blocks/40959
@@ -4,4 +4,4 @@
 backup config 1 to 40959 20488
 backup super 2 to 40958 20487
 backup root 3 to 40957 20486
-service mafs_test.3
+service test.3
--- a/tests/test.4/action.rc
+++ b/tests/test.4/action.rc
@@ -1,6 +1,8 @@
 #!/bin/rc
 
+service=$1
+
 # ls -l /srv/ /n/
-mkdir /n/mafs_test.4/dir.0
-dircp test.4/dir.0 /n/mafs_test.4/dir.0
-# du -a /n/mafs_test.4/dir.0
+mkdir /n/^$service^/dir.0
+dircp test.4/dir.0 /n/^$service^/dir.0
+# du -a /n/^$service^/dir.0
--- a/tests/test.5/action.rc
+++ b/tests/test.5/action.rc
@@ -1,7 +1,9 @@
 #!/bin/rc
 
+service=$1
+
 # ls -l /srv/ /n/
-time fcp -x test.5/23.messages.gz /n/mafs_test.5/
-time fcp -x test.5/01.messages.gz /n/mafs_test.5/
-du -a /n/mafs_test.5
-ls -l test.5/23.messages.gz test.5/01.messages.gz /n/mafs_test.5/
+time fcp -x test.5/23.messages.gz /n/^$service^/
+time fcp -x test.5/01.messages.gz /n/^$service^/
+du -a /n/^$service^
+ls -l test.5/23.messages.gz test.5/01.messages.gz /n/^$service^/
--- a/tests/test.6/action.rc
+++ b/tests/test.6/action.rc
@@ -1,9 +1,11 @@
 #!/bin/rc
 
-# du -a /n/mafs_test.6/
-mkdir /n/mafs_test.6/dir1
-touch /n/mafs_test.6/dir1/file1
-echo test >> /n/mafs_test.6/dir1/file1
+service=$1
 
-cat /n/mafs_test.6/adm/ctl
+# du -a /n/^$service^/
+mkdir /n/^$service^/dir1
+touch /n/^$service^/dir1/file1
+echo test >> /n/^$service^/dir1/file1
+
+cat /n/^$service^/adm/ctl
 sleep 1
--- a/tests/test.6/blocks/1
+++ b/tests/test.6/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.6
+service test.6
--- a/tests/test.6/blocks/24
+++ b/tests/test.6/blocks/24
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.6
+service test.6
--- a/tests/test.6/blocks/31
+++ b/tests/test.6/blocks/31
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.6
+service test.6
--- a/tests/test.7/action.rc
+++ b/tests/test.7/action.rc
@@ -1,13 +1,15 @@
 #!/bin/rc
 
+service=$1
+
 # ls -l /srv/ /n/
 
 for(i in `{seq 1 1 10}){
-	time fcp -x test.7/16384_blocks.file /n/mafs_test.7/16384_blocks.file.^$i &
+	time fcp -x test.7/16384_blocks.file /n/^$service^/16384_blocks.file.^$i &
 }
 
 wait
 sleep 1
-ls -ltr test.7/16384_blocks.file /n/mafs_test.7/16384_blocks.file.*
+ls -ltr test.7/16384_blocks.file /n/^$service^/16384_blocks.file.*
 
-cat /n/mafs_test.7/adm/ctl
+cat /n/^$service^/adm/ctl
--- a/tests/test.8/blocks/1
+++ b/tests/test.8/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 25 21
 backup super 2 to 24 20
 backup root 3 to 23 19
-service mafs_test.8
+service test.8
--- a/tests/test.8/blocks/21
+++ b/tests/test.8/blocks/21
@@ -4,4 +4,4 @@
 backup config 1 to 25 21
 backup super 2 to 24 20
 backup root 3 to 23 19
-service mafs_test.8
+service test.8
--- a/tests/test.8/blocks/25
+++ b/tests/test.8/blocks/25
@@ -4,4 +4,4 @@
 backup config 1 to 25 21
 backup super 2 to 24 20
 backup root 3 to 23 19
-service mafs_test.8
+service test.8
--- a/tests/test.9/action.rc
+++ b/tests/test.9/action.rc
@@ -1,24 +1,26 @@
 #!/bin/rc
 
-# du -a /n/mafs_test.9/
+service=$1
 
-mkdir /n/mafs_test.9/dir1
-touch /n/mafs_test.9/dir1/file1
-echo test >> /n/mafs_test.9/dir1/file1
+# du -a /n/^$service^/
 
-mkdir /n/mafs_test.9/dir2
-touch /n/mafs_test.9/dir2/file1
-echo test >> /n/mafs_test.9/dir2/file1
-touch /n/mafs_test.9/dir2/file2
-echo test >> /n/mafs_test.9/dir2/file2
+mkdir /n/^$service^/dir1
+touch /n/^$service^/dir1/file1
+echo test >> /n/^$service^/dir1/file1
 
+mkdir /n/^$service^/dir2
+touch /n/^$service^/dir2/file1
+echo test >> /n/^$service^/dir2/file1
+touch /n/^$service^/dir2/file2
+echo test >> /n/^$service^/dir2/file2
+
 # 4096 blocks = 2MB
-mkdir /n/mafs_test.9/dir3
-time fcp -x test.9/2MB.file /n/mafs_test.9/dir3/
+mkdir /n/^$service^/dir3
+time fcp -x test.9/2MB.file /n/^$service^/dir3/
 
 # 25 MB file
-mkdir /n/mafs_test.9/dir4
-time fcp -x test.9/25MB.file /n/mafs_test.9/dir4/
+mkdir /n/^$service^/dir4
+time fcp -x test.9/25MB.file /n/^$service^/dir4/
 
-du -a /n/mafs_test.9/
-cat /n/mafs_test.9/adm/ctl
+du -a /n/^$service^/
+cat /n/^$service^/adm/ctl
--- a/tests/test.9/blocks/1
+++ b/tests/test.9/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 131071 65544
 backup super 2 to 131070 65543
 backup root 3 to 131069 65542
-service mafs_test.9
+service test.9
--- a/tests/test.a/action.rc
+++ b/tests/test.a/action.rc
@@ -1,9 +1,11 @@
 #!/bin/rc
 
-time fcp -x test.a/big.file /n/mafs_test.a/
-ls -ltr test.a/big.file /n/mafs_test.a/big.file
-diff test.a/big.file /n/mafs_test.a/big.file # > /mnt/term/tmp/test.out
+service=$1
+
+time fcp -x test.a/big.file /n/^$service^/
+ls -ltr test.a/big.file /n/^$service^/big.file
+diff test.a/big.file /n/^$service^/big.file # > /mnt/term/tmp/test.out
 # tail /mnt/term/tmp/test.out
-rm /n/mafs_test.a/big.file
+rm /n/^$service^/big.file
 
-cat /n/mafs_test.a/adm/ctl
+cat /n/^$service^/adm/ctl
--- a/tests/test.b/action.rc
+++ b/tests/test.b/action.rc
@@ -1,8 +1,10 @@
 #!/bin/rc
 
-# du -a /n/mafs_test.b/
-mkdir /n/mafs_test.b/dir1
-touch /n/mafs_test.b/dir1/file1
-echo test >> /n/mafs_test.b/dir1/file1
+service=$1
 
-cat /n/mafs_test.b/adm/ctl
+# du -a /n/^$service^/
+mkdir /n/^$service^/dir1
+touch /n/^$service^/dir1/file1
+echo test >> /n/^$service^/dir1/file1
+
+cat /n/^$service^/adm/ctl
--- a/tests/test.b/blocks/1
+++ b/tests/test.b/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.b
+service test.b
--- a/tests/test.b/blocks/24
+++ b/tests/test.b/blocks/24
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.b
+service test.b
--- a/tests/test.b/blocks/31
+++ b/tests/test.b/blocks/31
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.b
+service test.b
--- a/tests/test.d/action.rc
+++ b/tests/test.d/action.rc
@@ -1,5 +1,7 @@
 #!/bin/rc
 
-mkdir -p /n/mafs_test.d/a/b/c/d/e/f/g
-du -a /n/mafs_test.d/
-cat /n/mafs_test.d/adm/ctl
+service=$1
+
+mkdir -p /n/^$service^/a/b/c/d/e/f/g
+du -a /n/^$service^/
+cat /n/^$service^/adm/ctl
--- a/tests/test.d/blocks/1
+++ b/tests/test.d/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.d
+service test.d
--- a/tests/test.d/blocks/24
+++ b/tests/test.d/blocks/24
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.d
+service test.d
--- a/tests/test.d/blocks/31
+++ b/tests/test.d/blocks/31
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.d
+service test.d
--- a/tests/test.e/action.rc
+++ b/tests/test.e/action.rc
@@ -1,9 +1,11 @@
 #!/bin/rc
 
-mkdir -p /n/mafs_test.e/a/^(b c)
-touch /n/mafs_test.e/a/^(1.txt 2.txt)
-du -a /n/mafs_test.e/
-rm -rf /n/mafs_test.e/a/b
-rm /n/mafs_test.e/a/1.txt
-du -a /n/mafs_test.e/
-cat /n/mafs_test.e/adm/ctl
+service=$1
+
+mkdir -p /n/^$service^/a/^(b c)
+touch /n/^$service^/a/^(1.txt 2.txt)
+du -a /n/^$service^/
+rm -rf /n/^$service^/a/b
+rm /n/^$service^/a/1.txt
+du -a /n/^$service^/
+cat /n/^$service^/adm/ctl
--- a/tests/test.e/blocks/1
+++ b/tests/test.e/blocks/1
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.e
+service test.e
--- a/tests/test.e/blocks/24
+++ b/tests/test.e/blocks/24
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.e
+service test.e
--- a/tests/test.e/blocks/31
+++ b/tests/test.e/blocks/31
@@ -4,4 +4,4 @@
 backup config 1 to 31 24
 backup super 2 to 30 23
 backup root 3 to 29 22
-service mafs_test.e
+service test.e