shithub: riscv

Download patch

ref: b9bf9f1d547fe819d87d7dbb2ec58bd0b53d711a
parent: ffa6f9c6ea8ce11c7ed895d5efb1458f256106fd
author: cinap_lenrek <[email protected]>
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){