File:  [MW Coherent from dump] / coherent / d / etc / fsck / phase5.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

/*
 *	phase 5 of fsck - Check Free List
 */

#include "fsck.h"

daddr_t	badcnt;			/* Number of bad blocks in free list */
daddr_t dupcnt;			/* Number of dup blocks in free list */
int	badflag;		/* Bad free list flag */
int 	fixerup;		/* Flag to salvage free list */

phase5()
{
	struct fblk *fbp;
	unsigned size;
	
	if (!qflag)
		printf("Phase 5 : Check Free List\n");
	fbp = (struct fblk *) &sbp->s_nfree;
	size = (unsigned) ((fsize+NBPC-1)/NBPC) * sizeof(char);
#if SMALLMODEL
	copyV(size);
#else
	memcpy(dupPtr, blockPtr, size);
#endif
	badcnt = dupcnt = 0;
	badflag = FALSE;
	freetrav(fbp);
	fixerup = FALSE;
	if (badflag || sflag) 
		asksalvage();
}


#define	IGNORE	3		/* Return Possibilities from chk() */
#define	ABORT	4		/* as well as perhaps GOOD and BAD */

freetrav(fbp)
struct fblk *fbp;
{
	daddr_t total=0;
	int i, flag;

	while ( fbp->df_nfree != 0 ) {
		if ( (unsigned) fbp->df_nfree > NICFREE ) {
			badflag = TRUE;
			printf("Bad freeblock count.\n");
			break;
		}
		for (i=1; i<fbp->df_nfree; i++) {
			if ( (flag=chk(fbp->df_free[i])) == GOOD ) {
				total++;
				continue;
			}
			if (flag == BAD)
				continue;
			break;		/* break for IGNORE or ABORT	*/
		}
		if ( (flag == IGNORE) || (flag == ABORT) )
			break;
		if ( chk(fbp->df_free[0]) != GOOD )
			break;
		total++;
		bread(fbp->df_free[0], databuf);
		fbp = (struct fblk *) databuf;
		if ( !canfblk(fbp) ) {
			badflag = TRUE;
			printf("Bad freeblock count.\n");
			break;
		}
	}

#if 0
	printf("Total traversed free blocks     = %U\n", total);	 
	printf("Total free blocks by Superblock = %U\n", sbp->s_tfree);	 
	printf("Running total free blocks       = %U\n", totfree);	 
#endif

	if ( flag == ABORT ) { 		/* To Terminate fsck on this 	*/
		badflag = FALSE;	/* File System, because of	*/
		return;			/* excessive dup or bad blocks	*/
	}

	if ( sbp->s_tfree != totfree )
		if ( (qflag==FALSE) && (daction!=NO) ) {
			printf("Free Block count wrong in superblock.  ");
			if ( action(fixit) == TRUE ) {
				sbp->s_tfree = totfree;
				sbpfix = TRUE;
			}
		} else {
			sbp->s_tfree = totfree;
			sbpfix = TRUE;
		}

	report("%U Bad Block%s in Free List\n", badcnt);
	report("%U Dup Block%s in Free List\n", dupcnt);
	report("%U Block%s missing\n", totfree - total);

}

report(message, num)
char *message;
daddr_t num;
{
	if ( num != 0 ) {
		printf(message, num, ( (num>1) ? "s" : "" ) );
		badflag = TRUE;
	}
}

chk(bn)
register daddr_t bn;
{
	if ( (bn<isize) || (bn>=fsize) ) {
		badflag = TRUE;
		if (++badcnt > MAXBADFREE) 
			return( stopit("bad") );
		return(BAD);
	}

	if ( testdup(bn) ) {
		badflag = TRUE;
		if (++dupcnt > MAXDUPFREE)
			return( stopit("dup") );
		return(BAD);
	} else {
		markdup(bn);
		return(GOOD);
	}
}
			
stopit(type)
char *type;
{
	printf("Excessive %s blocks in free list ", type);
	if ( query("(Continue)") == YES )
		return(IGNORE);
	else
		return(ABORT);
}
		
		
canfblk(fbp)
register struct fblk *fbp;
{
	register short i;

	canshort(fbp->df_nfree);
	if ( (unsigned) fbp->df_nfree > NICFREE )
		return(FALSE);

	for (i=0; i<fbp->df_nfree; i++)
		candaddr(fbp->df_free[i]);
	return(TRUE);
}

asksalvage()
{
	if ( (daction!=NO) && (qflag || sflag) ) {
		fixerup = TRUE;
		return;
	}
	if ( action("Bad Free List (SALVAGE)") )
		fixerup = TRUE;
}

unix.superglobalmegacorp.com

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