File:  [MW Coherent from dump] / coherent / d / etc / fsck / virtual.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:37 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * Virtual memory for fsck. Uses hash algorithm
 * rather than LRU to get it up fast.
 */
#include "assert.h"	/* special copy with printf() not fprintf() */
#include <sys/stat.h>
#include "fsck.h"
#if SMALLMODEL

#define VBLKB 9			/* bytes in virtual block as power of 2 */
#define VBLK (1 << VBLKB)	/* bytes in a virtual block */
#define MBKSB 6			/* number of virtual blocks as power of 2 */
#define MBKS (1 << MBKSB)	/* number of virtual blocks */

#define DVTMP "/dev/rram1"	/* Default Virtual Temp Filename */
#define DVTMPCLS "/dev/rram1close" /* Default Virtual Temp File Close */
#define	MAJORRAM 8		/* Major Device Number for the Ram Disk	*/

struct mapper {
	unsigned dirty:1;
	unsigned what_in:15;	/* which block is in memory */
};

static unsigned long flagdsp, blkdsp, dupdsp, duplim;
static struct mapper map[MBKS];
static unsigned char data[MBKS][VBLK];
static int tmp;

static char *dvtmp = DVTMP;
static char *dvtmpcls = DVTMPCLS;

/*
 * Init file system for virtual arrays.
 * Data is ordered links, flags, blocks then dups.
 */
initV(links, flags, blocks, dups)
unsigned links, flags, blocks, dups;
{
	register long bp;
	struct stat st;
	unsigned datasiz;

	flagdsp = links;
	blkdsp = flagdsp + flags;
	dupdsp = blkdsp + blocks;
	duplim = dupdsp + dups;

	memset(map, 0, sizeof(map));	/* zero ram arrays */
	memset(data, 0, sizeof(data));

	tmp = -1;

	datasiz = sizeof(data);
	if ( duplim < datasiz )
		return;

	if ( tmpfile == NULL ) {
		switch ( is_fs(dvtmp) ) {
		case -1:
			fatal(
"Can't access ram disk \"%s\", use the -t option", dvtmp);
		case 0:
			break;
		case 1:
			fatal(
"Possible file system on ram disk \"%s\", use the -t option", dvtmp);
		}
		if ( (-1 == stat(dvtmp, &st)) || !(st.st_mode&S_IFCHR) ||
			(major(st.st_rdev) != MAJORRAM) )
				fatal("Ram disk \"%s\" not mknod'ed properly",
								dvtmp);
		if ( -1 == (tmp = open(dvtmp, 2)) )
			fatal("Cannot open read/write Ram Disk \"%s\"", dvtmp);

		/* Ram disk driver may not promise zeroed start.
		 * This code may go later. Extra write not important. */
		for(bp = 0; bp < duplim; bp += VBLK) /* zero disk stuff */
			if ( VBLK != write(tmp, data[0], VBLK) )
				fatal("Error writing to tmp file");
	} else {
		if ( -1 == (tmp = open(tmpfile, 2)) ) {
			if ( -1 == (tmp = creat(tmpfile, 0600)) )
				fatal("Cannot create temp file \"%s\"", 
								tmpfile);
			close(tmp);
			tmp = open(tmpfile, 2);
			unlink(tmpfile);
		}
		if ( -1 == fstat(tmp, &st) )
			fatal("Can't stat temp file \"%s\"", tmpfile);
		if ( st.st_dev == fsysrdev )
			fatal("Temp File must not be on file system to fsck");
	}
}

/*
 * cleanup virtual system
 */
cleanV()
{
	struct stat st;

	if ( tmp == -1 )		/* No Virtual Temp File Opened	*/
		return;

	close(tmp);
	if ( tmpfile != NULL )		/* Virtual File not Default RAMDisk */
		return;
					/* Virtual File is Default RAMDisk */
	if ( (-1 == stat(dvtmpcls, &st)) || !(st.st_mode&S_IFCHR) ||
		(major(st.st_rdev) != MAJORRAM) ||
		((minor(st.st_rdev)&0x7F) != 0) )
		fatal("Ram disk close \"%s\" not mknod'ed properly", dvtmpcls);
	if ( -1 == (tmp = open(dvtmpcls, 2)) )
		fatal("Cannot open Ram Disk Close \"%s\"", dvtmpcls);
	if ( close(tmp) < 0 )
		fatal("Cannot close Ram Disk Close \"%s\"", dvtmpcls);
}

/*
 * All actions for virtual array
 */
