From 221f715d90ec5fec569a19119887445c037bca86 Mon Sep 17 00:00:00 2001 From: aliguori Date: Sat, 28 Mar 2009 17:28:41 +0000 Subject: new scsi-generic abstraction, use SG_IO (Christoph Hellwig) Okay, I started looking into how to handle scsi-generic I/O in the new world order. I think the best is to use the SG_IO ioctl instead of the read/write interface as that allows us to support scsi passthrough on disk/cdrom devices, too. See Hannes patch on the kvm list from August for an example. Now that we always do ioctls we don't need another abstraction than bdrv_ioctl for the synchronous requests for now, and for asynchronous requests I've added a aio_ioctl abstraction keeping it simple. Long-term we might want to move the ops to a higher-level abstraction and let the low-level code fill out the request header, but I'm lazy enough to leave that to the people trying to support scsi-passthrough on a non-Linux OS. Tested lightly by issuing various sg_ commands from sg3-utils in a guest to a host CDROM device. Signed-off-by: Christoph Hellwig Signed-off-by: Anthony Liguori git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6895 c046a42c-6fe2-441c-8c8c-71466251a162 --- posix-aio-compat.c | 100 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 34 deletions(-) (limited to 'posix-aio-compat.c') diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 6b547f41fd..65c80ecc3e 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -11,6 +11,7 @@ * */ +#include #include #include #include @@ -75,6 +76,47 @@ static void thread_create(pthread_t *thread, pthread_attr_t *attr, if (ret) die2(ret, "pthread_create"); } +static size_t handle_aiocb_readwrite(struct qemu_paiocb *aiocb) +{ + size_t offset = 0; + ssize_t len; + + while (offset < aiocb->aio_nbytes) { + if (aiocb->aio_type == QEMU_PAIO_WRITE) + len = pwrite(aiocb->aio_fildes, + (const char *)aiocb->aio_buf + offset, + aiocb->aio_nbytes - offset, + aiocb->aio_offset + offset); + else + len = pread(aiocb->aio_fildes, + (char *)aiocb->aio_buf + offset, + aiocb->aio_nbytes - offset, + aiocb->aio_offset + offset); + + if (len == -1 && errno == EINTR) + continue; + else if (len == -1) { + offset = -errno; + break; + } else if (len == 0) + break; + + offset += len; + } + + return offset; +} + +static size_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb) +{ + int ret; + + ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_buf); + if (ret == -1) + return -errno; + return ret; +} + static void *aio_thread(void *unused) { pid_t pid; @@ -88,8 +130,7 @@ static void *aio_thread(void *unused) while (1) { struct qemu_paiocb *aiocb; - size_t offset; - int ret = 0; + size_t ret = 0; qemu_timeval tv; struct timespec ts; @@ -109,40 +150,26 @@ static void *aio_thread(void *unused) aiocb = TAILQ_FIRST(&request_list); TAILQ_REMOVE(&request_list, aiocb, node); - - offset = 0; aiocb->active = 1; - idle_threads--; mutex_unlock(&lock); - while (offset < aiocb->aio_nbytes) { - ssize_t len; - - if (aiocb->is_write) - len = pwrite(aiocb->aio_fildes, - (const char *)aiocb->aio_buf + offset, - aiocb->aio_nbytes - offset, - aiocb->aio_offset + offset); - else - len = pread(aiocb->aio_fildes, - (char *)aiocb->aio_buf + offset, - aiocb->aio_nbytes - offset, - aiocb->aio_offset + offset); - - if (len == -1 && errno == EINTR) - continue; - else if (len == -1) { - offset = -errno; - break; - } else if (len == 0) - break; - - offset += len; - } + switch (aiocb->aio_type) { + case QEMU_PAIO_READ: + case QEMU_PAIO_WRITE: + ret = handle_aiocb_readwrite(aiocb); + break; + case QEMU_PAIO_IOCTL: + ret = handle_aiocb_ioctl(aiocb); + break; + default: + fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); + ret = -EINVAL; + break; + } mutex_lock(&lock); - aiocb->ret = offset; + aiocb->ret = ret; idle_threads++; mutex_unlock(&lock); @@ -178,9 +205,9 @@ int qemu_paio_init(struct qemu_paioinit *aioinit) return 0; } -static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write) +static int qemu_paio_submit(struct qemu_paiocb *aiocb, int type) { - aiocb->is_write = is_write; + aiocb->aio_type = type; aiocb->ret = -EINPROGRESS; aiocb->active = 0; mutex_lock(&lock); @@ -195,12 +222,17 @@ static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write) int qemu_paio_read(struct qemu_paiocb *aiocb) { - return qemu_paio_submit(aiocb, 0); + return qemu_paio_submit(aiocb, QEMU_PAIO_READ); } int qemu_paio_write(struct qemu_paiocb *aiocb) { - return qemu_paio_submit(aiocb, 1); + return qemu_paio_submit(aiocb, QEMU_PAIO_WRITE); +} + +int qemu_paio_ioctl(struct qemu_paiocb *aiocb) +{ + return qemu_paio_submit(aiocb, QEMU_PAIO_IOCTL); } ssize_t qemu_paio_return(struct qemu_paiocb *aiocb) -- cgit v1.2.3