fix unbounded recursion bug in hjfs

This commit is contained in:
aiju 2018-08-20 14:26:19 +01:00
parent c8a71691b4
commit 4a120a3816

View file

@ -112,8 +112,8 @@ err:
return -1; return -1;
} }
int static int
willmodify(Fs *fs, Loc *l, int nolock) willmodify1(Fs *fs, Loc *l)
{ {
Buf *p; Buf *p;
Loc *m; Loc *m;
@ -121,29 +121,20 @@ willmodify(Fs *fs, Loc *l, int nolock)
Dentry *d; Dentry *d;
int rc; int rc;
if((l->flags & LDUMPED) != 0)
return 1;
if(!nolock){
again:
runlock(fs);
wlock(fs);
}
if(l->next != nil && willmodify(fs, l->next, 1) < 0)
goto err;
rc = chref(fs, l->blk, 0); rc = chref(fs, l->blk, 0);
if(rc < 0) if(rc < 0)
goto err; return -1;
if(rc == 0){ if(rc == 0){
dprint("willmodify: block %lld has refcount 0\n", l->blk); dprint("willmodify: block %lld has refcount 0\n", l->blk);
werrstr("phase error -- willmodify"); werrstr("phase error -- willmodify");
goto err; return -1;
} }
if(rc == 1) if(rc == 1)
goto done; goto done;
p = getbuf(fs->d, l->next->blk, TDENTRY, 0); p = getbuf(fs->d, l->next->blk, TDENTRY, 0);
if(p == nil) if(p == nil)
goto err; return -1;
d = getdent(l->next, p); d = getdent(l->next, p);
if(d != nil) for(i = 0; i < d->size; i++){ if(d != nil) for(i = 0; i < d->size; i++){
rc = getblk(fs, l->next, p, i, &r, GBREAD); rc = getblk(fs, l->next, p, i, &r, GBREAD);
@ -155,12 +146,12 @@ again:
phase: phase:
werrstr("willmodify -- phase error"); werrstr("willmodify -- phase error");
putbuf(p); putbuf(p);
goto err; return -1;
found: found:
rc = getblk(fs, l->next, p, i, &r, GBWRITE); rc = getblk(fs, l->next, p, i, &r, GBWRITE);
if(rc < 0){ if(rc < 0){
putbuf(p); putbuf(p);
goto err; return -1;
} }
if(rc == 0) if(rc == 0)
goto phase; goto phase;
@ -180,17 +171,50 @@ found:
} }
done: done:
l->flags |= LDUMPED; l->flags |= LDUMPED;
return 0;
}
int
willmodify(Fs *fs, Loc *l, int nolock)
{
Loc **st;
int sti, rc;
if((l->flags & LDUMPED) != 0)
return 1;
if(!nolock){
again:
runlock(fs);
wlock(fs);
}
st = emalloc(sizeof(Loc *));
*st = l;
sti = 0;
for(;;){
if((st[sti]->flags & LDUMPED) != 0 || st[sti]->next == nil)
break;
st = erealloc(st, (sti + 2) * sizeof(Loc *));
st[sti + 1] = st[sti]->next;
sti++;
}
rc = 0;
for(; sti >= 0; sti--){
rc = willmodify1(fs, st[sti]);
if(rc < 0){
free(st);
if(!nolock){
wunlock(fs);
rlock(fs);
}
return -1;
}
}
if(!nolock){ if(!nolock){
wunlock(fs); wunlock(fs);
rlock(fs); rlock(fs);
if(chref(fs, l->blk, 0) != 1) if(chref(fs, l->blk, 0) != 1)
goto again; goto again;
} }
return 0; free(st);
err: return rc;
if(!nolock){
wunlock(fs);
rlock(fs);
}
return -1;
} }