findblock(bp, action, odata)
long bp;		/* data address */
enum vact action;	/* what to do */
unsigned odata;		/* optional data */
{
	unsigned which, what_in, byte_no, bit;
	unsigned long diskad;
	unsigned char *byte;
	extern long lseek();

	switch(action) {	/* use displacment to correct part of file */
	case testBlock:
	case markBlock:
	case unmarkBlock:
		bit = 1 << (bp & 7);
		bp >>= 3;
	case grabBlock:		/* 8 at a time for copy */
		assert(bp >= 0);
		bp += blkdsp;
		assert(bp < dupdsp);
		break;
	case testDup:
	case markDup:
	case unmarkDup:
		bit = 1 << (bp & 7);
		bp >>= 3;
	case setDup:		/* 8 at a time for copy */
		assert(bp >= 0);
		bp += dupdsp;
		assert(bp < duplim);
		break;
	case Flags:
	case setFlags:
	case orFlags:
		assert(bp > 0);
		bp += flagdsp - 1;
		assert(bp < blkdsp);
		break;
	case linkCtr:
	case incLinkctr:
	case setLinkctr:
		assert(bp > 0);
		bp--;
		assert(bp < flagdsp);
	}

	byte_no = bp & (VBLK - 1);
	bp >>= VBLKB;
	which = bp & (MBKS - 1);
	bp >>= MBKSB;
	what_in = bp & 0x7fff;

	if((diskad = map[which].what_in) != what_in)	{
		if(map[which].dirty) {
			diskad <<= VBLKB + MBKSB;
			diskad += which << VBLKB;
			if(-1 == lseek(tmp, diskad, 0))
				fatal("Error seeking tmp file");
			if(VBLK != write(tmp, data[which], VBLK))
				fatal("Error writing tmp file");
		}
		diskad = what_in;
		diskad <<= VBLKB + MBKSB;
		diskad += which << VBLKB;
		if(-1 == lseek(tmp, diskad, 0))
			fatal("Error seeking tmp file");
		if(VBLK != read(tmp, data[which], VBLK))
			memset(data[which], 0, VBLK);
		map[which].what_in = what_in;
		map[which].dirty = 0; /* clean */
	}
	byte = &data[which][byte_no];

	switch(action) {
	case testBlock:
	case testDup:
		return(*byte & bit);
	case markBlock:
	case markDup:
		map[which].dirty = 1;
		return(*byte |= bit);
	case unmarkBlock:
	case unmarkDup:
		map[which].dirty = 1;
		return(*byte ^= bit);
	case linkCtr:
	case Flags:
	case grabBlock:
		return(*byte);
	case setLinkctr:
	case setFlags:
	case setDup:
		map[which].dirty = 1;
		return(*byte = odata);
	case orFlags:
		map[which].dirty = 1;
		return(*byte |= odata);
	case incLinkctr:
		map[which].dirty = 1;
		return(++*byte);
	default:
		fatal("Bad action in virtual system");
	}
}

/*
 * copy virtual memory blockmap to dupmap
 * read and write groups to avoid possable thrashing.
 */
void
copyV(size)
unsigned size;
{
	char buf[128];
	register int i;
	long bp, bs;

	for(bs = bp = 0; bp < size; ) {
		for(i = 0; (i < 128) && (bp < size); i++, bp++)
			buf[i] = findblock(bp, grabBlock);

		for(i = 0; (i < 128) && (bs < size); i++, bs++)
			findblock(bs, setDup, buf[i]);
	}
}

#ifdef TEST
fatal(s)
char *s;
{
	printf("%s\n", s);
	exit(1);
}

static	char buf[80];
gbuf()
{
	if(NULL == gets(buf)) {
		unlink("vtmp");
		exit(0);
	}
	return(buf[0]);
}

main()
{
	unsigned long b;
	char data;

	initV(10000, 10000, 20000);
	for(;;) {
		printf("b = block, d = dup, f = flags, l = linkctr\n");
		switch(gbuf()) {
		case 'l':
			printf("s = set, d = display, i = increment: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 's':
				setlinkctr(b, 0); /* no data */
			case 'd':
				printf("%d\n", linkctr(b));
				break;
			case 'i':
				printf("%d\n", inclinkctr(b));
			}
			break;
		case 'f':
			printf("d = display, s = set, o = or: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld %c", &b, &data);
			switch(buf[0]) {
			case 's':
				setflags(b, data);
			case 'd':
				break;
			case 'o':
				orflags(b, data);
			}
			printf("%c\n", flags(b));
			break;
		case 'b':
			printf("t = test, m = mark, u = unmark: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 'm':
				markblock(b);
			case 't':
				break;
			case 'u':
				unmarkblock(b);
			}
			printf("%c\n", testblock(b) ? '1' : '0');
			break;
		case 'd':
			printf("t = test, m = mark, u = unmark: then loc\n");
			gbuf();
			sscanf(buf + 2, "%ld", &b);
			switch(buf[0]) {
			case 'm':
				markdup(b);
			case 't':
				break;
			case 'u':
				unmarkdup(b);
			}
			printf("%c\n", testdup(b) ? '1' : '0');
			break;
		}
	}
}
#endif
#endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.