Revision 9ef91a67 block/raw-posix.c

b/block/raw-posix.c
27 27
#include "qemu-log.h"
28 28
#include "block_int.h"
29 29
#include "module.h"
30
#include "posix-aio-compat.h"
30
#include "block/raw-posix-aio.h"
31 31

  
32 32
#ifdef CONFIG_COCOA
33 33
#include <paths.h>
......
107 107
    int type;
108 108
    unsigned int lseek_err_cnt;
109 109
    int open_flags;
110
    void *aio_ctx;
110 111
#if defined(__linux__)
111 112
    /* linux floppy specific */
112 113
    int64_t fd_open_time;
......
117 118
    uint8_t* aligned_buf;
118 119
} BDRVRawState;
119 120

  
120
static int posix_aio_init(void);
121

  
122 121
static int fd_open(BlockDriverState *bs);
123 122
static int64_t raw_getlength(BlockDriverState *bs);
124 123

  
......
132 131
    BDRVRawState *s = bs->opaque;
133 132
    int fd, ret;
134 133

  
135
    posix_aio_init();
136

  
137 134
    s->lseek_err_cnt = 0;
138 135

  
139 136
    s->open_flags = open_flags | O_BINARY;
......
165 162
    if ((bdrv_flags & BDRV_O_NOCACHE)) {
166 163
        s->aligned_buf = qemu_blockalign(bs, ALIGNED_BUFFER_SIZE);
167 164
        if (s->aligned_buf == NULL) {
168
            ret = -errno;
169
            close(fd);
170
            return ret;
165
            goto out_close;
171 166
        }
172 167
    }
168

  
169
    s->aio_ctx = paio_init();
170
    if (!s->aio_ctx) {
171
        goto out_free_buf;
172
    }
173

  
173 174
    return 0;
175

  
176
out_free_buf:
177
    qemu_vfree(s->aligned_buf);
178
out_close:
179
    close(fd);
180
    return -errno;
174 181
}
175 182

  
176 183
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
......
487 494
    return ret;
488 495
}
489 496

  
490
/***********************************************************/
491
/* Unix AIO using POSIX AIO */
492

  
493
typedef struct RawAIOCB {
494
    BlockDriverAIOCB common;
495
    struct qemu_paiocb aiocb;
496
    struct RawAIOCB *next;
497
    int ret;
498
} RawAIOCB;
499

  
500
typedef struct PosixAioState
501
{
502
    int rfd, wfd;
503
    RawAIOCB *first_aio;
504
} PosixAioState;
505

  
506
static void posix_aio_read(void *opaque)
507
{
508
    PosixAioState *s = opaque;
509
    RawAIOCB *acb, **pacb;
510
    int ret;
511
    ssize_t len;
512

  
513
    /* read all bytes from signal pipe */
514
    for (;;) {
515
        char bytes[16];
516

  
517
        len = read(s->rfd, bytes, sizeof(bytes));
518
        if (len == -1 && errno == EINTR)
519
            continue; /* try again */
520
        if (len == sizeof(bytes))
521
            continue; /* more to read */
522
        break;
523
    }
524

  
525
    for(;;) {
526
        pacb = &s->first_aio;
527
        for(;;) {
528
            acb = *pacb;
529
            if (!acb)
530
                goto the_end;
531
            ret = qemu_paio_error(&acb->aiocb);
532
            if (ret == ECANCELED) {
533
                /* remove the request */
534
                *pacb = acb->next;
535
                qemu_aio_release(acb);
536
            } else if (ret != EINPROGRESS) {
537
                /* end of aio */
538
                if (ret == 0) {
539
                    ret = qemu_paio_return(&acb->aiocb);
540
                    if (ret == acb->aiocb.aio_nbytes)
541
                        ret = 0;
542
                    else
543
                        ret = -EINVAL;
544
                } else {
545
                    ret = -ret;
546
                }
547
                /* remove the request */
548
                *pacb = acb->next;
549
                /* call the callback */
550
                acb->common.cb(acb->common.opaque, ret);
551
                qemu_aio_release(acb);
552
                break;
553
            } else {
554
                pacb = &acb->next;
555
            }
556
        }
557
    }
558
 the_end: ;
559
}
560

  
561
static int posix_aio_flush(void *opaque)
562
{
563
    PosixAioState *s = opaque;
564
    return !!s->first_aio;
565
}
566

  
567
static PosixAioState *posix_aio_state;
568

  
569
static void aio_signal_handler(int signum)
570
{
571
    if (posix_aio_state) {
572
        char byte = 0;
573

  
574
        write(posix_aio_state->wfd, &byte, sizeof(byte));
575
    }
576

  
577
    qemu_service_io();
578
}
579

  
580
static int posix_aio_init(void)
497
/*
498
 * Check if all memory in this vector is sector aligned.
499
 */
500
static int qiov_is_aligned(QEMUIOVector *qiov)
581 501
{
582
    struct sigaction act;
583
    PosixAioState *s;
584
    int fds[2];
585
    struct qemu_paioinit ai;
586
  
587
    if (posix_aio_state)
588
        return 0;
589

  
590
    s = qemu_malloc(sizeof(PosixAioState));
591

  
592
    sigfillset(&act.sa_mask);
593
    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
594
    act.sa_handler = aio_signal_handler;
595
    sigaction(SIGUSR2, &act, NULL);
596

  
597
    s->first_aio = NULL;
598
    if (pipe(fds) == -1) {
599
        fprintf(stderr, "failed to create pipe\n");
600
        return -errno;
601
    }
602

  
603
    s->rfd = fds[0];
604
    s->wfd = fds[1];
605

  
606
    fcntl(s->rfd, F_SETFL, O_NONBLOCK);
607
    fcntl(s->wfd, F_SETFL, O_NONBLOCK);
608

  
609
    qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s);
610

  
611
    memset(&ai, 0, sizeof(ai));
612
    ai.aio_threads = 64;
613
    ai.aio_num = 64;
614
    qemu_paio_init(&ai);
615

  
616
    posix_aio_state = s;
617

  
618
    return 0;
619
}
502
    int i;
620 503

  
621
static void raw_aio_remove(RawAIOCB *acb)
622
{
623
    RawAIOCB **pacb;
624

  
625
    /* remove the callback from the queue */
626
    pacb = &posix_aio_state->first_aio;
627
    for(;;) {
628
        if (*pacb == NULL) {
629
            fprintf(stderr, "raw_aio_remove: aio request not found!\n");
630
            break;
631
        } else if (*pacb == acb) {
632
            *pacb = acb->next;
633
            qemu_aio_release(acb);
634
            break;
504
    for (i = 0; i < qiov->niov; i++) {
505
        if ((uintptr_t) qiov->iov[i].iov_base % 512) {
506
            return 0;
635 507
        }
636
        pacb = &(*pacb)->next;
637 508
    }
638
}
639

  
640
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
641
{
642
    int ret;
643
    RawAIOCB *acb = (RawAIOCB *)blockacb;
644 509

  
645
    ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
646
    if (ret == QEMU_PAIO_NOTCANCELED) {
647
        /* fail safe: if the aio could not be canceled, we wait for
648
           it */
649
        while (qemu_paio_error(&acb->aiocb) == EINPROGRESS);
650
    }
651

  
652
    raw_aio_remove(acb);
510
    return 1;
653 511
}
654 512

  
655
static AIOPool raw_aio_pool = {
656
    .aiocb_size         = sizeof(RawAIOCB),
657
    .cancel             = raw_aio_cancel,
658
};
659

  
660
static RawAIOCB *raw_aio_setup(BlockDriverState *bs, int64_t sector_num,
661
        QEMUIOVector *qiov, int nb_sectors,
662
        BlockDriverCompletionFunc *cb, void *opaque)
513
static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
514
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
515
        BlockDriverCompletionFunc *cb, void *opaque, int type)
663 516
{
664 517
    BDRVRawState *s = bs->opaque;
665
    RawAIOCB *acb;
666 518

  
667 519
    if (fd_open(bs) < 0)
668 520
        return NULL;
669 521

  
670
    acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
671
    if (!acb)
672
        return NULL;
673
    acb->aiocb.aio_fildes = s->fd;
674
    acb->aiocb.ev_signo = SIGUSR2;
675
    acb->aiocb.aio_iov = qiov->iov;
676
    acb->aiocb.aio_niov = qiov->niov;
677
    acb->aiocb.aio_nbytes = nb_sectors * 512;
678
    acb->aiocb.aio_offset = sector_num * 512;
679
    acb->aiocb.aio_flags = 0;
680

  
681 522
    /*
682 523
     * If O_DIRECT is used the buffer needs to be aligned on a sector
683
     * boundary. Tell the low level code to ensure that in case it's
684
     * not done yet.
524
     * boundary.  Check if this is the case or telll the low-level
525
     * driver that it needs to copy the buffer.
685 526
     */
686
    if (s->aligned_buf)
687
        acb->aiocb.aio_flags |= QEMU_AIO_SECTOR_ALIGNED;
527
    if (s->aligned_buf && !qiov_is_aligned(qiov)) {
528
        type |= QEMU_AIO_MISALIGNED;
529
    }
688 530

  
689
    acb->next = posix_aio_state->first_aio;
690
    posix_aio_state->first_aio = acb;
691
    return acb;
531
    return paio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov, nb_sectors,
532
                       cb, opaque, type);
692 533
}
693 534

  
694 535
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
695 536
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
696 537
        BlockDriverCompletionFunc *cb, void *opaque)
697 538
{
698
    RawAIOCB *acb;
699

  
700
    acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque);
701
    if (!acb)
702
        return NULL;
703
    if (qemu_paio_read(&acb->aiocb) < 0) {
704
        raw_aio_remove(acb);
705
        return NULL;
706
    }
707
    return &acb->common;
539
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
540
                          cb, opaque, QEMU_AIO_READ);
708 541
}
709 542

  
710 543
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
711 544
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
712 545
        BlockDriverCompletionFunc *cb, void *opaque)
713 546
{
714
    RawAIOCB *acb;
715

  
716
    acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque);
717
    if (!acb)
718
        return NULL;
719
    if (qemu_paio_write(&acb->aiocb) < 0) {
720
        raw_aio_remove(acb);
721
        return NULL;
722
    }
723
    return &acb->common;
547
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
548
                          cb, opaque, QEMU_AIO_WRITE);
724 549
}
725 550

  
726 551
static void raw_close(BlockDriverState *bs)
......
1085 910
        BlockDriverCompletionFunc *cb, void *opaque)
1086 911
{
1087 912
    BDRVRawState *s = bs->opaque;
1088
    RawAIOCB *acb;
1089 913

  
1090 914
    if (fd_open(bs) < 0)
1091 915
        return NULL;
1092

  
1093
    acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
1094
    if (!acb)
1095
        return NULL;
1096
    acb->aiocb.aio_fildes = s->fd;
1097
    acb->aiocb.ev_signo = SIGUSR2;
1098
    acb->aiocb.aio_offset = 0;
1099
    acb->aiocb.aio_flags = 0;
1100

  
1101
    acb->next = posix_aio_state->first_aio;
1102
    posix_aio_state->first_aio = acb;
1103

  
1104
    acb->aiocb.aio_ioctl_buf = buf;
1105
    acb->aiocb.aio_ioctl_cmd = req;
1106
    if (qemu_paio_ioctl(&acb->aiocb) < 0) {
1107
        raw_aio_remove(acb);
1108
        return NULL;
1109
    }
1110

  
1111
    return &acb->common;
916
    return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
1112 917
}
1113 918

  
1114 919
#elif defined(__FreeBSD__)
......
1189 994
    BDRVRawState *s = bs->opaque;
1190 995
    int ret;
1191 996

  
1192
    posix_aio_init();
1193

  
1194 997
    s->type = FTYPE_FD;
1195 998

  
1196 999
    /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */

Also available in: Unified diff