[net.unix-wizards] Ram disk on 4.x

NEVILLE%umass-cs.csnet@csnet-relay.arpa (03/30/86)

We have just added an 8 meg. board to our Micro-Vax II  running Ultrix 1.1
and since we are a small group (usually only a dozen user processes) we
find that we are running with about 25% memory usage.  Our job mix lends
itself well to speed increase from RAM 'disk' emulation, in particular
we would like to put /tmp there or better yet make a /ramtmp that could
be tried before the real /tmp.  i would also like to put some images
like emacs, cc, ccom, more, etc.  there.

Has anyone done a driver for a RAM 'disk' device?

i will be happy to summarize responses to the list.

						-neville

				Internet:    neville@umass.csnet

meier@srcsip.UUCP (Christopher Meier) (04/08/86)

In article <2213@brl-smoke.ARPA> NEVILLE%umass-cs.csnet@csnet-relay.arpa writes:
>
>Has anyone done a driver for a RAM 'disk' device?
>
>i will be happy to summarize responses to the list.
>
>				Internet:    neville@umass.csnet

I would be interested in seeing the summary.

Christopher Meier   Honeywell S&RC/SIP/AIT   {philabs,ihnp4!mmm}!srcsip!meier
-- 
Christopher Meier   Honeywell S&RC/SIP/AIT   {philabs,ihnp4!mmm}!srcsip!meier

toma@fluke.UUCP (Tom Anderson) (04/17/86)

> 
> We have just added an 8 meg. board to our Micro-Vax II  running Ultrix 1.1
> and since we are a small group (usually only a dozen user processes) we
> find that we are running with about 25% memory usage.  Our job mix lends
> itself well to speed increase from RAM 'disk' emulation, in particular
> we would like to put /tmp there or better yet make a /ramtmp that could
> be tried before the real /tmp.  i would also like to put some images
> like emacs, cc, ccom, more, etc.  there.
> 
> Has anyone done a driver for a RAM 'disk' device?
> 
> i will be happy to summarize responses to the list.
> 
> 						-neville
> 
> 				Internet:    neville@umass.csnet



A few months ago, I put together a primitive ram disk driver for my 
Sun-2/120 (I don't recall which version of Sun Unix I was running at 
the time) to see if I could speed up button menu response by putting 
menu files there (it didn't; evidently the slow response was principally 
due to swapping in various pieces of the suntools chameleon).  It's 
rather small, but I've included two sizes so it should be obvious how
to scale it to any size you want.  It is primitive in that it does not
understand anything about special block numbers, so that it can't "fake"
the i-list, etc. and thus achieve better "disk" storage efficiency (it 
is pretty absymal for small sizes).  I did this so that it would be 
impervious to file sys. changes by Sun.  You'll definitely want to 
experiment a bit with the file system parameters.

(1) To install the driver, add the following lines to /sys/conf/files.sun
    (or whatever file your machine uses):

ramdisk/rd64.c		optional rdsmall
ramdisk/rd512.c		optional rdlarge

    Note: files.sun is in alphabetic order. I have no idea if this is 
    necessary, having noticed it at the outset and never having tried to
    violate it.  

(2) Next, your machine should have /sys/machine symbolically linked to 
    /sun or whatever.  Modify /sys/{sun,whatever}/conf.c according to 
    the following:

(2a) At the appropriate point above the declaration for bdevsw[], add:

#include "rdsmall.h"
#include "rdlarge.h"
#if NRDSMALL > 0 | NRDLARGE > 0
int	rdstrategy(), rdread(), rdwrite();
#define rdopen		nulldev
#define rdclose		nulldev
#else
#define rdstrategy	nodev
#define rdopen		nodev
#define rdclose		nodev
#define rdread		nodev
#define rdwrite		nodev
#endif

(2b) In bdevsw[], add a line for the block device, using whatever major
    device number (call it BDN) you think is safe:

struct bdevsw	bdevsw[] =
{

    . . . 

    { rdopen,	rdclose,	rdstrategy,	nodev,		/*9*/
      0,		0 },
};

