diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-11-01 18:57:11 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-11-01 18:57:11 +0100 |
commit | 413977c19bb65fb1b704d58ae9a59cdf64179c84 (patch) | |
tree | 43159f5a41cb1ed5cda9ac9ab93bd60d2ec49364 /sys/src/cmd/rio/xfid.c | |
parent | f87baec1d0369764b761e8ca26a910e982123453 (diff) |
rio: properly handle follow up flushes (fixes unexpected reply tag)
when multiple flushes are send, they need to be replied
in order. we ensure this by having the flush xfid taking
over the flushtag (synchronized with a new fs->csyncflush
channel) so the next flush will flush the previous flush.
Diffstat (limited to 'sys/src/cmd/rio/xfid.c')
-rw-r--r-- | sys/src/cmd/rio/xfid.c | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/sys/src/cmd/rio/xfid.c b/sys/src/cmd/rio/xfid.c index b505b2f06..662d686cf 100644 --- a/sys/src/cmd/rio/xfid.c +++ b/sys/src/cmd/rio/xfid.c @@ -124,24 +124,44 @@ xfidflush(Xfid *x) for(xf=xfid; xf; xf=xf->next) if(xf->flushtag == x->oldtag){ - xf->flushtag = -1; - xf->flushing = TRUE; incref(xf); /* to hold data structures up at tail of synchronization */ if(xf->ref == 1) error("ref 1 in flush"); - if(canqlock(&xf->active)){ - qunlock(&xf->active); - sendul(xf->flushc, 0); - }else{ - qlock(&xf->active); /* wait for him to finish */ - qunlock(&xf->active); - } - xf->flushing = FALSE; - if(decref(xf) == 0) - sendp(cxfidfree, xf); + /* take over flushtag so follow up flushes wait for us */ + x->flushtag = x->oldtag; + xf->flushtag = -1; break; } + + /* + * wakeup filsysflush() in the filsysproc so the next + * flush can come in. + */ + sendul(x->fs->csyncflush, 0); + + if(xf){ + qlock(&xf->active); + if(xf->buf){ /* not responded yet? */ + xf->flushing = TRUE; + qunlock(&xf->active); + sendul(xf->flushc, 0); + xf->flushing = FALSE; + }else{ + qunlock(&xf->active); + } + if(decref(xf) == 0) + sendp(cxfidfree, xf); + } + + qlock(&x->active); + if(x->flushing){ + qunlock(&x->active); + recv(x->flushc, nil); /* wakeup flushing xfid */ + filsyscancel(x); + return; + } filsysrespond(x->fs, x, &t, nil); + qunlock(&x->active); } void |