[net.unix-wizards] m and n of mkfs

merg@bunker.UUCP (Jim Stephenson) (11/16/83)

Hi,

Does anybody know how to calculate the best interleaving factors
for mkfs for different types of CPU's and different types of disks?
Is there some standard technique?

				Andy Rodnite
				Mergenthaler Linotype
				201 Old Country Rd.
				Melville, NY 11747
				(516) 673-4318
				ittvax!bunker!merg

thomson@utcsrgv.UUCP (Brian Thomson) (11/18/83)

m is the shuffle factor for disk block interleaving.
Usually m == 3, which means that the freelist is constructed
by linking together every third data block.  It should be
large enough that no disk rotations are lost between successive
io requests, and small enough that the rotational latency between
blocks is small.

n is the number of blocks in a cylinder (== number of blocks disk
can access without head movement).  The interleaving is done
on a cylinder-by-cylinder basis, so a 100 block filesystem
with m==2, n==50 would be interleaved like so:

0,2,4,6,...,48,1,3,5,...,49,50,52,54,...,96,98,51,53,55,...,97,99

Wherever I have said "block" above, I DON'T necessarily mean disk
segment (512 bytes), I mean filesystem logical block size, 1kbyte
in most 4.1BSD installations.
-- 
			Brian Thomson,	    CSRG Univ. of Toronto
			{linus,ihnp4,uw-beaver,floyd,utzoo}!utcsrgv!thomson

Ttang.uci-750a%rand-relay@sri-unix.UUCP (11/18/83)

I think the argument m should always be 3 and n is (# of sectors per cyl./2)
where you can find out the # of sectors per cylinder in a table in your
driver.  That's the pattern that they use to calculate n.  If you take a 
closer look, you see that pattern.

/ttang
Arpanet:ttang@uci
Csnet:ttang.uci@Csnet-relay
Uucp:ucivax!ttang

agp@mh3bs.UUCP (11/19/83)

A few USENIX conferences ago, someone presented a
paper on computing optimal magic numbers for a
cpu/disk pair.  For what it is worth, I will post
their program here:

#include	<stdio.h>

#define	SECTORS	(disk[n].d_sec_tk * disk[n].d_surf)

struct	cpu
{
	char	*cpu_name;
	int	Bps;
};

struct	cpu	cpu[] =
{
	"PDP23",	119,
	"pdp23",	119,
	"11/23",	119,
	"23",		119,
	"PDP34",	119,
	"pdp34",	119,
	"11/34",	119,
	"34",		119,
	"PDP45",	170,
	"pdp45",	170,
	"11/45",	170,
	"45",		170,
	"PDP70",	210,
	"pdp70",	210,
	"11/70",	210,
	"70",		210,
	"VAX780",	210,
	"vax780",	210,
	"11/780",	210,
	"780",		210,
	"VAX",		210,
	"vax",		210,
	NULL,		NULL
};

struct	disk
{
	char	*d_name;
	int	d_spin;
	int	d_sec_tk;
	int	d_byte_bk;
	int	d_surf;
	int	d_cyl;
	int	d_tk_seek;
	int	d_avg_seek;
};

struct disk	disk[] =
{
/*       disk   spin   sec_tk byte_blk surf     cyl   tk_seek  avg_seek  */
	"rk05",	1500,	12,	512,	2,	203,	10,	50,
	"rl01",	2400,	20,	256,	2,	256,	15,	55,
	"rp03",	2400,	10,	512,	20,	406,	8,	29,
	"rp04",	3600,	22,	512,	19,	411,	7,	28,
	"rp05",	3600,	22,	512,	19,	411,	6,	29,
	"rp06",	3600,	22,	512,	19,	815,	6,	29,
	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL
};

main(argc,argv)
char	**argv;
{
	register int	k, n, i;
	int	block, speed;
	int	f_n;

	for(k=0; cpu[k].cpu_name[0] != NULL; ++k) {
		if(strcmp(argv[1],cpu[k].cpu_name) == 0) break;
	}

	if(cpu[k].Bps == NULL) {
		printf("unknown cpu: %s\n",argv[1]);
		exit(1);
	}

	for(n=0; disk[n].d_name[0] != NULL; ++n) {

		block=((disk[n].d_spin/10)*disk[n].d_sec_tk);
		speed=((60*(cpu[k].Bps + 1))/10);

		for(i=1; i <= disk[n].d_surf; ++i) {
			f_n = SECTORS / i;
			if(f_n >= 100) continue;
			if((SECTORS % i) == 0) {
				if((f_n % disk[n].d_sec_tk) == 0) break;
			}
			break;
		}
		printf("%s:  %d / %d",
			disk[n].d_name,
			(block / speed) + 1, SECTORS);
		printf("\n");
	}
}