Revision 6dd2db52
b/block-raw-posix.c | ||
---|---|---|
77 | 77 |
typedef struct BDRVRawState { |
78 | 78 |
int fd; |
79 | 79 |
int type; |
80 |
int open_flags; |
|
81 | 80 |
unsigned int lseek_err_cnt; |
82 | 81 |
#if defined(__linux__) |
83 | 82 |
/* 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; |
|
115 | 114 |
s->type = FTYPE_FILE; |
116 | 115 |
|
117 | 116 |
fd = open(filename, open_flags, 0644); |
... | ... | |
142 | 141 |
#endif |
143 | 142 |
*/ |
144 | 143 |
|
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, |
|
144 |
static int raw_pread(BlockDriverState *bs, int64_t offset, |
|
153 | 145 |
uint8_t *buf, int count) |
154 | 146 |
{ |
155 | 147 |
BDRVRawState *s = bs->opaque; |
... | ... | |
202 | 194 |
return ret; |
203 | 195 |
} |
204 | 196 |
|
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, |
|
197 |
static int raw_pwrite(BlockDriverState *bs, int64_t offset, |
|
213 | 198 |
const uint8_t *buf, int count) |
214 | 199 |
{ |
215 | 200 |
BDRVRawState *s = bs->opaque; |
... | ... | |
245 | 230 |
return ret; |
246 | 231 |
} |
247 | 232 |
|
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 |
|
|
309 | 233 |
/***********************************************************/ |
310 | 234 |
/* Unix AIO using POSIX AIO */ |
311 | 235 |
|
... | ... | |
478 | 402 |
BlockDriverCompletionFunc *cb, void *opaque) |
479 | 403 |
{ |
480 | 404 |
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 |
} |
|
496 | 405 |
|
497 | 406 |
acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); |
498 | 407 |
if (!acb) |
499 | 408 |
return NULL; |
500 |
|
|
501 | 409 |
if (aio_read(&acb->aiocb) < 0) { |
502 | 410 |
qemu_aio_release(acb); |
503 | 411 |
return NULL; |
... | ... | |
510 | 418 |
BlockDriverCompletionFunc *cb, void *opaque) |
511 | 419 |
{ |
512 | 420 |
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 |
} |
|
528 | 421 |
|
529 | 422 |
acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); |
530 | 423 |
if (!acb) |
... | ... | |
786 | 679 |
s->type = FTYPE_CD; |
787 | 680 |
} else if (strstart(filename, "/dev/fd", NULL)) { |
788 | 681 |
s->type = FTYPE_FD; |
789 |
s->open_flags = open_flags; |
|
682 |
s->fd_open_flags = open_flags;
|
|
790 | 683 |
/* open will not fail even if no floppy is inserted */ |
791 | 684 |
open_flags |= O_NONBLOCK; |
792 | 685 |
} else if (strstart(filename, "/dev/sg", NULL)) { |
... | ... | |
841 | 734 |
#endif |
842 | 735 |
return -EIO; |
843 | 736 |
} |
844 |
s->fd = open(bs->filename, s->open_flags); |
|
737 |
s->fd = open(bs->filename, s->fd_open_flags);
|
|
845 | 738 |
if (s->fd < 0) { |
846 | 739 |
s->fd_error_time = qemu_get_clock(rt_clock); |
847 | 740 |
s->fd_got_error = 1; |
... | ... | |
938 | 831 |
close(s->fd); |
939 | 832 |
s->fd = -1; |
940 | 833 |
} |
941 |
fd = open(bs->filename, s->open_flags | O_NONBLOCK); |
|
834 |
fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
|
|
942 | 835 |
if (fd >= 0) { |
943 | 836 |
if (ioctl(fd, FDEJECT, 0) < 0) |
944 | 837 |
perror("FDEJECT"); |
Also available in: Unified diff