git: 9front

Download patch

ref: 8047c827640de8b848e1ec9e635478c1467300e7
parent: 7918c550725322e699c4665b024fe7cb1825414d
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Nov 16 08:42:45 EST 2012

hjfs: dentry qid checking, prevent newentry() from allocating already in use slot

always check if the directory entry qid from the loc still
matches the one on disk before doing anything. helps
catching bugs and is basically equivalent to what cwfs does
with its checktag.

make a haveloc() check in newentry() to make sure we dont
allocate a file slot thats still in use, but deleted.
this seems to fix the NPROC>1 build problems.

--- a/sys/src/cmd/hjfs/buf.c
+++ b/sys/src/cmd/hjfs/buf.c
@@ -269,7 +269,8 @@
 	if(nodata)
 		b->type = type;
 	if(b->type != type && type != -1){
-		dprint("hjfs: type mismatch, dev %s, block %lld, got %T, want %T, caller %#p\n", d->name, off, b->type, type, getcallerpc(&d));
+		dprint("hjfs: 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");
 		putbuf(b);
 		return nil;
--- a/sys/src/cmd/hjfs/dump.c
+++ b/sys/src/cmd/hjfs/dump.c
@@ -143,8 +143,8 @@
 	p = getbuf(fs->d, l->next->blk, TDENTRY, 0);
 	if(p == nil)
 		goto err;
-	d = &p->de[l->next->deind];
-	for(i = 0; i < d->size; i++){
+	d = getdent(l->next, p);
+	if(d != nil) for(i = 0; i < d->size; i++){
 		rc = getblk(fs, l->next, p, i, &r, GBREAD);
 		if(rc <= 0)
 			continue;
--- a/sys/src/cmd/hjfs/fns.h
+++ b/sys/src/cmd/hjfs/fns.h
@@ -8,6 +8,7 @@
 Dev*	newdev(char *);
 ThrData*	getthrdata(void);
 Fs*	initfs(Dev *, int, int);
+Dentry*	getdent(FLoc *, Buf *);
 int	getfree(Fs *, uvlong *);
 int	putfree(Fs *, uvlong);
 Chan*	chanattach(Fs *, int);
--- a/sys/src/cmd/hjfs/fs1.c
+++ b/sys/src/cmd/hjfs/fs1.c
@@ -29,6 +29,35 @@
 	return rc;
 }
 
+static int
+qidcmp(Qid *a, Qid *b)
+{
+	if(a->type != b->type)
+		return 1;
+	if(a->path != b->path)
+		return 1;
+	return 0;
+}
+
+Dentry*
+getdent(FLoc *l, Buf *b)
+{
+	Dentry *d;
+
+	d = &b->de[l->deind];
+	if((d->mode & (DGONE | DALLOC)) == 0){
+		dprint("hjfs: getdent: file gone, callerpc %#p\n", getcallerpc(&l));
+		werrstr("phase error -- getdent");
+		return nil;
+	}
+	if(qidcmp(d, l) != 0){
+		dprint("hjfs: getdent: wrong qid, callerpc %#p\n", getcallerpc(&l));
+		werrstr("phase error -- getdent");
+		return nil;
+	}
+	return d;
+}
+
 int
 getfree(Fs *fs, uvlong *r)
 {
@@ -364,13 +393,13 @@
 
 	qlock(&fs->loctree);
 	l = next->child;
-	do{
+	if(l != nil) do{
 		if(l->blk == blk && l->deind == deind){
 			qunlock(&fs->loctree);
 			return 1;
 		}
 		l = l->cnext;
-	}while(l != next->child);
+	} while(l != next->child);
 	qunlock(&fs->loctree);
 	return 0;
 }
@@ -511,7 +540,11 @@
 	Dentry *d;
 
 	b = bd;
-	d = &bd->de[L->deind];
+	d = getdent(L, b);
+	if(d == nil){
+		dprint("hjfs: getblk: dirent gone\n");
+		return -1;
+	}
 	if(blk < NDIRECT){
 		loc = &d->db[blk];
 		goto found;
@@ -696,7 +729,9 @@
 	uvlong l;
 	int i, j;
 
-	d = &bd->de[ll->deind];
+	d = getdent(ll, bd);
+	if(d == nil)
+		return -1;
 	if(size >= d->size)
 		goto done;
 	blk = HOWMANY(size, RBLOCK);
@@ -758,7 +793,9 @@
 	uvlong r;
 	Buf *c;
 	
-	d = &b->de[l->deind];
+	d = getdent(l, b);
+	if(d == nil)
+		return -1;
 	for(i = 0; i < d->size; i++){
 		if(getblk(fs, l, b, i, &r, GBREAD) <= 0)
 			continue;
@@ -816,7 +853,10 @@
 		if(b == nil)
 			return -1;
 	}
-	s = b->de[p->deind].size;
+	d = getdent(p, b);
+	if(d == nil)
+		return -1;
+	s = d->size;
 	for(i = 0; i < s; i++){
 		rc = getblk(fs, p, b, i, &r, GBREAD);
 		if(rc <= 0)
@@ -835,6 +875,7 @@
 					dd = emalloc(sizeof(Del));
 					dd->blk = i;
 					dd->deind = j;
+					dd->Qid = d->Qid;
 					dd->prev = *last;
 					(*last)->next = dd;
 					*last = dd;
@@ -854,8 +895,10 @@
 	Dentry *d;
 	Buf *c;
 	Del *first, *last, *p, *q;
-	
-	d = &b->de[l->deind];
+
+	d = getdent(l, b);
+	if(d == nil)
+		return -1;
 	if((d->type & QTDIR) == 0){
 		trunc(fs, l, b, 0);
 		memset(d, 0, sizeof(*d));
@@ -873,9 +916,12 @@
 			c = getbuf(fs->d, p->blk, TDENTRY, 0);
 		if(c == nil)
 			continue;
-		trunc(fs, p, c, 0);
-		memset(&c->de[p->deind], 0, sizeof(Dentry));
-		c->op |= BDELWRI;
+		d = getdent(p, c);
+		if(d != nil){
+			trunc(fs, p, c, 0);
+			memset(d, 0, sizeof(*d));
+			c->op |= BDELWRI;
+		}
 		if(p != first)
 			putbuf(c);
 	}
@@ -885,7 +931,7 @@
 int
 newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res)
 {
-	Dentry *d;
+	Dentry *d, *dd;
 	uvlong i, si, r;
 	int j, sj, rc;
 	Buf *c;
@@ -892,9 +938,9 @@
 	FLoc f;
 
 	si = sj = -1;
-	d = &b->de[l->deind];
-	for(i = 0; i <= d->size; i++){
-		if(i == d->size && si != -1)
+	d = getdent(l, b);
+	if(d != nil) for(i = 0; i <= d->size; i++){
+		if(i >= d->size && si != -1)
 			break;
 		rc = getblk(fs, l, b, i, &r, si == -1 ? GBCREATE : GBREAD);
 		if(rc < 0)
@@ -906,32 +952,34 @@
 			continue;
 		if(rc == 0){
 			memset(c->de, 0, sizeof(c->de));
-			if(i == d->size){
-				d->size++;
+			if(i >= d->size){
+				d->size = i+1;
 				b->op |= BDELWRI;
 			}
 			c->op |= BDELWRI;
 		}
 		for(j = 0; j < DEPERBLK; j++){
-			if(si == -1 && (c->de[j].mode & DALLOC) == 0){
-				si = i;
-				sj = j;
+			dd = &c->de[j];
+			if((dd->mode & DALLOC) != 0){
+				if(strcmp(dd->name, name) == 0){
+					werrstr(Eexists);
+					putbuf(c);
+					return 0;
+				}
+				continue;
 			}
-			if(si == -1 && (c->de[j].mode & DGONE) != 0 && !haveloc(fs, r, j, l)){
+			if(si != -1 || haveloc(fs, r, j, l))
+				continue;
+			if((dd->mode & DGONE) != 0){
 				memset(&f, 0, sizeof(f));
 				f.blk = r;
 				f.deind = j;
-				if(delete(fs, &f, c) >= 0){
-					si = i;
-					sj = j;
-				}
+				f.Qid = dd->Qid;
+				if(delete(fs, &f, c) < 0)
+					continue;
 			}
-			if((c->de[j].mode & DALLOC) != 0 &&
-			   strcmp(c->de[j].name, name) == 0){
-				werrstr(Eexists);
-				putbuf(c);
-				return 0;
-			}
+			si = i;
+			sj = j;
 		}
 		putbuf(c);
 	}
@@ -942,5 +990,6 @@
 	if(getblk(fs, l, b, si, &res->blk, GBWRITE) <= 0)
 		return -1;
 	res->deind = sj;
+	res->Qid = (Qid){0, 0, 0};
 	return 1;
 }
--- a/sys/src/cmd/hjfs/fs2.c
+++ b/sys/src/cmd/hjfs/fs2.c
@@ -53,7 +53,9 @@
 		chend(ch);
 		return -1;
 	}
-	d = &b->de[ch->loc->deind];
+	d = getdent(ch->loc, b);
+	if(d == nil)
+		goto error;
 	if((d->type & QTDIR) == 0){
 		werrstr(Enotadir);
 		goto error;
@@ -132,7 +134,9 @@
 		chend(ch);
 		return -1;
 	}
-	d = &b->de[ch->loc->deind];
+	d = getdent(ch->loc, b);
+	if(d == nil)
+		goto error;
 	if((d->type & QTDIR) == 0){
 		werrstr(Enotadir);
 		goto error;
@@ -146,9 +150,9 @@
 	c = getbuf(ch->fs->d, f.blk, TDENTRY, 0);
 	if(c == nil)
 		goto error;
-	c->op |= BDELWRI;
-	b->op |= BDELWRI;
 	modified(ch, d);
+	b->op |= BDELWRI;
+	c->op |= BDELWRI;
 	if(isdir)
 		perm &= ~0777 | d->mode & 0777;
 	else
@@ -213,7 +217,9 @@
 		chend(ch);
 		return -1;
 	}
-	d = &b->de[ch->loc->deind];
+	d = getdent(ch->loc, b);
+	if(d == nil)
+		goto err;
 	if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC)){
 	permerr:
 		werrstr(Eperm);
@@ -325,7 +331,12 @@
 		chend(ch);
 		return -1;
 	}
-	d = &b->de[ch->loc->deind];
+	d = getdent(ch->loc, b);
+	if(d == nil){
+		putbuf(b);
+		chend(ch);
+		return -1;
+	}
 	if((d->type & QTAPPEND) != 0)
 		off = d->size;
 	e = off + n;
@@ -392,7 +403,12 @@
 		chend(ch);
 		return -1;
 	}
-	d = &b->de[ch->loc->deind];
+	d = getdent(ch->loc, b);
+	if(d == nil){
+		putbuf(b);
+		chend(ch);
+		return -1;
+	}
 	if(off >= d->size)
 		n = 0;
 	else if(off + n > d->size)
@@ -465,6 +481,7 @@
 chanstat(Chan *ch, Dir *di)
 {
 	Buf *b;
+	Dentry *d;
 	
 	chbegin(ch);
 	b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
@@ -472,7 +489,13 @@
 		chend(ch);
 		return -1;
 	}
-	statbuf(ch->fs, &b->de[ch->loc->deind], di, nil);
+	d = getdent(ch->loc, b);
+	if(d == nil){
+		putbuf(b);
+		chend(ch);
+		return -1;
+	}
+	statbuf(ch->fs, d, di, nil);
 	putbuf(b);
 	chend(ch);
 	return 0;
@@ -504,7 +527,12 @@
 		chend(ch);
 		return -1;
 	}
-	d = &b->de[ch->loc->deind];
+	d = getdent(ch->loc, b);
+	if(d == nil){
+		putbuf(b);
+		chend(ch);
+		return -1;
+	}
 	if(ch->dwblk >= d->size){
 		putbuf(b);
 		chend(ch);
@@ -590,11 +618,16 @@
 		b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
 		if(b == nil)
 			goto err;
-		if(!permcheck(ch->fs, &p->de[ch->loc->next->deind], ch->uid, OWRITE)){
+		d = getdent(ch->loc->next, p);
+		if(d == nil)
+			goto err;
+		if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
 			werrstr(Eperm);
 			goto err;
 		}
-		d = &b->de[ch->loc->deind];
+		d = getdent(ch->loc, b);
+		if(d == nil)
+			goto err;
 		if((d->type & QTDIR) != 0 && findentry(ch->fs, ch->loc, b, nil, nil, ch->flags & CHFDUMP) != 0)
 			goto inval;
 		if((d->mode & DGONE) != 0)
@@ -653,7 +686,10 @@
 		pb = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
 		if(pb == nil)
 			goto error;
-		if(!permcheck(ch->fs, &pb->de[ch->loc->next->deind], ch->uid, OWRITE))
+		d = getdent(ch->loc->next, pb);
+		if(d == nil)
+			goto error;
+		if(!permcheck(ch->fs, d, ch->uid, OWRITE))
 			goto perm;
 		rc = findentry(ch->fs, ch->loc->next, pb, di->name, nil, ch->flags & CHFDUMP);
 		if(rc > 0)
@@ -664,7 +700,9 @@
 	b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
 	if(b == nil)
 		goto error;
-	d = &b->de[ch->loc->deind];
+	d = getdent(ch->loc, b);
+	if(d == nil)
+		goto error;
 	isdir = (d->type & QTDIR) != 0;
 	owner = ch->uid == d->uid || ingroup(ch->fs, ch->uid, d->gid, 1) || (ch->fs->flags & FSNOPERM) != 0;
 	if((uvlong)~di->length){
--