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){--
⑨