Revision adcbebaa
b/block-raw-posix.c | ||
---|---|---|
77 | 77 |
typedef struct BDRVRawState { |
78 | 78 |
int fd; |
79 | 79 |
int type; |
80 |
int open_flags; |
|
80 | 81 |
unsigned int lseek_err_cnt; |
81 | 82 |
#if defined(__linux__) |
82 | 83 |
/* linux floppy specific */ |
83 |
int fd_open_flags; |
|
84 | 84 |
int64_t fd_open_time; |
85 | 85 |
int64_t fd_error_time; |
86 | 86 |
int fd_got_error; |
... | ... | |
111 | 111 |
open_flags |= O_DIRECT; |
112 | 112 |
#endif |
113 | 113 |
|
114 |
s->open_flags = open_flags; |
|
114 | 115 |
s->type = FTYPE_FILE; |
115 | 116 |
|
116 | 117 |
fd = open(filename, open_flags, 0644); |
... | ... | |
141 | 142 |
#endif |
142 | 143 |
*/ |
143 | 144 |
|
144 |
static int raw_pread(BlockDriverState *bs, int64_t offset, |
|
145 |
/* |
|
146 |
* offset and count are in bytes, but must be multiples of 512 for files |
|
147 |
* opened with O_DIRECT. buf must be aligned to 512 bytes then. |
|
148 |
* |
|
149 |
* This function may be called without alignment if the caller ensures |
|
150 |
* that O_DIRECT is not in effect. |
|
151 |
*/ |
|
152 |
static int raw_pread_aligned(BlockDriverState *bs, int64_t offset, |
|
145 | 153 |
uint8_t *buf, int count) |
146 | 154 |
{ |
147 | 155 |
BDRVRawState *s = bs->opaque; |
... | ... | |
194 | 202 |
return ret; |
195 | 203 |
} |
196 | 204 |
|
197 |
static int raw_pwrite(BlockDriverState *bs, int64_t offset, |
|
205 |
/* |
|
206 |
* offset and count are in bytes, but must be multiples of 512 for files |
|
207 |
* opened with O_DIRECT. buf must be aligned to 512 bytes then. |
|
208 |
* |
|
209 |
* This function may be called without alignment if the caller ensures |
|
210 |
* that O_DIRECT is not in effect. |
|
211 |
*/ |
|
212 |
static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset, |
|
198 | 213 |
const uint8_t *buf, int count) |
199 | 214 |
{ |
200 | 215 |
BDRVRawState *s = bs->opaque; |
... | ... | |
230 | 245 |
return ret; |
231 | 246 |
} |
232 | 247 |
|
248 |
|
|
249 |
#ifdef O_DIRECT |
|
250 |
/* |
|
251 |
* offset and count are in bytes and possibly not aligned. For files opened |
|
252 |
* with O_DIRECT, necessary alignments are ensured before calling |
|
253 |
* raw_pread_aligned to do the actual read. |
|
254 |
*/ |
|
255 |
static int raw_pread(BlockDriverState *bs, int64_t offset, |
|
256 |
uint8_t *buf, int count) |
|
257 |
{ |
|
258 |
BDRVRawState *s = bs->opaque; |
|
259 |
|
|
260 |
if (unlikely((s->open_flags & O_DIRECT) && |
|
261 |
(offset % 512 || count % 512 || (uintptr_t) buf % 512))) { |
|
262 |
|
|
263 |
int ret; |
|
264 |
|
|
265 |
// Temporarily disable O_DIRECT for unaligned access |
|
266 |
fcntl(s->fd, F_SETFL, s->open_flags & ~O_DIRECT); |
|
267 |
ret = raw_pread_aligned(bs, offset, buf, count); |
|
268 |
fcntl(s->fd, F_SETFL, s->open_flags); |
|
269 |
|
|
270 |
return ret; |
|
271 |
|
|
272 |
} else { |
|
273 |
return raw_pread_aligned(bs, offset, buf, count); |
|
274 |
} |
|
275 |
} |
|
276 |
|
|
277 |
/* |
|
278 |
* offset and count are in bytes and possibly not aligned. For files opened |
|
279 |
* with O_DIRECT, necessary alignments are ensured before calling |
|
280 |
* raw_pwrite_aligned to do the actual write. |
|
281 |
*/ |
|
282 |
static int raw_pwrite(BlockDriverState *bs, int64_t offset, |
|
283 |
const uint8_t *buf, int count) |
|
284 |
{ |
|
285 |
BDRVRawState *s = bs->opaque; |
|
286 |
|
|
287 |
if (unlikely((s->open_flags & O_DIRECT) && |
|
288 |
(offset % 512 || count % 512 || (uintptr_t) buf % 512))) { |
|
289 |
|
|
290 |
int ret; |
|
291 |
|
|
292 |
// Temporarily disable O_DIRECT for unaligned access |
|
293 |
fcntl(s->fd, F_SETFL, s->open_flags & ~O_DIRECT); |
|
294 |
ret = raw_pwrite_aligned(bs, offset, buf, count); |
|
295 |
fcntl(s->fd, F_SETFL, s->open_flags); |
|
296 |
|
|
297 |
return ret; |
|
298 |
} else { |
|
299 |
return raw_pwrite_aligned(bs, offset, buf, count); |
|
300 |
} |
|
301 |
} |
|
302 |
|
|
303 |
#else |
|
304 |
#define raw_pread raw_pread_aligned |
|
305 |
#define raw_pwrite raw_pwrite_aligned |
|
306 |
#endif |
|
307 |
|
|
308 |
|
|
233 | 309 |
/***********************************************************/ |
234 | 310 |
/* Unix AIO using POSIX AIO */ |
235 | 311 |
|
... | ... | |
402 | 478 |
BlockDriverCompletionFunc *cb, void *opaque) |
403 | 479 |
{ |
404 | 480 |
RawAIOCB *acb; |
481 |
BDRVRawState *s = bs->opaque; |
|
482 |
|
|
483 |
/* |
|
484 |
* If O_DIRECT is used and the buffer is not aligned fall back |
|
485 |
* to synchronous IO. |
|
486 |
*/ |
|
487 |
if (unlikely((s->open_flags & O_DIRECT) && ((uintptr_t) buf % 512))) { |
|
488 |
int ret; |
|
489 |
|
|
490 |
acb = qemu_aio_get(bs, cb, opaque); |
|
491 |
ret = raw_pread(bs, 512 * sector_num, buf, 512 * nb_sectors); |
|
492 |
acb->common.cb(acb->common.opaque, ret); |
|
493 |
qemu_aio_release(acb); |
|
494 |
return &acb->common; |
|
495 |
} |
|
405 | 496 |
|
406 | 497 |
acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); |
407 | 498 |
if (!acb) |
408 | 499 |
return NULL; |
500 |
|
|
409 | 501 |
if (aio_read(&acb->aiocb) < 0) { |
410 | 502 |
qemu_aio_release(acb); |
411 | 503 |
return NULL; |
... | ... | |
418 | 510 |
BlockDriverCompletionFunc *cb, void *opaque) |
419 | 511 |
{ |
420 | 512 |
RawAIOCB *acb; |
513 |
BDRVRawState *s = bs->opaque; |
|
514 |
|
|
515 |
/* |
|
516 |
* If O_DIRECT is used and the buffer is not aligned fall back |
|
517 |
* to synchronous IO. |
|
518 |
*/ |
|
519 |
if (unlikely((s->open_flags & O_DIRECT) && ((uintptr_t) buf % 512))) { |
|
520 |
int ret; |
|
521 |
|
|
522 |
acb = qemu_aio_get(bs, cb, opaque); |
|
523 |
ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors); |
|
524 |
acb->common.cb(acb->common.opaque, ret); |
|
525 |
qemu_aio_release(acb); |
|
526 |
return &acb->common; |
|
527 |
} |
|
421 | 528 |
|
422 | 529 |
acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); |
423 | 530 |
if (!acb) |
... | ... | |
679 | 786 |
s->type = FTYPE_CD; |
680 | 787 |
} else if (strstart(filename, "/dev/fd", NULL)) { |
681 | 788 |
s->type = FTYPE_FD; |
682 |
s->fd_open_flags = open_flags;
|
|
789 |
s->open_flags = open_flags; |
|
683 | 790 |
/* open will not fail even if no floppy is inserted */ |
684 | 791 |
open_flags |= O_NONBLOCK; |
685 | 792 |
} else if (strstart(filename, "/dev/sg", NULL)) { |
... | ... | |
734 | 841 |
#endif |
735 | 842 |
return -EIO; |
736 | 843 |
} |
737 |
s->fd = open(bs->filename, s->fd_open_flags);
|
|
844 |
s->fd = open(bs->filename, s->open_flags); |
|
738 | 845 |
if (s->fd < 0) { |
739 | 846 |
s->fd_error_time = qemu_get_clock(rt_clock); |
740 | 847 |
s->fd_got_error = 1; |
... | ... | |
831 | 938 |
close(s->fd); |
832 | 939 |
s->fd = -1; |
833 | 940 |
} |
834 |
fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
|
|
941 |
fd = open(bs->filename, s->open_flags | O_NONBLOCK); |
|
835 | 942 |
if (fd >= 0) { |
836 | 943 |
if (ioctl(fd, FDEJECT, 0) < 0) |
837 | 944 |
perror("FDEJECT"); |
Also available in: Unified diff