summaryrefslogtreecommitdiff
path: root/sys/src/cmd/rio/xfid.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/src/cmd/rio/xfid.c')
-rw-r--r--sys/src/cmd/rio/xfid.c44
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