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