hjfs: fix getfree() races, fix very rare buf leak in deltraverse()

This commit is contained in:
cinap_lenrek 2012-11-16 22:57:43 +01:00
parent 84ddc4cd4b
commit 08cd0ea8d4

View file

@ -62,44 +62,57 @@ int
getfree(Fs *fs, uvlong *r) getfree(Fs *fs, uvlong *r)
{ {
Dev *d; Dev *d;
Buf *b, *c; Buf *b;
uvlong i, l; uvlong i, l, e;
int j, have; int j, have;
d = fs->d; d = fs->d;
while(nbrecv(fs->freelist, &l) > 0){
i = fs->fstart + l / REFPERBLK;
j = l % REFPERBLK;
b = getbuf(d, i, TREF, 0);
if(b != nil){
if(b->refs[j] == 0){
b->refs[j] = 1;
*r = l;
goto found;
}
putbuf(b);
}
}
b = getbuf(d, SUPERBLK, TSUPERBLOCK, 0); b = getbuf(d, SUPERBLK, TSUPERBLOCK, 0);
if(b == nil) if(b == nil)
return -1; return -1;
if(nbrecv(fs->freelist, r) > 0) e = b->sb.fend;
goto found; putbuf(b);
have = 0; have = 0;
for(i = b->sb.fstart, l = 0; i < b->sb.fend; i++){ for(l = 0, i = fs->fstart; i < e; i++){
c = getbuf(d, i, TREF, 0); b = getbuf(d, i, TREF, 0);
if(c == nil){ if(b == nil){
putbuf(b); l += REFPERBLK;
return -1; continue;
} }
for(j = 0; j < REFPERBLK; j++, l++) for(j = 0; j < REFPERBLK; j++, l++)
if(c->refs[j] == 0){ if(b->refs[j] == 0){
if(!have){ if(!have){
have = 1; b->refs[j] = 1;
*r = l; *r = l;
}else if(nbsend(fs->freelist, &l) <= 0){ have = 1;
putbuf(c);
goto done;
} }
else if(nbsend(fs->freelist, &l) <= 0)
goto found;
} }
putbuf(c); if(have)
} goto found;
done: putbuf(b);
if(!have){
werrstr("disk full");
return -1;
} }
werrstr("disk full");
return -1;
found: found:
b->op |= BDELWRI;
putbuf(b); putbuf(b);
if(chref(fs, *r, 1) < 0)
return -1;
return 1; return 1;
} }
@ -854,14 +867,17 @@ deltraverse(Fs *fs, Del *p, Buf *b, Del **last)
Del *dd; Del *dd;
frb = b == nil; frb = b == nil;
if(b == nil){ if(frb){
b = getbuf(fs->d, p->blk, TDENTRY, 0); b = getbuf(fs->d, p->blk, TDENTRY, 0);
if(b == nil) if(b == nil)
return -1; return -1;
} }
d = getdent(p, b); d = getdent(p, b);
if(d == nil) if(d == nil){
if(frb)
putbuf(b);
return -1; return -1;
}
s = d->size; s = d->size;
for(i = 0; i < s; i++){ for(i = 0; i < s; i++){
rc = getblk(fs, p, b, i, &r, GBREAD); rc = getblk(fs, p, b, i, &r, GBREAD);