diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-11-16 22:57:43 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-11-16 22:57:43 +0100 |
commit | 08cd0ea8d4cb921004e8f06caf0f99c944057bdf (patch) | |
tree | 8c2b045f36ccceca08560c44893e70c5b280d9a7 /sys/src/cmd/hjfs | |
parent | 84ddc4cd4b0fae049f9fa68ee586fbc53cfa2f83 (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.c | 64 |
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); |