Revision ceb42de8 posix-aio-compat.c

b/posix-aio-compat.c
33 33
static int idle_threads = 0;
34 34
static TAILQ_HEAD(, qemu_paiocb) request_list;
35 35

  
36
#ifdef HAVE_PREADV
37
static int preadv_present = 1;
38
#else
39
static int preadv_present = 0;
40
#endif
41

  
36 42
static void die2(int err, const char *what)
37 43
{
38 44
    fprintf(stderr, "%s failed: %s\n", what, strerror(err));
......
87 93
	return ret;
88 94
}
89 95

  
96
#ifdef HAVE_PREADV
97

  
98
static ssize_t
99
qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
100
{
101
    return preadv(fd, iov, nr_iov, offset);
102
}
103

  
104
static ssize_t
105
qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
106
{
107
    return pwritev(fd, iov, nr_iov, offset);
108
}
109

  
110
#else
111

  
112
static ssize_t
113
qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
114
{
115
    return -ENOSYS;
116
}
117

  
118
static ssize_t
119
qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
120
{
121
    return -ENOSYS;
122
}
123

  
124
#endif
125

  
90 126
/*
91 127
 * Check if we need to copy the data in the aiocb into a new
92 128
 * properly aligned buffer.
......
104 140
    return 0;
105 141
}
106 142

  
143
static size_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
144
{
145
    size_t offset = 0;
146
    ssize_t len;
147

  
148
    do {
149
        if (aiocb->aio_type == QEMU_PAIO_WRITE)
150
            len = qemu_pwritev(aiocb->aio_fildes,
151
                               aiocb->aio_iov,
152
                               aiocb->aio_niov,
153
                               aiocb->aio_offset + offset);
154
         else
155
            len = qemu_preadv(aiocb->aio_fildes,
156
                              aiocb->aio_iov,
157
                              aiocb->aio_niov,
158
                              aiocb->aio_offset + offset);
159
    } while (len == -1 && errno == EINTR);
160

  
161
    if (len == -1)
162
        return -errno;
163
    return len;
164
}
165

  
107 166
static size_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf)
108 167
{
109 168
    size_t offset = 0;
......
140 199
    size_t nbytes;
141 200
    char *buf;
142 201

  
143
    if (!aiocb_needs_copy(aiocb) && aiocb->aio_niov == 1) {
202
    if (!aiocb_needs_copy(aiocb)) {
144 203
        /*
145 204
         * If there is just a single buffer, and it is properly aligned
146 205
         * we can just use plain pread/pwrite without any problems.
147 206
         */
148
        return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
207
        if (aiocb->aio_niov == 1)
208
             return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
209

  
210
        /*
211
         * We have more than one iovec, and all are properly aligned.
212
         *
213
         * Try preadv/pwritev first and fall back to linearizing the
214
         * buffer if it's not supported.
215
         */
216
	if (preadv_present) {
217
            nbytes = handle_aiocb_rw_vector(aiocb);
218
            if (nbytes == aiocb->aio_nbytes)
219
	        return nbytes;
220
            if (nbytes < 0 && nbytes != -ENOSYS)
221
                return nbytes;
222
            preadv_present = 0;
223
        }
224

  
225
        /*
226
         * XXX(hch): short read/write.  no easy way to handle the reminder
227
         * using these interfaces.  For now retry using plain
228
         * pread/pwrite?
229
         */
149 230
    }
150 231

  
151 232
    /*

Also available in: Unified diff