[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] blktap: Remove some code duplication
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1203930740 0 # Node ID 89ee92328720b13c5f70c6bea81027382a6ea682 # Parent cd06c0c1bfff8a8ad2eb28e5571c2299f1329b3e blktap: Remove some code duplication With my qcow2 patch to blktap I contributed a bit to the mess, so here an attempt to clean up and remove at least some of the code duplication in the functions dealing with aio operations. Signed-off-by: Kevin Wolf <kwolf@xxxxxxx> --- tools/blktap/drivers/block-aio.c | 144 ++++--------------- tools/blktap/drivers/block-qcow.c | 249 ++++----------------------------- tools/blktap/drivers/block-qcow2.c | 275 ++++--------------------------------- tools/blktap/drivers/tapaio.c | 190 ++++++++++++++++++++++++- tools/blktap/drivers/tapaio.h | 64 +++++++- 5 files changed, 339 insertions(+), 583 deletions(-) diff -r cd06c0c1bfff -r 89ee92328720 tools/blktap/drivers/block-aio.c --- a/tools/blktap/drivers/block-aio.c Mon Feb 25 09:09:01 2008 +0000 +++ b/tools/blktap/drivers/block-aio.c Mon Feb 25 09:12:20 2008 +0000 @@ -52,28 +52,11 @@ #define O_LARGEFILE 0 #endif -struct pending_aio { - td_callback_t cb; - int id; - void *private; - uint64_t lsec; -}; - struct tdaio_state { int fd; - - /* libaio state */ - tap_aio_context_t aio_ctx; - struct iocb iocb_list [MAX_AIO_REQS]; - struct iocb *iocb_free [MAX_AIO_REQS]; - struct pending_aio pending_aio[MAX_AIO_REQS]; - int iocb_free_count; - struct iocb *iocb_queue[MAX_AIO_REQS]; - int iocb_queued; - struct io_event aio_events[MAX_AIO_REQS]; + tap_aio_context_t aio; }; -#define IOCB_IDX(_s, _io) ((_io) - (_s)->iocb_list) /*Get Image size, secsize*/ static int get_image_info(struct td_state *s, int fd) @@ -131,7 +114,7 @@ static inline void init_fds(struct disk_ for(i = 0; i < MAX_IOFD; i++) dd->io_fd[i] = 0; - dd->io_fd[0] = prv->aio_ctx.pollfd; + dd->io_fd[0] = prv->aio.aio_ctx.pollfd; } /* Open the disk file and initialize aio state. */ @@ -142,27 +125,11 @@ int tdaio_open (struct disk_driver *dd, struct tdaio_state *prv = (struct tdaio_state *)dd->private; DPRINTF("block-aio open('%s')", name); + /* Initialize AIO */ - prv->iocb_free_count = MAX_AIO_REQS; - prv->iocb_queued = 0; - - ret = tap_aio_setup(&prv->aio_ctx, prv->aio_events, MAX_AIO_REQS); - if (ret < 0) { - if (ret == -EAGAIN) { - DPRINTF("Couldn't setup AIO context. If you are " - "trying to concurrently use a large number " - "of blktap-based disks, you may need to " - "increase the system-wide aio request limit. " - "(e.g. 'echo echo 1048576 > /proc/sys/fs/" - "aio-max-nr')\n"); - } else { - DPRINTF("Couldn't setup AIO context.\n"); - } - goto done; - } - - for (i=0;i<MAX_AIO_REQS;i++) - prv->iocb_free[i] = &prv->iocb_list[i]; + ret = tap_aio_init(&prv->aio, 0, MAX_AIO_REQS); + if (ret != 0) + return ret; /* Open the file */ o_flags = O_DIRECT | O_LARGEFILE | @@ -198,87 +165,40 @@ int tdaio_queue_read(struct disk_driver int nb_sectors, char *buf, td_callback_t cb, int id, void *private) { - struct iocb *io; - struct pending_aio *pio; struct td_state *s = dd->td_state; struct tdaio_state *prv = (struct tdaio_state *)dd->private; int size = nb_sectors * s->sector_size; uint64_t offset = sector * (uint64_t)s->sector_size; - long ioidx; - - if (prv->iocb_free_count == 0) - return -ENOMEM; - io = prv->iocb_free[--prv->iocb_free_count]; - - ioidx = IOCB_IDX(prv, io); - pio = &prv->pending_aio[ioidx]; - pio->cb = cb; - pio->id = id; - pio->private = private; - pio->lsec = sector; - - io_prep_pread(io, prv->fd, buf, size, offset); - io->data = (void *)ioidx; - - prv->iocb_queue[prv->iocb_queued++] = io; - - return 0; + + return tap_aio_read(&prv->aio, prv->fd, size, offset, buf, + cb, id, sector, private); } int tdaio_queue_write(struct disk_driver *dd, uint64_t sector, int nb_sectors, char *buf, td_callback_t cb, int id, void *private) { - struct iocb *io; - struct pending_aio *pio; struct td_state *s = dd->td_state; struct tdaio_state *prv = (struct tdaio_state *)dd->private; int size = nb_sectors * s->sector_size; uint64_t offset = sector * (uint64_t)s->sector_size; - long ioidx; + + return tap_aio_write(&prv->aio, prv->fd, size, offset, buf, + cb, id, sector, private); +} + +int tdaio_submit(struct disk_driver *dd) +{ + struct tdaio_state *prv = (struct tdaio_state *)dd->private; + + return tap_aio_submit(&prv->aio); +} + +int tdaio_close(struct disk_driver *dd) +{ + struct tdaio_state *prv = (struct tdaio_state *)dd->private; - if (prv->iocb_free_count == 0) - return -ENOMEM; - io = prv->iocb_free[--prv->iocb_free_count]; - - ioidx = IOCB_IDX(prv, io); - pio = &prv->pending_aio[ioidx]; - pio->cb = cb; - pio->id = id; - pio->private = private; - pio->lsec = sector; - - io_prep_pwrite(io, prv->fd, buf, size, offset); - io->data = (void *)ioidx; - - prv->iocb_queue[prv->iocb_queued++] = io; - - return 0; -} - -int tdaio_submit(struct disk_driver *dd) -{ - int ret; - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - - if (!prv->iocb_queued) - return 0; - - ret = io_submit(prv->aio_ctx.aio_ctx, prv->iocb_queued, prv->iocb_queue); - - /* XXX: TODO: Handle error conditions here. */ - - /* Success case: */ - prv->iocb_queued = 0; - - return 0; -} - -int tdaio_close(struct disk_driver *dd) -{ - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - - io_destroy(prv->aio_ctx.aio_ctx); + io_destroy(prv->aio.aio_ctx.aio_ctx); close(prv->fd); return 0; @@ -290,26 +210,26 @@ int tdaio_do_callbacks(struct disk_drive struct io_event *ep; struct tdaio_state *prv = (struct tdaio_state *)dd->private; - nr_events = tap_aio_get_events(&prv->aio_ctx); + nr_events = tap_aio_get_events(&prv->aio.aio_ctx); repeat: - for (ep = prv->aio_events, i = nr_events; i-- > 0; ep++) { + for (ep = prv->aio.aio_events, i = nr_events; i-- > 0; ep++) { struct iocb *io = ep->obj; struct pending_aio *pio; - pio = &prv->pending_aio[(long)io->data]; + pio = &prv->aio.pending_aio[(long)io->data]; rsp += pio->cb(dd, ep->res == io->u.c.nbytes ? 0 : 1, - pio->lsec, io->u.c.nbytes >> 9, + pio->sector, io->u.c.nbytes >> 9, pio->id, pio->private); - prv->iocb_free[prv->iocb_free_count++] = io; + prv->aio.iocb_free[prv->aio.iocb_free_count++] = io; } if (nr_events) { - nr_events = tap_aio_more_events(&prv->aio_ctx); + nr_events = tap_aio_more_events(&prv->aio.aio_ctx); goto repeat; } - tap_aio_continue(&prv->aio_ctx); + tap_aio_continue(&prv->aio.aio_ctx); return rsp; } diff -r cd06c0c1bfff -r 89ee92328720 tools/blktap/drivers/block-qcow.c --- a/tools/blktap/drivers/block-qcow.c Mon Feb 25 09:09:01 2008 +0000 +++ b/tools/blktap/drivers/block-qcow.c Mon Feb 25 09:12:20 2008 +0000 @@ -59,15 +59,7 @@ (l + (s - 1)) - ((l + (s - 1)) % s)); \ }) -struct pending_aio { - td_callback_t cb; - int id; - void *private; - int nb_sectors; - char *buf; - uint64_t sector; -}; - +#undef IOCB_IDX #define IOCB_IDX(_s, _io) ((_io) - (_s)->iocb_list) #define ZERO_TEST(_b) (_b | 0x00) @@ -140,109 +132,18 @@ struct tdqcow_state { uint32_t l2_cache_counts[L2_CACHE_SIZE]; /*Cache access record*/ uint8_t *cluster_cache; uint8_t *cluster_data; - uint8_t *sector_lock; /*Locking bitmap for AIO reads/writes*/ uint64_t cluster_cache_offset; /**/ uint32_t crypt_method; /*current crypt method, 0 if no *key yet */ uint32_t crypt_method_header; /**/ AES_KEY aes_encrypt_key; /*AES key*/ AES_KEY aes_decrypt_key; /*AES key*/ - /* libaio state */ - tap_aio_context_t aio_ctx; - int max_aio_reqs; - struct iocb *iocb_list; - struct iocb **iocb_free; - struct pending_aio *pending_aio; - int iocb_free_count; - struct iocb **iocb_queue; - int iocb_queued; - struct io_event *aio_events; + + /* libaio state */ + tap_aio_context_t aio; }; static int decompress_cluster(struct tdqcow_state *s, uint64_t cluster_offset); - -static void free_aio_state(struct disk_driver *dd) -{ - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - - if (s->sector_lock) - free(s->sector_lock); - if (s->iocb_list) - free(s->iocb_list); - if (s->pending_aio) - free(s->pending_aio); - if (s->aio_events) - free(s->aio_events); - if (s->iocb_free) - free(s->iocb_free); - if (s->iocb_queue) - free(s->iocb_queue); -} - -static int init_aio_state(struct disk_driver *dd) -{ - int i, ret; - struct td_state *bs = dd->td_state; - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - long ioidx; - - s->iocb_list = NULL; - s->pending_aio = NULL; - s->aio_events = NULL; - s->iocb_free = NULL; - s->iocb_queue = NULL; - - /*Initialize Locking bitmap*/ - s->sector_lock = calloc(1, bs->size); - - if (!s->sector_lock) { - DPRINTF("Failed to allocate sector lock\n"); - goto fail; - } - - /* A segment (i.e. a page) can span multiple clusters */ - s->max_aio_reqs = ((getpagesize() / s->cluster_size) + 1) * - MAX_SEGMENTS_PER_REQ * MAX_REQUESTS; - - /* Initialize AIO */ - s->iocb_free_count = s->max_aio_reqs; - s->iocb_queued = 0; - - if (!(s->iocb_list = malloc(sizeof(struct iocb) * s->max_aio_reqs)) || - !(s->pending_aio = malloc(sizeof(struct pending_aio) * s->max_aio_reqs)) || - !(s->aio_events = malloc(sizeof(struct io_event) * s->max_aio_reqs)) || - !(s->iocb_free = malloc(sizeof(struct iocb *) * s->max_aio_reqs)) || - !(s->iocb_queue = malloc(sizeof(struct iocb *) * s->max_aio_reqs))) { - DPRINTF("Failed to allocate AIO structs (max_aio_reqs = %d)\n", - s->max_aio_reqs); - goto fail; - } - - ret = tap_aio_setup(&s->aio_ctx, s->aio_events, s->max_aio_reqs); - if (ret < 0) { - if (ret == -EAGAIN) { - DPRINTF("Couldn't setup AIO context. If you are " - "trying to concurrently use a large number " - "of blktap-based disks, you may need to " - "increase the system-wide aio request limit. " - "(e.g. 'echo echo 1048576 > /proc/sys/fs/" - "aio-max-nr')\n"); - } else { - DPRINTF("Couldn't setup AIO context.\n"); - } - goto fail; - } - - for (i=0;i<s->max_aio_reqs;i++) - s->iocb_free[i] = &s->iocb_list[i]; - - DPRINTF("AIO state initialised\n"); - - return 0; - - fail: - return -1; -} static uint32_t gen_cksum(char *ptr, int len) { @@ -337,79 +238,6 @@ static int qcow_set_key(struct tdqcow_st } #endif return 0; -} - -static int async_read(struct tdqcow_state *s, int size, - uint64_t offset, char *buf, td_callback_t cb, - int id, uint64_t sector, void *private) -{ - struct iocb *io; - struct pending_aio *pio; - long ioidx; - - io = s->iocb_free[--s->iocb_free_count]; - - ioidx = IOCB_IDX(s, io); - pio = &s->pending_aio[ioidx]; - pio->cb = cb; - pio->id = id; - pio->private = private; - pio->nb_sectors = size/512; - pio->buf = buf; - pio->sector = sector; - - io_prep_pread(io, s->fd, buf, size, offset); - io->data = (void *)ioidx; - - s->iocb_queue[s->iocb_queued++] = io; - - return 1; -} - -static int async_write(struct tdqcow_state *s, int size, - uint64_t offset, char *buf, td_callback_t cb, - int id, uint64_t sector, void *private) -{ - struct iocb *io; - struct pending_aio *pio; - long ioidx; - - io = s->iocb_free[--s->iocb_free_count]; - - ioidx = IOCB_IDX(s, io); - pio = &s->pending_aio[ioidx]; - pio->cb = cb; - pio->id = id; - pio->private = private; - pio->nb_sectors = size/512; - pio->buf = buf; - pio->sector = sector; - - io_prep_pwrite(io, s->fd, buf, size, offset); - io->data = (void *)ioidx; - - s->iocb_queue[s->iocb_queued++] = io; - - return 1; -} - -/*TODO: Fix sector span!*/ -static int aio_can_lock(struct tdqcow_state *s, uint64_t sector) -{ - return (s->sector_lock[sector] ? 0 : 1); -} - -static int aio_lock(struct tdqcow_state *s, uint64_t sector) -{ - return ++s->sector_lock[sector]; -} - -static void aio_unlock(struct tdqcow_state *s, uint64_t sector) -{ - if (!s->sector_lock[sector]) return; - - --s->sector_lock[sector]; - return; } /* @@ -841,13 +669,14 @@ static inline void init_fds(struct disk_ for(i = 0; i < MAX_IOFD; i++) dd->io_fd[i] = 0; - dd->io_fd[0] = s->aio_ctx.pollfd; + dd->io_fd[0] = s->aio.aio_ctx.pollfd; } /* Open the disk file and initialize qcow state. */ int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flags) { int fd, len, i, shift, ret, size, l1_table_size, o_flags; + int max_aio_reqs; struct td_state *bs = dd->td_state; struct tdqcow_state *s = (struct tdqcow_state *)dd->private; char *buf; @@ -996,9 +825,14 @@ int tdqcow_open (struct disk_driver *dd, } end_xenhdr: - if (init_aio_state(dd)!=0) { + + /* A segment (i.e. a page) can span multiple clusters */ + max_aio_reqs = ((getpagesize() / s->cluster_size) + 1) * + MAX_SEGMENTS_PER_REQ * MAX_REQUESTS; + + if (tap_aio_init(&s->aio, bs->size, max_aio_reqs)!=0) { DPRINTF("Unable to initialise AIO state\n"); - free_aio_state(dd); + tap_aio_free(&s->aio); goto fail; } init_fds(dd); @@ -1015,7 +849,7 @@ int tdqcow_open (struct disk_driver *dd, fail: DPRINTF("QCOW Open failed\n"); - free_aio_state(dd); + tap_aio_free(&s->aio); free(s->l1_table); free(s->l2_cache); free(s->cluster_cache); @@ -1037,7 +871,7 @@ int tdqcow_queue_read(struct disk_driver /*Check we can get a lock*/ for (i = 0; i < nb_sectors; i++) - if (!aio_can_lock(s, sector + i)) + if (!tap_aio_can_lock(&s->aio, sector + i)) return cb(dd, -EBUSY, sector, nb_sectors, id, private); /*We store a local record of the request*/ @@ -1049,11 +883,11 @@ int tdqcow_queue_read(struct disk_driver if (n > nb_sectors) n = nb_sectors; - if (s->iocb_free_count == 0 || !aio_lock(s, sector)) + if (s->aio.iocb_free_count == 0 || !tap_aio_lock(&s->aio, sector)) return cb(dd, -EBUSY, sector, nb_sectors, id, private); if(!cluster_offset) { - aio_unlock(s, sector); + tap_aio_unlock(&s->aio, sector); ret = cb(dd, BLK_NOT_ALLOCATED, sector, n, id, private); if (ret == -EBUSY) { @@ -1064,7 +898,7 @@ int tdqcow_queue_read(struct disk_driver } else rsp += ret; } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - aio_unlock(s, sector); + tap_aio_unlock(&s->aio, sector); if (decompress_cluster(s, cluster_offset) < 0) { rsp += cb(dd, -EIO, sector, nb_sectors, id, private); @@ -1074,7 +908,7 @@ int tdqcow_queue_read(struct disk_driver 512 * n); rsp += cb(dd, 0, sector, n, id, private); } else { - async_read(s, n * 512, + tap_aio_read(&s->aio, s->fd, n * 512, (cluster_offset + index_in_cluster * 512), buf, cb, id, sector, private); } @@ -1099,7 +933,7 @@ int tdqcow_queue_write(struct disk_drive /*Check we can get a lock*/ for (i = 0; i < nb_sectors; i++) - if (!aio_can_lock(s, sector + i)) + if (!tap_aio_can_lock(&s->aio, sector + i)) return cb(dd, -EBUSY, sector, nb_sectors, id, private); /*We store a local record of the request*/ @@ -1109,7 +943,7 @@ int tdqcow_queue_write(struct disk_drive if (n > nb_sectors) n = nb_sectors; - if (s->iocb_free_count == 0 || !aio_lock(s, sector)) + if (s->aio.iocb_free_count == 0 || !tap_aio_lock(&s->aio, sector)) return cb(dd, -EBUSY, sector, nb_sectors, id, private); cluster_offset = get_cluster_offset(s, sector << 9, 1, 0, @@ -1117,7 +951,7 @@ int tdqcow_queue_write(struct disk_drive index_in_cluster+n); if (!cluster_offset) { DPRINTF("Ooops, no write cluster offset!\n"); - aio_unlock(s, sector); + tap_aio_unlock(&s->aio, sector); return cb(dd, -EIO, sector, nb_sectors, id, private); } @@ -1125,12 +959,12 @@ int tdqcow_queue_write(struct disk_drive encrypt_sectors(s, sector, s->cluster_data, (unsigned char *)buf, n, 1, &s->aes_encrypt_key); - async_write(s, n * 512, + tap_aio_write(&s->aio, s->fd, n * 512, (cluster_offset + index_in_cluster*512), (char *)s->cluster_data, cb, id, sector, private); } else { - async_write(s, n * 512, + tap_aio_write(&s->aio, s->fd, n * 512, (cluster_offset + index_in_cluster*512), buf, cb, id, sector, private); } @@ -1146,20 +980,9 @@ int tdqcow_queue_write(struct disk_drive int tdqcow_submit(struct disk_driver *dd) { - int ret; - struct tdqcow_state *prv = (struct tdqcow_state *)dd->private; - - if (!prv->iocb_queued) - return 0; - - ret = io_submit(prv->aio_ctx.aio_ctx, prv->iocb_queued, prv->iocb_queue); - - /* XXX: TODO: Handle error conditions here. */ - - /* Success case: */ - prv->iocb_queued = 0; - - return 0; + struct tdqcow_state *prv = (struct tdqcow_state *)dd->private; + + return tap_aio_submit(&prv->aio); } int tdqcow_close(struct disk_driver *dd) @@ -1180,7 +1003,7 @@ int tdqcow_close(struct disk_driver *dd) close(fd); } - io_destroy(s->aio_ctx.aio_ctx); + io_destroy(s->aio.aio_ctx.aio_ctx); free(s->name); free(s->l1_table); free(s->l2_cache); @@ -1198,15 +1021,15 @@ int tdqcow_do_callbacks(struct disk_driv if (sid > MAX_IOFD) return 1; - nr_events = tap_aio_get_events(&prv->aio_ctx); + nr_events = tap_aio_get_events(&prv->aio.aio_ctx); repeat: - for (ep = prv->aio_events, i = nr_events; i-- > 0; ep++) { + for (ep = prv->aio.aio_events, i = nr_events; i-- > 0; ep++) { struct iocb *io = ep->obj; struct pending_aio *pio; - pio = &prv->pending_aio[(long)io->data]; - - aio_unlock(prv, pio->sector); + pio = &prv->aio.pending_aio[(long)io->data]; + + tap_aio_unlock(&prv->aio, pio->sector); if (prv->crypt_method) encrypt_sectors(prv, pio->sector, @@ -1219,15 +1042,15 @@ repeat: pio->sector, pio->nb_sectors, pio->id, pio->private); - prv->iocb_free[prv->iocb_free_count++] = io; + prv->aio.iocb_free[prv->aio.iocb_free_count++] = io; } if (nr_events) { - nr_events = tap_aio_more_events(&prv->aio_ctx); + nr_events = tap_aio_more_events(&prv->aio.aio_ctx); goto repeat; } - tap_aio_continue(&prv->aio_ctx); + tap_aio_continue(&prv->aio.aio_ctx); return rsp; } diff -r cd06c0c1bfff -r 89ee92328720 tools/blktap/drivers/block-qcow2.c --- a/tools/blktap/drivers/block-qcow2.c Mon Feb 25 09:09:01 2008 +0000 +++ b/tools/blktap/drivers/block-qcow2.c Mon Feb 25 09:12:20 2008 +0000 @@ -145,20 +145,7 @@ typedef struct BDRVQcowState { int64_t total_sectors; - - struct { - tap_aio_context_t aio_ctx; - int max_aio_reqs; - struct iocb *iocb_list; - struct iocb **iocb_free; - struct pending_aio *pending_aio; - int iocb_free_count; - struct iocb **iocb_queue; - int iocb_queued; - struct io_event *aio_events; - - uint8_t *sector_lock; /*Locking bitmap for AIO reads/writes*/ - } async; + tap_aio_context_t async; /* Original qemu variables */ int cluster_bits; @@ -222,9 +209,6 @@ static void check_refcounts(struct disk_ static void check_refcounts(struct disk_driver *bs); #endif -static int init_aio_state(struct disk_driver *bs); -static void free_aio_state(struct disk_driver *bs); - static int qcow_sync_read(struct disk_driver *dd, uint64_t sector, int nb_sectors, char *buf, td_callback_t cb, int id, void *prv); @@ -309,7 +293,7 @@ static int qcow_open(struct disk_driver static int qcow_open(struct disk_driver *bs, const char *filename, td_flag_t flags) { BDRVQcowState *s = bs->private; - int len, i, shift, ret; + int len, i, shift, ret, max_aio_reqs; QCowHeader header; int fd, o_flags; @@ -475,9 +459,14 @@ static int qcow_open(struct disk_driver #ifdef USE_AIO /* Initialize AIO */ - if (init_aio_state(bs)!=0) { + + /* A segment (i.e. a page) can span multiple clusters */ + max_aio_reqs = ((getpagesize() / s->cluster_size) + 1) * + MAX_SEGMENTS_PER_REQ * MAX_REQUESTS; + + if (tap_aio_init(&s->async, bs->td_state->size, max_aio_reqs)) { DPRINTF("Unable to initialise AIO state\n"); - free_aio_state(bs); + tap_aio_free(&s->async); goto fail; } @@ -496,7 +485,7 @@ static int qcow_open(struct disk_driver DPRINTF("qcow_open failed\n"); #ifdef USE_AIO - free_aio_state(bs); + tap_aio_free(&s->async); #endif qcow_free_snapshots(bs); @@ -1070,200 +1059,6 @@ static int qcow_write(struct disk_driver #ifdef USE_AIO /* - * General AIO helper functions - */ - -#define IOCB_IDX(_s, _io) ((_io) - (_s)->async.iocb_list) - -struct pending_aio { - td_callback_t cb; - int id; - void *private; - int nb_sectors; - char *buf; - uint64_t sector; -}; - - -static int init_aio_state(struct disk_driver *dd) -{ - int i, ret; - struct td_state *bs = dd->td_state; - struct BDRVQcowState *s = (struct BDRVQcowState*) dd->private; - long ioidx; - - s->async.iocb_list = NULL; - s->async.pending_aio = NULL; - s->async.aio_events = NULL; - s->async.iocb_free = NULL; - s->async.iocb_queue = NULL; - - /*Initialize Locking bitmap*/ - s->async.sector_lock = calloc(1, bs->size); - - if (!s->async.sector_lock) { - DPRINTF("Failed to allocate sector lock\n"); - goto fail; - } - - /* A segment (i.e. a page) can span multiple clusters */ - s->async.max_aio_reqs = ((getpagesize() / s->cluster_size) + 1) * - MAX_SEGMENTS_PER_REQ * MAX_REQUESTS; - - /* Initialize AIO */ - s->async.iocb_free_count = s->async.max_aio_reqs; - s->async.iocb_queued = 0; - - if (!(s->async.iocb_list = malloc(sizeof(struct iocb) * s->async.max_aio_reqs)) || - !(s->async.pending_aio = malloc(sizeof(struct pending_aio) * s->async.max_aio_reqs)) || - !(s->async.aio_events = malloc(sizeof(struct io_event) * s->async.max_aio_reqs)) || - !(s->async.iocb_free = malloc(sizeof(struct iocb *) * s->async.max_aio_reqs)) || - !(s->async.iocb_queue = malloc(sizeof(struct iocb *) * s->async.max_aio_reqs))) - { - DPRINTF("Failed to allocate AIO structs (max_aio_reqs = %d)\n", - s->async.max_aio_reqs); - goto fail; - } - - ret = tap_aio_setup(&s->async.aio_ctx, s->async.aio_events, s->async.max_aio_reqs); - if (ret < 0) { - if (ret == -EAGAIN) { - DPRINTF("Couldn't setup AIO context. If you are " - "trying to concurrently use a large number " - "of blktap-based disks, you may need to " - "increase the system-wide aio request limit. " - "(e.g. 'echo echo 1048576 > /proc/sys/fs/" - "aio-max-nr')\n"); - } else { - DPRINTF("Couldn't setup AIO context.\n"); - } - goto fail; - } - - for (i=0;i<s->async.max_aio_reqs;i++) - s->async.iocb_free[i] = &s->async.iocb_list[i]; - - DPRINTF("AIO state initialised\n"); - - return 0; - -fail: - return -1; -} - -static void free_aio_state(struct disk_driver *dd) -{ - struct BDRVQcowState *s = (struct BDRVQcowState*) dd->private; - - if (s->async.sector_lock) - free(s->async.sector_lock); - if (s->async.iocb_list) - free(s->async.iocb_list); - if (s->async.pending_aio) - free(s->async.pending_aio); - if (s->async.aio_events) - free(s->async.aio_events); - if (s->async.iocb_free) - free(s->async.iocb_free); - if (s->async.iocb_queue) - free(s->async.iocb_queue); -} - -static int async_read(struct BDRVQcowState *s, int size, - uint64_t offset, char *buf, td_callback_t cb, - int id, uint64_t sector, void *private) -{ - struct iocb *io; - struct pending_aio *pio; - long ioidx; - - io = s->async.iocb_free[--s->async.iocb_free_count]; - - ioidx = IOCB_IDX(s, io); - pio = &s->async.pending_aio[ioidx]; - pio->cb = cb; - pio->id = id; - pio->private = private; - pio->nb_sectors = size/512; - pio->buf = buf; - pio->sector = sector; - - io_prep_pread(io, s->fd, buf, size, offset); - io->data = (void *)ioidx; - - s->async.iocb_queue[s->async.iocb_queued++] = io; - - return 1; -} - -static int async_write(struct BDRVQcowState *s, int size, - uint64_t offset, char *buf, td_callback_t cb, - int id, uint64_t sector, void *private) -{ - struct iocb *io; - struct pending_aio *pio; - long ioidx; - - io = s->async.iocb_free[--s->async.iocb_free_count]; - - ioidx = IOCB_IDX(s, io); - pio = &s->async.pending_aio[ioidx]; - pio->cb = cb; - pio->id = id; - pio->private = private; - pio->nb_sectors = size/512; - pio->buf = buf; - pio->sector = sector; - - io_prep_pwrite(io, s->fd, buf, size, offset); - io->data = (void *)ioidx; - - s->async.iocb_queue[s->async.iocb_queued++] = io; - - return 1; -} - -static int async_submit(struct disk_driver *dd) -{ - int ret; - struct BDRVQcowState *prv = (struct BDRVQcowState*) dd->private; - - if (!prv->async.iocb_queued) - return 0; - - ret = io_submit(prv->async.aio_ctx.aio_ctx, prv->async.iocb_queued, prv->async.iocb_queue); - - /* XXX: TODO: Handle error conditions here. */ - - /* Success case: */ - prv->async.iocb_queued = 0; - - return 0; -} - -/*TODO: Fix sector span!*/ -static int aio_can_lock(struct BDRVQcowState *s, uint64_t sector) -{ - return (s->async.sector_lock[sector] ? 0 : 1); -} - -static int aio_lock(struct BDRVQcowState *s, uint64_t sector) -{ - return ++s->async.sector_lock[sector]; -} - -static void aio_unlock(struct BDRVQcowState *s, uint64_t sector) -{ - if (!s->async.sector_lock[sector]) return; - - --s->async.sector_lock[sector]; - return; -} - - - - -/* * QCOW2 specific AIO functions */ @@ -1278,7 +1073,7 @@ static int qcow_queue_read(struct disk_d /*Check we can get a lock*/ for (i = 0; i < nb_sectors; i++) - if (!aio_can_lock(s, sector + i)) + if (!tap_aio_can_lock(&s->async, sector + i)) return cb(bs, -EBUSY, sector, nb_sectors, id, private); while (nb_sectors > 0) { @@ -1290,13 +1085,13 @@ static int qcow_queue_read(struct disk_d if (n > nb_sectors) n = nb_sectors; - if (s->async.iocb_free_count == 0 || !aio_lock(s, sector)) + if (s->async.iocb_free_count == 0 || !tap_aio_lock(&s->async, sector)) return cb(bs, -EBUSY, sector, nb_sectors, id, private); if (!cluster_offset) { /* The requested sector is not allocated */ - aio_unlock(s, sector); + tap_aio_unlock(&s->async, sector); ret = cb(bs, BLK_NOT_ALLOCATED, sector, n, id, private); if (ret == -EBUSY) { @@ -1311,7 +1106,7 @@ static int qcow_queue_read(struct disk_d } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { /* sync read for compressed clusters */ - aio_unlock(s, sector); + tap_aio_unlock(&s->async, sector); if (decompress_cluster(s, cluster_offset) < 0) { rsp += cb(bs, -EIO, sector, nb_sectors, id, private); goto done; @@ -1323,7 +1118,7 @@ static int qcow_queue_read(struct disk_d } else { /* async read */ - async_read(s, n * 512, + tap_aio_read(&s->async, s->fd, n * 512, (cluster_offset + index_in_cluster * 512), buf, cb, id, sector, private); } @@ -1351,7 +1146,7 @@ static int qcow_queue_write(struct disk_ /*Check we can get a lock*/ for (i = 0; i < nb_sectors; i++) - if (!aio_can_lock(s, sector + i)) + if (!tap_aio_can_lock(&s->async, sector + i)) return cb(bs, -EBUSY, sector, nb_sectors, id, private); @@ -1362,7 +1157,7 @@ static int qcow_queue_write(struct disk_ if (n > nb_sectors) n = nb_sectors; - if (s->async.iocb_free_count == 0 || !aio_lock(s, sector)) + if (s->async.iocb_free_count == 0 || !tap_aio_lock(&s->async, sector)) return cb(bs, -EBUSY, sector, nb_sectors, id, private); @@ -1372,14 +1167,14 @@ static int qcow_queue_write(struct disk_ if (!cluster_offset) { DPRINTF("Ooops, no write cluster offset!\n"); - aio_unlock(s, sector); + tap_aio_unlock(&s->async, sector); return cb(bs, -EIO, sector, nb_sectors, id, private); } // TODO Encryption - async_write(s, n * 512, + tap_aio_write(&s->async, s->fd, n * 512, (cluster_offset + index_in_cluster*512), buf, cb, id, sector, private); @@ -1402,9 +1197,14 @@ static int qcow_close(struct disk_driver static int qcow_close(struct disk_driver *bs) { BDRVQcowState *s = bs->private; - + +#ifdef USE_AIO + io_destroy(s->async.aio_ctx.aio_ctx); + tap_aio_free(&s->async); +#else close(s->poll_pipe[0]); - close(s->poll_pipe[1]); + close(s->poll_pipe[1]); +#endif qemu_free(s->l1_table); qemu_free(s->l2_cache); @@ -1606,23 +1406,10 @@ static int qcow_write_compressed(struct static int qcow_submit(struct disk_driver *bs) { - int ret; - struct BDRVQcowState *prv = (struct BDRVQcowState*)bs->private; - - - fsync(prv->fd); - - if (!prv->async.iocb_queued) - return 0; - - ret = io_submit(prv->async.aio_ctx.aio_ctx, prv->async.iocb_queued, prv->async.iocb_queue); - - /* XXX: TODO: Handle error conditions here. */ - - /* Success case: */ - prv->async.iocb_queued = 0; - - return 0; + struct BDRVQcowState *s = (struct BDRVQcowState*) bs->private; + + fsync(s->fd); + return tap_aio_submit(&s->async); } @@ -2246,7 +2033,7 @@ repeat: pio = &prv->async.pending_aio[(long)io->data]; - aio_unlock(prv, pio->sector); + tap_aio_unlock(&prv->async, pio->sector); if (prv->crypt_method) encrypt_sectors(prv, pio->sector, diff -r cd06c0c1bfff -r 89ee92328720 tools/blktap/drivers/tapaio.c --- a/tools/blktap/drivers/tapaio.c Mon Feb 25 09:09:01 2008 +0000 +++ b/tools/blktap/drivers/tapaio.c Mon Feb 25 09:12:20 2008 +0000 @@ -32,6 +32,7 @@ #include <unistd.h> #include <errno.h> #include <string.h> +#include <stdlib.h> /** * We used a kernel patch to return an fd associated with the AIO context @@ -62,7 +63,7 @@ static void * static void * tap_aio_completion_thread(void *arg) { - tap_aio_context_t *ctx = (tap_aio_context_t *) arg; + tap_aio_internal_context_t *ctx = (tap_aio_internal_context_t *) arg; int command; int nr_events; int rc; @@ -84,7 +85,7 @@ tap_aio_completion_thread(void *arg) } void -tap_aio_continue(tap_aio_context_t *ctx) +tap_aio_continue(tap_aio_internal_context_t *ctx) { int cmd = 0; @@ -95,8 +96,8 @@ tap_aio_continue(tap_aio_context_t *ctx) DPRINTF("Cannot write to command pipe\n"); } -int -tap_aio_setup(tap_aio_context_t *ctx, +static int +tap_aio_setup(tap_aio_internal_context_t *ctx, struct io_event *aio_events, int max_aio_events) { @@ -144,7 +145,7 @@ tap_aio_setup(tap_aio_context_t *ctx, } int -tap_aio_get_events(tap_aio_context_t *ctx) +tap_aio_get_events(tap_aio_internal_context_t *ctx) { int nr_events = 0; @@ -171,10 +172,185 @@ tap_aio_get_events(tap_aio_context_t *ct return nr_events; } -int tap_aio_more_events(tap_aio_context_t *ctx) +int tap_aio_more_events(tap_aio_internal_context_t *ctx) { return io_getevents(ctx->aio_ctx, 0, ctx->max_aio_events, ctx->aio_events, NULL); } - +int tap_aio_init(tap_aio_context_t *ctx, uint64_t sectors, + int max_aio_reqs) +{ + int i, ret; + long ioidx; + + ctx->iocb_list = NULL; + ctx->pending_aio = NULL; + ctx->aio_events = NULL; + ctx->iocb_free = NULL; + ctx->iocb_queue = NULL; + + /*Initialize Locking bitmap*/ + ctx->sector_lock = calloc(1, sectors); + + if (!ctx->sector_lock) { + DPRINTF("Failed to allocate sector lock\n"); + goto fail; + } + + + /* Initialize AIO */ + ctx->max_aio_reqs = max_aio_reqs; + ctx->iocb_free_count = ctx->max_aio_reqs; + ctx->iocb_queued = 0; + + if (!(ctx->iocb_list = malloc(sizeof(struct iocb) * ctx->max_aio_reqs)) || + !(ctx->pending_aio = malloc(sizeof(struct pending_aio) * ctx->max_aio_reqs)) || + !(ctx->aio_events = malloc(sizeof(struct io_event) * ctx->max_aio_reqs)) || + !(ctx->iocb_free = malloc(sizeof(struct iocb *) * ctx->max_aio_reqs)) || + !(ctx->iocb_queue = malloc(sizeof(struct iocb *) * ctx->max_aio_reqs))) + { + DPRINTF("Failed to allocate AIO structs (max_aio_reqs = %d)\n", + ctx->max_aio_reqs); + goto fail; + } + + ret = tap_aio_setup(&ctx->aio_ctx, ctx->aio_events, ctx->max_aio_reqs); + if (ret < 0) { + if (ret == -EAGAIN) { + DPRINTF("Couldn't setup AIO context. If you are " + "trying to concurrently use a large number " + "of blktap-based disks, you may need to " + "increase the system-wide aio request limit. " + "(e.g. 'echo echo 1048576 > /proc/sys/fs/" + "aio-max-nr')\n"); + } else { + DPRINTF("Couldn't setup AIO context.\n"); + } + goto fail; + } + + for (i=0;i<ctx->max_aio_reqs;i++) + ctx->iocb_free[i] = &ctx->iocb_list[i]; + + DPRINTF("AIO state initialised\n"); + + return 0; + +fail: + return -1; +} + +void tap_aio_free(tap_aio_context_t *ctx) +{ + if (ctx->sector_lock) + free(ctx->sector_lock); + if (ctx->iocb_list) + free(ctx->iocb_list); + if (ctx->pending_aio) + free(ctx->pending_aio); + if (ctx->aio_events) + free(ctx->aio_events); + if (ctx->iocb_free) + free(ctx->iocb_free); + if (ctx->iocb_queue) + free(ctx->iocb_queue); +} + +/*TODO: Fix sector span!*/ +int tap_aio_can_lock(tap_aio_context_t *ctx, uint64_t sector) +{ + return (ctx->sector_lock[sector] ? 0 : 1); +} + +int tap_aio_lock(tap_aio_context_t *ctx, uint64_t sector) +{ + return ++ctx->sector_lock[sector]; +} + +void tap_aio_unlock(tap_aio_context_t *ctx, uint64_t sector) +{ + if (!ctx->sector_lock[sector]) return; + + --ctx->sector_lock[sector]; + return; +} + + +int tap_aio_read(tap_aio_context_t *ctx, int fd, int size, + uint64_t offset, char *buf, td_callback_t cb, + int id, uint64_t sector, void *private) +{ + struct iocb *io; + struct pending_aio *pio; + long ioidx; + + if (ctx->iocb_free_count == 0) + return -ENOMEM; + + io = ctx->iocb_free[--ctx->iocb_free_count]; + + ioidx = IOCB_IDX(ctx, io); + pio = &ctx->pending_aio[ioidx]; + pio->cb = cb; + pio->id = id; + pio->private = private; + pio->nb_sectors = size/512; + pio->buf = buf; + pio->sector = sector; + + io_prep_pread(io, fd, buf, size, offset); + io->data = (void *)ioidx; + + ctx->iocb_queue[ctx->iocb_queued++] = io; + + return 0; +} + +int tap_aio_write(tap_aio_context_t *ctx, int fd, int size, + uint64_t offset, char *buf, td_callback_t cb, + int id, uint64_t sector, void *private) +{ + struct iocb *io; + struct pending_aio *pio; + long ioidx; + + if (ctx->iocb_free_count == 0) + return -ENOMEM; + + io = ctx->iocb_free[--ctx->iocb_free_count]; + + ioidx = IOCB_IDX(ctx, io); + pio = &ctx->pending_aio[ioidx]; + pio->cb = cb; + pio->id = id; + pio->private = private; + pio->nb_sectors = size/512; + pio->buf = buf; + pio->sector = sector; + + io_prep_pwrite(io, fd, buf, size, offset); + io->data = (void *)ioidx; + + ctx->iocb_queue[ctx->iocb_queued++] = io; + + return 0; +} + +int tap_aio_submit(tap_aio_context_t *ctx) +{ + int ret; + + if (!ctx->iocb_queued) + return 0; + + ret = io_submit(ctx->aio_ctx.aio_ctx, ctx->iocb_queued, ctx->iocb_queue); + + /* XXX: TODO: Handle error conditions here. */ + + /* Success case: */ + ctx->iocb_queued = 0; + + return 0; +} + diff -r cd06c0c1bfff -r 89ee92328720 tools/blktap/drivers/tapaio.h --- a/tools/blktap/drivers/tapaio.h Mon Feb 25 09:09:01 2008 +0000 +++ b/tools/blktap/drivers/tapaio.h Mon Feb 25 09:12:20 2008 +0000 @@ -32,8 +32,13 @@ #include <pthread.h> #include <libaio.h> +#include <stdint.h> -struct tap_aio_context { +#include "tapdisk.h" + +#define IOCB_IDX(_ctx, _io) ((_io) - (_ctx)->iocb_list) + +struct tap_aio_internal_context { io_context_t aio_ctx; struct io_event *aio_events; @@ -45,14 +50,59 @@ struct tap_aio_context { int pollfd; unsigned int poll_in_thread : 1; }; + + +typedef struct tap_aio_internal_context tap_aio_internal_context_t; + + +struct pending_aio { + td_callback_t cb; + int id; + void *private; + int nb_sectors; + char *buf; + uint64_t sector; +}; + + +struct tap_aio_context { + tap_aio_internal_context_t aio_ctx; + + int max_aio_reqs; + struct iocb *iocb_list; + struct iocb **iocb_free; + struct pending_aio *pending_aio; + int iocb_free_count; + struct iocb **iocb_queue; + int iocb_queued; + struct io_event *aio_events; + + /* Locking bitmap for AIO reads/writes */ + uint8_t *sector_lock; +}; typedef struct tap_aio_context tap_aio_context_t; -int tap_aio_setup (tap_aio_context_t *ctx, - struct io_event *aio_events, - int max_aio_events); -void tap_aio_continue (tap_aio_context_t *ctx); -int tap_aio_get_events (tap_aio_context_t *ctx); -int tap_aio_more_events(tap_aio_context_t *ctx); +void tap_aio_continue (tap_aio_internal_context_t *ctx); +int tap_aio_get_events (tap_aio_internal_context_t *ctx); +int tap_aio_more_events(tap_aio_internal_context_t *ctx); + + +int tap_aio_init(tap_aio_context_t *ctx, uint64_t sectors, + int max_aio_reqs); +void tap_aio_free(tap_aio_context_t *ctx); + +int tap_aio_can_lock(tap_aio_context_t *ctx, uint64_t sector); +int tap_aio_lock(tap_aio_context_t *ctx, uint64_t sector); +void tap_aio_unlock(tap_aio_context_t *ctx, uint64_t sector); + + +int tap_aio_read(tap_aio_context_t *ctx, int fd, int size, + uint64_t offset, char *buf, td_callback_t cb, + int id, uint64_t sector, void *private); +int tap_aio_write(tap_aio_context_t *ctx, int fd, int size, + uint64_t offset, char *buf, td_callback_t cb, + int id, uint64_t sector, void *private); +int tap_aio_submit(tap_aio_context_t *ctx); #endif /* __TAPAIO_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |