debuggers.hg

changeset 20917:218026df8d5f

blktap2: Separate tapdisk raw I/O into different backends.

Hide tapdisk support for different raw I/O interfaces behind a new
struct tio. Libaio remains to dominate the interface, requiring
everyone to dispatch iocb/ioevent structs.

Backends:
- lio: Kernel AIO via libaio.
- rwio: Canonical read/write() mode.

Misc:
- Fixes a bug in tapdisk-vbd which locks up the sync io mode.
- Wants a PERROR macro in blktaplib.h
- Removes dead code in qcow2raw to make it link again.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
Signed-off-by: Jake Wires <jake.wires@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jan 29 08:54:51 2010 +0000 (2010-01-29)
parents f2ef85551a09
children b0ffb4912c46
files tools/blktap2/drivers/tapdisk-queue.c tools/blktap2/drivers/tapdisk-queue.h tools/blktap2/drivers/tapdisk-server.c tools/blktap2/drivers/tapdisk-vbd.c tools/blktap2/include/blktaplib.h
line diff
     1.1 --- a/tools/blktap2/drivers/tapdisk-queue.c	Fri Jan 29 08:54:22 2010 +0000
     1.2 +++ b/tools/blktap2/drivers/tapdisk-queue.c	Fri Jan 29 08:54:51 2010 +0000
     1.3 @@ -141,7 +141,7 @@ cancel_tiocbs(struct tqueue *queue, int 
     1.4  	 * use a private linked list to keep track
     1.5  	 * of the tiocbs we're cancelling. 
     1.6  	 */
     1.7 -	tiocb  = (struct tiocb *)queue->iocbs[0]->data;
     1.8 +	tiocb  = queue->iocbs[0]->data;
     1.9  	queued = queue->queued;
    1.10  	queue->queued = 0;
    1.11  
    1.12 @@ -165,8 +165,40 @@ fail_tiocbs(struct tqueue *queue, int su
    1.13  	return cancel_tiocbs(queue, err);
    1.14  }
    1.15  
    1.16 +/*
    1.17 + * rwio
    1.18 + */
    1.19 +
    1.20 +struct rwio {
    1.21 +	struct io_event *aio_events;
    1.22 +};
    1.23 +
    1.24 +static void
    1.25 +tapdisk_rwio_destroy(struct tqueue *queue)
    1.26 +{
    1.27 +	struct rwio *rwio = queue->tio_data;
    1.28 +
    1.29 +	if (rwio->aio_events) {
    1.30 +		free(rwio->aio_events);
    1.31 +		rwio->aio_events = NULL;
    1.32 +	}
    1.33 +}
    1.34 +
    1.35 +static int
    1.36 +tapdisk_rwio_setup(struct tqueue *queue, int size)
    1.37 +{
    1.38 +	struct rwio *rwio = queue->tio_data;
    1.39 +	int err;
    1.40 +
    1.41 +	rwio->aio_events = calloc(size, sizeof(struct io_event));
    1.42 +	if (!rwio->aio_events)
    1.43 +		return -errno;
    1.44 +
    1.45 +	return 0;
    1.46 +}
    1.47 +
    1.48  static inline ssize_t
    1.49 -iocb_rw(struct iocb *iocb)
    1.50 +tapdisk_rwio_rw(const struct iocb *iocb)
    1.51  {
    1.52  	int fd        = iocb->aio_fildes;
    1.53  	char *buf     = iocb->u.c.buf;
    1.54 @@ -177,7 +209,7 @@ iocb_rw(struct iocb *iocb)
    1.55  
    1.56  	if (lseek(fd, off, SEEK_SET) == (off_t)-1)
    1.57  		return -errno;
    1.58 -	
    1.59 +
    1.60  	if (atomicio(func, fd, buf, size) != size)
    1.61  		return -errno;
    1.62  
    1.63 @@ -185,8 +217,9 @@ iocb_rw(struct iocb *iocb)
    1.64  }
    1.65  
    1.66  static int
    1.67 -io_synchronous_rw(struct tqueue *queue)
    1.68 +tapdisk_rwio_submit(struct tqueue *queue)
    1.69  {
    1.70 +	struct rwio *rwio = queue->tio_data;
    1.71  	int i, merged, split;
    1.72  	struct iocb *iocb;
    1.73  	struct tiocb *tiocb;
    1.74 @@ -201,18 +234,18 @@ io_synchronous_rw(struct tqueue *queue)
    1.75  	queue->queued = 0;
    1.76  
    1.77  	for (i = 0; i < merged; i++) {
    1.78 -		ep      = queue->aio_events + i;
    1.79 +		ep      = rwio->aio_events + i;
    1.80  		iocb    = queue->iocbs[i];
    1.81  		ep->obj = iocb;
    1.82 -		ep->res = iocb_rw(iocb);
    1.83 +		ep->res = tapdisk_rwio_rw(iocb);
    1.84  	}
    1.85  
    1.86 -	split = io_split(&queue->opioctx, queue->aio_events, merged);
    1.87 -	tapdisk_filter_events(queue->filter, queue->aio_events, split);
    1.88 +	split = io_split(&queue->opioctx, rwio->aio_events, merged);
    1.89 +	tapdisk_filter_events(queue->filter, rwio->aio_events, split);
    1.90  
    1.91 -	for (i = split, ep = queue->aio_events; i-- > 0; ep++) {
    1.92 +	for (i = split, ep = rwio->aio_events; i-- > 0; ep++) {
    1.93  		iocb  = ep->obj;
    1.94 -		tiocb = (struct tiocb *)iocb->data;
    1.95 +		tiocb = iocb->data;
    1.96  		complete_tiocb(queue, tiocb, ep->res);
    1.97  	}
    1.98  
    1.99 @@ -221,65 +254,258 @@ io_synchronous_rw(struct tqueue *queue)
   1.100  	return split;
   1.101  }
   1.102  
   1.103 -static void tapdisk_tiocb_event(event_id_t id, char mode, void *private);
   1.104 +static const struct tio td_tio_rwio = {
   1.105 +	.name        = "rwio",
   1.106 +	.data_size   = 0,
   1.107 +	.tio_setup   = NULL,
   1.108 +	.tio_destroy = NULL,
   1.109 +	.tio_submit  = tapdisk_rwio_submit
   1.110 +};
   1.111 +
   1.112 +/*
   1.113 + * libaio
   1.114 + */
   1.115 +
   1.116 +struct lio {
   1.117 +	io_context_t     aio_ctx;
   1.118 +	struct io_event *aio_events;
   1.119 +
   1.120 +	int              poll_fd;
   1.121 +	int              event_id;
   1.122 +};
   1.123 +
   1.124 +static void
   1.125 +tapdisk_lio_destroy(struct tqueue *queue)
   1.126 +{
   1.127 +	struct lio *lio = queue->tio_data;
   1.128 +
   1.129 +	if (!lio)
   1.130 +		return;
   1.131 +
   1.132 +	if (lio->event_id >= 0) {
   1.133 +		tapdisk_server_unregister_event(lio->event_id);
   1.134 +		lio->event_id = -1;
   1.135 +	}
   1.136 +
   1.137 +	if (lio->aio_ctx) {
   1.138 +		io_destroy(lio->aio_ctx);
   1.139 +		lio->aio_ctx = NULL;
   1.140 +	}
   1.141 +
   1.142 +	if (lio->aio_events) {
   1.143 +		free(lio->aio_events);
   1.144 +		lio->aio_events = NULL;
   1.145 +	}
   1.146 +}
   1.147 +
   1.148 +static void
   1.149 +tapdisk_lio_event(event_id_t id, char mode, void *private)
   1.150 +{
   1.151 +	struct tqueue *queue = private;
   1.152 +	struct lio *lio;
   1.153 +	int i, ret, split;
   1.154 +	struct iocb *iocb;
   1.155 +	struct tiocb *tiocb;
   1.156 +	struct io_event *ep;
   1.157 +
   1.158 +	lio   = queue->tio_data;
   1.159 +	ret   = io_getevents(lio->aio_ctx, 0,
   1.160 +			     queue->size, lio->aio_events, NULL);
   1.161 +	split = io_split(&queue->opioctx, lio->aio_events, ret);
   1.162 +	tapdisk_filter_events(queue->filter, lio->aio_events, split);
   1.163 +
   1.164 +	DBG("events: %d, tiocbs: %d\n", ret, split);
   1.165 +
   1.166 +	queue->iocbs_pending  -= ret;
   1.167 +	queue->tiocbs_pending -= split;
   1.168 +
   1.169 +	for (i = split, ep = lio->aio_events; i-- > 0; ep++) {
   1.170 +		iocb  = ep->obj;
   1.171 +		tiocb = iocb->data;
   1.172 +		complete_tiocb(queue, tiocb, ep->res);
   1.173 +	}
   1.174 +
   1.175 +	queue_deferred_tiocbs(queue);
   1.176 +}
   1.177 +
   1.178 +static int
   1.179 +tapdisk_lio_setup(struct tqueue *queue, int qlen)
   1.180 +{
   1.181 +	struct lio *lio = queue->tio_data;
   1.182 +	size_t sz;
   1.183 +	int err;
   1.184 +
   1.185 +	lio->event_id = -1;
   1.186 +	lio->aio_ctx  = REQUEST_ASYNC_FD;
   1.187 +
   1.188 +	lio->poll_fd = io_setup(qlen, &lio->aio_ctx);
   1.189 +	err = lio->poll_fd;
   1.190 +	if (err < 0) {
   1.191 +		lio->aio_ctx = NULL;
   1.192 +
   1.193 +		if (err == -EAGAIN)
   1.194 +			goto fail_rsv;
   1.195 +
   1.196 +		goto fail_fd;
   1.197 +	}
   1.198 +
   1.199 +	lio->event_id =
   1.200 +		tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
   1.201 +					      lio->poll_fd, 0,
   1.202 +					      tapdisk_lio_event,
   1.203 +					      queue);
   1.204 +	err = lio->event_id;
   1.205 +	if (err < 0)
   1.206 +		goto fail;
   1.207 +
   1.208 +	lio->aio_events = calloc(qlen, sizeof(struct io_event));
   1.209 +	if (!lio->aio_events) {
   1.210 +		err = -errno;
   1.211 +		goto fail;
   1.212 +	}
   1.213 +
   1.214 +	return 0;
   1.215 +
   1.216 +fail:
   1.217 +	tapdisk_lio_destroy(queue);
   1.218 +	return err;
   1.219 +
   1.220 +fail_rsv:
   1.221 +	DPRINTF("Couldn't setup AIO context. If you are trying to "
   1.222 +		"concurrently use a large number of blktap-based disks, you may "
   1.223 +		"need to increase the system-wide aio request limit. "
   1.224 +		"(e.g. 'echo 1048576 > /proc/sys/fs/aio-max-nr')\n");
   1.225 +	goto fail;
   1.226 +
   1.227 +fail_fd:
   1.228 +	DPRINTF("Couldn't get fd for AIO poll support. This is probably "
   1.229 +		"because your kernel does not have  the aio-poll patch "
   1.230 +		"applied.\n");
   1.231 +	goto fail;
   1.232 +}
   1.233 +
   1.234 +static int
   1.235 +tapdisk_lio_submit(struct tqueue *queue)
   1.236 +{
   1.237 +	struct lio *lio = queue->tio_data;
   1.238 +	int merged, submitted, err = 0;
   1.239 +
   1.240 +	if (!queue->queued)
   1.241 +		return 0;
   1.242 +
   1.243 +	tapdisk_filter_iocbs(queue->filter, queue->iocbs, queue->queued);
   1.244 +	merged    = io_merge(&queue->opioctx, queue->iocbs, queue->queued);
   1.245 +	submitted = io_submit(lio->aio_ctx, merged, queue->iocbs);
   1.246 +
   1.247 +	DBG("queued: %d, merged: %d, submitted: %d\n",
   1.248 +	    queue->queued, merged, submitted);
   1.249 +
   1.250 +	if (submitted < 0) {
   1.251 +		err = submitted;
   1.252 +		submitted = 0;
   1.253 +	} else if (submitted < merged)
   1.254 +		err = -EIO;
   1.255 +
   1.256 +	queue->iocbs_pending  += submitted;
   1.257 +	queue->tiocbs_pending += queue->queued;
   1.258 +	queue->queued          = 0;
   1.259 +
   1.260 +	if (err)
   1.261 +		queue->tiocbs_pending -= 
   1.262 +			fail_tiocbs(queue, submitted, merged, err);
   1.263 +
   1.264 +	return submitted;
   1.265 +}
   1.266 +
   1.267 +static const struct tio td_tio_lio = {
   1.268 +	.name        = "lio",
   1.269 +	.data_size   = sizeof(struct lio),
   1.270 +	.tio_setup   = tapdisk_lio_setup,
   1.271 +	.tio_destroy = tapdisk_lio_destroy,
   1.272 +	.tio_submit  = tapdisk_lio_submit,
   1.273 +};
   1.274 +
   1.275 +static void
   1.276 +tapdisk_queue_free_io(struct tqueue *queue)
   1.277 +{
   1.278 +	if (queue->tio) {
   1.279 +		if (queue->tio->tio_destroy)
   1.280 +			queue->tio->tio_destroy(queue);
   1.281 +		queue->tio = NULL;
   1.282 +	}
   1.283 +
   1.284 +	if (queue->tio_data) {
   1.285 +		free(queue->tio_data);
   1.286 +		queue->tio_data = NULL;
   1.287 +	}
   1.288 +}
   1.289 +
   1.290 +static int
   1.291 +tapdisk_queue_init_io(struct tqueue *queue, int drv)
   1.292 +{
   1.293 +	const struct tio *tio;
   1.294 +	int err;
   1.295 +
   1.296 +	switch (drv) {
   1.297 +	case TIO_DRV_LIO:
   1.298 +		tio = &td_tio_lio;
   1.299 +		break;
   1.300 +	case TIO_DRV_RWIO:
   1.301 +		tio = &td_tio_rwio;
   1.302 +		break;
   1.303 +	default:
   1.304 +		err = -EINVAL;
   1.305 +		goto fail;
   1.306 +	}
   1.307 +
   1.308 +	queue->tio_data = calloc(1, tio->data_size);
   1.309 +	if (!queue->tio_data) {
   1.310 +		PERROR("malloc(%zu)", tio->data_size);
   1.311 +		err = -errno;
   1.312 +		goto fail;
   1.313 +	}
   1.314 +
   1.315 +	queue->tio = tio;
   1.316 +
   1.317 +	if (tio->tio_setup) {
   1.318 +		err = tio->tio_setup(queue, queue->size);
   1.319 +		if (err)
   1.320 +			goto fail;
   1.321 +	}
   1.322 +
   1.323 +	DPRINTF("I/O queue driver: %s\n", tio->name);
   1.324 +
   1.325 +	return 0;
   1.326 +
   1.327 +fail:
   1.328 +	tapdisk_queue_free_io(queue);
   1.329 +	return err;
   1.330 +}
   1.331  
   1.332  int
   1.333  tapdisk_init_queue(struct tqueue *queue, int size,
   1.334 -		   int sync, struct tfilter *filter)
   1.335 +		   int drv, struct tfilter *filter)
   1.336  {
   1.337  	int i, err;
   1.338  
   1.339  	memset(queue, 0, sizeof(struct tqueue));
   1.340  
   1.341  	queue->size   = size;
   1.342 -	queue->sync   = sync;
   1.343  	queue->filter = filter;
   1.344  
   1.345 -	queue->event   = -1;
   1.346 -	queue->aio_ctx = NULL;
   1.347 -
   1.348  	if (!size)
   1.349  		return 0;
   1.350  
   1.351 -	if (!sync) {
   1.352 -		queue->aio_ctx = REQUEST_ASYNC_FD;
   1.353 -		queue->poll_fd = io_setup(size, &queue->aio_ctx);
   1.354 -		err = queue->poll_fd;
   1.355 -		if (err < 0) {
   1.356 -			if (err == -EAGAIN)
   1.357 -				DPRINTF("Couldn't setup AIO context.  If you "
   1.358 -					"are trying to concurrently use a "
   1.359 -					"large number of blktap-based disks, "
   1.360 -					"you may need to increase the "
   1.361 -					"system-wide aio request limit. "
   1.362 -					"(e.g. 'echo 1048576 > /proc/sys/fs/"
   1.363 -					"aio-max-nr')\n");
   1.364 -			else
   1.365 -				DPRINTF("Couldn't get fd for AIO poll "
   1.366 -					"support.  This is probably because "
   1.367 -					"your kernel does not have the "
   1.368 -					"aio-poll patch applied.\n");
   1.369 -			queue->aio_ctx = NULL;
   1.370 -			goto fail;
   1.371 -		}
   1.372 +	err = tapdisk_queue_init_io(queue, drv);
   1.373 +	if (err)
   1.374 +		goto fail;
   1.375  
   1.376 -		queue->event =
   1.377 -			tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
   1.378 -						      queue->poll_fd, 0,
   1.379 -						      tapdisk_tiocb_event,
   1.380 -						      queue);
   1.381 -		err = queue->event;
   1.382 -		if (err < 0)
   1.383 -			goto fail;
   1.384 -
   1.385 +	queue->iocbs = calloc(size, sizeof(struct iocb *));
   1.386 +	if (!queue->iocbs) {
   1.387 +		err = -errno;
   1.388 +		goto fail;
   1.389  	}
   1.390  
   1.391 -	err               = -ENOMEM;
   1.392 -	queue->iocbs      = calloc(size, sizeof(struct iocb *));
   1.393 -	queue->aio_events = calloc(size, sizeof(struct io_event));
   1.394 -	if (!queue->iocbs || !queue->aio_events)
   1.395 -		goto fail;
   1.396 -
   1.397  	err = opio_init(&queue->opioctx, size);
   1.398  	if (err)
   1.399  		goto fail;
   1.400 @@ -294,22 +520,11 @@ tapdisk_init_queue(struct tqueue *queue,
   1.401  void
   1.402  tapdisk_free_queue(struct tqueue *queue)
   1.403  {
   1.404 -	if (queue->event >= 0) {
   1.405 -		tapdisk_server_unregister_event(queue->event);
   1.406 -		queue->event = -1;
   1.407 -	}
   1.408 -
   1.409 -	if (queue->aio_ctx) {
   1.410 -		io_destroy(queue->aio_ctx);
   1.411 -		queue->aio_ctx = NULL;
   1.412 -	}
   1.413 +	tapdisk_queue_free_io(queue);
   1.414  
   1.415  	free(queue->iocbs);
   1.416  	queue->iocbs = NULL;
   1.417  
   1.418 -	free(queue->aio_events);
   1.419 -	queue->aio_events = NULL;
   1.420 -
   1.421  	opio_free(&queue->opioctx);
   1.422  }
   1.423  
   1.424 @@ -319,9 +534,9 @@ tapdisk_debug_queue(struct tqueue *queue
   1.425  	struct tiocb *tiocb = queue->deferred.head;
   1.426  
   1.427  	WARN("TAPDISK QUEUE:\n");
   1.428 -	WARN("size: %d, sync: %d, queued: %d, iocbs_pending: %d, "
   1.429 +	WARN("size: %d, tio: %s, queued: %d, iocbs_pending: %d, "
   1.430  	     "tiocbs_pending: %d, tiocbs_deferred: %d, deferrals: %"PRIx64"\n",
   1.431 -	     queue->size, queue->sync, queue->queued, queue->iocbs_pending,
   1.432 +	     queue->size, queue->tio->name, queue->queued, queue->iocbs_pending,
   1.433  	     queue->tiocbs_pending, queue->tiocbs_deferred, queue->deferrals);
   1.434  
   1.435  	if (tiocb) {
   1.436 @@ -362,42 +577,14 @@ tapdisk_queue_tiocb(struct tqueue *queue
   1.437  		defer_tiocb(queue, tiocb);
   1.438  }
   1.439  
   1.440 +
   1.441  /*
   1.442   * fail_tiocbs may queue more tiocbs
   1.443   */
   1.444  int
   1.445  tapdisk_submit_tiocbs(struct tqueue *queue)
   1.446  {
   1.447 -	int merged, submitted, err = 0;
   1.448 -
   1.449 -	if (!queue->queued)
   1.450 -		return 0;
   1.451 -
   1.452 -	if (queue->sync)
   1.453 -		return io_synchronous_rw(queue);
   1.454 -
   1.455 -	tapdisk_filter_iocbs(queue->filter, queue->iocbs, queue->queued);
   1.456 -	merged    = io_merge(&queue->opioctx, queue->iocbs, queue->queued);
   1.457 -	submitted = io_submit(queue->aio_ctx, merged, queue->iocbs);
   1.458 -
   1.459 -	DBG("queued: %d, merged: %d, submitted: %d\n",
   1.460 -	    queue->queued, merged, submitted);
   1.461 -
   1.462 -	if (submitted < 0) {
   1.463 -		err = submitted;
   1.464 -		submitted = 0;
   1.465 -	} else if (submitted < merged)
   1.466 -		err = -EIO;
   1.467 -
   1.468 -	queue->iocbs_pending  += submitted;
   1.469 -	queue->tiocbs_pending += queue->queued;
   1.470 -	queue->queued          = 0;
   1.471 -
   1.472 -	if (err)
   1.473 -		queue->tiocbs_pending -= 
   1.474 -			fail_tiocbs(queue, submitted, merged, err);
   1.475 -
   1.476 -	return submitted;
   1.477 +	return queue->tio->tio_submit(queue);
   1.478  }
   1.479  
   1.480  int
   1.481 @@ -412,40 +599,6 @@ tapdisk_submit_all_tiocbs(struct tqueue 
   1.482  	return submitted;
   1.483  }
   1.484  
   1.485 -static void
   1.486 -tapdisk_complete_tiocbs(struct tqueue *queue)
   1.487 -{
   1.488 -	int i, ret, split;
   1.489 -	struct iocb *iocb;
   1.490 -	struct tiocb *tiocb;
   1.491 -	struct io_event *ep;
   1.492 -
   1.493 -	ret   = io_getevents(queue->aio_ctx, 0,
   1.494 -			     queue->size, queue->aio_events, NULL);
   1.495 -	split = io_split(&queue->opioctx, queue->aio_events, ret);
   1.496 -	tapdisk_filter_events(queue->filter, queue->aio_events, split);
   1.497 -
   1.498 -	DBG("events: %d, tiocbs: %d\n", ret, split);
   1.499 -
   1.500 -	queue->iocbs_pending  -= ret;
   1.501 -	queue->tiocbs_pending -= split;
   1.502 -
   1.503 -	for (i = split, ep = queue->aio_events; i-- > 0; ep++) {
   1.504 -		iocb  = ep->obj;
   1.505 -		tiocb = (struct tiocb *)iocb->data;
   1.506 -		complete_tiocb(queue, tiocb, ep->res);
   1.507 -	}
   1.508 -
   1.509 -	queue_deferred_tiocbs(queue);
   1.510 -}
   1.511 -
   1.512 -static void
   1.513 -tapdisk_tiocb_event(event_id_t id, char mode, void *private)
   1.514 -{
   1.515 -	struct tqueue *queue = private;
   1.516 -	tapdisk_complete_tiocbs(queue);
   1.517 -}
   1.518 -
   1.519  /*
   1.520   * cancel_tiocbs may queue more tiocbs
   1.521   */
     2.1 --- a/tools/blktap2/drivers/tapdisk-queue.h	Fri Jan 29 08:54:22 2010 +0000
     2.2 +++ b/tools/blktap2/drivers/tapdisk-queue.h	Fri Jan 29 08:54:51 2010 +0000
     2.3 @@ -55,16 +55,14 @@ struct tlist {
     2.4  
     2.5  struct tqueue {
     2.6  	int                   size;
     2.7 -	int                   sync;
     2.8  
     2.9 -	int                   poll_fd;
    2.10 -	event_id_t	      event;
    2.11 -	io_context_t          aio_ctx;
    2.12 +	const struct tio     *tio;
    2.13 +	void                 *tio_data;
    2.14 +
    2.15  	struct opioctx        opioctx;
    2.16  
    2.17  	int                   queued;
    2.18  	struct iocb         **iocbs;
    2.19 -	struct io_event      *aio_events;
    2.20  
    2.21  	/* number of iocbs pending in the aio layer */
    2.22  	int                   iocbs_pending;
    2.23 @@ -86,6 +84,20 @@ struct tqueue {
    2.24  	uint64_t              deferrals;
    2.25  };
    2.26  
    2.27 +struct tio {
    2.28 +	const char           *name;
    2.29 +	size_t                data_size;
    2.30 +
    2.31 +	int  (*tio_setup)    (struct tqueue *queue, int qlen);
    2.32 +	void (*tio_destroy)  (struct tqueue *queue);
    2.33 +	int  (*tio_submit)   (struct tqueue *queue);
    2.34 +};
    2.35 +
    2.36 +enum {
    2.37 +	TIO_DRV_LIO     = 1,
    2.38 +	TIO_DRV_RWIO    = 2,
    2.39 +};
    2.40 +
    2.41  /*
    2.42   * Interface for request producer (i.e., tapdisk)
    2.43   * NB: the following functions may cause additional tiocbs to be queued:
    2.44 @@ -99,7 +111,7 @@ struct tqueue {
    2.45  #define tapdisk_queue_empty(q) ((q)->queued == 0)
    2.46  #define tapdisk_queue_full(q)  \
    2.47  	(((q)->tiocbs_pending + (q)->queued) >= (q)->size)
    2.48 -int tapdisk_init_queue(struct tqueue *, int size, int sync, struct tfilter *);
    2.49 +int tapdisk_init_queue(struct tqueue *, int size, int drv, struct tfilter *);
    2.50  void tapdisk_free_queue(struct tqueue *);
    2.51  void tapdisk_debug_queue(struct tqueue *);
    2.52  void tapdisk_queue_tiocb(struct tqueue *, struct tiocb *);
     3.1 --- a/tools/blktap2/drivers/tapdisk-server.c	Fri Jan 29 08:54:22 2010 +0000
     3.2 +++ b/tools/blktap2/drivers/tapdisk-server.c	Fri Jan 29 08:54:51 2010 +0000
     3.3 @@ -236,7 +236,8 @@ tapdisk_server_close_ipc(void)
     3.4  static int
     3.5  tapdisk_server_init_aio(void)
     3.6  {
     3.7 -	return tapdisk_init_queue(&server.aio_queue, TAPDISK_TIOCBS, 0, NULL);
     3.8 +	return tapdisk_init_queue(&server.aio_queue, TAPDISK_TIOCBS,
     3.9 +				  TIO_DRV_LIO, NULL);
    3.10  }
    3.11  
    3.12  static void
     4.1 --- a/tools/blktap2/drivers/tapdisk-vbd.c	Fri Jan 29 08:54:22 2010 +0000
     4.2 +++ b/tools/blktap2/drivers/tapdisk-vbd.c	Fri Jan 29 08:54:51 2010 +0000
     4.3 @@ -1260,6 +1260,8 @@ tapdisk_vbd_kick(td_vbd_t *vbd)
     4.4  	int n;
     4.5  	td_ring_t *ring;
     4.6  
     4.7 +	tapdisk_vbd_check_state(vbd);
     4.8 +
     4.9  	ring = &vbd->ring;
    4.10  	if (!ring->sring)
    4.11  		return 0;
     5.1 --- a/tools/blktap2/include/blktaplib.h	Fri Jan 29 08:54:22 2010 +0000
     5.2 +++ b/tools/blktap2/include/blktaplib.h	Fri Jan 29 08:54:51 2010 +0000
     5.3 @@ -43,6 +43,7 @@
     5.4  #endif
     5.5  
     5.6  #define EPRINTF(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a)
     5.7 +#define PERROR(_f, _a...)  EPRINTF(_f ": %s", ##_a, strerror(errno))
     5.8  
     5.9  #define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, XC_PAGE_SIZE)
    5.10