739 lines · 15.3 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "stdinc.h"#include "dat.h"#include "fns.h" /* * disk structure conversion routines */#define	U8GET(p)	((p)[0])#define	U16GET(p)	(((p)[0]<<8)|(p)[1])#define	U32GET(p)	((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))#define	U64GET(p)	(((u64int)U32GET(p)<<32)|(u64int)U32GET((p)+4)) #define	U8PUT(p,v)	(p)[0]=(v)&0xFF#define	U16PUT(p,v)	(p)[0]=((v)>>8)&0xFF;(p)[1]=(v)&0xFF#define	U32PUT(p,v)	(p)[0]=((v)>>24)&0xFF;(p)[1]=((v)>>16)&0xFF;(p)[2]=((v)>>8)&0xFF;(p)[3]=(v)&0xFF#define	U64PUT(p,v,t32)	t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32) int debugarena = -1;		/* hack to improve error reporting */ static struct {	u32int m;	char *s;} magics[] = {	ArenaPartMagic, "ArenaPartMagic",	ArenaHeadMagic, "ArenaHeadMagic",	ArenaMagic, "ArenaMagic",	ISectMagic, "ISectMagic",	BloomMagic, "BloomMagic",}; static char*fmtmagic(char *s, u32int m){	int i; 	for(i=0; i<nelem(magics); i++)		if(magics[i].m == m)			return magics[i].s;	sprint(s, "%#08ux", m);	return s;} u32intunpackmagic(u8int *buf){	return U32GET(buf);} voidpackmagic(u32int magic, u8int *buf){	U32PUT(buf, magic);} intunpackarenapart(ArenaPart *ap, u8int *buf){	u8int *p;	u32int m;	char fbuf[20]; 	p = buf; 	m = U32GET(p);	if(m != ArenaPartMagic){		seterr(ECorrupt, "arena set has wrong magic number: %s expected ArenaPartMagic (%#lux)", fmtmagic(fbuf, m), ArenaPartMagic);		return -1;	}	p += U32Size;	ap->version = U32GET(p);	p += U32Size;	ap->blocksize = U32GET(p);	p += U32Size;	ap->arenabase = U32GET(p);	p += U32Size; 	if(buf + ArenaPartSize != p)		sysfatal("unpackarenapart unpacked wrong amount"); 	return 0;} intpackarenapart(ArenaPart *ap, u8int *buf){	u8int *p; 	p = buf; 	U32PUT(p, ArenaPartMagic);	p += U32Size;	U32PUT(p, ap->version);	p += U32Size;	U32PUT(p, ap->blocksize);	p += U32Size;	U32PUT(p, ap->arenabase);	p += U32Size; 	if(buf + ArenaPartSize != p)		sysfatal("packarenapart packed wrong amount"); 	return 0;} intunpackarena(Arena *arena, u8int *buf){	int sz;	u8int *p;	u32int m;	char fbuf[20]; 	p = buf; 	m = U32GET(p);	if(m != ArenaMagic){		seterr(ECorrupt, "arena %d has wrong magic number: %s "			"expected ArenaMagic (%#lux)", debugarena,			fmtmagic(fbuf, m), ArenaMagic);		return -1;	}	p += U32Size;	arena->version = U32GET(p);	p += U32Size;	namecp(arena->name, (char*)p);	p += ANameSize;	arena->diskstats.clumps = U32GET(p);	p += U32Size;	arena->diskstats.cclumps = U32GET(p);	p += U32Size;	arena->ctime = U32GET(p);	p += U32Size;	arena->wtime = U32GET(p);	p += U32Size;	if(arena->version == ArenaVersion5){		arena->clumpmagic = U32GET(p);		p += U32Size;	}	arena->diskstats.used = U64GET(p);	p += U64Size;	arena->diskstats.uncsize = U64GET(p);	p += U64Size;	arena->diskstats.sealed = U8GET(p);	p += U8Size;	switch(arena->version){	case ArenaVersion4:		sz = ArenaSize4;		arena->clumpmagic = _ClumpMagic;		break;	case ArenaVersion5:		sz = ArenaSize5;		break;	default:		seterr(ECorrupt, "arena has bad version number %d", arena->version);		return -1;	}	/*	 * Additional fields for the memstats version of the stats.	 * Diskstats reflects what is committed to the index.	 * Memstats reflects what is in the arena.  Originally intended	 * this to be a version 5 extension, but might as well use for	 * all the existing version 4 arenas too.	 *	 * To maintain backwards compatibility with existing venti	 * installations using the older format, we define that if 	 * memstats == diskstats, then the extension fields are not	 * included (see packarena below).  That is, only partially	 * indexed arenas have these fields.  Fully indexed arenas	 * (in particular, sealed arenas) do not.	 */	if(U8GET(p) == 1){		sz += ArenaSize5a-ArenaSize5;		p += U8Size;		arena->memstats.clumps = U32GET(p);		p += U32Size;		arena->memstats.cclumps = U32GET(p);		p += U32Size;		arena->memstats.used = U64GET(p);		p += U64Size;		arena->memstats.uncsize = U64GET(p);		p += U64Size;		arena->memstats.sealed = U8GET(p);		p += U8Size;				/*		 * 2008/4/2		 * Packarena (below) used to have a bug in which it would		 * not zero out any existing extension fields when writing		 * the arena metadata.  This would manifest itself as arenas		 * with arena->diskstats.sealed == 1 but arena->memstats.sealed == 0		 * after a server restart.  Because arena->memstats.sealed wouldn't		 * be set, the server might try to fit another block into the arena		 * (and succeed), violating the append-only structure of the log		 * and invalidating any already-computed seal on the arena.		 *		 * It might end up that other fields in arena->memstats end up		 * behind arena->diskstats too, but that would be considerably		 * more rare, and the bug is fixed now.  The case we need to		 * handle is just the sealed mismatch.		 *		 * If we encounter such a bogus arena, fix the sealed field.		 */		if(arena->diskstats.sealed)			arena->memstats.sealed = 1;	}else		arena->memstats = arena->diskstats;	if(buf + sz != p)		sysfatal("unpackarena unpacked wrong amount"); 	return 0;} intpackarena(Arena *arena, u8int *buf){	return _packarena(arena, buf, 0);} int_packarena(Arena *arena, u8int *buf, int forceext){	int sz;	u8int *p;	u32int t32; 	switch(arena->version){	case ArenaVersion4:		sz = ArenaSize4;		if(arena->clumpmagic != _ClumpMagic)			fprint(2, "warning: writing old arena tail loses clump magic 0x%lux != 0x%lux\n",				(ulong)arena->clumpmagic, (ulong)_ClumpMagic);		break;	case ArenaVersion5:		sz = ArenaSize5;		break;	default:		sysfatal("packarena unknown version %d", arena->version);		return -1;	} 	p = buf; 	U32PUT(p, ArenaMagic);	p += U32Size;	U32PUT(p, arena->version);	p += U32Size;	namecp((char*)p, arena->name);	p += ANameSize;	U32PUT(p, arena->diskstats.clumps);	p += U32Size;	U32PUT(p, arena->diskstats.cclumps);	p += U32Size;	U32PUT(p, arena->ctime);	p += U32Size;	U32PUT(p, arena->wtime);	p += U32Size;	if(arena->version == ArenaVersion5){		U32PUT(p, arena->clumpmagic);		p += U32Size;	}	U64PUT(p, arena->diskstats.used, t32);	p += U64Size;	U64PUT(p, arena->diskstats.uncsize, t32);	p += U64Size;	U8PUT(p, arena->diskstats.sealed);	p += U8Size;		/*	 * Extension fields; see above.	 */	if(forceext	|| arena->memstats.clumps != arena->diskstats.clumps	|| arena->memstats.cclumps != arena->diskstats.cclumps	|| arena->memstats.used != arena->diskstats.used	|| arena->memstats.uncsize != arena->diskstats.uncsize	|| arena->memstats.sealed != arena->diskstats.sealed){		sz += ArenaSize5a - ArenaSize5;		U8PUT(p, 1);		p += U8Size;		U32PUT(p, arena->memstats.clumps);		p += U32Size;		U32PUT(p, arena->memstats.cclumps);		p += U32Size;		U64PUT(p, arena->memstats.used, t32);			p += U64Size;		U64PUT(p, arena->memstats.uncsize, t32);		p += U64Size;		U8PUT(p, arena->memstats.sealed);		p += U8Size;	}else{		/* Clear any extension fields already on disk. */		memset(p, 0, ArenaSize5a - ArenaSize5);		p += ArenaSize5a - ArenaSize5;		sz += ArenaSize5a - ArenaSize5;	} 	if(buf + sz != p)		sysfatal("packarena packed wrong amount"); 	return 0;} intunpackarenahead(ArenaHead *head, u8int *buf){	u8int *p;	u32int m;	int sz;	char fbuf[20]; 	p = buf; 	m = U32GET(p);	if(m != ArenaHeadMagic){		seterr(ECorrupt, "arena %d head has wrong magic number: %s "			"expected ArenaHeadMagic (%#lux)", debugarena,			fmtmagic(fbuf, m), ArenaHeadMagic);		return -1;	} 	p += U32Size;	head->version = U32GET(p);	p += U32Size;	namecp(head->name, (char*)p);	p += ANameSize;	head->blocksize = U32GET(p);	p += U32Size;	head->size = U64GET(p);	p += U64Size;	if(head->version == ArenaVersion5){		head->clumpmagic = U32GET(p);		p += U32Size;	} 	switch(head->version){	case ArenaVersion4:		sz = ArenaHeadSize4;		head->clumpmagic = _ClumpMagic;		break;	case ArenaVersion5:		sz = ArenaHeadSize5;		break;	default:		seterr(ECorrupt, "arena head has unexpected version %d", head->version);		return -1;	} 	if(buf + sz != p)		sysfatal("unpackarenahead unpacked wrong amount"); 	return 0;} intpackarenahead(ArenaHead *head, u8int *buf){	u8int *p;	int sz;	u32int t32; 	switch(head->version){	case ArenaVersion4:		sz = ArenaHeadSize4;		if(head->clumpmagic != _ClumpMagic)			fprint(2, "warning: writing old arena header loses clump magic 0x%lux != 0x%lux\n",				(ulong)head->clumpmagic, (ulong)_ClumpMagic);		break;	case ArenaVersion5:		sz = ArenaHeadSize5;		break;	default:		sysfatal("packarenahead unknown version %d", head->version);		return -1;	} 	p = buf; 	U32PUT(p, ArenaHeadMagic);	p += U32Size;	U32PUT(p, head->version);	p += U32Size;	namecp((char*)p, head->name);	p += ANameSize;	U32PUT(p, head->blocksize);	p += U32Size;	U64PUT(p, head->size, t32);	p += U64Size;	if(head->version == ArenaVersion5){		U32PUT(p, head->clumpmagic);		p += U32Size;	}	if(buf + sz != p)		sysfatal("packarenahead packed wrong amount"); 	return 0;} static intcheckclump(Clump *w){	if(w->encoding == ClumpENone){		if(w->info.size != w->info.uncsize){			seterr(ECorrupt, "uncompressed wad size mismatch");			return -1;		}	}else if(w->encoding == ClumpECompress){		if(w->info.size >= w->info.uncsize){			seterr(ECorrupt, "compressed lump has inconsistent block sizes %d %d", w->info.size, w->info.uncsize);			return -1;		}	}else{		seterr(ECorrupt, "clump has illegal encoding");		return -1;	} 	return 0;} intunpackclump(Clump *c, u8int *buf, u32int cmagic){	u8int *p;	u32int magic; 	p = buf;	magic = U32GET(p);	if(magic != cmagic){		seterr(ECorrupt, "clump has bad magic number=%#8.8ux != %#8.8ux", magic, cmagic);		return -1;	}	p += U32Size; 	c->info.type = vtfromdisktype(U8GET(p));	p += U8Size;	c->info.size = U16GET(p);	p += U16Size;	c->info.uncsize = U16GET(p);	p += U16Size;	scorecp(c->info.score, p);	p += VtScoreSize; 	c->encoding = U8GET(p);	p += U8Size;	c->creator = U32GET(p);	p += U32Size;	c->time = U32GET(p);	p += U32Size; 	if(buf + ClumpSize != p)		sysfatal("unpackclump unpacked wrong amount"); 	return checkclump(c);} intpackclump(Clump *c, u8int *buf, u32int magic){	u8int *p; 	p = buf;	U32PUT(p, magic);	p += U32Size; 	U8PUT(p, vttodisktype(c->info.type));	p += U8Size;	U16PUT(p, c->info.size);	p += U16Size;	U16PUT(p, c->info.uncsize);	p += U16Size;	scorecp(p, c->info.score);	p += VtScoreSize; 	U8PUT(p, c->encoding);	p += U8Size;	U32PUT(p, c->creator);	p += U32Size;	U32PUT(p, c->time);	p += U32Size; 	if(buf + ClumpSize != p)		sysfatal("packclump packed wrong amount"); 	return checkclump(c);} voidunpackclumpinfo(ClumpInfo *ci, u8int *buf){	u8int *p; 	p = buf;

Lines 1–500 of 739.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t