Commit adcbebaa40933e15d18fa629fa8528e5c8388695

Authored by blueswir1
1 parent dd53ded3

Align file accesses with cache=off (Kevin Wolf, Laurent Vivier)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4367 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 113 additions and 6 deletions
block-raw-posix.c
... ... @@ -77,10 +77,10 @@
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,6 +111,7 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
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,7 +142,14 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
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,7 +202,14 @@ label__raw_read__success:
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,6 +245,67 @@ label__raw_write__success:
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,10 +478,26 @@ static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
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,6 +510,21 @@ static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
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,7 +786,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
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,7 +841,7 @@ static int fd_open(BlockDriverState *bs)
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,7 +938,7 @@ static int raw_eject(BlockDriverState *bs, int eject_flag)
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");
... ...