Diff for /qemu/block-raw-posix.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2018/04/24 16:47:26 version 1.1.1.2, 2018/04/24 16:50:44
Line 22 Line 22
  * THE SOFTWARE.   * THE SOFTWARE.
  */   */
 #include "qemu-common.h"  #include "qemu-common.h"
 #ifndef QEMU_IMG  
 #include "qemu-timer.h"  #include "qemu-timer.h"
 #include "exec-all.h"  #include "qemu-char.h"
 #endif  
 #include "block_int.h"  #include "block_int.h"
 #include <assert.h>  #include <assert.h>
 #include <aio.h>  #ifdef CONFIG_AIO
   #include "posix-aio-compat.h"
   #endif
   
 #ifdef CONFIG_COCOA  #ifdef CONFIG_COCOA
 #include <paths.h>  #include <paths.h>
Line 53 Line 53
 #include <linux/fd.h>  #include <linux/fd.h>
 #endif  #endif
 #ifdef __FreeBSD__  #ifdef __FreeBSD__
   #include <signal.h>
 #include <sys/disk.h>  #include <sys/disk.h>
 #endif  #endif
   
   #ifdef __OpenBSD__
   #include <sys/ioctl.h>
   #include <sys/disklabel.h>
   #include <sys/dkio.h>
   #endif
   
 //#define DEBUG_FLOPPY  //#define DEBUG_FLOPPY
   
 //#define DEBUG_BLOCK  //#define DEBUG_BLOCK
 #if defined(DEBUG_BLOCK) && !defined(QEMU_IMG)  #if defined(DEBUG_BLOCK)
 #define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)  \  #define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (qemu_log_enabled())     \
     { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)      { qemu_log(formatCstr, ##args); qemu_log_flush(); } } while (0)
 #else  #else
 #define DEBUG_BLOCK_PRINT(formatCstr, args...)  #define DEBUG_BLOCK_PRINT(formatCstr, args...)
 #endif  #endif
   
   /* OS X does not have O_DSYNC */
   #ifndef O_DSYNC
   #define O_DSYNC O_SYNC
   #endif
   
   /* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
   #ifndef O_DIRECT
   #define O_DIRECT O_DSYNC
   #endif
   
 #define FTYPE_FILE   0  #define FTYPE_FILE   0
 #define FTYPE_CD     1  #define FTYPE_CD     1
 #define FTYPE_FD     2  #define FTYPE_FD     2
   
   #define ALIGNED_BUFFER_SIZE (32 * 512)
   
 /* if the FD is not accessed during that time (in ms), we try to  /* if the FD is not accessed during that time (in ms), we try to
    reopen it to see if the disk has been changed */     reopen it to see if the disk has been changed */
 #define FD_OPEN_TIMEOUT 1000  #define FD_OPEN_TIMEOUT 1000
Line 86  typedef struct BDRVRawState { Line 105  typedef struct BDRVRawState {
     int fd_got_error;      int fd_got_error;
     int fd_media_changed;      int fd_media_changed;
 #endif  #endif
       uint8_t* aligned_buf;
 } BDRVRawState;  } BDRVRawState;
   
   static int posix_aio_init(void);
   
 static int fd_open(BlockDriverState *bs);  static int fd_open(BlockDriverState *bs);
   
 static int raw_open(BlockDriverState *bs, const char *filename, int flags)  static int raw_open(BlockDriverState *bs, const char *filename, int flags)
Line 95  static int raw_open(BlockDriverState *bs Line 117  static int raw_open(BlockDriverState *bs
     BDRVRawState *s = bs->opaque;      BDRVRawState *s = bs->opaque;
     int fd, open_flags, ret;      int fd, open_flags, ret;
   
       posix_aio_init();
   
     s->lseek_err_cnt = 0;      s->lseek_err_cnt = 0;
   
     open_flags = O_BINARY;      open_flags = O_BINARY;
Line 106  static int raw_open(BlockDriverState *bs Line 130  static int raw_open(BlockDriverState *bs
     }      }
     if (flags & BDRV_O_CREAT)      if (flags & BDRV_O_CREAT)
         open_flags |= O_CREAT | O_TRUNC;          open_flags |= O_CREAT | O_TRUNC;
 #ifdef O_DIRECT  
     if (flags & BDRV_O_DIRECT)      /* Use O_DSYNC for write-through caching, no flags for write-back caching,
        * and O_DIRECT for no caching. */
       if ((flags & BDRV_O_NOCACHE))
         open_flags |= O_DIRECT;          open_flags |= O_DIRECT;
 #endif      else if (!(flags & BDRV_O_CACHE_WB))
           open_flags |= O_DSYNC;
   
     s->type = FTYPE_FILE;      s->type = FTYPE_FILE;
   
Line 121  static int raw_open(BlockDriverState *bs Line 148  static int raw_open(BlockDriverState *bs
         return ret;          return ret;
     }      }
     s->fd = fd;      s->fd = fd;
       s->aligned_buf = NULL;
       if ((flags & BDRV_O_NOCACHE)) {
           s->aligned_buf = qemu_memalign(512, ALIGNED_BUFFER_SIZE);
           if (s->aligned_buf == NULL) {
               ret = -errno;
               close(fd);
               return ret;
           }
       }
     return 0;      return 0;
 }  }
   
Line 141  static int raw_open(BlockDriverState *bs Line 177  static int raw_open(BlockDriverState *bs
 #endif  #endif
 */  */
   
 static int raw_pread(BlockDriverState *bs, int64_t offset,  /*
    * offset and count are in bytes, but must be multiples of 512 for files
    * opened with O_DIRECT. buf must be aligned to 512 bytes then.
    *
    * This function may be called without alignment if the caller ensures
    * that O_DIRECT is not in effect.
    */
   static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
                      uint8_t *buf, int count)                       uint8_t *buf, int count)
 {  {
     BDRVRawState *s = bs->opaque;      BDRVRawState *s = bs->opaque;
Line 194  label__raw_read__success: Line 237  label__raw_read__success:
     return ret;      return ret;
 }  }
   
 static int raw_pwrite(BlockDriverState *bs, int64_t offset,  /*
    * offset and count are in bytes, but must be multiples of 512 for files
    * opened with O_DIRECT. buf must be aligned to 512 bytes then.
    *
    * This function may be called without alignment if the caller ensures
    * that O_DIRECT is not in effect.
    */
   static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
                       const uint8_t *buf, int count)                        const uint8_t *buf, int count)
 {  {
     BDRVRawState *s = bs->opaque;      BDRVRawState *s = bs->opaque;
Line 202  static int raw_pwrite(BlockDriverState * Line 252  static int raw_pwrite(BlockDriverState *
   
     ret = fd_open(bs);      ret = fd_open(bs);
     if (ret < 0)      if (ret < 0)
         return ret;          return -errno;
   
     if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {      if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
         ++(s->lseek_err_cnt);          ++(s->lseek_err_cnt);
Line 212  static int raw_pwrite(BlockDriverState * Line 262  static int raw_pwrite(BlockDriverState *
                               s->fd, bs->filename, offset, buf, count,                                s->fd, bs->filename, offset, buf, count,
                               bs->total_sectors, errno, strerror(errno));                                bs->total_sectors, errno, strerror(errno));
         }          }
         return -1;          return -EIO;
     }      }
     s->lseek_err_cnt = 0;      s->lseek_err_cnt = 0;
   
Line 227  static int raw_pwrite(BlockDriverState * Line 277  static int raw_pwrite(BlockDriverState *
   
 label__raw_write__success:  label__raw_write__success:
   
     return ret;      return  (ret < 0) ? -errno : ret;
 }  }
   
 /***********************************************************/  
 /* Unix AIO using POSIX AIO */  
   
 typedef struct RawAIOCB {  /*
     BlockDriverAIOCB common;   * offset and count are in bytes and possibly not aligned. For files opened
     struct aiocb aiocb;   * with O_DIRECT, necessary alignments are ensured before calling
     struct RawAIOCB *next;   * raw_pread_aligned to do the actual read.
 } RawAIOCB;   */
   static int raw_pread(BlockDriverState *bs, int64_t offset,
                        uint8_t *buf, int count)
   {
       BDRVRawState *s = bs->opaque;
       int size, ret, shift, sum;
   
 static int aio_sig_num = SIGUSR2;      sum = 0;
 static RawAIOCB *first_aio; /* AIO issued */  
 static int aio_initialized = 0;  
   
 static void aio_signal_handler(int signum)      if (s->aligned_buf != NULL)  {
 {  
 #ifndef QEMU_IMG          if (offset & 0x1ff) {
     CPUState *env = cpu_single_env;              /* align offset on a 512 bytes boundary */
     if (env) {  
         /* stop the currently executing cpu because a timer occured */              shift = offset & 0x1ff;
         cpu_interrupt(env, CPU_INTERRUPT_EXIT);              size = (shift + count + 0x1ff) & ~0x1ff;
 #ifdef USE_KQEMU              if (size > ALIGNED_BUFFER_SIZE)
         if (env->kqemu_enabled) {                  size = ALIGNED_BUFFER_SIZE;
             kqemu_cpu_interrupt(env);              ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
               if (ret < 0)
                   return ret;
   
               size = 512 - shift;
               if (size > count)
                   size = count;
               memcpy(buf, s->aligned_buf + shift, size);
   
               buf += size;
               offset += size;
               count -= size;
               sum += size;
   
               if (count == 0)
                   return sum;
           }
           if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
   
               /* read on aligned buffer */
   
               while (count) {
   
                   size = (count + 0x1ff) & ~0x1ff;
                   if (size > ALIGNED_BUFFER_SIZE)
                       size = ALIGNED_BUFFER_SIZE;
   
                   ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
                   if (ret < 0)
                       return ret;
   
                   size = ret;
                   if (size > count)
                       size = count;
   
                   memcpy(buf, s->aligned_buf, size);
   
                   buf += size;
                   offset += size;
                   count -= size;
                   sum += size;
               }
   
               return sum;
         }          }
 #endif  
     }      }
 #endif  
       return raw_pread_aligned(bs, offset, buf, count) + sum;
 }  }
   
 void qemu_aio_init(void)  /*
    * offset and count are in bytes and possibly not aligned. For files opened
    * with O_DIRECT, necessary alignments are ensured before calling
    * raw_pwrite_aligned to do the actual write.
    */
   static int raw_pwrite(BlockDriverState *bs, int64_t offset,
                         const uint8_t *buf, int count)
 {  {
     struct sigaction act;      BDRVRawState *s = bs->opaque;
       int size, ret, shift, sum;
   
     aio_initialized = 1;      sum = 0;
   
     sigfillset(&act.sa_mask);      if (s->aligned_buf != NULL) {
     act.sa_flags = 0; /* do not restart syscalls to interrupt select() */  
     act.sa_handler = aio_signal_handler;  
     sigaction(aio_sig_num, &act, NULL);  
   
 #if defined(__GLIBC__) && defined(__linux__)          if (offset & 0x1ff) {
     {              /* align offset on a 512 bytes boundary */
         /* XXX: aio thread exit seems to hang on RedHat 9 and this init              shift = offset & 0x1ff;
            seems to fix the problem. */              ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512);
         struct aioinit ai;              if (ret < 0)
         memset(&ai, 0, sizeof(ai));                  return ret;
         ai.aio_threads = 1;  
         ai.aio_num = 1;              size = 512 - shift;
         ai.aio_idle_time = 365 * 100000;              if (size > count)
         aio_init(&ai);                  size = count;
               memcpy(s->aligned_buf + shift, buf, size);
   
               ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512);
               if (ret < 0)
                   return ret;
   
               buf += size;
               offset += size;
               count -= size;
               sum += size;
   
               if (count == 0)
                   return sum;
           }
           if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
   
               while ((size = (count & ~0x1ff)) != 0) {
   
                   if (size > ALIGNED_BUFFER_SIZE)
                       size = ALIGNED_BUFFER_SIZE;
   
                   memcpy(s->aligned_buf, buf, size);
   
                   ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
                   if (ret < 0)
                       return ret;
   
                   buf += ret;
                   offset += ret;
                   count -= ret;
                   sum += ret;
               }
               /* here, count < 512 because (count & ~0x1ff) == 0 */
               if (count) {
                   ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512);
                   if (ret < 0)
                       return ret;
                    memcpy(s->aligned_buf, buf, count);
   
                    ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512);
                    if (ret < 0)
                        return ret;
                    if (count < ret)
                        ret = count;
   
                    sum += ret;
               }
               return sum;
           }
     }      }
 #endif      return raw_pwrite_aligned(bs, offset, buf, count) + sum;
 }  }
   
 void qemu_aio_poll(void)  #ifdef CONFIG_AIO
   /***********************************************************/
   /* Unix AIO using POSIX AIO */
   
   typedef struct RawAIOCB {
       BlockDriverAIOCB common;
       struct qemu_paiocb aiocb;
       struct RawAIOCB *next;
       int ret;
   } RawAIOCB;
   
   typedef struct PosixAioState
 {  {
       int rfd, wfd;
       RawAIOCB *first_aio;
   } PosixAioState;
   
   static void posix_aio_read(void *opaque)
   {
       PosixAioState *s = opaque;
     RawAIOCB *acb, **pacb;      RawAIOCB *acb, **pacb;
     int ret;      int ret;
       ssize_t len;
   
       /* read all bytes from signal pipe */
       for (;;) {
           char bytes[16];
   
           len = read(s->rfd, bytes, sizeof(bytes));
           if (len == -1 && errno == EINTR)
               continue; /* try again */
           if (len == sizeof(bytes))
               continue; /* more to read */
           break;
       }
   
     for(;;) {      for(;;) {
         pacb = &first_aio;          pacb = &s->first_aio;
         for(;;) {          for(;;) {
             acb = *pacb;              acb = *pacb;
             if (!acb)              if (!acb)
                 goto the_end;                  goto the_end;
             ret = aio_error(&acb->aiocb);              ret = qemu_paio_error(&acb->aiocb);
             if (ret == ECANCELED) {              if (ret == ECANCELED) {
                 /* remove the request */                  /* remove the request */
                 *pacb = acb->next;                  *pacb = acb->next;
Line 303  void qemu_aio_poll(void) Line 481  void qemu_aio_poll(void)
             } else if (ret != EINPROGRESS) {              } else if (ret != EINPROGRESS) {
                 /* end of aio */                  /* end of aio */
                 if (ret == 0) {                  if (ret == 0) {
                     ret = aio_return(&acb->aiocb);                      ret = qemu_paio_return(&acb->aiocb);
                     if (ret == acb->aiocb.aio_nbytes)                      if (ret == acb->aiocb.aio_nbytes)
                         ret = 0;                          ret = 0;
                     else                      else
Line 325  void qemu_aio_poll(void) Line 503  void qemu_aio_poll(void)
  the_end: ;   the_end: ;
 }  }
   
 /* Wait for all IO requests to complete.  */  static int posix_aio_flush(void *opaque)
 void qemu_aio_flush(void)  
 {  {
     qemu_aio_wait_start();      PosixAioState *s = opaque;
     qemu_aio_poll();      return !!s->first_aio;
     while (first_aio) {  
         qemu_aio_wait();  
     }  
     qemu_aio_wait_end();  
 }  }
   
 /* wait until at least one AIO was handled */  static PosixAioState *posix_aio_state;
 static sigset_t wait_oset;  
   
 void qemu_aio_wait_start(void)  static void aio_signal_handler(int signum)
 {  {
     sigset_t set;      if (posix_aio_state) {
           char byte = 0;
   
     if (!aio_initialized)          write(posix_aio_state->wfd, &byte, sizeof(byte));
         qemu_aio_init();      }
     sigemptyset(&set);  
     sigaddset(&set, aio_sig_num);      qemu_service_io();
     sigprocmask(SIG_BLOCK, &set, &wait_oset);  
 }  }
   
 void qemu_aio_wait(void)  static int posix_aio_init(void)
 {  {
     sigset_t set;      struct sigaction act;
     int nb_sigs;      PosixAioState *s;
       int fds[2];
       struct qemu_paioinit ai;
     
       if (posix_aio_state)
           return 0;
   
 #ifndef QEMU_IMG      s = qemu_malloc(sizeof(PosixAioState));
     if (qemu_bh_poll())  
         return;  
 #endif  
     sigemptyset(&set);  
     sigaddset(&set, aio_sig_num);  
     sigwait(&set, &nb_sigs);  
     qemu_aio_poll();  
 }  
   
 void qemu_aio_wait_end(void)      sigfillset(&act.sa_mask);
 {      act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
     sigprocmask(SIG_SETMASK, &wait_oset, NULL);      act.sa_handler = aio_signal_handler;
       sigaction(SIGUSR2, &act, NULL);
   
       s->first_aio = NULL;
       if (pipe(fds) == -1) {
           fprintf(stderr, "failed to create pipe\n");
           return -errno;
       }
   
       s->rfd = fds[0];
       s->wfd = fds[1];
   
       fcntl(s->rfd, F_SETFL, O_NONBLOCK);
       fcntl(s->wfd, F_SETFL, O_NONBLOCK);
   
       qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s);
   
       memset(&ai, 0, sizeof(ai));
       ai.aio_threads = 64;
       ai.aio_num = 64;
       qemu_paio_init(&ai);
   
       posix_aio_state = s;
   
       return 0;
 }  }
   
 static RawAIOCB *raw_aio_setup(BlockDriverState *bs,  static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
Line 384  static RawAIOCB *raw_aio_setup(BlockDriv Line 577  static RawAIOCB *raw_aio_setup(BlockDriv
     if (!acb)      if (!acb)
         return NULL;          return NULL;
     acb->aiocb.aio_fildes = s->fd;      acb->aiocb.aio_fildes = s->fd;
     acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;      acb->aiocb.ev_signo = SIGUSR2;
     acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;  
     acb->aiocb.aio_buf = buf;      acb->aiocb.aio_buf = buf;
     if (nb_sectors < 0)      if (nb_sectors < 0)
         acb->aiocb.aio_nbytes = -nb_sectors;          acb->aiocb.aio_nbytes = -nb_sectors;
     else      else
         acb->aiocb.aio_nbytes = nb_sectors * 512;          acb->aiocb.aio_nbytes = nb_sectors * 512;
     acb->aiocb.aio_offset = sector_num * 512;      acb->aiocb.aio_offset = sector_num * 512;
     acb->next = first_aio;      acb->next = posix_aio_state->first_aio;
     first_aio = acb;      posix_aio_state->first_aio = acb;
     return acb;      return acb;
 }  }
   
   static void raw_aio_em_cb(void* opaque)
   {
       RawAIOCB *acb = opaque;
       acb->common.cb(acb->common.opaque, acb->ret);
       qemu_aio_release(acb);
   }
   
   static void raw_aio_remove(RawAIOCB *acb)
   {
       RawAIOCB **pacb;
   
       /* remove the callback from the queue */
       pacb = &posix_aio_state->first_aio;
       for(;;) {
           if (*pacb == NULL) {
               fprintf(stderr, "raw_aio_remove: aio request not found!\n");
               break;
           } else if (*pacb == acb) {
               *pacb = acb->next;
               qemu_aio_release(acb);
               break;
           }
           pacb = &(*pacb)->next;
       }
   }
   
 static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,  static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
         int64_t sector_num, uint8_t *buf, int nb_sectors,          int64_t sector_num, uint8_t *buf, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque)          BlockDriverCompletionFunc *cb, void *opaque)
 {  {
     RawAIOCB *acb;      RawAIOCB *acb;
   
       /*
        * If O_DIRECT is used and the buffer is not aligned fall back
        * to synchronous IO.
        */
       BDRVRawState *s = bs->opaque;
   
       if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
           QEMUBH *bh;
           acb = qemu_aio_get(bs, cb, opaque);
           acb->ret = raw_pread(bs, 512 * sector_num, buf, 512 * nb_sectors);
           bh = qemu_bh_new(raw_aio_em_cb, acb);
           qemu_bh_schedule(bh);
           return &acb->common;
       }
   
     acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);      acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
     if (!acb)      if (!acb)
         return NULL;          return NULL;
     if (aio_read(&acb->aiocb) < 0) {      if (qemu_paio_read(&acb->aiocb) < 0) {
         qemu_aio_release(acb);          raw_aio_remove(acb);
         return NULL;          return NULL;
     }      }
     return &acb->common;      return &acb->common;
Line 419  static BlockDriverAIOCB *raw_aio_write(B Line 652  static BlockDriverAIOCB *raw_aio_write(B
 {  {
     RawAIOCB *acb;      RawAIOCB *acb;
   
       /*
        * If O_DIRECT is used and the buffer is not aligned fall back
        * to synchronous IO.
        */
       BDRVRawState *s = bs->opaque;
   
       if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
           QEMUBH *bh;
           acb = qemu_aio_get(bs, cb, opaque);
           acb->ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors);
           bh = qemu_bh_new(raw_aio_em_cb, acb);
           qemu_bh_schedule(bh);
           return &acb->common;
       }
   
     acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);      acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
     if (!acb)      if (!acb)
         return NULL;          return NULL;
     if (aio_write(&acb->aiocb) < 0) {      if (qemu_paio_write(&acb->aiocb) < 0) {
         qemu_aio_release(acb);          raw_aio_remove(acb);
         return NULL;          return NULL;
     }      }
     return &acb->common;      return &acb->common;
Line 433  static void raw_aio_cancel(BlockDriverAI Line 681  static void raw_aio_cancel(BlockDriverAI
 {  {
     int ret;      int ret;
     RawAIOCB *acb = (RawAIOCB *)blockacb;      RawAIOCB *acb = (RawAIOCB *)blockacb;
     RawAIOCB **pacb;  
   
     ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);      ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
     if (ret == AIO_NOTCANCELED) {      if (ret == QEMU_PAIO_NOTCANCELED) {
         /* fail safe: if the aio could not be canceled, we wait for          /* fail safe: if the aio could not be canceled, we wait for
            it */             it */
         while (aio_error(&acb->aiocb) == EINPROGRESS);          while (qemu_paio_error(&acb->aiocb) == EINPROGRESS);
     }      }
   
     /* remove the callback from the queue */      raw_aio_remove(acb);
     pacb = &first_aio;  }
     for(;;) {  #else /* CONFIG_AIO */
         if (*pacb == NULL) {  static int posix_aio_init(void)
             break;  {
         } else if (*pacb == acb) {      return 0;
             *pacb = acb->next;  
             qemu_aio_release(acb);  
             break;  
         }  
         pacb = &acb->next;  
     }  
 }  }
   #endif /* CONFIG_AIO */
   
   
 static void raw_close(BlockDriverState *bs)  static void raw_close(BlockDriverState *bs)
 {  {
Line 462  static void raw_close(BlockDriverState * Line 705  static void raw_close(BlockDriverState *
     if (s->fd >= 0) {      if (s->fd >= 0) {
         close(s->fd);          close(s->fd);
         s->fd = -1;          s->fd = -1;
           if (s->aligned_buf != NULL)
               qemu_free(s->aligned_buf);
     }      }
 }  }
   
Line 475  static int raw_truncate(BlockDriverState Line 720  static int raw_truncate(BlockDriverState
     return 0;      return 0;
 }  }
   
   #ifdef __OpenBSD__
   static int64_t raw_getlength(BlockDriverState *bs)
   {
       BDRVRawState *s = bs->opaque;
       int fd = s->fd;
       struct stat st;
   
       if (fstat(fd, &st))
           return -1;
       if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
           struct disklabel dl;
   
           if (ioctl(fd, DIOCGDINFO, &dl))
               return -1;
           return (uint64_t)dl.d_secsize *
               dl.d_partitions[DISKPART(st.st_rdev)].p_size;
       } else
           return st.st_size;
   }
   #else /* !__OpenBSD__ */
 static int64_t  raw_getlength(BlockDriverState *bs)  static int64_t  raw_getlength(BlockDriverState *bs)
 {  {
     BDRVRawState *s = bs->opaque;      BDRVRawState *s = bs->opaque;
Line 521  static int64_t  raw_getlength(BlockDrive Line 786  static int64_t  raw_getlength(BlockDrive
     }      }
     return size;      return size;
 }  }
   #endif
   
 static int raw_create(const char *filename, int64_t total_size,  static int raw_create(const char *filename, int64_t total_size,
                       const char *backing_file, int flags)                        const char *backing_file, int flags)
Line 556  BlockDriver bdrv_raw = { Line 822  BlockDriver bdrv_raw = {
     raw_create,      raw_create,
     raw_flush,      raw_flush,
   
   #ifdef CONFIG_AIO
     .bdrv_aio_read = raw_aio_read,      .bdrv_aio_read = raw_aio_read,
     .bdrv_aio_write = raw_aio_write,      .bdrv_aio_write = raw_aio_write,
     .bdrv_aio_cancel = raw_aio_cancel,      .bdrv_aio_cancel = raw_aio_cancel,
     .aiocb_size = sizeof(RawAIOCB),      .aiocb_size = sizeof(RawAIOCB),
     .protocol_name = "file",  #endif
   
     .bdrv_pread = raw_pread,      .bdrv_pread = raw_pread,
     .bdrv_pwrite = raw_pwrite,      .bdrv_pwrite = raw_pwrite,
     .bdrv_truncate = raw_truncate,      .bdrv_truncate = raw_truncate,
Line 633  static int hdev_open(BlockDriverState *b Line 901  static int hdev_open(BlockDriverState *b
     BDRVRawState *s = bs->opaque;      BDRVRawState *s = bs->opaque;
     int fd, open_flags, ret;      int fd, open_flags, ret;
   
       posix_aio_init();
   
 #ifdef CONFIG_COCOA  #ifdef CONFIG_COCOA
     if (strstart(filename, "/dev/cdrom", NULL)) {      if (strstart(filename, "/dev/cdrom", NULL)) {
         kern_return_t kernResult;          kern_return_t kernResult;
Line 666  static int hdev_open(BlockDriverState *b Line 936  static int hdev_open(BlockDriverState *b
         open_flags |= O_RDONLY;          open_flags |= O_RDONLY;
         bs->read_only = 1;          bs->read_only = 1;
     }      }
 #ifdef O_DIRECT      /* Use O_DSYNC for write-through caching, no flags for write-back caching,
     if (flags & BDRV_O_DIRECT)       * and O_DIRECT for no caching. */
       if ((flags & BDRV_O_NOCACHE))
         open_flags |= O_DIRECT;          open_flags |= O_DIRECT;
 #endif      else if (!(flags & BDRV_O_CACHE_WB))
           open_flags |= O_DSYNC;
   
     s->type = FTYPE_FILE;      s->type = FTYPE_FILE;
 #if defined(__linux__)  #if defined(__linux__)
Line 705  static int hdev_open(BlockDriverState *b Line 977  static int hdev_open(BlockDriverState *b
     return 0;      return 0;
 }  }
   
 #if defined(__linux__) && !defined(QEMU_IMG)  #if defined(__linux__)
   
 /* Note: we do not have a reliable method to detect if the floppy is  /* Note: we do not have a reliable method to detect if the floppy is
    present. The current method is to try to open the floppy at every     present. The current method is to try to open the floppy at every
    I/O and to keep it opened during a few hundreds of ms. */     I/O and to keep it opened during a few hundreds of ms. */
Line 755  static int fd_open(BlockDriverState *bs) Line 1026  static int fd_open(BlockDriverState *bs)
     s->fd_got_error = 0;      s->fd_got_error = 0;
     return 0;      return 0;
 }  }
 #else  
 static int fd_open(BlockDriverState *bs)  
 {  
     return 0;  
 }  
 #endif  
   
 #if defined(__linux__)  
   
 static int raw_is_inserted(BlockDriverState *bs)  static int raw_is_inserted(BlockDriverState *bs)
 {  {
Line 871  static int raw_ioctl(BlockDriverState *b Line 1134  static int raw_ioctl(BlockDriverState *b
 }  }
 #else  #else
   
   static int fd_open(BlockDriverState *bs)
   {
       return 0;
   }
   
 static int raw_is_inserted(BlockDriverState *bs)  static int raw_is_inserted(BlockDriverState *bs)
 {  {
     return 1;      return 1;
Line 908  BlockDriver bdrv_host_device = { Line 1176  BlockDriver bdrv_host_device = {
     NULL,      NULL,
     raw_flush,      raw_flush,
   
   #ifdef CONFIG_AIO
     .bdrv_aio_read = raw_aio_read,      .bdrv_aio_read = raw_aio_read,
     .bdrv_aio_write = raw_aio_write,      .bdrv_aio_write = raw_aio_write,
     .bdrv_aio_cancel = raw_aio_cancel,      .bdrv_aio_cancel = raw_aio_cancel,
     .aiocb_size = sizeof(RawAIOCB),      .aiocb_size = sizeof(RawAIOCB),
   #endif
   
     .bdrv_pread = raw_pread,      .bdrv_pread = raw_pread,
     .bdrv_pwrite = raw_pwrite,      .bdrv_pwrite = raw_pwrite,
     .bdrv_getlength = raw_getlength,      .bdrv_getlength = raw_getlength,

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


unix.superglobalmegacorp.com