Annotation of qemu/block-raw-posix.c, revision 1.1.1.2
1.1 root 1: /*
2: * Block driver for RAW files (posix)
3: *
4: * Copyright (c) 2006 Fabrice Bellard
5: *
6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
24: #include "qemu-common.h"
25: #include "qemu-timer.h"
1.1.1.2 ! root 26: #include "qemu-char.h"
1.1 root 27: #include "block_int.h"
28: #include <assert.h>
1.1.1.2 ! root 29: #ifdef CONFIG_AIO
! 30: #include "posix-aio-compat.h"
! 31: #endif
1.1 root 32:
33: #ifdef CONFIG_COCOA
34: #include <paths.h>
35: #include <sys/param.h>
36: #include <IOKit/IOKitLib.h>
37: #include <IOKit/IOBSD.h>
38: #include <IOKit/storage/IOMediaBSDClient.h>
39: #include <IOKit/storage/IOMedia.h>
40: #include <IOKit/storage/IOCDMedia.h>
41: //#include <IOKit/storage/IOCDTypes.h>
42: #include <CoreFoundation/CoreFoundation.h>
43: #endif
44:
45: #ifdef __sun__
46: #define _POSIX_PTHREAD_SEMANTICS 1
47: #include <signal.h>
48: #include <sys/dkio.h>
49: #endif
50: #ifdef __linux__
51: #include <sys/ioctl.h>
52: #include <linux/cdrom.h>
53: #include <linux/fd.h>
54: #endif
55: #ifdef __FreeBSD__
1.1.1.2 ! root 56: #include <signal.h>
1.1 root 57: #include <sys/disk.h>
58: #endif
59:
1.1.1.2 ! root 60: #ifdef __OpenBSD__
! 61: #include <sys/ioctl.h>
! 62: #include <sys/disklabel.h>
! 63: #include <sys/dkio.h>
! 64: #endif
! 65:
1.1 root 66: //#define DEBUG_FLOPPY
67:
68: //#define DEBUG_BLOCK
1.1.1.2 ! root 69: #if defined(DEBUG_BLOCK)
! 70: #define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (qemu_log_enabled()) \
! 71: { qemu_log(formatCstr, ##args); qemu_log_flush(); } } while (0)
1.1 root 72: #else
73: #define DEBUG_BLOCK_PRINT(formatCstr, args...)
74: #endif
75:
1.1.1.2 ! root 76: /* OS X does not have O_DSYNC */
! 77: #ifndef O_DSYNC
! 78: #define O_DSYNC O_SYNC
! 79: #endif
! 80:
! 81: /* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
! 82: #ifndef O_DIRECT
! 83: #define O_DIRECT O_DSYNC
! 84: #endif
! 85:
1.1 root 86: #define FTYPE_FILE 0
87: #define FTYPE_CD 1
88: #define FTYPE_FD 2
89:
1.1.1.2 ! root 90: #define ALIGNED_BUFFER_SIZE (32 * 512)
! 91:
1.1 root 92: /* if the FD is not accessed during that time (in ms), we try to
93: reopen it to see if the disk has been changed */
94: #define FD_OPEN_TIMEOUT 1000
95:
96: typedef struct BDRVRawState {
97: int fd;
98: int type;
99: unsigned int lseek_err_cnt;
100: #if defined(__linux__)
101: /* linux floppy specific */
102: int fd_open_flags;
103: int64_t fd_open_time;
104: int64_t fd_error_time;
105: int fd_got_error;
106: int fd_media_changed;
107: #endif
1.1.1.2 ! root 108: uint8_t* aligned_buf;
1.1 root 109: } BDRVRawState;
110:
1.1.1.2 ! root 111: static int posix_aio_init(void);
! 112:
1.1 root 113: static int fd_open(BlockDriverState *bs);
114:
115: static int raw_open(BlockDriverState *bs, const char *filename, int flags)
116: {
117: BDRVRawState *s = bs->opaque;
118: int fd, open_flags, ret;
119:
1.1.1.2 ! root 120: posix_aio_init();
! 121:
1.1 root 122: s->lseek_err_cnt = 0;
123:
124: open_flags = O_BINARY;
125: if ((flags & BDRV_O_ACCESS) == O_RDWR) {
126: open_flags |= O_RDWR;
127: } else {
128: open_flags |= O_RDONLY;
129: bs->read_only = 1;
130: }
131: if (flags & BDRV_O_CREAT)
132: open_flags |= O_CREAT | O_TRUNC;
1.1.1.2 ! root 133:
! 134: /* Use O_DSYNC for write-through caching, no flags for write-back caching,
! 135: * and O_DIRECT for no caching. */
! 136: if ((flags & BDRV_O_NOCACHE))
1.1 root 137: open_flags |= O_DIRECT;
1.1.1.2 ! root 138: else if (!(flags & BDRV_O_CACHE_WB))
! 139: open_flags |= O_DSYNC;
1.1 root 140:
141: s->type = FTYPE_FILE;
142:
143: fd = open(filename, open_flags, 0644);
144: if (fd < 0) {
145: ret = -errno;
146: if (ret == -EROFS)
147: ret = -EACCES;
148: return ret;
149: }
150: s->fd = fd;
1.1.1.2 ! root 151: s->aligned_buf = NULL;
! 152: if ((flags & BDRV_O_NOCACHE)) {
! 153: s->aligned_buf = qemu_memalign(512, ALIGNED_BUFFER_SIZE);
! 154: if (s->aligned_buf == NULL) {
! 155: ret = -errno;
! 156: close(fd);
! 157: return ret;
! 158: }
! 159: }
1.1 root 160: return 0;
161: }
162:
163: /* XXX: use host sector size if necessary with:
164: #ifdef DIOCGSECTORSIZE
165: {
166: unsigned int sectorsize = 512;
167: if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) &&
168: sectorsize > bufsize)
169: bufsize = sectorsize;
170: }
171: #endif
172: #ifdef CONFIG_COCOA
173: u_int32_t blockSize = 512;
174: if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
175: bufsize = blockSize;
176: }
177: #endif
178: */
179:
1.1.1.2 ! root 180: /*
! 181: * offset and count are in bytes, but must be multiples of 512 for files
! 182: * opened with O_DIRECT. buf must be aligned to 512 bytes then.
! 183: *
! 184: * This function may be called without alignment if the caller ensures
! 185: * that O_DIRECT is not in effect.
! 186: */
! 187: static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
1.1 root 188: uint8_t *buf, int count)
189: {
190: BDRVRawState *s = bs->opaque;
191: int ret;
192:
193: ret = fd_open(bs);
194: if (ret < 0)
195: return ret;
196:
197: if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
198: ++(s->lseek_err_cnt);
199: if(s->lseek_err_cnt <= 10) {
200: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
201: "] lseek failed : %d = %s\n",
202: s->fd, bs->filename, offset, buf, count,
203: bs->total_sectors, errno, strerror(errno));
204: }
205: return -1;
206: }
207: s->lseek_err_cnt=0;
208:
209: ret = read(s->fd, buf, count);
210: if (ret == count)
211: goto label__raw_read__success;
212:
213: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
214: "] read failed %d : %d = %s\n",
215: s->fd, bs->filename, offset, buf, count,
216: bs->total_sectors, ret, errno, strerror(errno));
217:
218: /* Try harder for CDrom. */
219: if (bs->type == BDRV_TYPE_CDROM) {
220: lseek(s->fd, offset, SEEK_SET);
221: ret = read(s->fd, buf, count);
222: if (ret == count)
223: goto label__raw_read__success;
224: lseek(s->fd, offset, SEEK_SET);
225: ret = read(s->fd, buf, count);
226: if (ret == count)
227: goto label__raw_read__success;
228:
229: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
230: "] retry read failed %d : %d = %s\n",
231: s->fd, bs->filename, offset, buf, count,
232: bs->total_sectors, ret, errno, strerror(errno));
233: }
234:
235: label__raw_read__success:
236:
237: return ret;
238: }
239:
1.1.1.2 ! root 240: /*
! 241: * offset and count are in bytes, but must be multiples of 512 for files
! 242: * opened with O_DIRECT. buf must be aligned to 512 bytes then.
! 243: *
! 244: * This function may be called without alignment if the caller ensures
! 245: * that O_DIRECT is not in effect.
! 246: */
! 247: static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
1.1 root 248: const uint8_t *buf, int count)
249: {
250: BDRVRawState *s = bs->opaque;
251: int ret;
252:
253: ret = fd_open(bs);
254: if (ret < 0)
1.1.1.2 ! root 255: return -errno;
1.1 root 256:
257: if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
258: ++(s->lseek_err_cnt);
259: if(s->lseek_err_cnt) {
260: DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
261: PRId64 "] lseek failed : %d = %s\n",
262: s->fd, bs->filename, offset, buf, count,
263: bs->total_sectors, errno, strerror(errno));
264: }
1.1.1.2 ! root 265: return -EIO;
1.1 root 266: }
267: s->lseek_err_cnt = 0;
268:
269: ret = write(s->fd, buf, count);
270: if (ret == count)
271: goto label__raw_write__success;
272:
273: DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
274: "] write failed %d : %d = %s\n",
275: s->fd, bs->filename, offset, buf, count,
276: bs->total_sectors, ret, errno, strerror(errno));
277:
278: label__raw_write__success:
279:
1.1.1.2 ! root 280: return (ret < 0) ? -errno : ret;
1.1 root 281: }
282:
283:
1.1.1.2 ! root 284: /*
! 285: * offset and count are in bytes and possibly not aligned. For files opened
! 286: * with O_DIRECT, necessary alignments are ensured before calling
! 287: * raw_pread_aligned to do the actual read.
! 288: */
! 289: static int raw_pread(BlockDriverState *bs, int64_t offset,
! 290: uint8_t *buf, int count)
! 291: {
! 292: BDRVRawState *s = bs->opaque;
! 293: int size, ret, shift, sum;
1.1 root 294:
1.1.1.2 ! root 295: sum = 0;
1.1 root 296:
1.1.1.2 ! root 297: if (s->aligned_buf != NULL) {
! 298:
! 299: if (offset & 0x1ff) {
! 300: /* align offset on a 512 bytes boundary */
! 301:
! 302: shift = offset & 0x1ff;
! 303: size = (shift + count + 0x1ff) & ~0x1ff;
! 304: if (size > ALIGNED_BUFFER_SIZE)
! 305: size = ALIGNED_BUFFER_SIZE;
! 306: ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
! 307: if (ret < 0)
! 308: return ret;
! 309:
! 310: size = 512 - shift;
! 311: if (size > count)
! 312: size = count;
! 313: memcpy(buf, s->aligned_buf + shift, size);
! 314:
! 315: buf += size;
! 316: offset += size;
! 317: count -= size;
! 318: sum += size;
! 319:
! 320: if (count == 0)
! 321: return sum;
! 322: }
! 323: if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
! 324:
! 325: /* read on aligned buffer */
! 326:
! 327: while (count) {
! 328:
! 329: size = (count + 0x1ff) & ~0x1ff;
! 330: if (size > ALIGNED_BUFFER_SIZE)
! 331: size = ALIGNED_BUFFER_SIZE;
! 332:
! 333: ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
! 334: if (ret < 0)
! 335: return ret;
! 336:
! 337: size = ret;
! 338: if (size > count)
! 339: size = count;
! 340:
! 341: memcpy(buf, s->aligned_buf, size);
! 342:
! 343: buf += size;
! 344: offset += size;
! 345: count -= size;
! 346: sum += size;
! 347: }
! 348:
! 349: return sum;
1.1 root 350: }
351: }
1.1.1.2 ! root 352:
! 353: return raw_pread_aligned(bs, offset, buf, count) + sum;
1.1 root 354: }
355:
1.1.1.2 ! root 356: /*
! 357: * offset and count are in bytes and possibly not aligned. For files opened
! 358: * with O_DIRECT, necessary alignments are ensured before calling
! 359: * raw_pwrite_aligned to do the actual write.
! 360: */
! 361: static int raw_pwrite(BlockDriverState *bs, int64_t offset,
! 362: const uint8_t *buf, int count)
1.1 root 363: {
1.1.1.2 ! root 364: BDRVRawState *s = bs->opaque;
! 365: int size, ret, shift, sum;
1.1 root 366:
1.1.1.2 ! root 367: sum = 0;
1.1 root 368:
1.1.1.2 ! root 369: if (s->aligned_buf != NULL) {
1.1 root 370:
1.1.1.2 ! root 371: if (offset & 0x1ff) {
! 372: /* align offset on a 512 bytes boundary */
! 373: shift = offset & 0x1ff;
! 374: ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512);
! 375: if (ret < 0)
! 376: return ret;
! 377:
! 378: size = 512 - shift;
! 379: if (size > count)
! 380: size = count;
! 381: memcpy(s->aligned_buf + shift, buf, size);
! 382:
! 383: ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512);
! 384: if (ret < 0)
! 385: return ret;
! 386:
! 387: buf += size;
! 388: offset += size;
! 389: count -= size;
! 390: sum += size;
! 391:
! 392: if (count == 0)
! 393: return sum;
! 394: }
! 395: if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
! 396:
! 397: while ((size = (count & ~0x1ff)) != 0) {
! 398:
! 399: if (size > ALIGNED_BUFFER_SIZE)
! 400: size = ALIGNED_BUFFER_SIZE;
! 401:
! 402: memcpy(s->aligned_buf, buf, size);
! 403:
! 404: ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
! 405: if (ret < 0)
! 406: return ret;
! 407:
! 408: buf += ret;
! 409: offset += ret;
! 410: count -= ret;
! 411: sum += ret;
! 412: }
! 413: /* here, count < 512 because (count & ~0x1ff) == 0 */
! 414: if (count) {
! 415: ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512);
! 416: if (ret < 0)
! 417: return ret;
! 418: memcpy(s->aligned_buf, buf, count);
! 419:
! 420: ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512);
! 421: if (ret < 0)
! 422: return ret;
! 423: if (count < ret)
! 424: ret = count;
! 425:
! 426: sum += ret;
! 427: }
! 428: return sum;
! 429: }
1.1 root 430: }
1.1.1.2 ! root 431: return raw_pwrite_aligned(bs, offset, buf, count) + sum;
1.1 root 432: }
433:
1.1.1.2 ! root 434: #ifdef CONFIG_AIO
! 435: /***********************************************************/
! 436: /* Unix AIO using POSIX AIO */
! 437:
! 438: typedef struct RawAIOCB {
! 439: BlockDriverAIOCB common;
! 440: struct qemu_paiocb aiocb;
! 441: struct RawAIOCB *next;
! 442: int ret;
! 443: } RawAIOCB;
! 444:
! 445: typedef struct PosixAioState
! 446: {
! 447: int rfd, wfd;
! 448: RawAIOCB *first_aio;
! 449: } PosixAioState;
! 450:
! 451: static void posix_aio_read(void *opaque)
1.1 root 452: {
1.1.1.2 ! root 453: PosixAioState *s = opaque;
1.1 root 454: RawAIOCB *acb, **pacb;
455: int ret;
1.1.1.2 ! root 456: ssize_t len;
! 457:
! 458: /* read all bytes from signal pipe */
! 459: for (;;) {
! 460: char bytes[16];
! 461:
! 462: len = read(s->rfd, bytes, sizeof(bytes));
! 463: if (len == -1 && errno == EINTR)
! 464: continue; /* try again */
! 465: if (len == sizeof(bytes))
! 466: continue; /* more to read */
! 467: break;
! 468: }
1.1 root 469:
470: for(;;) {
1.1.1.2 ! root 471: pacb = &s->first_aio;
1.1 root 472: for(;;) {
473: acb = *pacb;
474: if (!acb)
475: goto the_end;
1.1.1.2 ! root 476: ret = qemu_paio_error(&acb->aiocb);
1.1 root 477: if (ret == ECANCELED) {
478: /* remove the request */
479: *pacb = acb->next;
480: qemu_aio_release(acb);
481: } else if (ret != EINPROGRESS) {
482: /* end of aio */
483: if (ret == 0) {
1.1.1.2 ! root 484: ret = qemu_paio_return(&acb->aiocb);
1.1 root 485: if (ret == acb->aiocb.aio_nbytes)
486: ret = 0;
487: else
488: ret = -EINVAL;
489: } else {
490: ret = -ret;
491: }
492: /* remove the request */
493: *pacb = acb->next;
494: /* call the callback */
495: acb->common.cb(acb->common.opaque, ret);
496: qemu_aio_release(acb);
497: break;
498: } else {
499: pacb = &acb->next;
500: }
501: }
502: }
503: the_end: ;
504: }
505:
1.1.1.2 ! root 506: static int posix_aio_flush(void *opaque)
1.1 root 507: {
1.1.1.2 ! root 508: PosixAioState *s = opaque;
! 509: return !!s->first_aio;
1.1 root 510: }
511:
1.1.1.2 ! root 512: static PosixAioState *posix_aio_state;
1.1 root 513:
1.1.1.2 ! root 514: static void aio_signal_handler(int signum)
1.1 root 515: {
1.1.1.2 ! root 516: if (posix_aio_state) {
! 517: char byte = 0;
1.1 root 518:
1.1.1.2 ! root 519: write(posix_aio_state->wfd, &byte, sizeof(byte));
! 520: }
! 521:
! 522: qemu_service_io();
1.1 root 523: }
524:
1.1.1.2 ! root 525: static int posix_aio_init(void)
1.1 root 526: {
1.1.1.2 ! root 527: struct sigaction act;
! 528: PosixAioState *s;
! 529: int fds[2];
! 530: struct qemu_paioinit ai;
! 531:
! 532: if (posix_aio_state)
! 533: return 0;
1.1 root 534:
1.1.1.2 ! root 535: s = qemu_malloc(sizeof(PosixAioState));
1.1 root 536:
1.1.1.2 ! root 537: sigfillset(&act.sa_mask);
! 538: act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
! 539: act.sa_handler = aio_signal_handler;
! 540: sigaction(SIGUSR2, &act, NULL);
! 541:
! 542: s->first_aio = NULL;
! 543: if (pipe(fds) == -1) {
! 544: fprintf(stderr, "failed to create pipe\n");
! 545: return -errno;
! 546: }
! 547:
! 548: s->rfd = fds[0];
! 549: s->wfd = fds[1];
! 550:
! 551: fcntl(s->rfd, F_SETFL, O_NONBLOCK);
! 552: fcntl(s->wfd, F_SETFL, O_NONBLOCK);
! 553:
! 554: qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s);
! 555:
! 556: memset(&ai, 0, sizeof(ai));
! 557: ai.aio_threads = 64;
! 558: ai.aio_num = 64;
! 559: qemu_paio_init(&ai);
! 560:
! 561: posix_aio_state = s;
! 562:
! 563: return 0;
1.1 root 564: }
565:
566: static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
567: int64_t sector_num, uint8_t *buf, int nb_sectors,
568: BlockDriverCompletionFunc *cb, void *opaque)
569: {
570: BDRVRawState *s = bs->opaque;
571: RawAIOCB *acb;
572:
573: if (fd_open(bs) < 0)
574: return NULL;
575:
576: acb = qemu_aio_get(bs, cb, opaque);
577: if (!acb)
578: return NULL;
579: acb->aiocb.aio_fildes = s->fd;
1.1.1.2 ! root 580: acb->aiocb.ev_signo = SIGUSR2;
1.1 root 581: acb->aiocb.aio_buf = buf;
582: if (nb_sectors < 0)
583: acb->aiocb.aio_nbytes = -nb_sectors;
584: else
585: acb->aiocb.aio_nbytes = nb_sectors * 512;
586: acb->aiocb.aio_offset = sector_num * 512;
1.1.1.2 ! root 587: acb->next = posix_aio_state->first_aio;
! 588: posix_aio_state->first_aio = acb;
1.1 root 589: return acb;
590: }
591:
1.1.1.2 ! root 592: static void raw_aio_em_cb(void* opaque)
! 593: {
! 594: RawAIOCB *acb = opaque;
! 595: acb->common.cb(acb->common.opaque, acb->ret);
! 596: qemu_aio_release(acb);
! 597: }
! 598:
! 599: static void raw_aio_remove(RawAIOCB *acb)
! 600: {
! 601: RawAIOCB **pacb;
! 602:
! 603: /* remove the callback from the queue */
! 604: pacb = &posix_aio_state->first_aio;
! 605: for(;;) {
! 606: if (*pacb == NULL) {
! 607: fprintf(stderr, "raw_aio_remove: aio request not found!\n");
! 608: break;
! 609: } else if (*pacb == acb) {
! 610: *pacb = acb->next;
! 611: qemu_aio_release(acb);
! 612: break;
! 613: }
! 614: pacb = &(*pacb)->next;
! 615: }
! 616: }
! 617:
1.1 root 618: static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
619: int64_t sector_num, uint8_t *buf, int nb_sectors,
620: BlockDriverCompletionFunc *cb, void *opaque)
621: {
622: RawAIOCB *acb;
623:
1.1.1.2 ! root 624: /*
! 625: * If O_DIRECT is used and the buffer is not aligned fall back
! 626: * to synchronous IO.
! 627: */
! 628: BDRVRawState *s = bs->opaque;
! 629:
! 630: if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
! 631: QEMUBH *bh;
! 632: acb = qemu_aio_get(bs, cb, opaque);
! 633: acb->ret = raw_pread(bs, 512 * sector_num, buf, 512 * nb_sectors);
! 634: bh = qemu_bh_new(raw_aio_em_cb, acb);
! 635: qemu_bh_schedule(bh);
! 636: return &acb->common;
! 637: }
! 638:
1.1 root 639: acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
640: if (!acb)
641: return NULL;
1.1.1.2 ! root 642: if (qemu_paio_read(&acb->aiocb) < 0) {
! 643: raw_aio_remove(acb);
1.1 root 644: return NULL;
645: }
646: return &acb->common;
647: }
648:
649: static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
650: int64_t sector_num, const uint8_t *buf, int nb_sectors,
651: BlockDriverCompletionFunc *cb, void *opaque)
652: {
653: RawAIOCB *acb;
654:
1.1.1.2 ! root 655: /*
! 656: * If O_DIRECT is used and the buffer is not aligned fall back
! 657: * to synchronous IO.
! 658: */
! 659: BDRVRawState *s = bs->opaque;
! 660:
! 661: if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
! 662: QEMUBH *bh;
! 663: acb = qemu_aio_get(bs, cb, opaque);
! 664: acb->ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors);
! 665: bh = qemu_bh_new(raw_aio_em_cb, acb);
! 666: qemu_bh_schedule(bh);
! 667: return &acb->common;
! 668: }
! 669:
1.1 root 670: acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
671: if (!acb)
672: return NULL;
1.1.1.2 ! root 673: if (qemu_paio_write(&acb->aiocb) < 0) {
! 674: raw_aio_remove(acb);
1.1 root 675: return NULL;
676: }
677: return &acb->common;
678: }
679:
680: static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
681: {
682: int ret;
683: RawAIOCB *acb = (RawAIOCB *)blockacb;
684:
1.1.1.2 ! root 685: ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
! 686: if (ret == QEMU_PAIO_NOTCANCELED) {
1.1 root 687: /* fail safe: if the aio could not be canceled, we wait for
688: it */
1.1.1.2 ! root 689: while (qemu_paio_error(&acb->aiocb) == EINPROGRESS);
1.1 root 690: }
691:
1.1.1.2 ! root 692: raw_aio_remove(acb);
1.1 root 693: }
1.1.1.2 ! root 694: #else /* CONFIG_AIO */
! 695: static int posix_aio_init(void)
! 696: {
! 697: return 0;
! 698: }
! 699: #endif /* CONFIG_AIO */
! 700:
1.1 root 701:
702: static void raw_close(BlockDriverState *bs)
703: {
704: BDRVRawState *s = bs->opaque;
705: if (s->fd >= 0) {
706: close(s->fd);
707: s->fd = -1;
1.1.1.2 ! root 708: if (s->aligned_buf != NULL)
! 709: qemu_free(s->aligned_buf);
1.1 root 710: }
711: }
712:
713: static int raw_truncate(BlockDriverState *bs, int64_t offset)
714: {
715: BDRVRawState *s = bs->opaque;
716: if (s->type != FTYPE_FILE)
717: return -ENOTSUP;
718: if (ftruncate(s->fd, offset) < 0)
719: return -errno;
720: return 0;
721: }
722:
1.1.1.2 ! root 723: #ifdef __OpenBSD__
! 724: static int64_t raw_getlength(BlockDriverState *bs)
! 725: {
! 726: BDRVRawState *s = bs->opaque;
! 727: int fd = s->fd;
! 728: struct stat st;
! 729:
! 730: if (fstat(fd, &st))
! 731: return -1;
! 732: if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
! 733: struct disklabel dl;
! 734:
! 735: if (ioctl(fd, DIOCGDINFO, &dl))
! 736: return -1;
! 737: return (uint64_t)dl.d_secsize *
! 738: dl.d_partitions[DISKPART(st.st_rdev)].p_size;
! 739: } else
! 740: return st.st_size;
! 741: }
! 742: #else /* !__OpenBSD__ */
1.1 root 743: static int64_t raw_getlength(BlockDriverState *bs)
744: {
745: BDRVRawState *s = bs->opaque;
746: int fd = s->fd;
747: int64_t size;
748: #ifdef _BSD
749: struct stat sb;
750: #endif
751: #ifdef __sun__
752: struct dk_minfo minfo;
753: int rv;
754: #endif
755: int ret;
756:
757: ret = fd_open(bs);
758: if (ret < 0)
759: return ret;
760:
761: #ifdef _BSD
762: if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
763: #ifdef DIOCGMEDIASIZE
764: if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
765: #endif
766: #ifdef CONFIG_COCOA
767: size = LONG_LONG_MAX;
768: #else
769: size = lseek(fd, 0LL, SEEK_END);
770: #endif
771: } else
772: #endif
773: #ifdef __sun__
774: /*
775: * use the DKIOCGMEDIAINFO ioctl to read the size.
776: */
777: rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
778: if ( rv != -1 ) {
779: size = minfo.dki_lbsize * minfo.dki_capacity;
780: } else /* there are reports that lseek on some devices
781: fails, but irc discussion said that contingency
782: on contingency was overkill */
783: #endif
784: {
785: size = lseek(fd, 0, SEEK_END);
786: }
787: return size;
788: }
1.1.1.2 ! root 789: #endif
1.1 root 790:
791: static int raw_create(const char *filename, int64_t total_size,
792: const char *backing_file, int flags)
793: {
794: int fd;
795:
796: if (flags || backing_file)
797: return -ENOTSUP;
798:
799: fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
800: 0644);
801: if (fd < 0)
802: return -EIO;
803: ftruncate(fd, total_size * 512);
804: close(fd);
805: return 0;
806: }
807:
808: static void raw_flush(BlockDriverState *bs)
809: {
810: BDRVRawState *s = bs->opaque;
811: fsync(s->fd);
812: }
813:
814: BlockDriver bdrv_raw = {
815: "raw",
816: sizeof(BDRVRawState),
817: NULL, /* no probe for protocols */
818: raw_open,
819: NULL,
820: NULL,
821: raw_close,
822: raw_create,
823: raw_flush,
824:
1.1.1.2 ! root 825: #ifdef CONFIG_AIO
1.1 root 826: .bdrv_aio_read = raw_aio_read,
827: .bdrv_aio_write = raw_aio_write,
828: .bdrv_aio_cancel = raw_aio_cancel,
829: .aiocb_size = sizeof(RawAIOCB),
1.1.1.2 ! root 830: #endif
! 831:
1.1 root 832: .bdrv_pread = raw_pread,
833: .bdrv_pwrite = raw_pwrite,
834: .bdrv_truncate = raw_truncate,
835: .bdrv_getlength = raw_getlength,
836: };
837:
838: /***********************************************/
839: /* host device */
840:
841: #ifdef CONFIG_COCOA
842: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
843: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
844:
845: kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
846: {
847: kern_return_t kernResult;
848: mach_port_t masterPort;
849: CFMutableDictionaryRef classesToMatch;
850:
851: kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
852: if ( KERN_SUCCESS != kernResult ) {
853: printf( "IOMasterPort returned %d\n", kernResult );
854: }
855:
856: classesToMatch = IOServiceMatching( kIOCDMediaClass );
857: if ( classesToMatch == NULL ) {
858: printf( "IOServiceMatching returned a NULL dictionary.\n" );
859: } else {
860: CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
861: }
862: kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
863: if ( KERN_SUCCESS != kernResult )
864: {
865: printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
866: }
867:
868: return kernResult;
869: }
870:
871: kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
872: {
873: io_object_t nextMedia;
874: kern_return_t kernResult = KERN_FAILURE;
875: *bsdPath = '\0';
876: nextMedia = IOIteratorNext( mediaIterator );
877: if ( nextMedia )
878: {
879: CFTypeRef bsdPathAsCFString;
880: bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
881: if ( bsdPathAsCFString ) {
882: size_t devPathLength;
883: strcpy( bsdPath, _PATH_DEV );
884: strcat( bsdPath, "r" );
885: devPathLength = strlen( bsdPath );
886: if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
887: kernResult = KERN_SUCCESS;
888: }
889: CFRelease( bsdPathAsCFString );
890: }
891: IOObjectRelease( nextMedia );
892: }
893:
894: return kernResult;
895: }
896:
897: #endif
898:
899: static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
900: {
901: BDRVRawState *s = bs->opaque;
902: int fd, open_flags, ret;
903:
1.1.1.2 ! root 904: posix_aio_init();
! 905:
1.1 root 906: #ifdef CONFIG_COCOA
907: if (strstart(filename, "/dev/cdrom", NULL)) {
908: kern_return_t kernResult;
909: io_iterator_t mediaIterator;
910: char bsdPath[ MAXPATHLEN ];
911: int fd;
912:
913: kernResult = FindEjectableCDMedia( &mediaIterator );
914: kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
915:
916: if ( bsdPath[ 0 ] != '\0' ) {
917: strcat(bsdPath,"s0");
918: /* some CDs don't have a partition 0 */
919: fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
920: if (fd < 0) {
921: bsdPath[strlen(bsdPath)-1] = '1';
922: } else {
923: close(fd);
924: }
925: filename = bsdPath;
926: }
927:
928: if ( mediaIterator )
929: IOObjectRelease( mediaIterator );
930: }
931: #endif
932: open_flags = O_BINARY;
933: if ((flags & BDRV_O_ACCESS) == O_RDWR) {
934: open_flags |= O_RDWR;
935: } else {
936: open_flags |= O_RDONLY;
937: bs->read_only = 1;
938: }
1.1.1.2 ! root 939: /* Use O_DSYNC for write-through caching, no flags for write-back caching,
! 940: * and O_DIRECT for no caching. */
! 941: if ((flags & BDRV_O_NOCACHE))
1.1 root 942: open_flags |= O_DIRECT;
1.1.1.2 ! root 943: else if (!(flags & BDRV_O_CACHE_WB))
! 944: open_flags |= O_DSYNC;
1.1 root 945:
946: s->type = FTYPE_FILE;
947: #if defined(__linux__)
948: if (strstart(filename, "/dev/cd", NULL)) {
949: /* open will not fail even if no CD is inserted */
950: open_flags |= O_NONBLOCK;
951: s->type = FTYPE_CD;
952: } else if (strstart(filename, "/dev/fd", NULL)) {
953: s->type = FTYPE_FD;
954: s->fd_open_flags = open_flags;
955: /* open will not fail even if no floppy is inserted */
956: open_flags |= O_NONBLOCK;
957: } else if (strstart(filename, "/dev/sg", NULL)) {
958: bs->sg = 1;
959: }
960: #endif
961: fd = open(filename, open_flags, 0644);
962: if (fd < 0) {
963: ret = -errno;
964: if (ret == -EROFS)
965: ret = -EACCES;
966: return ret;
967: }
968: s->fd = fd;
969: #if defined(__linux__)
970: /* close fd so that we can reopen it as needed */
971: if (s->type == FTYPE_FD) {
972: close(s->fd);
973: s->fd = -1;
974: s->fd_media_changed = 1;
975: }
976: #endif
977: return 0;
978: }
979:
1.1.1.2 ! root 980: #if defined(__linux__)
1.1 root 981: /* Note: we do not have a reliable method to detect if the floppy is
982: present. The current method is to try to open the floppy at every
983: I/O and to keep it opened during a few hundreds of ms. */
984: static int fd_open(BlockDriverState *bs)
985: {
986: BDRVRawState *s = bs->opaque;
987: int last_media_present;
988:
989: if (s->type != FTYPE_FD)
990: return 0;
991: last_media_present = (s->fd >= 0);
992: if (s->fd >= 0 &&
993: (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
994: close(s->fd);
995: s->fd = -1;
996: #ifdef DEBUG_FLOPPY
997: printf("Floppy closed\n");
998: #endif
999: }
1000: if (s->fd < 0) {
1001: if (s->fd_got_error &&
1002: (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
1003: #ifdef DEBUG_FLOPPY
1004: printf("No floppy (open delayed)\n");
1005: #endif
1006: return -EIO;
1007: }
1008: s->fd = open(bs->filename, s->fd_open_flags);
1009: if (s->fd < 0) {
1010: s->fd_error_time = qemu_get_clock(rt_clock);
1011: s->fd_got_error = 1;
1012: if (last_media_present)
1013: s->fd_media_changed = 1;
1014: #ifdef DEBUG_FLOPPY
1015: printf("No floppy\n");
1016: #endif
1017: return -EIO;
1018: }
1019: #ifdef DEBUG_FLOPPY
1020: printf("Floppy opened\n");
1021: #endif
1022: }
1023: if (!last_media_present)
1024: s->fd_media_changed = 1;
1025: s->fd_open_time = qemu_get_clock(rt_clock);
1026: s->fd_got_error = 0;
1027: return 0;
1028: }
1029:
1030: static int raw_is_inserted(BlockDriverState *bs)
1031: {
1032: BDRVRawState *s = bs->opaque;
1033: int ret;
1034:
1035: switch(s->type) {
1036: case FTYPE_CD:
1037: ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1038: if (ret == CDS_DISC_OK)
1039: return 1;
1040: else
1041: return 0;
1042: break;
1043: case FTYPE_FD:
1044: ret = fd_open(bs);
1045: return (ret >= 0);
1046: default:
1047: return 1;
1048: }
1049: }
1050:
1051: /* currently only used by fdc.c, but a CD version would be good too */
1052: static int raw_media_changed(BlockDriverState *bs)
1053: {
1054: BDRVRawState *s = bs->opaque;
1055:
1056: switch(s->type) {
1057: case FTYPE_FD:
1058: {
1059: int ret;
1060: /* XXX: we do not have a true media changed indication. It
1061: does not work if the floppy is changed without trying
1062: to read it */
1063: fd_open(bs);
1064: ret = s->fd_media_changed;
1065: s->fd_media_changed = 0;
1066: #ifdef DEBUG_FLOPPY
1067: printf("Floppy changed=%d\n", ret);
1068: #endif
1069: return ret;
1070: }
1071: default:
1072: return -ENOTSUP;
1073: }
1074: }
1075:
1076: static int raw_eject(BlockDriverState *bs, int eject_flag)
1077: {
1078: BDRVRawState *s = bs->opaque;
1079:
1080: switch(s->type) {
1081: case FTYPE_CD:
1082: if (eject_flag) {
1083: if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
1084: perror("CDROMEJECT");
1085: } else {
1086: if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
1087: perror("CDROMEJECT");
1088: }
1089: break;
1090: case FTYPE_FD:
1091: {
1092: int fd;
1093: if (s->fd >= 0) {
1094: close(s->fd);
1095: s->fd = -1;
1096: }
1097: fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
1098: if (fd >= 0) {
1099: if (ioctl(fd, FDEJECT, 0) < 0)
1100: perror("FDEJECT");
1101: close(fd);
1102: }
1103: }
1104: break;
1105: default:
1106: return -ENOTSUP;
1107: }
1108: return 0;
1109: }
1110:
1111: static int raw_set_locked(BlockDriverState *bs, int locked)
1112: {
1113: BDRVRawState *s = bs->opaque;
1114:
1115: switch(s->type) {
1116: case FTYPE_CD:
1117: if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
1118: /* Note: an error can happen if the distribution automatically
1119: mounts the CD-ROM */
1120: // perror("CDROM_LOCKDOOR");
1121: }
1122: break;
1123: default:
1124: return -ENOTSUP;
1125: }
1126: return 0;
1127: }
1128:
1129: static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1130: {
1131: BDRVRawState *s = bs->opaque;
1132:
1133: return ioctl(s->fd, req, buf);
1134: }
1135: #else
1136:
1.1.1.2 ! root 1137: static int fd_open(BlockDriverState *bs)
! 1138: {
! 1139: return 0;
! 1140: }
! 1141:
1.1 root 1142: static int raw_is_inserted(BlockDriverState *bs)
1143: {
1144: return 1;
1145: }
1146:
1147: static int raw_media_changed(BlockDriverState *bs)
1148: {
1149: return -ENOTSUP;
1150: }
1151:
1152: static int raw_eject(BlockDriverState *bs, int eject_flag)
1153: {
1154: return -ENOTSUP;
1155: }
1156:
1157: static int raw_set_locked(BlockDriverState *bs, int locked)
1158: {
1159: return -ENOTSUP;
1160: }
1161:
1162: static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1163: {
1164: return -ENOTSUP;
1165: }
1166: #endif /* !linux */
1167:
1168: BlockDriver bdrv_host_device = {
1169: "host_device",
1170: sizeof(BDRVRawState),
1171: NULL, /* no probe for protocols */
1172: hdev_open,
1173: NULL,
1174: NULL,
1175: raw_close,
1176: NULL,
1177: raw_flush,
1178:
1.1.1.2 ! root 1179: #ifdef CONFIG_AIO
1.1 root 1180: .bdrv_aio_read = raw_aio_read,
1181: .bdrv_aio_write = raw_aio_write,
1182: .bdrv_aio_cancel = raw_aio_cancel,
1183: .aiocb_size = sizeof(RawAIOCB),
1.1.1.2 ! root 1184: #endif
! 1185:
1.1 root 1186: .bdrv_pread = raw_pread,
1187: .bdrv_pwrite = raw_pwrite,
1188: .bdrv_getlength = raw_getlength,
1189:
1190: /* removable device support */
1191: .bdrv_is_inserted = raw_is_inserted,
1192: .bdrv_media_changed = raw_media_changed,
1193: .bdrv_eject = raw_eject,
1194: .bdrv_set_locked = raw_set_locked,
1195: /* generic scsi device */
1196: .bdrv_ioctl = raw_ioctl,
1197: };
unix.superglobalmegacorp.com