⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 check.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "stdinc.h"#include "dat.h"#include "fns.h"static void error(Fsck*, char*, ...);static void setBit(uchar*, u32int);static int getBit(uchar*, u32int);static int walkEpoch(Fsck *chk, Block *b, uchar score[VtScoreSize], int type, u32int tag, u32int epoch);static void warn(Fsck*, char*, ...);static void checkLeak(Fsck*);static void clrenop(Fsck*, Block*, int);static void closenop(Fsck*, Block*, u32int);static void clrinop(Fsck*, char*, MetaBlock*, int, Block*);static int printnop(char*, ...);static void checkEpochs(Fsck*);static void checkDirs(Fsck*);#pragma varargck argpos error 2#pragma varargck argpos warn 2static Fsck*checkInit(Fsck *chk){	chk->cache = chk->fs->cache;	chk->nblocks = cacheLocalSize(chk->cache, PartData);;	chk->bsize = chk->fs->blockSize;	chk->walkdepth = 0;	chk->hint = 0;	chk->quantum = chk->nblocks/100;	if(chk->quantum == 0)		chk->quantum = 1;	if(chk->print == nil)		chk->print = printnop;	if(chk->clre == nil)		chk->clre = clrenop;	if(chk->close == nil)		chk->close = closenop;	if(chk->clri == nil)		chk->clri = clrinop;	return chk;}/* * BUG: Should merge checkEpochs and checkDirs so that  * bad blocks are only reported once, and so that errors in checkEpochs * can have the affected file names attached, and so that the file system * is only read once. *  * Also should summarize the errors instead of printing for every one * (e.g., XXX bad or unreachable blocks in /active/usr/rsc/foo). */voidfsCheck(Fsck *chk){	Block *b;	Super super;	checkInit(chk);	b = superGet(chk->cache, &super);	if(b == nil){		chk->print("could not load super block: %R");		return;	}	blockPut(b);	chk->hint = super.active;	checkEpochs(chk);	chk->smap = vtMemAllocZ(chk->nblocks/8+1);	checkDirs(chk);	vtMemFree(chk->smap);}static void checkEpoch(Fsck*, u32int);/* * Walk through all the blocks in the write buffer. * Then we can look for ones we missed -- those are leaks. */static voidcheckEpochs(Fsck *chk){	u32int e;	uint nb;	nb = chk->nblocks;	chk->amap = vtMemAllocZ(nb/8+1);	chk->emap = vtMemAllocZ(nb/8+1);	chk->xmap = vtMemAllocZ(nb/8+1);	chk->errmap = vtMemAllocZ(nb/8+1);	for(e=chk->fs->ehi; e >= chk->fs->elo; e--){		memset(chk->emap, 0, chk->nblocks/8+1);		memset(chk->xmap, 0, chk->nblocks/8+1);		checkEpoch(chk, e);	}	checkLeak(chk);	vtMemFree(chk->amap);	vtMemFree(chk->emap);	vtMemFree(chk->xmap);	vtMemFree(chk->errmap);}static voidcheckEpoch(Fsck *chk, u32int epoch){	u32int a;	Block *b;	Entry e;	Label l;		chk->print("checking epoch %ud...\n", epoch);	for(a=0; a<chk->nblocks; a++){		if(!readLabel(chk->cache, &l, (a+chk->hint)%chk->nblocks)){			error(chk, "could not read label for addr %.8#ux", a);			continue;		}		if(l.tag == RootTag && l.epoch == epoch)			break;	}	if(a == chk->nblocks){		chk->print("could not find root block for epoch %ud", epoch);		return;	}	a = (a+chk->hint)%chk->nblocks;	b = cacheLocalData(chk->cache, a, BtDir, RootTag, OReadOnly, 0);	if(b == nil){		error(chk, "could not read root block %.8#ux: %R", a);		return;	}	/* no one should point at root blocks */	setBit(chk->amap, a);	setBit(chk->emap, a);	setBit(chk->xmap, a);	/*	 * First entry is the rest of the file system.	 * Second entry is link to previous epoch root,	 * just a convenience to help the search.	 */	if(!entryUnpack(&e, b->data, 0)){		error(chk, "could not unpack root block %.8#ux: %R", a);		blockPut(b);		return;	}	walkEpoch(chk, b, e.score, BtDir, e.tag, epoch);	if(entryUnpack(&e, b->data, 1))		chk->hint = globalToLocal(e.score);	blockPut(b);}/* * When b points at bb, need to check: * * (i) b.e in [bb.e, bb.eClose) * (ii) if b.e==bb.e,  then no other b' in e points at bb. * (iii) if !(b.state&Copied) and b.e==bb.e then no other b' points at bb. * (iv) if b is active then no other active b' points at bb. * (v) if b is a past life of b' then only one of b and b' is active (too hard to check) */static intwalkEpoch(Fsck *chk, Block *b, uchar score[VtScoreSize], int type, u32int tag, u32int epoch){	int i, ret;	u32int addr, ep;	Block *bb;	Entry e;	if(b && chk->walkdepth == 0 && chk->printblocks)		chk->print("%V %d %#.8ux %#.8ux\n", b->score, b->l.type, b->l.tag, b->l.epoch);	if(!chk->useventi && globalToLocal(score) == NilBlock)		return 1;	chk->walkdepth++;	bb = cacheGlobal(chk->cache, score, type, tag, OReadOnly);	if(bb == nil){		error(chk, "could not load block %V type %d tag %ux: %R", score, type, tag);		chk->walkdepth--;		return 0;	}	if(chk->printblocks)		chk->print("%*s%V %d %#.8ux %#.8ux\n", chk->walkdepth*2, "", score, type, tag, bb->l.epoch);	ret = 0;	addr = globalToLocal(score);	if(addr == NilBlock){		ret = 1;		goto Exit;	}	if(b){		/* (i) */		if(b->l.epoch < bb->l.epoch || bb->l.epochClose <= b->l.epoch){			error(chk, "walk: block %#ux [%ud, %ud) points at %#ux [%ud, %ud)",				b->addr, b->l.epoch, b->l.epochClose,				bb->addr, bb->l.epoch, bb->l.epochClose);			goto Exit;		}			/* (ii) */		if(b->l.epoch == epoch && bb->l.epoch == epoch){			if(getBit(chk->emap, addr)){				error(chk, "walk: epoch join detected: addr %#ux %L", bb->addr, &bb->l);				goto Exit;			}			setBit(chk->emap, addr);		}			/* (iii) */		if(!(b->l.state&BsCopied) && b->l.epoch == bb->l.epoch){			if(getBit(chk->xmap, addr)){				error(chk, "walk: copy join detected; addr %#ux %L", bb->addr, &bb->l);				goto Exit;			}			setBit(chk->xmap, addr);		}	}	/* (iv) */	if(epoch == chk->fs->ehi){		/* since epoch==fs->ehi is first, amap is same as ``have seen active'' */		if(getBit(chk->amap, addr)){			error(chk, "walk: active join detected: addr %#ux %L", bb->addr, &bb->l);			goto Exit;		}		if(bb->l.state&BsClosed)			error(chk, "walk: addr %#ux: block is in active tree but is closed", addr);	}else{		if(!getBit(chk->amap, addr)){			if(!(bb->l.state&BsClosed)){				// error(chk, "walk: addr %#ux: block is not in active tree, not closed (%d)", addr, bb->l.epochClose);				chk->close(chk, bb, epoch+1);				chk->nclose++;			}		}	}	if(getBit(chk->amap, addr)){		ret = 1;		goto Exit;	}	setBit(chk->amap, addr);	if(chk->nseen++%chk->quantum == 0)		chk->print("check: visited %d/%d blocks (%.0f%%)\n",			chk->nseen, chk->nblocks, chk->nseen*100./chk->nblocks);	b = nil;		/* make sure no more refs to parent */	USED(b);	switch(type){	default:		/* pointer block */		for(i=0; i<chk->bsize/VtScoreSize; i++)			if(!walkEpoch(chk, bb, bb->data + i*VtScoreSize, type-1, tag, epoch)){				setBit(chk->errmap, bb->addr);				chk->clrp(chk, bb, i);				chk->nclrp++;			}		break;	case BtData:		break;	case BtDir:		for(i=0; i<chk->bsize/VtEntrySize; i++){			if(!entryUnpack(&e, bb->data, i)){				// error(chk, "walk: could not unpack entry: %ux[%d]: %R", addr, i);				setBit(chk->errmap, bb->addr);				chk->clre(chk, bb, i);				chk->nclre++;				continue;			}			if(!(e.flags & VtEntryActive))				continue;//fprint(2, "%x[%d] tag=%x snap=%d score=%V\n", addr, i, e.tag, e.snap, e.score);			ep = epoch;			if(e.snap != 0){				if(e.snap >= epoch){					// error(chk, "bad snap in entry: %ux[%d] snap = %ud: epoch = %ud",					//	addr, i, e.snap, epoch);					setBit(chk->errmap, bb->addr);					chk->clre(chk, bb, i);					chk->nclre++;					continue;				}				continue;			}			if(e.flags & VtEntryLocal){				if(e.tag < UserTag)				if(e.tag != RootTag || tag != RootTag || i != 1){					// error(chk, "bad tag in entry: %ux[%d] tag = %ux", addr, i, e.tag);					setBit(chk->errmap, bb->addr);					chk->clre(chk, bb, i);					chk->nclre++;					continue;				}			}else{				if(e.tag != 0){					// error(chk, "bad tag in entry: %ux[%d] tag = %ux", addr, i, e.tag);					setBit(chk->errmap, bb->addr);					chk->clre(chk, bb, i);					chk->nclre++;					continue;				}			}			if(!walkEpoch(chk, bb, e.score, entryType(&e), e.tag, ep)){				setBit(chk->errmap, bb->addr);				chk->clre(chk, bb, i);				chk->nclre++;			}		}		break;	}	ret = 1;Exit:	chk->walkdepth--;	blockPut(bb);	return ret;}/* * We've just walked the whole write buffer.  Notice blocks that * aren't marked available but that we didn't visit.  They are lost. */static voidcheckLeak(Fsck *chk){	u32int a;	Label l;	u32int nfree;	u32int nlost;	Block *b;	nfree = 0;	nlost = 0;	for(a=0; a<chk->nblocks; a++){		if(!readLabel(chk->cache, &l, a)){			error(chk, "could not read label: addr %ux %d %d: %R",				a, l.type, l.state);			continue;		}		if(getBit(chk->amap, a))			continue;		if(l.state == BsFree || l.epochClose <= chk->fs->elo || l.epochClose == l.epoch){			nfree++;			setBit(chk->amap, a);			continue;		}		if(l.state&BsClosed)			continue;		nlost++;		// warn(chk, "unreachable block: addr %ux type %d tag %ux state %s epoch %ud close %ud",		// 	a, l.type, l.tag, bsStr(l.state), l.epoch, l.epochClose);		b = cacheLocal(chk->cache, PartData, a, OReadOnly);		if(b == nil){			error(chk, "could not read block %#.8ux", a);			continue;		}		chk->close(chk, b, 0);		chk->nclose++;		setBit(chk->amap, a);		blockPut(b);	}	chk->print("fsys blocks: total=%ud used=%ud(%.1f%%) free=%ud(%.1f%%) lost=%ud(%.1f%%)\n",		chk->nblocks, 		chk->nblocks-nfree-nlost, 		100.*(chk->nblocks-nfree-nlost)/chk->nblocks,		nfree, 100.*nfree/chk->nblocks,		nlost, 100.*nlost/chk->nblocks);}/* * Check that all sources in the tree are accessible. */static Source *openSource(Fsck *chk, Source *s, char *name, uchar *bm, u32int offset, u32int gen, int dir, MetaBlock *mb, int i, Block *b){	Source *r;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -