|
|
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" ! 26: #include "qemu-char.h" ! 27: #include "qemu-log.h" ! 28: #include "block_int.h" ! 29: #include "module.h" ! 30: #ifdef CONFIG_AIO ! 31: #include "posix-aio-compat.h" ! 32: #endif ! 33: ! 34: #ifdef CONFIG_COCOA ! 35: #include <paths.h> ! 36: #include <sys/param.h> ! 37: #include <IOKit/IOKitLib.h> ! 38: #include <IOKit/IOBSD.h> ! 39: #include <IOKit/storage/IOMediaBSDClient.h> ! 40: #include <IOKit/storage/IOMedia.h> ! 41: #include <IOKit/storage/IOCDMedia.h> ! 42: //#include <IOKit/storage/IOCDTypes.h> ! 43: #include <CoreFoundation/CoreFoundation.h> ! 44: #endif ! 45: ! 46: #ifdef __sun__ ! 47: #define _POSIX_PTHREAD_SEMANTICS 1 ! 48: #include <signal.h> ! 49: #include <sys/dkio.h> ! 50: #endif ! 51: #ifdef __linux__ ! 52: #include <sys/ioctl.h> ! 53: #include <linux/cdrom.h> ! 54: #include <linux/fd.h> ! 55: #endif ! 56: #ifdef __FreeBSD__ ! 57: #include <signal.h> ! 58: #include <sys/disk.h> ! 59: #include <sys/cdio.h> ! 60: #endif ! 61: ! 62: #ifdef __OpenBSD__ ! 63: #include <sys/ioctl.h> ! 64: #include <sys/disklabel.h> ! 65: #include <sys/dkio.h> ! 66: #endif ! 67: ! 68: #ifdef __DragonFly__ ! 69: #include <sys/ioctl.h> ! 70: #include <sys/diskslice.h> ! 71: #endif ! 72: ! 73: //#define DEBUG_FLOPPY ! 74: ! 75: //#define DEBUG_BLOCK ! 76: #if defined(DEBUG_BLOCK) ! 77: #define DEBUG_BLOCK_PRINT(formatCstr, ...) do { if (qemu_log_enabled()) \ ! 78: { qemu_log(formatCstr, ## __VA_ARGS__); qemu_log_flush(); } } while (0) ! 79: #else ! 80: #define DEBUG_BLOCK_PRINT(formatCstr, ...) ! 81: #endif ! 82: ! 83: /* OS X does not have O_DSYNC */ ! 84: #ifndef O_DSYNC ! 85: #ifdef O_SYNC ! 86: #define O_DSYNC O_SYNC ! 87: #elif defined(O_FSYNC) ! 88: #define O_DSYNC O_FSYNC ! 89: #endif ! 90: #endif ! 91: ! 92: /* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */ ! 93: #ifndef O_DIRECT ! 94: #define O_DIRECT O_DSYNC ! 95: #endif ! 96: ! 97: #define FTYPE_FILE 0 ! 98: #define FTYPE_CD 1 ! 99: #define FTYPE_FD 2 ! 100: ! 101: #define ALIGNED_BUFFER_SIZE (32 * 512) ! 102: ! 103: /* if the FD is not accessed during that time (in ms), we try to ! 104: reopen it to see if the disk has been changed */ ! 105: #define FD_OPEN_TIMEOUT 1000 ! 106: ! 107: typedef struct BDRVRawState { ! 108: int fd; ! 109: int type; ! 110: unsigned int lseek_err_cnt; ! 111: int open_flags; ! 112: #if defined(__linux__) ! 113: /* linux floppy specific */ ! 114: int64_t fd_open_time; ! 115: int64_t fd_error_time; ! 116: int fd_got_error; ! 117: int fd_media_changed; ! 118: #endif ! 119: uint8_t* aligned_buf; ! 120: } BDRVRawState; ! 121: ! 122: static int posix_aio_init(void); ! 123: ! 124: static int fd_open(BlockDriverState *bs); ! 125: static int64_t raw_getlength(BlockDriverState *bs); ! 126: ! 127: #if defined(__FreeBSD__) ! 128: static int cdrom_reopen(BlockDriverState *bs); ! 129: #endif ! 130: ! 131: static int raw_open_common(BlockDriverState *bs, const char *filename, ! 132: int bdrv_flags, int open_flags) ! 133: { ! 134: BDRVRawState *s = bs->opaque; ! 135: int fd, ret; ! 136: ! 137: posix_aio_init(); ! 138: ! 139: s->lseek_err_cnt = 0; ! 140: ! 141: s->open_flags = open_flags | O_BINARY; ! 142: s->open_flags &= ~O_ACCMODE; ! 143: if ((bdrv_flags & BDRV_O_ACCESS) == BDRV_O_RDWR) { ! 144: s->open_flags |= O_RDWR; ! 145: } else { ! 146: s->open_flags |= O_RDONLY; ! 147: bs->read_only = 1; ! 148: } ! 149: ! 150: /* Use O_DSYNC for write-through caching, no flags for write-back caching, ! 151: * and O_DIRECT for no caching. */ ! 152: if ((bdrv_flags & BDRV_O_NOCACHE)) ! 153: s->open_flags |= O_DIRECT; ! 154: else if (!(bdrv_flags & BDRV_O_CACHE_WB)) ! 155: s->open_flags |= O_DSYNC; ! 156: ! 157: s->fd = -1; ! 158: fd = open(filename, s->open_flags, 0644); ! 159: if (fd < 0) { ! 160: ret = -errno; ! 161: if (ret == -EROFS) ! 162: ret = -EACCES; ! 163: return ret; ! 164: } ! 165: s->fd = fd; ! 166: s->aligned_buf = NULL; ! 167: if ((bdrv_flags & BDRV_O_NOCACHE)) { ! 168: s->aligned_buf = qemu_blockalign(bs, ALIGNED_BUFFER_SIZE); ! 169: if (s->aligned_buf == NULL) { ! 170: ret = -errno; ! 171: close(fd); ! 172: return ret; ! 173: } ! 174: } ! 175: return 0; ! 176: } ! 177: ! 178: static int raw_open(BlockDriverState *bs, const char *filename, int flags) ! 179: { ! 180: BDRVRawState *s = bs->opaque; ! 181: int open_flags = 0; ! 182: ! 183: s->type = FTYPE_FILE; ! 184: if (flags & BDRV_O_CREAT) ! 185: open_flags = O_CREAT | O_TRUNC; ! 186: ! 187: return raw_open_common(bs, filename, flags, open_flags); ! 188: } ! 189: ! 190: /* XXX: use host sector size if necessary with: ! 191: #ifdef DIOCGSECTORSIZE ! 192: { ! 193: unsigned int sectorsize = 512; ! 194: if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) && ! 195: sectorsize > bufsize) ! 196: bufsize = sectorsize; ! 197: } ! 198: #endif ! 199: #ifdef CONFIG_COCOA ! 200: u_int32_t blockSize = 512; ! 201: if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) { ! 202: bufsize = blockSize; ! 203: } ! 204: #endif ! 205: */ ! 206: ! 207: /* ! 208: * offset and count are in bytes, but must be multiples of 512 for files ! 209: * opened with O_DIRECT. buf must be aligned to 512 bytes then. ! 210: * ! 211: * This function may be called without alignment if the caller ensures ! 212: * that O_DIRECT is not in effect. ! 213: */ ! 214: static int raw_pread_aligned(BlockDriverState *bs, int64_t offset, ! 215: uint8_t *buf, int count) ! 216: { ! 217: BDRVRawState *s = bs->opaque; ! 218: int ret; ! 219: ! 220: ret = fd_open(bs); ! 221: if (ret < 0) ! 222: return ret; ! 223: ! 224: if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) { ! 225: ++(s->lseek_err_cnt); ! 226: if(s->lseek_err_cnt <= 10) { ! 227: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 ! 228: "] lseek failed : %d = %s\n", ! 229: s->fd, bs->filename, offset, buf, count, ! 230: bs->total_sectors, errno, strerror(errno)); ! 231: } ! 232: return -1; ! 233: } ! 234: s->lseek_err_cnt=0; ! 235: ! 236: ret = read(s->fd, buf, count); ! 237: if (ret == count) ! 238: goto label__raw_read__success; ! 239: ! 240: /* Allow reads beyond the end (needed for pwrite) */ ! 241: if ((ret == 0) && bs->growable) { ! 242: int64_t size = raw_getlength(bs); ! 243: if (offset >= size) { ! 244: memset(buf, 0, count); ! 245: ret = count; ! 246: goto label__raw_read__success; ! 247: } ! 248: } ! 249: ! 250: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 ! 251: "] read failed %d : %d = %s\n", ! 252: s->fd, bs->filename, offset, buf, count, ! 253: bs->total_sectors, ret, errno, strerror(errno)); ! 254: ! 255: /* Try harder for CDrom. */ ! 256: if (bs->type == BDRV_TYPE_CDROM) { ! 257: lseek(s->fd, offset, SEEK_SET); ! 258: ret = read(s->fd, buf, count); ! 259: if (ret == count) ! 260: goto label__raw_read__success; ! 261: lseek(s->fd, offset, SEEK_SET); ! 262: ret = read(s->fd, buf, count); ! 263: if (ret == count) ! 264: goto label__raw_read__success; ! 265: ! 266: DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 ! 267: "] retry read failed %d : %d = %s\n", ! 268: s->fd, bs->filename, offset, buf, count, ! 269: bs->total_sectors, ret, errno, strerror(errno)); ! 270: } ! 271: ! 272: label__raw_read__success: ! 273: ! 274: return (ret < 0) ? -errno : ret; ! 275: } ! 276: ! 277: /* ! 278: * offset and count are in bytes, but must be multiples of 512 for files ! 279: * opened with O_DIRECT. buf must be aligned to 512 bytes then. ! 280: * ! 281: * This function may be called without alignment if the caller ensures ! 282: * that O_DIRECT is not in effect. ! 283: */ ! 284: static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset, ! 285: const uint8_t *buf, int count) ! 286: { ! 287: BDRVRawState *s = bs->opaque; ! 288: int ret; ! 289: ! 290: ret = fd_open(bs); ! 291: if (ret < 0) ! 292: return -errno; ! 293: ! 294: if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) { ! 295: ++(s->lseek_err_cnt); ! 296: if(s->lseek_err_cnt) { ! 297: DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" ! 298: PRId64 "] lseek failed : %d = %s\n", ! 299: s->fd, bs->filename, offset, buf, count, ! 300: bs->total_sectors, errno, strerror(errno)); ! 301: } ! 302: return -EIO; ! 303: } ! 304: s->lseek_err_cnt = 0; ! 305: ! 306: ret = write(s->fd, buf, count); ! 307: if (ret == count) ! 308: goto label__raw_write__success; ! 309: ! 310: DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 ! 311: "] write failed %d : %d = %s\n", ! 312: s->fd, bs->filename, offset, buf, count, ! 313: bs->total_sectors, ret, errno, strerror(errno)); ! 314: ! 315: label__raw_write__success: ! 316: ! 317: return (ret < 0) ? -errno : ret; ! 318: } ! 319: ! 320: ! 321: /* ! 322: * offset and count are in bytes and possibly not aligned. For files opened ! 323: * with O_DIRECT, necessary alignments are ensured before calling ! 324: * raw_pread_aligned to do the actual read. ! 325: */ ! 326: static int raw_pread(BlockDriverState *bs, int64_t offset, ! 327: uint8_t *buf, int count) ! 328: { ! 329: BDRVRawState *s = bs->opaque; ! 330: int size, ret, shift, sum; ! 331: ! 332: sum = 0; ! 333: ! 334: if (s->aligned_buf != NULL) { ! 335: ! 336: if (offset & 0x1ff) { ! 337: /* align offset on a 512 bytes boundary */ ! 338: ! 339: shift = offset & 0x1ff; ! 340: size = (shift + count + 0x1ff) & ~0x1ff; ! 341: if (size > ALIGNED_BUFFER_SIZE) ! 342: size = ALIGNED_BUFFER_SIZE; ! 343: ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size); ! 344: if (ret < 0) ! 345: return ret; ! 346: ! 347: size = 512 - shift; ! 348: if (size > count) ! 349: size = count; ! 350: memcpy(buf, s->aligned_buf + shift, size); ! 351: ! 352: buf += size; ! 353: offset += size; ! 354: count -= size; ! 355: sum += size; ! 356: ! 357: if (count == 0) ! 358: return sum; ! 359: } ! 360: if (count & 0x1ff || (uintptr_t) buf & 0x1ff) { ! 361: ! 362: /* read on aligned buffer */ ! 363: ! 364: while (count) { ! 365: ! 366: size = (count + 0x1ff) & ~0x1ff; ! 367: if (size > ALIGNED_BUFFER_SIZE) ! 368: size = ALIGNED_BUFFER_SIZE; ! 369: ! 370: ret = raw_pread_aligned(bs, offset, s->aligned_buf, size); ! 371: if (ret < 0) ! 372: return ret; ! 373: ! 374: size = ret; ! 375: if (size > count) ! 376: size = count; ! 377: ! 378: memcpy(buf, s->aligned_buf, size); ! 379: ! 380: buf += size; ! 381: offset += size; ! 382: count -= size; ! 383: sum += size; ! 384: } ! 385: ! 386: return sum; ! 387: } ! 388: } ! 389: ! 390: return raw_pread_aligned(bs, offset, buf, count) + sum; ! 391: } ! 392: ! 393: static int raw_read(BlockDriverState *bs, int64_t sector_num, ! 394: uint8_t *buf, int nb_sectors) ! 395: { ! 396: int ret; ! 397: ! 398: ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512); ! 399: if (ret == (nb_sectors * 512)) ! 400: ret = 0; ! 401: return ret; ! 402: } ! 403: ! 404: /* ! 405: * offset and count are in bytes and possibly not aligned. For files opened ! 406: * with O_DIRECT, necessary alignments are ensured before calling ! 407: * raw_pwrite_aligned to do the actual write. ! 408: */ ! 409: static int raw_pwrite(BlockDriverState *bs, int64_t offset, ! 410: const uint8_t *buf, int count) ! 411: { ! 412: BDRVRawState *s = bs->opaque; ! 413: int size, ret, shift, sum; ! 414: ! 415: sum = 0; ! 416: ! 417: if (s->aligned_buf != NULL) { ! 418: ! 419: if (offset & 0x1ff) { ! 420: /* align offset on a 512 bytes boundary */ ! 421: shift = offset & 0x1ff; ! 422: ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512); ! 423: if (ret < 0) ! 424: return ret; ! 425: ! 426: size = 512 - shift; ! 427: if (size > count) ! 428: size = count; ! 429: memcpy(s->aligned_buf + shift, buf, size); ! 430: ! 431: ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512); ! 432: if (ret < 0) ! 433: return ret; ! 434: ! 435: buf += size; ! 436: offset += size; ! 437: count -= size; ! 438: sum += size; ! 439: ! 440: if (count == 0) ! 441: return sum; ! 442: } ! 443: if (count & 0x1ff || (uintptr_t) buf & 0x1ff) { ! 444: ! 445: while ((size = (count & ~0x1ff)) != 0) { ! 446: ! 447: if (size > ALIGNED_BUFFER_SIZE) ! 448: size = ALIGNED_BUFFER_SIZE; ! 449: ! 450: memcpy(s->aligned_buf, buf, size); ! 451: ! 452: ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size); ! 453: if (ret < 0) ! 454: return ret; ! 455: ! 456: buf += ret; ! 457: offset += ret; ! 458: count -= ret; ! 459: sum += ret; ! 460: } ! 461: /* here, count < 512 because (count & ~0x1ff) == 0 */ ! 462: if (count) { ! 463: ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512); ! 464: if (ret < 0) ! 465: return ret; ! 466: memcpy(s->aligned_buf, buf, count); ! 467: ! 468: ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512); ! 469: if (ret < 0) ! 470: return ret; ! 471: if (count < ret) ! 472: ret = count; ! 473: ! 474: sum += ret; ! 475: } ! 476: return sum; ! 477: } ! 478: } ! 479: return raw_pwrite_aligned(bs, offset, buf, count) + sum; ! 480: } ! 481: ! 482: static int raw_write(BlockDriverState *bs, int64_t sector_num, ! 483: const uint8_t *buf, int nb_sectors) ! 484: { ! 485: int ret; ! 486: ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512); ! 487: if (ret == (nb_sectors * 512)) ! 488: ret = 0; ! 489: return ret; ! 490: } ! 491: ! 492: #ifdef CONFIG_AIO ! 493: /***********************************************************/ ! 494: /* Unix AIO using POSIX AIO */ ! 495: ! 496: typedef struct RawAIOCB { ! 497: BlockDriverAIOCB common; ! 498: struct qemu_paiocb aiocb; ! 499: struct RawAIOCB *next; ! 500: int ret; ! 501: } RawAIOCB; ! 502: ! 503: typedef struct PosixAioState ! 504: { ! 505: int rfd, wfd; ! 506: RawAIOCB *first_aio; ! 507: } PosixAioState; ! 508: ! 509: static void posix_aio_read(void *opaque) ! 510: { ! 511: PosixAioState *s = opaque; ! 512: RawAIOCB *acb, **pacb; ! 513: int ret; ! 514: ssize_t len; ! 515: ! 516: /* read all bytes from signal pipe */ ! 517: for (;;) { ! 518: char bytes[16]; ! 519: ! 520: len = read(s->rfd, bytes, sizeof(bytes)); ! 521: if (len == -1 && errno == EINTR) ! 522: continue; /* try again */ ! 523: if (len == sizeof(bytes)) ! 524: continue; /* more to read */ ! 525: break; ! 526: } ! 527: ! 528: for(;;) { ! 529: pacb = &s->first_aio; ! 530: for(;;) { ! 531: acb = *pacb; ! 532: if (!acb) ! 533: goto the_end; ! 534: ret = qemu_paio_error(&acb->aiocb); ! 535: if (ret == ECANCELED) { ! 536: /* remove the request */ ! 537: *pacb = acb->next; ! 538: qemu_aio_release(acb); ! 539: } else if (ret != EINPROGRESS) { ! 540: /* end of aio */ ! 541: if (ret == 0) { ! 542: ret = qemu_paio_return(&acb->aiocb); ! 543: if (ret == acb->aiocb.aio_nbytes) ! 544: ret = 0; ! 545: else ! 546: ret = -EINVAL; ! 547: } else { ! 548: ret = -ret; ! 549: } ! 550: /* remove the request */ ! 551: *pacb = acb->next; ! 552: /* call the callback */ ! 553: acb->common.cb(acb->common.opaque, ret); ! 554: qemu_aio_release(acb); ! 555: break; ! 556: } else { ! 557: pacb = &acb->next; ! 558: } ! 559: } ! 560: } ! 561: the_end: ; ! 562: } ! 563: ! 564: static int posix_aio_flush(void *opaque) ! 565: { ! 566: PosixAioState *s = opaque; ! 567: return !!s->first_aio; ! 568: } ! 569: ! 570: static PosixAioState *posix_aio_state; ! 571: ! 572: static void aio_signal_handler(int signum) ! 573: { ! 574: if (posix_aio_state) { ! 575: char byte = 0; ! 576: ! 577: write(posix_aio_state->wfd, &byte, sizeof(byte)); ! 578: } ! 579: ! 580: qemu_service_io(); ! 581: } ! 582: ! 583: static int posix_aio_init(void) ! 584: { ! 585: struct sigaction act; ! 586: PosixAioState *s; ! 587: int fds[2]; ! 588: struct qemu_paioinit ai; ! 589: ! 590: if (posix_aio_state) ! 591: return 0; ! 592: ! 593: s = qemu_malloc(sizeof(PosixAioState)); ! 594: ! 595: sigfillset(&act.sa_mask); ! 596: act.sa_flags = 0; /* do not restart syscalls to interrupt select() */ ! 597: act.sa_handler = aio_signal_handler; ! 598: sigaction(SIGUSR2, &act, NULL); ! 599: ! 600: s->first_aio = NULL; ! 601: if (pipe(fds) == -1) { ! 602: fprintf(stderr, "failed to create pipe\n"); ! 603: return -errno; ! 604: } ! 605: ! 606: s->rfd = fds[0]; ! 607: s->wfd = fds[1]; ! 608: ! 609: fcntl(s->rfd, F_SETFL, O_NONBLOCK); ! 610: fcntl(s->wfd, F_SETFL, O_NONBLOCK); ! 611: ! 612: qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s); ! 613: ! 614: memset(&ai, 0, sizeof(ai)); ! 615: ai.aio_threads = 64; ! 616: ai.aio_num = 64; ! 617: qemu_paio_init(&ai); ! 618: ! 619: posix_aio_state = s; ! 620: ! 621: return 0; ! 622: } ! 623: ! 624: static void raw_aio_remove(RawAIOCB *acb) ! 625: { ! 626: RawAIOCB **pacb; ! 627: ! 628: /* remove the callback from the queue */ ! 629: pacb = &posix_aio_state->first_aio; ! 630: for(;;) { ! 631: if (*pacb == NULL) { ! 632: fprintf(stderr, "raw_aio_remove: aio request not found!\n"); ! 633: break; ! 634: } else if (*pacb == acb) { ! 635: *pacb = acb->next; ! 636: qemu_aio_release(acb); ! 637: break; ! 638: } ! 639: pacb = &(*pacb)->next; ! 640: } ! 641: } ! 642: ! 643: static void raw_aio_cancel(BlockDriverAIOCB *blockacb) ! 644: { ! 645: int ret; ! 646: RawAIOCB *acb = (RawAIOCB *)blockacb; ! 647: ! 648: ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb); ! 649: if (ret == QEMU_PAIO_NOTCANCELED) { ! 650: /* fail safe: if the aio could not be canceled, we wait for ! 651: it */ ! 652: while (qemu_paio_error(&acb->aiocb) == EINPROGRESS); ! 653: } ! 654: ! 655: raw_aio_remove(acb); ! 656: } ! 657: ! 658: static AIOPool raw_aio_pool = { ! 659: .aiocb_size = sizeof(RawAIOCB), ! 660: .cancel = raw_aio_cancel, ! 661: }; ! 662: ! 663: static RawAIOCB *raw_aio_setup(BlockDriverState *bs, int64_t sector_num, ! 664: QEMUIOVector *qiov, int nb_sectors, ! 665: BlockDriverCompletionFunc *cb, void *opaque) ! 666: { ! 667: BDRVRawState *s = bs->opaque; ! 668: RawAIOCB *acb; ! 669: ! 670: if (fd_open(bs) < 0) ! 671: return NULL; ! 672: ! 673: acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque); ! 674: if (!acb) ! 675: return NULL; ! 676: acb->aiocb.aio_fildes = s->fd; ! 677: acb->aiocb.ev_signo = SIGUSR2; ! 678: acb->aiocb.aio_iov = qiov->iov; ! 679: acb->aiocb.aio_niov = qiov->niov; ! 680: acb->aiocb.aio_nbytes = nb_sectors * 512; ! 681: acb->aiocb.aio_offset = sector_num * 512; ! 682: acb->aiocb.aio_flags = 0; ! 683: ! 684: /* ! 685: * If O_DIRECT is used the buffer needs to be aligned on a sector ! 686: * boundary. Tell the low level code to ensure that in case it's ! 687: * not done yet. ! 688: */ ! 689: if (s->aligned_buf) ! 690: acb->aiocb.aio_flags |= QEMU_AIO_SECTOR_ALIGNED; ! 691: ! 692: acb->next = posix_aio_state->first_aio; ! 693: posix_aio_state->first_aio = acb; ! 694: return acb; ! 695: } ! 696: ! 697: static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, ! 698: int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, ! 699: BlockDriverCompletionFunc *cb, void *opaque) ! 700: { ! 701: RawAIOCB *acb; ! 702: ! 703: acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque); ! 704: if (!acb) ! 705: return NULL; ! 706: if (qemu_paio_read(&acb->aiocb) < 0) { ! 707: raw_aio_remove(acb); ! 708: return NULL; ! 709: } ! 710: return &acb->common; ! 711: } ! 712: ! 713: static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, ! 714: int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, ! 715: BlockDriverCompletionFunc *cb, void *opaque) ! 716: { ! 717: RawAIOCB *acb; ! 718: ! 719: acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque); ! 720: if (!acb) ! 721: return NULL; ! 722: if (qemu_paio_write(&acb->aiocb) < 0) { ! 723: raw_aio_remove(acb); ! 724: return NULL; ! 725: } ! 726: return &acb->common; ! 727: } ! 728: #else /* CONFIG_AIO */ ! 729: static int posix_aio_init(void) ! 730: { ! 731: return 0; ! 732: } ! 733: #endif /* CONFIG_AIO */ ! 734: ! 735: ! 736: static void raw_close(BlockDriverState *bs) ! 737: { ! 738: BDRVRawState *s = bs->opaque; ! 739: if (s->fd >= 0) { ! 740: close(s->fd); ! 741: s->fd = -1; ! 742: if (s->aligned_buf != NULL) ! 743: qemu_free(s->aligned_buf); ! 744: } ! 745: } ! 746: ! 747: static int raw_truncate(BlockDriverState *bs, int64_t offset) ! 748: { ! 749: BDRVRawState *s = bs->opaque; ! 750: if (s->type != FTYPE_FILE) ! 751: return -ENOTSUP; ! 752: if (ftruncate(s->fd, offset) < 0) ! 753: return -errno; ! 754: return 0; ! 755: } ! 756: ! 757: #ifdef __OpenBSD__ ! 758: static int64_t raw_getlength(BlockDriverState *bs) ! 759: { ! 760: BDRVRawState *s = bs->opaque; ! 761: int fd = s->fd; ! 762: struct stat st; ! 763: ! 764: if (fstat(fd, &st)) ! 765: return -1; ! 766: if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { ! 767: struct disklabel dl; ! 768: ! 769: if (ioctl(fd, DIOCGDINFO, &dl)) ! 770: return -1; ! 771: return (uint64_t)dl.d_secsize * ! 772: dl.d_partitions[DISKPART(st.st_rdev)].p_size; ! 773: } else ! 774: return st.st_size; ! 775: } ! 776: #else /* !__OpenBSD__ */ ! 777: static int64_t raw_getlength(BlockDriverState *bs) ! 778: { ! 779: BDRVRawState *s = bs->opaque; ! 780: int fd = s->fd; ! 781: int64_t size; ! 782: #ifdef HOST_BSD ! 783: struct stat sb; ! 784: #ifdef __FreeBSD__ ! 785: int reopened = 0; ! 786: #endif ! 787: #endif ! 788: #ifdef __sun__ ! 789: struct dk_minfo minfo; ! 790: int rv; ! 791: #endif ! 792: int ret; ! 793: ! 794: ret = fd_open(bs); ! 795: if (ret < 0) ! 796: return ret; ! 797: ! 798: #ifdef HOST_BSD ! 799: #ifdef __FreeBSD__ ! 800: again: ! 801: #endif ! 802: if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { ! 803: #ifdef DIOCGMEDIASIZE ! 804: if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) ! 805: #elif defined(DIOCGPART) ! 806: { ! 807: struct partinfo pi; ! 808: if (ioctl(fd, DIOCGPART, &pi) == 0) ! 809: size = pi.media_size; ! 810: else ! 811: size = 0; ! 812: } ! 813: if (size == 0) ! 814: #endif ! 815: #ifdef CONFIG_COCOA ! 816: size = LONG_LONG_MAX; ! 817: #else ! 818: size = lseek(fd, 0LL, SEEK_END); ! 819: #endif ! 820: #ifdef __FreeBSD__ ! 821: switch(s->type) { ! 822: case FTYPE_CD: ! 823: /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */ ! 824: if (size == 2048LL * (unsigned)-1) ! 825: size = 0; ! 826: /* XXX no disc? maybe we need to reopen... */ ! 827: if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) { ! 828: reopened = 1; ! 829: goto again; ! 830: } ! 831: } ! 832: #endif ! 833: } else ! 834: #endif ! 835: #ifdef __sun__ ! 836: /* ! 837: * use the DKIOCGMEDIAINFO ioctl to read the size. ! 838: */ ! 839: rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo ); ! 840: if ( rv != -1 ) { ! 841: size = minfo.dki_lbsize * minfo.dki_capacity; ! 842: } else /* there are reports that lseek on some devices ! 843: fails, but irc discussion said that contingency ! 844: on contingency was overkill */ ! 845: #endif ! 846: { ! 847: size = lseek(fd, 0, SEEK_END); ! 848: } ! 849: return size; ! 850: } ! 851: #endif ! 852: ! 853: static int raw_create(const char *filename, QEMUOptionParameter *options) ! 854: { ! 855: int fd; ! 856: int result = 0; ! 857: int64_t total_size = 0; ! 858: ! 859: /* Read out options */ ! 860: while (options && options->name) { ! 861: if (!strcmp(options->name, BLOCK_OPT_SIZE)) { ! 862: total_size = options->value.n / 512; ! 863: } ! 864: options++; ! 865: } ! 866: ! 867: fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, ! 868: 0644); ! 869: if (fd < 0) { ! 870: result = -errno; ! 871: } else { ! 872: if (ftruncate(fd, total_size * 512) != 0) { ! 873: result = -errno; ! 874: } ! 875: if (close(fd) != 0) { ! 876: result = -errno; ! 877: } ! 878: } ! 879: return result; ! 880: } ! 881: ! 882: static void raw_flush(BlockDriverState *bs) ! 883: { ! 884: BDRVRawState *s = bs->opaque; ! 885: fsync(s->fd); ! 886: } ! 887: ! 888: ! 889: static QEMUOptionParameter raw_create_options[] = { ! 890: { ! 891: .name = BLOCK_OPT_SIZE, ! 892: .type = OPT_SIZE, ! 893: .help = "Virtual disk size" ! 894: }, ! 895: { NULL } ! 896: }; ! 897: ! 898: static BlockDriver bdrv_raw = { ! 899: .format_name = "raw", ! 900: .instance_size = sizeof(BDRVRawState), ! 901: .bdrv_probe = NULL, /* no probe for protocols */ ! 902: .bdrv_open = raw_open, ! 903: .bdrv_read = raw_read, ! 904: .bdrv_write = raw_write, ! 905: .bdrv_close = raw_close, ! 906: .bdrv_create = raw_create, ! 907: .bdrv_flush = raw_flush, ! 908: ! 909: #ifdef CONFIG_AIO ! 910: .bdrv_aio_readv = raw_aio_readv, ! 911: .bdrv_aio_writev = raw_aio_writev, ! 912: #endif ! 913: ! 914: .bdrv_truncate = raw_truncate, ! 915: .bdrv_getlength = raw_getlength, ! 916: ! 917: .create_options = raw_create_options, ! 918: }; ! 919: ! 920: /***********************************************/ ! 921: /* host device */ ! 922: ! 923: #ifdef CONFIG_COCOA ! 924: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ); ! 925: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ); ! 926: ! 927: kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ) ! 928: { ! 929: kern_return_t kernResult; ! 930: mach_port_t masterPort; ! 931: CFMutableDictionaryRef classesToMatch; ! 932: ! 933: kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort ); ! 934: if ( KERN_SUCCESS != kernResult ) { ! 935: printf( "IOMasterPort returned %d\n", kernResult ); ! 936: } ! 937: ! 938: classesToMatch = IOServiceMatching( kIOCDMediaClass ); ! 939: if ( classesToMatch == NULL ) { ! 940: printf( "IOServiceMatching returned a NULL dictionary.\n" ); ! 941: } else { ! 942: CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); ! 943: } ! 944: kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator ); ! 945: if ( KERN_SUCCESS != kernResult ) ! 946: { ! 947: printf( "IOServiceGetMatchingServices returned %d\n", kernResult ); ! 948: } ! 949: ! 950: return kernResult; ! 951: } ! 952: ! 953: kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ) ! 954: { ! 955: io_object_t nextMedia; ! 956: kern_return_t kernResult = KERN_FAILURE; ! 957: *bsdPath = '\0'; ! 958: nextMedia = IOIteratorNext( mediaIterator ); ! 959: if ( nextMedia ) ! 960: { ! 961: CFTypeRef bsdPathAsCFString; ! 962: bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); ! 963: if ( bsdPathAsCFString ) { ! 964: size_t devPathLength; ! 965: strcpy( bsdPath, _PATH_DEV ); ! 966: strcat( bsdPath, "r" ); ! 967: devPathLength = strlen( bsdPath ); ! 968: if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) { ! 969: kernResult = KERN_SUCCESS; ! 970: } ! 971: CFRelease( bsdPathAsCFString ); ! 972: } ! 973: IOObjectRelease( nextMedia ); ! 974: } ! 975: ! 976: return kernResult; ! 977: } ! 978: ! 979: #endif ! 980: ! 981: static int hdev_probe_device(const char *filename) ! 982: { ! 983: struct stat st; ! 984: ! 985: /* allow a dedicated CD-ROM driver to match with a higher priority */ ! 986: if (strstart(filename, "/dev/cdrom", NULL)) ! 987: return 50; ! 988: ! 989: if (stat(filename, &st) >= 0 && ! 990: (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) { ! 991: return 100; ! 992: } ! 993: ! 994: return 0; ! 995: } ! 996: ! 997: static int hdev_open(BlockDriverState *bs, const char *filename, int flags) ! 998: { ! 999: BDRVRawState *s = bs->opaque; ! 1000: ! 1001: #ifdef CONFIG_COCOA ! 1002: if (strstart(filename, "/dev/cdrom", NULL)) { ! 1003: kern_return_t kernResult; ! 1004: io_iterator_t mediaIterator; ! 1005: char bsdPath[ MAXPATHLEN ]; ! 1006: int fd; ! 1007: ! 1008: kernResult = FindEjectableCDMedia( &mediaIterator ); ! 1009: kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) ); ! 1010: ! 1011: if ( bsdPath[ 0 ] != '\0' ) { ! 1012: strcat(bsdPath,"s0"); ! 1013: /* some CDs don't have a partition 0 */ ! 1014: fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE); ! 1015: if (fd < 0) { ! 1016: bsdPath[strlen(bsdPath)-1] = '1'; ! 1017: } else { ! 1018: close(fd); ! 1019: } ! 1020: filename = bsdPath; ! 1021: } ! 1022: ! 1023: if ( mediaIterator ) ! 1024: IOObjectRelease( mediaIterator ); ! 1025: } ! 1026: #endif ! 1027: ! 1028: s->type = FTYPE_FILE; ! 1029: #if defined(__linux__) && defined(CONFIG_AIO) ! 1030: if (strstart(filename, "/dev/sg", NULL)) { ! 1031: bs->sg = 1; ! 1032: } ! 1033: #endif ! 1034: ! 1035: return raw_open_common(bs, filename, flags, 0); ! 1036: } ! 1037: ! 1038: #if defined(__linux__) ! 1039: /* Note: we do not have a reliable method to detect if the floppy is ! 1040: present. The current method is to try to open the floppy at every ! 1041: I/O and to keep it opened during a few hundreds of ms. */ ! 1042: static int fd_open(BlockDriverState *bs) ! 1043: { ! 1044: BDRVRawState *s = bs->opaque; ! 1045: int last_media_present; ! 1046: ! 1047: if (s->type != FTYPE_FD) ! 1048: return 0; ! 1049: last_media_present = (s->fd >= 0); ! 1050: if (s->fd >= 0 && ! 1051: (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) { ! 1052: close(s->fd); ! 1053: s->fd = -1; ! 1054: #ifdef DEBUG_FLOPPY ! 1055: printf("Floppy closed\n"); ! 1056: #endif ! 1057: } ! 1058: if (s->fd < 0) { ! 1059: if (s->fd_got_error && ! 1060: (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) { ! 1061: #ifdef DEBUG_FLOPPY ! 1062: printf("No floppy (open delayed)\n"); ! 1063: #endif ! 1064: return -EIO; ! 1065: } ! 1066: s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK); ! 1067: if (s->fd < 0) { ! 1068: s->fd_error_time = qemu_get_clock(rt_clock); ! 1069: s->fd_got_error = 1; ! 1070: if (last_media_present) ! 1071: s->fd_media_changed = 1; ! 1072: #ifdef DEBUG_FLOPPY ! 1073: printf("No floppy\n"); ! 1074: #endif ! 1075: return -EIO; ! 1076: } ! 1077: #ifdef DEBUG_FLOPPY ! 1078: printf("Floppy opened\n"); ! 1079: #endif ! 1080: } ! 1081: if (!last_media_present) ! 1082: s->fd_media_changed = 1; ! 1083: s->fd_open_time = qemu_get_clock(rt_clock); ! 1084: s->fd_got_error = 0; ! 1085: return 0; ! 1086: } ! 1087: ! 1088: static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) ! 1089: { ! 1090: BDRVRawState *s = bs->opaque; ! 1091: ! 1092: return ioctl(s->fd, req, buf); ! 1093: } ! 1094: ! 1095: #ifdef CONFIG_AIO ! 1096: static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs, ! 1097: unsigned long int req, void *buf, ! 1098: BlockDriverCompletionFunc *cb, void *opaque) ! 1099: { ! 1100: BDRVRawState *s = bs->opaque; ! 1101: RawAIOCB *acb; ! 1102: ! 1103: if (fd_open(bs) < 0) ! 1104: return NULL; ! 1105: ! 1106: acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque); ! 1107: if (!acb) ! 1108: return NULL; ! 1109: acb->aiocb.aio_fildes = s->fd; ! 1110: acb->aiocb.ev_signo = SIGUSR2; ! 1111: acb->aiocb.aio_offset = 0; ! 1112: acb->aiocb.aio_flags = 0; ! 1113: ! 1114: acb->next = posix_aio_state->first_aio; ! 1115: posix_aio_state->first_aio = acb; ! 1116: ! 1117: acb->aiocb.aio_ioctl_buf = buf; ! 1118: acb->aiocb.aio_ioctl_cmd = req; ! 1119: if (qemu_paio_ioctl(&acb->aiocb) < 0) { ! 1120: raw_aio_remove(acb); ! 1121: return NULL; ! 1122: } ! 1123: ! 1124: return &acb->common; ! 1125: } ! 1126: #endif ! 1127: ! 1128: #elif defined(__FreeBSD__) ! 1129: static int fd_open(BlockDriverState *bs) ! 1130: { ! 1131: BDRVRawState *s = bs->opaque; ! 1132: ! 1133: /* this is just to ensure s->fd is sane (its called by io ops) */ ! 1134: if (s->fd >= 0) ! 1135: return 0; ! 1136: return -EIO; ! 1137: } ! 1138: #else /* !linux && !FreeBSD */ ! 1139: ! 1140: static int fd_open(BlockDriverState *bs) ! 1141: { ! 1142: return 0; ! 1143: } ! 1144: ! 1145: #endif /* !linux && !FreeBSD */ ! 1146: ! 1147: static int hdev_create(const char *filename, QEMUOptionParameter *options) ! 1148: { ! 1149: int fd; ! 1150: int ret = 0; ! 1151: struct stat stat_buf; ! 1152: int64_t total_size = 0; ! 1153: ! 1154: /* Read out options */ ! 1155: while (options && options->name) { ! 1156: if (!strcmp(options->name, "size")) { ! 1157: total_size = options->value.n / 512; ! 1158: } ! 1159: options++; ! 1160: } ! 1161: ! 1162: fd = open(filename, O_WRONLY | O_BINARY); ! 1163: if (fd < 0) ! 1164: return -EIO; ! 1165: ! 1166: if (fstat(fd, &stat_buf) < 0) ! 1167: ret = -EIO; ! 1168: else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode)) ! 1169: ret = -EIO; ! 1170: else if (lseek(fd, 0, SEEK_END) < total_size * 512) ! 1171: ret = -ENOSPC; ! 1172: ! 1173: close(fd); ! 1174: return ret; ! 1175: } ! 1176: ! 1177: static BlockDriver bdrv_host_device = { ! 1178: .format_name = "host_device", ! 1179: .instance_size = sizeof(BDRVRawState), ! 1180: .bdrv_probe_device = hdev_probe_device, ! 1181: .bdrv_open = hdev_open, ! 1182: .bdrv_close = raw_close, ! 1183: .bdrv_create = hdev_create, ! 1184: .bdrv_flush = raw_flush, ! 1185: ! 1186: #ifdef CONFIG_AIO ! 1187: .bdrv_aio_readv = raw_aio_readv, ! 1188: .bdrv_aio_writev = raw_aio_writev, ! 1189: #endif ! 1190: ! 1191: .bdrv_read = raw_read, ! 1192: .bdrv_write = raw_write, ! 1193: .bdrv_getlength = raw_getlength, ! 1194: ! 1195: /* generic scsi device */ ! 1196: #ifdef __linux__ ! 1197: .bdrv_ioctl = hdev_ioctl, ! 1198: #ifdef CONFIG_AIO ! 1199: .bdrv_aio_ioctl = hdev_aio_ioctl, ! 1200: #endif ! 1201: #endif ! 1202: }; ! 1203: ! 1204: #ifdef __linux__ ! 1205: static int floppy_open(BlockDriverState *bs, const char *filename, int flags) ! 1206: { ! 1207: BDRVRawState *s = bs->opaque; ! 1208: int ret; ! 1209: ! 1210: posix_aio_init(); ! 1211: ! 1212: s->type = FTYPE_FD; ! 1213: ! 1214: /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */ ! 1215: ret = raw_open_common(bs, filename, flags, O_NONBLOCK); ! 1216: if (ret) ! 1217: return ret; ! 1218: ! 1219: /* close fd so that we can reopen it as needed */ ! 1220: close(s->fd); ! 1221: s->fd = -1; ! 1222: s->fd_media_changed = 1; ! 1223: ! 1224: return 0; ! 1225: } ! 1226: ! 1227: static int floppy_probe_device(const char *filename) ! 1228: { ! 1229: if (strstart(filename, "/dev/fd", NULL)) ! 1230: return 100; ! 1231: return 0; ! 1232: } ! 1233: ! 1234: ! 1235: static int floppy_is_inserted(BlockDriverState *bs) ! 1236: { ! 1237: return fd_open(bs) >= 0; ! 1238: } ! 1239: ! 1240: static int floppy_media_changed(BlockDriverState *bs) ! 1241: { ! 1242: BDRVRawState *s = bs->opaque; ! 1243: int ret; ! 1244: ! 1245: /* ! 1246: * XXX: we do not have a true media changed indication. ! 1247: * It does not work if the floppy is changed without trying to read it. ! 1248: */ ! 1249: fd_open(bs); ! 1250: ret = s->fd_media_changed; ! 1251: s->fd_media_changed = 0; ! 1252: #ifdef DEBUG_FLOPPY ! 1253: printf("Floppy changed=%d\n", ret); ! 1254: #endif ! 1255: return ret; ! 1256: } ! 1257: ! 1258: static int floppy_eject(BlockDriverState *bs, int eject_flag) ! 1259: { ! 1260: BDRVRawState *s = bs->opaque; ! 1261: int fd; ! 1262: ! 1263: if (s->fd >= 0) { ! 1264: close(s->fd); ! 1265: s->fd = -1; ! 1266: } ! 1267: fd = open(bs->filename, s->open_flags | O_NONBLOCK); ! 1268: if (fd >= 0) { ! 1269: if (ioctl(fd, FDEJECT, 0) < 0) ! 1270: perror("FDEJECT"); ! 1271: close(fd); ! 1272: } ! 1273: ! 1274: return 0; ! 1275: } ! 1276: ! 1277: static BlockDriver bdrv_host_floppy = { ! 1278: .format_name = "host_floppy", ! 1279: .instance_size = sizeof(BDRVRawState), ! 1280: .bdrv_probe_device = floppy_probe_device, ! 1281: .bdrv_open = floppy_open, ! 1282: .bdrv_close = raw_close, ! 1283: .bdrv_create = hdev_create, ! 1284: .bdrv_flush = raw_flush, ! 1285: ! 1286: #ifdef CONFIG_AIO ! 1287: .bdrv_aio_readv = raw_aio_readv, ! 1288: .bdrv_aio_writev = raw_aio_writev, ! 1289: #endif ! 1290: ! 1291: .bdrv_read = raw_read, ! 1292: .bdrv_write = raw_write, ! 1293: .bdrv_getlength = raw_getlength, ! 1294: ! 1295: /* removable device support */ ! 1296: .bdrv_is_inserted = floppy_is_inserted, ! 1297: .bdrv_media_changed = floppy_media_changed, ! 1298: .bdrv_eject = floppy_eject, ! 1299: }; ! 1300: ! 1301: static int cdrom_open(BlockDriverState *bs, const char *filename, int flags) ! 1302: { ! 1303: BDRVRawState *s = bs->opaque; ! 1304: ! 1305: s->type = FTYPE_CD; ! 1306: ! 1307: /* open will not fail even if no CD is inserted, so add O_NONBLOCK */ ! 1308: return raw_open_common(bs, filename, flags, O_NONBLOCK); ! 1309: } ! 1310: ! 1311: static int cdrom_probe_device(const char *filename) ! 1312: { ! 1313: if (strstart(filename, "/dev/cd", NULL)) ! 1314: return 100; ! 1315: return 0; ! 1316: } ! 1317: ! 1318: static int cdrom_is_inserted(BlockDriverState *bs) ! 1319: { ! 1320: BDRVRawState *s = bs->opaque; ! 1321: int ret; ! 1322: ! 1323: ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); ! 1324: if (ret == CDS_DISC_OK) ! 1325: return 1; ! 1326: return 0; ! 1327: } ! 1328: ! 1329: static int cdrom_eject(BlockDriverState *bs, int eject_flag) ! 1330: { ! 1331: BDRVRawState *s = bs->opaque; ! 1332: ! 1333: if (eject_flag) { ! 1334: if (ioctl(s->fd, CDROMEJECT, NULL) < 0) ! 1335: perror("CDROMEJECT"); ! 1336: } else { ! 1337: if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0) ! 1338: perror("CDROMEJECT"); ! 1339: } ! 1340: ! 1341: return 0; ! 1342: } ! 1343: ! 1344: static int cdrom_set_locked(BlockDriverState *bs, int locked) ! 1345: { ! 1346: BDRVRawState *s = bs->opaque; ! 1347: ! 1348: if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) { ! 1349: /* ! 1350: * Note: an error can happen if the distribution automatically ! 1351: * mounts the CD-ROM ! 1352: */ ! 1353: /* perror("CDROM_LOCKDOOR"); */ ! 1354: } ! 1355: ! 1356: return 0; ! 1357: } ! 1358: ! 1359: static BlockDriver bdrv_host_cdrom = { ! 1360: .format_name = "host_cdrom", ! 1361: .instance_size = sizeof(BDRVRawState), ! 1362: .bdrv_probe_device = cdrom_probe_device, ! 1363: .bdrv_open = cdrom_open, ! 1364: .bdrv_close = raw_close, ! 1365: .bdrv_create = hdev_create, ! 1366: .bdrv_flush = raw_flush, ! 1367: ! 1368: #ifdef CONFIG_AIO ! 1369: .bdrv_aio_readv = raw_aio_readv, ! 1370: .bdrv_aio_writev = raw_aio_writev, ! 1371: #endif ! 1372: ! 1373: .bdrv_read = raw_read, ! 1374: .bdrv_write = raw_write, ! 1375: .bdrv_getlength = raw_getlength, ! 1376: ! 1377: /* removable device support */ ! 1378: .bdrv_is_inserted = cdrom_is_inserted, ! 1379: .bdrv_eject = cdrom_eject, ! 1380: .bdrv_set_locked = cdrom_set_locked, ! 1381: ! 1382: /* generic scsi device */ ! 1383: .bdrv_ioctl = hdev_ioctl, ! 1384: #ifdef CONFIG_AIO ! 1385: .bdrv_aio_ioctl = hdev_aio_ioctl, ! 1386: #endif ! 1387: }; ! 1388: #endif /* __linux__ */ ! 1389: ! 1390: #ifdef __FreeBSD__ ! 1391: static int cdrom_open(BlockDriverState *bs, const char *filename, int flags) ! 1392: { ! 1393: BDRVRawState *s = bs->opaque; ! 1394: int ret; ! 1395: ! 1396: s->type = FTYPE_CD; ! 1397: ! 1398: ret = raw_open_common(bs, filename, flags, 0); ! 1399: if (ret) ! 1400: return ret; ! 1401: ! 1402: /* make sure the door isnt locked at this time */ ! 1403: ioctl(s->fd, CDIOCALLOW); ! 1404: return 0; ! 1405: } ! 1406: ! 1407: static int cdrom_probe_device(const char *filename) ! 1408: { ! 1409: if (strstart(filename, "/dev/cd", NULL) || ! 1410: strstart(filename, "/dev/acd", NULL)) ! 1411: return 100; ! 1412: return 0; ! 1413: } ! 1414: ! 1415: static int cdrom_reopen(BlockDriverState *bs) ! 1416: { ! 1417: BDRVRawState *s = bs->opaque; ! 1418: int fd; ! 1419: ! 1420: /* ! 1421: * Force reread of possibly changed/newly loaded disc, ! 1422: * FreeBSD seems to not notice sometimes... ! 1423: */ ! 1424: if (s->fd >= 0) ! 1425: close(s->fd); ! 1426: fd = open(bs->filename, s->open_flags, 0644); ! 1427: if (fd < 0) { ! 1428: s->fd = -1; ! 1429: return -EIO; ! 1430: } ! 1431: s->fd = fd; ! 1432: ! 1433: /* make sure the door isnt locked at this time */ ! 1434: ioctl(s->fd, CDIOCALLOW); ! 1435: return 0; ! 1436: } ! 1437: ! 1438: static int cdrom_is_inserted(BlockDriverState *bs) ! 1439: { ! 1440: return raw_getlength(bs) > 0; ! 1441: } ! 1442: ! 1443: static int cdrom_eject(BlockDriverState *bs, int eject_flag) ! 1444: { ! 1445: BDRVRawState *s = bs->opaque; ! 1446: ! 1447: if (s->fd < 0) ! 1448: return -ENOTSUP; ! 1449: ! 1450: (void) ioctl(s->fd, CDIOCALLOW); ! 1451: ! 1452: if (eject_flag) { ! 1453: if (ioctl(s->fd, CDIOCEJECT) < 0) ! 1454: perror("CDIOCEJECT"); ! 1455: } else { ! 1456: if (ioctl(s->fd, CDIOCCLOSE) < 0) ! 1457: perror("CDIOCCLOSE"); ! 1458: } ! 1459: ! 1460: if (cdrom_reopen(bs) < 0) ! 1461: return -ENOTSUP; ! 1462: return 0; ! 1463: } ! 1464: ! 1465: static int cdrom_set_locked(BlockDriverState *bs, int locked) ! 1466: { ! 1467: BDRVRawState *s = bs->opaque; ! 1468: ! 1469: if (s->fd < 0) ! 1470: return -ENOTSUP; ! 1471: if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) { ! 1472: /* ! 1473: * Note: an error can happen if the distribution automatically ! 1474: * mounts the CD-ROM ! 1475: */ ! 1476: /* perror("CDROM_LOCKDOOR"); */ ! 1477: } ! 1478: ! 1479: return 0; ! 1480: } ! 1481: ! 1482: static BlockDriver bdrv_host_cdrom = { ! 1483: .format_name = "host_cdrom", ! 1484: .instance_size = sizeof(BDRVRawState), ! 1485: .bdrv_probe_device = cdrom_probe_device, ! 1486: .bdrv_open = cdrom_open, ! 1487: .bdrv_close = raw_close, ! 1488: .bdrv_create = hdev_create, ! 1489: .bdrv_flush = raw_flush, ! 1490: ! 1491: #ifdef CONFIG_AIO ! 1492: .bdrv_aio_readv = raw_aio_readv, ! 1493: .bdrv_aio_writev = raw_aio_writev, ! 1494: #endif ! 1495: ! 1496: .bdrv_read = raw_read, ! 1497: .bdrv_write = raw_write, ! 1498: .bdrv_getlength = raw_getlength, ! 1499: ! 1500: /* removable device support */ ! 1501: .bdrv_is_inserted = cdrom_is_inserted, ! 1502: .bdrv_eject = cdrom_eject, ! 1503: .bdrv_set_locked = cdrom_set_locked, ! 1504: }; ! 1505: #endif /* __FreeBSD__ */ ! 1506: ! 1507: static void bdrv_raw_init(void) ! 1508: { ! 1509: /* ! 1510: * Register all the drivers. Note that order is important, the driver ! 1511: * registered last will get probed first. ! 1512: */ ! 1513: bdrv_register(&bdrv_raw); ! 1514: bdrv_register(&bdrv_host_device); ! 1515: #ifdef __linux__ ! 1516: bdrv_register(&bdrv_host_floppy); ! 1517: bdrv_register(&bdrv_host_cdrom); ! 1518: #endif ! 1519: #ifdef __FreeBSD__ ! 1520: bdrv_register(&bdrv_host_cdrom); ! 1521: #endif ! 1522: } ! 1523: ! 1524: block_init(bdrv_raw_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.