static void posix_aio_read(void *opaque) { PosixAioState *s = opaque; RawAIOCB *acb, **pacb; int ret; ssize_t len; /* read all bytes from signal pipe */ for (;;) { char bytes[16]; len = read(s->rfd, bytes, sizeof(bytes)); if (len == -1 && errno == EINTR) continue; /* try again */ if (len == sizeof(bytes)) continue; /* more to read */ break; } for(;;) { pacb = &s->first_aio; for(;;) { acb = *pacb; if (!acb) goto the_end; ret = qemu_paio_error(&acb->aiocb); if (ret == ECANCELED) { /* remove the request */ *pacb = acb->next; qemu_aio_release(acb); } else if (ret != EINPROGRESS) { /* end of aio */ if (ret == 0) { ret = qemu_paio_return(&acb->aiocb); if (ret == acb->aiocb.aio_nbytes) ret = 0; else ret = -EINVAL; } else { ret = -ret; } /* remove the request */ *pacb = acb->next; /* call the callback */ acb->common.cb(acb->common.opaque, ret); qemu_aio_release(acb); break; } else { pacb = &acb->next; } } } the_end: ; }
static void raw_aio_cancel(BlockDriverAIOCB *blockacb) { int ret; RawAIOCB *acb = (RawAIOCB *)blockacb; ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb); if (ret == QEMU_PAIO_NOTCANCELED) { /* fail safe: if the aio could not be canceled, we wait for it */ while (qemu_paio_error(&acb->aiocb) == EINPROGRESS); } raw_aio_remove(acb); }
static void posix_aio_read(void *opaque) { PosixAioState *s = opaque; RawAIOCB *acb, **pacb; int ret; size_t offset; union { struct qemu_signalfd_siginfo siginfo; char buf[128]; } sig; /* try to read from signalfd, don't freak out if we can't read anything */ offset = 0; while (offset < 128) { ssize_t len; len = read(s->fd, sig.buf + offset, 128 - offset); if (len == -1 && errno == EINTR) continue; if (len == -1 && errno == EAGAIN) { /* there is no natural reason for this to happen, * so we'll spin hard until we get everything just * to be on the safe side. */ if (offset > 0) continue; } offset += len; } for(;;) { pacb = &s->first_aio; for(;;) { acb = *pacb; if (!acb) goto the_end; ret = qemu_paio_error(&acb->aiocb); if (ret == ECANCELED) { /* remove the request */ *pacb = acb->next; qemu_aio_release(acb); } else if (ret != EINPROGRESS) { /* end of aio */ if (ret == 0) { ret = qemu_paio_return(&acb->aiocb); if (ret == acb->aiocb.aio_nbytes) ret = 0; else ret = -EINVAL; } else { ret = -ret; } /* remove the request */ *pacb = acb->next; /* call the callback */ acb->common.cb(acb->common.opaque, ret); qemu_aio_release(acb); break; } else { pacb = &acb->next; } } } the_end: ; }