summaryrefslogtreecommitdiff
path: root/sys/src/cmd/hjfs
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-11-16 22:57:43 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2012-11-16 22:57:43 +0100
commit08cd0ea8d4cb921004e8f06caf0f99c944057bdf (patch)
tree8c2b045f36ccceca08560c44893e70c5b280d9a7 /sys/src/cmd/hjfs
parent84ddc4cd4b0fae049f9fa68ee586fbc53cfa2f83 (diff)
hjfs: fix getfree() races, fix very rare buf leak in deltraverse()
Diffstat (limited to 'sys/src/cmd/hjfs')
-rw-r--r--sys/src/cmd/hjfs/fs1.c64
1 files changed, 40 insertions, 24 deletions
diff --git a/sys/src/cmd/hjfs/fs1.c b/sys/src/cmd/hjfs/fs1.c
index e7a116ba8..6f914f911 100644
--- a/sys/src/cmd/hjfs/fs1.c
+++ b/sys/src/cmd/hjfs/fs1.c
@@ -62,44 +62,57 @@ int
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);
- }
-done:
- if(!have){
- werrstr("disk full");
- return -1;
+ if(have)
+ goto found;
+ putbuf(b);
}
+ 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 @@ deltraverse(Fs *fs, Del *p, Buf *b, Del **last)
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);