shithub: riscv

Download patch

ref: 1c13d41b8c1f2b94c5e9dcbf3154252c823f14d3
parent: e51044884b329d808015c7972d1c8409303faab3
author: spew <devnull@localhost>
date: Tue Mar 28 16:39:14 EDT 2017

hjfs: Fix bugs in ref count scan check. Enable as a console command (caveat: command arguments will change as I implement more functionality)

--- a/sys/src/cmd/hjfs/buf.c
+++ b/sys/src/cmd/hjfs/buf.c
@@ -273,7 +273,7 @@
 	}
 	if(nodata)
 		b->type = type;
-	if(b->type != type && type != -1){
+	if(b->type != type && type != TDONTCARE){
 		dprint("type mismatch, dev %s, block %lld, got %T, want %T, caller %#p\n",
 			d->name, off, b->type, type, getcallerpc(&d));
 		werrstr("phase error -- type mismatch");
--- a/sys/src/cmd/hjfs/cons.c
+++ b/sys/src/cmd/hjfs/cons.c
@@ -110,20 +110,26 @@
 	Dentry *d;
 	char *ftype;
 	int btype;
-	uvlong i, r;
+	uvlong i, r, blocks;
 
 	d = getdent(l, b);
+	if(d == nil){
+		dprint("checkfile: bad entry: %r\n");
+		return;
+	}
 	if((d->type & QTDIR) == 0){
 		ftype = "file";
 		btype = TRAW;
+		blocks = HOWMANY(d->size);
 	}else{
 		ftype = "directory";
 		btype = TDENTRY;
+		blocks = d->size;
 	}
 
-	for(i = 0; i < d->size; i++){
+	for(i = 0; i < blocks; i++){
 		if(getblk(fsmain, l, b, i, &r, GBREAD) <= 0){
-			dprint("%s in block %ulld at index %d has a bad block at index %ulld: %r\n", ftype, l->blk, l->deind, i);
+			dprint("%s %s in block %ulld at index %d has a bad block at index %ulld: %r\n", ftype, d->name, l->blk, l->deind, i);
 			continue;
 		}
 		c = getbuf(fsmain->d, r, btype, 0);
@@ -148,19 +154,20 @@
 		return -1;
 	switch(type = b->type){
 	case TSUPERBLOCK:
-		dprint("checkblk: should not have found superblock at %ulld\n", blk);
+		if(blk != SUPERBLK)
+			dprint("checkblk: should not have found superblock at %ulld\n", blk);
 		break;
 	case TDENTRY:
 		l.blk = blk;
 		for(i = 0; i < DEPERBLK; i++){
 			d = &b->de[i];
+			if((d->mode & (DGONE | DALLOC)) == 0)
+				break;
 			l.deind = i;
 			l.Qid = d->Qid;
 			checkfile(&l, b);
 		}
 		break;
-	case TINDIR:
-		break;
 	}
 	putbuf(b);
 	return type;
@@ -169,6 +176,7 @@
 int
 cmdcheck(int, char**)
 {
+	static ulong refs[REFPERBLK];
 	uvlong fblk, fend, blk;
 	uvlong ndentry, nindir, nraw, nref, nsuperblock;
 	int j;
@@ -191,9 +199,11 @@
 			blk += REFPERBLK;
 			continue;
 		}
-		for(j = 0; j < REFPERBLK; j++, blk++) {
-			if(b->refs[j] > 0)
-				switch(checkblk(blk)) {
+		memcpy(refs, b->refs, sizeof(refs));
+		putbuf(b);
+		for(j = 0; j < REFPERBLK; j++, blk++){
+			if(refs[j] > 0 && refs[j] != REFSENTINEL){
+				switch(checkblk(blk)){
 				case TDENTRY:
 					ndentry++;
 					break;
@@ -210,8 +220,8 @@
 					nsuperblock++;
 					break;
 				}
+			}
 		}
-		putbuf(b);
 	}
 	wunlock(fsmain);
 	dprint("%T block count %ulld\n", TDENTRY, ndentry);
@@ -454,6 +464,7 @@
 	{"allow", 1, cmdallow},
 	{"noauth", 1, cmdnoauth},
 	{"chatty", 1, cmdchatty},
+	{"check", 0, cmdcheck},
 	{"create", 0, cmdcreate},
 	{"disallow", 1, cmddisallow},
 	{"dump", 1, cmddump},
--- a/sys/src/cmd/hjfs/dat.h
+++ b/sys/src/cmd/hjfs/dat.h
@@ -87,6 +87,7 @@
 	OFFPERBLK = RBLOCK / 12,
 	REFSIZ = 3,
 	REFPERBLK = RBLOCK / REFSIZ,
+	REFSENTINEL = (1 << 8*REFSIZ) - 1,
 };
 
 struct BufReq {