Request queues are only processed once per iteration, once after
select. Presently, request completion goes last, after after new I/O.
As a consequence, vreq completion in filter drivers cannot easily
drive new requests without some pipe loop hooked into the event loop.
Fixed by iterating VBD runs. Iteration stops once all VBDs stop
indicating progress.
Iteration runs a dedicated vbd_recheck_state, because normal
vbd_check_state contains which should not be iterated (most notably
-EBUSY failures).
Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
tapdisk_vbd_check_state(vbd);
}
+static int
+tapdisk_server_recheck_vbds(void)
+{
+ td_vbd_t *vbd, *tmp;
+ int rv = 0;
+
+ tapdisk_server_for_each_vbd(vbd, tmp)
+ rv += tapdisk_vbd_recheck_state(vbd);
+
+ return rv;
+}
+
static void
tapdisk_server_stop_vbds(void)
{
DBG(TLOG_WARN, "server wait returned %d\n", ret);
tapdisk_server_check_vbds();
- tapdisk_server_submit_tiocbs();
- tapdisk_server_kick_responses();
+ do {
+ tapdisk_server_submit_tiocbs();
+ tapdisk_server_kick_responses();
+
+ ret = tapdisk_server_recheck_vbds();
+ } while (ret);
}
static void
return 0;
}
+int
+tapdisk_vbd_recheck_state(td_vbd_t *vbd)
+{
+ if (list_empty(&vbd->new_requests))
+ return 0;
+
+ tapdisk_vbd_issue_new_requests(vbd);
+
+ return 1;
+}
+
static int
tapdisk_vbd_kill_requests(td_vbd_t *vbd)
{
int tapdisk_vbd_resume(td_vbd_t *, const char *);
void tapdisk_vbd_kick(td_vbd_t *);
void tapdisk_vbd_check_state(td_vbd_t *);
+int tapdisk_vbd_recheck_state(td_vbd_t *);
void tapdisk_vbd_check_progress(td_vbd_t *);
void tapdisk_vbd_debug(td_vbd_t *);
void tapdisk_vbd_stats(td_vbd_t *, td_stats_t *);