File:  [Qemu by Fabrice Bellard] / qemu / block-raw-posix.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:44 2018 UTC (2 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    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 "block_int.h"
   28: #include <assert.h>
   29: #ifdef CONFIG_AIO
   30: #include "posix-aio-compat.h"
   31: #endif
   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__
   56: #include <signal.h>
   57: #include <sys/disk.h>
   58: #endif
   59: 
   60: #ifdef __OpenBSD__
   61: #include <sys/ioctl.h>
   62: #include <sys/disklabel.h>
   63: #include <sys/dkio.h>
   64: #endif
   65: 
   66: //#define DEBUG_FLOPPY
   67: 
   68: //#define DEBUG_BLOCK
   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)
   72: #else
   73: #define DEBUG_BLOCK_PRINT(formatCstr, args...)
   74: #endif
   75: 
   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: 
   86: #define FTYPE_FILE   0
   87: #define FTYPE_CD     1
   88: #define FTYPE_FD     2
   89: 
   90: #define ALIGNED_BUFFER_SIZE (32 * 512)
   91: 
   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
  108:     uint8_t* aligned_buf;
  109: } BDRVRawState;
  110: 
  111: static int posix_aio_init(void);
  112: 
  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: 
  120:     posix_aio_init();
  121: 
  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;
  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))
  137:         open_flags |= O_DIRECT;
  138:     else if (!(flags & BDRV_O_CACHE_WB))
  139:         open_flags |= O_DSYNC;
  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;
  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:     }
  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, &sectorsize) &&
  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: 
  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,
  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: 
  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,
  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)
  255:         return -errno;
  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:         }
  265:         return -EIO;
  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: 
  280:     return  (ret < 0) ? -errno : ret;
  281: }
  282: 
  283: 
  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;
  294: 
  295:     sum = 0;
  296: 
  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;
  350:         }
  351:     }
  352: 
  353:     return raw_pread_aligned(bs, offset, buf, count) + sum;
  354: }
  355: 
  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)
  363: {
  364:     BDRVRawState *s = bs->opaque;
  365:     int size, ret, shift, sum;
  366: 
  367:     sum = 0;
  368: 
  369:     if (s->aligned_buf != NULL) {
  370: 
  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:         }
  430:     }
  431:     return raw_pwrite_aligned(bs, offset, buf, count) + sum;
  432: }
  433: 
  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)
  452: {
  453:     PosixAioState *s = opaque;
  454:     RawAIOCB *acb, **pacb;
  455:     int ret;
  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:     }
  469: 
  470:     for(;;) {
  471:         pacb = &s->first_aio;
  472:         for(;;) {
  473:             acb = *pacb;
  474:             if (!acb)
  475:                 goto the_end;
  476:             ret = qemu_paio_error(&acb->aiocb);
  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) {
  484:                     ret = qemu_paio_return(&acb->aiocb);
  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: 
  506: static int posix_aio_flush(void *opaque)
  507: {
  508:     PosixAioState *s = opaque;
  509:     return !!s->first_aio;
  510: }
  511: 
  512: static PosixAioState *posix_aio_state;
  513: 
  514: static void aio_signal_handler(int signum)
  515: {
  516:     if (posix_aio_state) {
  517:         char byte = 0;
  518: 
  519:         write(posix_aio_state->wfd, &byte, sizeof(byte));
  520:     }
  521: 
  522:     qemu_service_io();
  523: }
  524: 
  525: static int posix_aio_init(void)
  526: {
  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;
  534: 
  535:     s = qemu_malloc(sizeof(PosixAioState));
  536: 
  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;
  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;
  580:     acb->aiocb.ev_signo = SIGUSR2;
  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;
  587:     acb->next = posix_aio_state->first_aio;
  588:     posix_aio_state->first_aio = acb;
  589:     return acb;
  590: }
  591: 
  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: 
  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: 
  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: 
  639:     acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  640:     if (!acb)
  641:         return NULL;
  642:     if (qemu_paio_read(&acb->aiocb) < 0) {
  643:         raw_aio_remove(acb);
  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: 
  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: 
  670:     acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
  671:     if (!acb)
  672:         return NULL;
  673:     if (qemu_paio_write(&acb->aiocb) < 0) {
  674:         raw_aio_remove(acb);
  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: 
  685:     ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
  686:     if (ret == QEMU_PAIO_NOTCANCELED) {
  687:         /* fail safe: if the aio could not be canceled, we wait for
  688:            it */
  689:         while (qemu_paio_error(&acb->aiocb) == EINPROGRESS);
  690:     }
  691: 
  692:     raw_aio_remove(acb);
  693: }
  694: #else /* CONFIG_AIO */
  695: static int posix_aio_init(void)
  696: {
  697:     return 0;
  698: }
  699: #endif /* CONFIG_AIO */
  700: 
  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;
  708:         if (s->aligned_buf != NULL)
  709:             qemu_free(s->aligned_buf);
  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: 
  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__ */
  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: }
  789: #endif
  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: 
  825: #ifdef CONFIG_AIO
  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),
  830: #endif
  831: 
  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: 
  904:     posix_aio_init();
  905: 
  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:     }
  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))
  942:         open_flags |= O_DIRECT;
  943:     else if (!(flags & BDRV_O_CACHE_WB))
  944:         open_flags |= O_DSYNC;
  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: 
  980: #if defined(__linux__)
  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: 
 1137: static int fd_open(BlockDriverState *bs)
 1138: {
 1139:     return 0;
 1140: }
 1141: 
 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: 
 1179: #ifdef CONFIG_AIO
 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),
 1184: #endif
 1185: 
 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