hjfs: fix getfree() races, fix very rare buf leak in deltraverse()
This commit is contained in:
parent
84ddc4cd4b
commit
08cd0ea8d4
1 changed files with 40 additions and 24 deletions
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue