ref: 789003556965182198cd7dcf90e43a9f90e3794f
parent: 69c877e2d7aa0a391d1b7169827f6c922f5cf777
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Nov 16 17:57:43 EST 2012
hjfs: fix getfree() races, fix very rare buf leak in deltraverse()
--- a/sys/src/cmd/hjfs/fs1.c
+++ b/sys/src/cmd/hjfs/fs1.c
@@ -62,44 +62,57 @@
getfree(Fs *fs, uvlong *r)
{Dev *d;
- Buf *b, *c;
- uvlong i, l;
+ Buf *b;
+ uvlong i, l, e;
int j, have;
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);
if(b == nil)
return -1;
- if(nbrecv(fs->freelist, r) > 0)
- goto found;
+ e = b->sb.fend;
+ putbuf(b);
+
have = 0;
- for(i = b->sb.fstart, l = 0; i < b->sb.fend; i++){- c = getbuf(d, i, TREF, 0);
- if(c == nil){- putbuf(b);
- return -1;
+ for(l = 0, i = fs->fstart; i < e; i++){+ b = getbuf(d, i, TREF, 0);
+ if(b == nil){+ l += REFPERBLK;
+ continue;
}
for(j = 0; j < REFPERBLK; j++, l++)
- if(c->refs[j] == 0){+ if(b->refs[j] == 0){ if(!have){- have = 1;
+ b->refs[j] = 1;
*r = l;
- }else if(nbsend(fs->freelist, &l) <= 0){- putbuf(c);
- goto done;
+ have = 1;
}
+ else if(nbsend(fs->freelist, &l) <= 0)
+ goto found;
}
- putbuf(c);
+ if(have)
+ goto found;
+ putbuf(b);
}
-done:
- if(!have){- werrstr("disk full");- return -1;
- }
+ werrstr("disk full");+ return -1;
found:
+ b->op |= BDELWRI;
putbuf(b);
- if(chref(fs, *r, 1) < 0)
- return -1;
return 1;
}
@@ -854,14 +867,17 @@
Del *dd;
frb = b == nil;
- if(b == nil){+ if(frb){b = getbuf(fs->d, p->blk, TDENTRY, 0);
if(b == nil)
return -1;
}
d = getdent(p, b);
- if(d == nil)
+ if(d == nil){+ if(frb)
+ putbuf(b);
return -1;
+ }
s = d->size;
for(i = 0; i < s; i++){rc = getblk(fs, p, b, i, &r, GBREAD);
--
⑨