(2c) In cdevsw[], add a line for the character device (call it CDN):

struct cdevsw	cdevsw[] =
{

    . . .

    {
	rdopen,		rdclose,	rdread,		rdwrite,	/*36*/
	nodev,		nodev,		nulldev,	0,
	nodev,		0,
    },
};

(3) Add a line to your configuration description file in /sys/conf:

pseudo-device	rdlarge1

OR

pseudo-device	rdsmall1

    where you can only have one size or the other, not both (I found it 
    convenient to set it up this way - you may prefer to only have one
    driver and re-define the size).  Also, if want more than one ram
    disk partition, change the trailing digit.

(4) Add entries in /dev for the ram disk:

/etc/mknod rd0 b BDN 0		; chmod 600 rd0
/etc/mknod rrd0 c CDN 0		; chmod 600 rrd0

(6) Append the following lines to /etc/rc.local, modifying the mount point,
adding appropriate lines if you have more than one partition you wish
to use as a file system, and modifying the file sys. parameters appropriately:

(for the 64K ram disk):

/etc/mkfs /dev/rrd0 128 128 1 4096 512 1 10 60 1024
/etc/mount /dev/rd0 /ram0
/bin/rm /ram0/lost+found

(for the 512K ram disk):

/etc/mkfs /dev/rrd0 1024 128 1 4096 512 1 10 60 1024
/etc/mount /dev/rd0 /ram0
/bin/rm /ram0/lost+found

(7) Finally, create the directory /sys/ramdisk, extract the following
shell archive there, and build your new kernel.

Naturally, neither I nor John Fluke Mfg. Co. can assume any responsibility
for damage, mutations, premature balding, etc. caused by using this 
driver.  However, this is taken directly from the /sys arena on my
machine, where it does work.  If you have any problems, bugs, excess
money, lucrative job offers, etc., feel free to drop a line.

Tom Anderson
John Fluke Mfg. Co., Inc.
PO Box C9090, MS 245F
Everett, Wa. 98206
(206) 356-5895

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by toma on Wed Apr 16 16:18:50 PST 1986
# Contents:  rd512.c rd64.c
 
echo x - rd512.c
sed 's/^@//' > "rd512.c" <<'@//E*O*F rd512.c//'
/*
 * rd512.c - 512k ram disk driver for 4.2bsd Unix
 *
 * 1/25/86 - toma - creation date
 */

/* #define RDDEBUG */

#include "rdlarge.h"

#include "../h/param.h"
#include "../h/buf.h"
#include "../h/user.h"
#include "../h/uio.h"

#define RDNUMBLKS 1024	/* block count of each "ram disk" */

char rdarray[NRDLARGE][RDNUMBLKS][DEV_BSIZE] ; /* the "ram disk" */

struct buf rrdbuf [NRDLARGE] ; /* buffers for raw i/o */

/*
 * strategy routine for block dev. i/f (no open, close necessary)
 */
rdstrategy (bp)
    register struct buf * bp;
{
    int unit;
    register long count;
    register char * cp, * rdp ;

    unit = minor(bp->b_dev);
    /* check for illegal minor dev. num. */
    if (unit >= NRDLARGE) {
	bp->b_flags |= B_ERROR ;
    /* check for reads or writes past the end of rdarray for that unit */
    } else if (
	&rdarray[unit][bp->b_blkno][bp->b_bcount-1] - 
	&rdarray[unit][0][0] >= RDNUMBLKS * DEV_BSIZE ){
	bp->b_flags |= B_ERROR ;
	printf("rd: read/write past end of device attempted\n");
    } else {
#ifdef RDDEBUG
	printf("rdarray size: %d\n", sizeof(rdarray));
	printf("rd: bcount: %d, blkno: %d\n", bp->b_bcount, bp->b_blkno);
	bp->b_resid = 0L ;
	iodone(bp);
	return;
#endif
	rdp = rdarray[unit][bp->b_blkno];
	cp = bp->b_un.b_addr;
	count = bp->b_bcount;
	if ((bp->b_flags & (B_READ|B_WRITE)) == B_READ) {
	    while (count--) *cp++ = *rdp++;
	} else {
	    while (count--) *rdp++ = *cp++;
	}
	bp->b_resid = 0L ;
    }
    iodone(bp);
}

