Revision ceb42de8
b/block.c | ||
---|---|---|
1354 | 1354 |
{ |
1355 | 1355 |
BlockDriverAIOCBSync *acb = opaque; |
1356 | 1356 |
|
1357 |
qemu_vfree(acb->bounce); |
|
1358 |
|
|
1359 | 1357 |
if (!acb->is_write) |
1360 | 1358 |
qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size); |
1359 |
qemu_vfree(acb->bounce); |
|
1361 | 1360 |
acb->common.cb(acb->common.opaque, acb->ret); |
1362 | 1361 |
|
1363 | 1362 |
qemu_aio_release(acb); |
b/configure | ||
---|---|---|
1108 | 1108 |
fi |
1109 | 1109 |
|
1110 | 1110 |
########################################## |
1111 |
# preadv probe |
|
1112 |
cat > $TMPC <<EOF |
|
1113 |
#include <sys/types.h> |
|
1114 |
#include <sys/uio.h> |
|
1115 |
#include <unistd.h> |
|
1116 |
int main(void) { preadv; } |
|
1117 |
EOF |
|
1118 |
preadv=no |
|
1119 |
if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then |
|
1120 |
preadv=yes |
|
1121 |
fi |
|
1122 |
|
|
1123 |
########################################## |
|
1111 | 1124 |
# fdt probe |
1112 | 1125 |
if test "$fdt" = "yes" ; then |
1113 | 1126 |
fdt=no |
... | ... | |
1221 | 1234 |
echo "Install blobs $blobs" |
1222 | 1235 |
echo "KVM support $kvm" |
1223 | 1236 |
echo "fdt support $fdt" |
1237 |
echo "preadv support $preadv" |
|
1224 | 1238 |
|
1225 | 1239 |
if test $sdl_too_old = "yes"; then |
1226 | 1240 |
echo "-> Your SDL version is too old - please upgrade to have SDL support" |
... | ... | |
1522 | 1536 |
if test "$iovec" = "yes" ; then |
1523 | 1537 |
echo "#define HAVE_IOVEC 1" >> $config_h |
1524 | 1538 |
fi |
1539 |
if test "$preadv" = "yes" ; then |
|
1540 |
echo "#define HAVE_PREADV 1" >> $config_h |
|
1541 |
fi |
|
1525 | 1542 |
if test "$fdt" = "yes" ; then |
1526 | 1543 |
echo "#define HAVE_FDT 1" >> $config_h |
1527 | 1544 |
echo "FDT_LIBS=-lfdt" >> $config_mak |
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