/*
 * Raw I/O I/F routines: read, write (nulldev for open, close 
 * in conf.c)
 */

rdread (dev, uio)
    dev_t dev;
    struct uio * uio;
{
    int unit = minor(dev);

    if (unit >= NRDLARGE) return (ENXIO);
    return (physio(rdstrategy, &rrdbuf[unit], dev, B_READ, minphys, uio));
}

rdwrite (dev, uio)
    dev_t dev;
    struct uio * uio;
{
    int unit = minor(dev);

    if (unit >= NRDLARGE) return (ENXIO);
    return (physio(rdstrategy, &rrdbuf[unit], dev, B_WRITE, minphys, uio));
}
@//E*O*F rd512.c//
chmod u=rw,g=r,o=r rd512.c
 
echo x - rd64.c
sed 's/^@//' > "rd64.c" <<'@//E*O*F rd64.c//'
/*
 * rd64.c - 64k ram disk driver for 4.2bsd Unix
 *
 * 1/25/86 - toma - creation date
 */

/* #define RDDEBUG */

#include "rdsmall.h"

#include "../h/param.h"
#include "../h/buf.h"
#include "../h/user.h"
#include "../h/uio.h"

#define RDNUMBLKS 128	/* block count of each "ram disk" */

char rdarray[NRDSMALL][RDNUMBLKS][DEV_BSIZE] ; /* the "ram disk" */

struct buf rrdbuf [NRDSMALL] ; /* buffers for raw i/o */

/*
 * strategy routine for block dev. i/f (no open, close necessary)
 */
rdstrategy (bp)
    register struct buf * bp;
{
    int unit;
    register long count;
    register char * cp, * rdp ;

    unit = minor(bp->b_dev);
    /* check for illegal minor dev. num. */
    if (unit >= NRDSMALL) {
	bp->b_flags |= B_ERROR ;
    /* check for reads or writes past the end of rdarray for that unit */
    } else if (
	&rdarray[unit][bp->b_blkno][bp->b_bcount-1] - 
	&rdarray[unit][0][0] >= RDNUMBLKS * DEV_BSIZE ){
	bp->b_flags |= B_ERROR ;
	printf("rd: read/write past end of device attempted\n");
    } else {
#ifdef RDDEBUG
	printf("rdarray size: %d\n", sizeof(rdarray));
	printf("rd: bcount: %d, blkno: %d\n", bp->b_bcount, bp->b_blkno);
	bp->b_resid = 0L ;
	iodone(bp);
	return;
#endif
	rdp = rdarray[unit][bp->b_blkno];
	cp = bp->b_un.b_addr;
	count = bp->b_bcount;
	if ((bp->b_flags & (B_READ|B_WRITE)) == B_READ) {
	    while (count--) *cp++ = *rdp++;
	} else {
	    while (count--) *rdp++ = *cp++;
	}
	bp->b_resid = 0L ;
    }
    iodone(bp);
}

/*
 * Raw I/O I/F routines: read, write (nulldev for open, close 
 * in conf.c)
 */

rdread (dev, uio)
    dev_t dev;
    struct uio * uio;
{
    int unit = minor(dev);

    if (unit >= NRDSMALL) return (ENXIO);
    return (physio(rdstrategy, &rrdbuf[unit], dev, B_READ, minphys, uio));
}

rdwrite (dev, uio)
    dev_t dev;
    struct uio * uio;
{
    int unit = minor(dev);

    if (unit >= NRDSMALL) return (ENXIO);
    return (physio(rdstrategy, &rrdbuf[unit], dev, B_WRITE, minphys, uio));
}
@//E*O*F rd64.c//
chmod u=rw,g=r,o=r rd64.c
 
exit 0