ia64/xen-unstable

changeset 17397:6bf674bd386d

stubdom: add asynchronous disk flush support

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Sat Apr 05 22:20:25 2008 +0100 (2008-04-05)
parents e0f9bee70cbf
children 0551891920b2
files extras/mini-os/blkfront.c extras/mini-os/include/blkfront.h extras/mini-os/kernel.c tools/ioemu/block-vbd.c
line diff
     1.1 --- a/extras/mini-os/blkfront.c	Sat Apr 05 22:19:02 2008 +0100
     1.2 +++ b/extras/mini-os/blkfront.c	Sat Apr 05 22:20:25 2008 +0100
     1.3 @@ -48,11 +48,7 @@ struct blkfront_dev {
     1.4  
     1.5      char *nodename;
     1.6      char *backend;
     1.7 -    unsigned sector_size;
     1.8 -    unsigned sectors;
     1.9 -    int mode;
    1.10 -    int barrier;
    1.11 -    int flush;
    1.12 +    struct blkfront_info info;
    1.13  
    1.14  #ifdef HAVE_LIBC
    1.15      int fd;
    1.16 @@ -70,7 +66,7 @@ void blkfront_handler(evtchn_port_t port
    1.17      wake_up(&blkfront_queue);
    1.18  }
    1.19  
    1.20 -struct blkfront_dev *init_blkfront(char *nodename, uint64_t *sectors, unsigned *sector_size, int *mode, int *info)
    1.21 +struct blkfront_dev *init_blkfront(char *nodename, struct blkfront_info *info)
    1.22  {
    1.23      xenbus_transaction_t xbt;
    1.24      char* err;
    1.25 @@ -163,9 +159,9 @@ done:
    1.26              return NULL;
    1.27          }
    1.28          if (*c == 'w')
    1.29 -            *mode = dev->mode = O_RDWR;
    1.30 +            dev->info.mode = O_RDWR;
    1.31          else
    1.32 -            *mode = dev->mode = O_RDONLY;
    1.33 +            dev->info.mode = O_RDONLY;
    1.34          free(c);
    1.35  
    1.36          snprintf(path, sizeof(path), "%s/state", dev->backend);
    1.37 @@ -177,24 +173,26 @@ done:
    1.38          xenbus_unwatch_path(XBT_NIL, path);
    1.39  
    1.40          snprintf(path, sizeof(path), "%s/info", dev->backend);
    1.41 -        *info = xenbus_read_integer(path);
    1.42 +        dev->info.info = xenbus_read_integer(path);
    1.43  
    1.44          snprintf(path, sizeof(path), "%s/sectors", dev->backend);
    1.45          // FIXME: read_integer returns an int, so disk size limited to 1TB for now
    1.46 -        *sectors = dev->sectors = xenbus_read_integer(path);
    1.47 +        dev->info.sectors = xenbus_read_integer(path);
    1.48  
    1.49          snprintf(path, sizeof(path), "%s/sector-size", dev->backend);
    1.50 -        *sector_size = dev->sector_size = xenbus_read_integer(path);
    1.51 +        dev->info.sector_size = xenbus_read_integer(path);
    1.52  
    1.53          snprintf(path, sizeof(path), "%s/feature-barrier", dev->backend);
    1.54 -        dev->barrier = xenbus_read_integer(path);
    1.55 +        dev->info.barrier = xenbus_read_integer(path);
    1.56  
    1.57          snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend);
    1.58 -        dev->flush = xenbus_read_integer(path);
    1.59 +        dev->info.flush = xenbus_read_integer(path);
    1.60 +
    1.61 +        *info = dev->info;
    1.62      }
    1.63      unmask_evtchn(dev->evtchn);
    1.64  
    1.65 -    printk("%u sectors of %u bytes\n", dev->sectors, dev->sector_size);
    1.66 +    printk("%u sectors of %u bytes\n", dev->info.sectors, dev->info.sector_size);
    1.67      printk("**************************\n");
    1.68  
    1.69      return dev;
    1.70 @@ -258,11 +256,11 @@ void blkfront_aio(struct blkfront_aiocb 
    1.71      uintptr_t start, end;
    1.72  
    1.73      // Can't io at non-sector-aligned location
    1.74 -    ASSERT(!(aiocbp->aio_offset & (dev->sector_size-1)));
    1.75 +    ASSERT(!(aiocbp->aio_offset & (dev->info.sector_size-1)));
    1.76      // Can't io non-sector-sized amounts
    1.77 -    ASSERT(!(aiocbp->aio_nbytes & (dev->sector_size-1)));
    1.78 +    ASSERT(!(aiocbp->aio_nbytes & (dev->info.sector_size-1)));
    1.79      // Can't io non-sector-aligned buffer
    1.80 -    ASSERT(!((uintptr_t) aiocbp->aio_buf & (dev->sector_size-1)));
    1.81 +    ASSERT(!((uintptr_t) aiocbp->aio_buf & (dev->info.sector_size-1)));
    1.82  
    1.83      start = (uintptr_t)aiocbp->aio_buf & PAGE_MASK;
    1.84      end = ((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes + PAGE_SIZE - 1) & PAGE_MASK;
    1.85 @@ -280,7 +278,7 @@ void blkfront_aio(struct blkfront_aiocb 
    1.86      req->nr_segments = n;
    1.87      req->handle = dev->handle;
    1.88      req->id = (uintptr_t) aiocbp;
    1.89 -    req->sector_number = aiocbp->aio_offset / dev->sector_size;
    1.90 +    req->sector_number = aiocbp->aio_offset / dev->info.sector_size;
    1.91  
    1.92      for (j = 0; j < n; j++) {
    1.93  	uintptr_t data = start + j * PAGE_SIZE;
    1.94 @@ -292,10 +290,10 @@ void blkfront_aio(struct blkfront_aiocb 
    1.95  	aiocbp->gref[j] = req->seg[j].gref =
    1.96              gnttab_grant_access(dev->dom, virtual_to_mfn(data), write);
    1.97  	req->seg[j].first_sect = 0;
    1.98 -	req->seg[j].last_sect = PAGE_SIZE / dev->sector_size - 1;
    1.99 +	req->seg[j].last_sect = PAGE_SIZE / dev->info.sector_size - 1;
   1.100      }
   1.101 -    req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / dev->sector_size;
   1.102 -    req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / dev->sector_size;
   1.103 +    req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / dev->info.sector_size;
   1.104 +    req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / dev->info.sector_size;
   1.105  
   1.106      dev->ring.req_prod_pvt = i + 1;
   1.107  
   1.108 @@ -315,6 +313,62 @@ void blkfront_aio_read(struct blkfront_a
   1.109      blkfront_aio(aiocbp, 0);
   1.110  }
   1.111  
   1.112 +static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op, uint64_t id)
   1.113 +{
   1.114 +    int i;
   1.115 +    struct blkif_request *req;
   1.116 +    int notify;
   1.117 +
   1.118 +    blkfront_wait_slot(dev);
   1.119 +    i = dev->ring.req_prod_pvt;
   1.120 +    req = RING_GET_REQUEST(&dev->ring, i);
   1.121 +    req->operation = op;
   1.122 +    req->nr_segments = 0;
   1.123 +    req->handle = dev->handle;
   1.124 +    req->id = id;
   1.125 +    /* Not needed anyway, but the backend will check it */
   1.126 +    req->sector_number = 0;
   1.127 +    dev->ring.req_prod_pvt = i + 1;
   1.128 +    wmb();
   1.129 +    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
   1.130 +    if (notify) notify_remote_via_evtchn(dev->evtchn);
   1.131 +}
   1.132 +
   1.133 +void blkfront_aio_push_operation(struct blkfront_aiocb *aiocbp, uint8_t op)
   1.134 +{
   1.135 +    struct blkfront_dev *dev = aiocbp->aio_dev;
   1.136 +    blkfront_push_operation(dev, op, (uintptr_t) aiocbp);
   1.137 +}
   1.138 +
   1.139 +void blkfront_sync(struct blkfront_dev *dev)
   1.140 +{
   1.141 +    unsigned long flags;
   1.142 +
   1.143 +    if (dev->info.mode == O_RDWR) {
   1.144 +        if (dev->info.barrier == 1)
   1.145 +            blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER, 0);
   1.146 +
   1.147 +        if (dev->info.flush == 1)
   1.148 +            blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
   1.149 +    }
   1.150 +
   1.151 +    /* Note: This won't finish if another thread enqueues requests.  */
   1.152 +    local_irq_save(flags);
   1.153 +    DEFINE_WAIT(w);
   1.154 +    while (1) {
   1.155 +	blkfront_aio_poll(dev);
   1.156 +	if (RING_FREE_REQUESTS(&dev->ring) == RING_SIZE(&dev->ring))
   1.157 +	    break;
   1.158 +
   1.159 +	add_waiter(w, blkfront_queue);
   1.160 +	local_irq_restore(flags);
   1.161 +	schedule();
   1.162 +	local_irq_save(flags);
   1.163 +    }
   1.164 +    remove_waiter(w);
   1.165 +    local_irq_restore(flags);
   1.166 +}
   1.167 +
   1.168  int blkfront_aio_poll(struct blkfront_dev *dev)
   1.169  {
   1.170      RING_IDX rp, cons;
   1.171 @@ -337,95 +391,47 @@ moretodo:
   1.172  	rsp = RING_GET_RESPONSE(&dev->ring, cons);
   1.173  	nr_consumed++;
   1.174  
   1.175 -        if (rsp->status != BLKIF_RSP_OKAY)
   1.176 -            printk("block error %d for op %d\n", rsp->status, rsp->operation);
   1.177 +        struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id;
   1.178 +        int status = rsp->status;
   1.179 +
   1.180 +        if (status != BLKIF_RSP_OKAY)
   1.181 +            printk("block error %d for op %d\n", status, rsp->operation);
   1.182  
   1.183          switch (rsp->operation) {
   1.184          case BLKIF_OP_READ:
   1.185          case BLKIF_OP_WRITE:
   1.186          {
   1.187 -            struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id;
   1.188 -            int status = rsp->status;
   1.189              int j;
   1.190  
   1.191              for (j = 0; j < aiocbp->n; j++)
   1.192                  gnttab_end_access(aiocbp->gref[j]);
   1.193  
   1.194 -            dev->ring.rsp_cons = ++cons;
   1.195 -            /* Nota: callback frees aiocbp itself */
   1.196 -            aiocbp->aio_cb(aiocbp, status ? -EIO : 0);
   1.197 -            if (dev->ring.rsp_cons != cons)
   1.198 -                /* We reentered, we must not continue here */
   1.199 -                goto out;
   1.200              break;
   1.201          }
   1.202 -        default:
   1.203 -            printk("unrecognized block operation %d response\n", rsp->operation);
   1.204 +
   1.205          case BLKIF_OP_WRITE_BARRIER:
   1.206          case BLKIF_OP_FLUSH_DISKCACHE:
   1.207 -            dev->ring.rsp_cons = ++cons;
   1.208              break;
   1.209 +
   1.210 +        default:
   1.211 +            printk("unrecognized block operation %d response\n", rsp->operation);
   1.212          }
   1.213 +
   1.214 +        dev->ring.rsp_cons = ++cons;
   1.215 +        /* Nota: callback frees aiocbp itself */
   1.216 +        if (aiocbp && aiocbp->aio_cb)
   1.217 +            aiocbp->aio_cb(aiocbp, status ? -EIO : 0);
   1.218 +        if (dev->ring.rsp_cons != cons)
   1.219 +            /* We reentered, we must not continue here */
   1.220 +            break;
   1.221      }
   1.222  
   1.223 -out:
   1.224      RING_FINAL_CHECK_FOR_RESPONSES(&dev->ring, more);
   1.225      if (more) goto moretodo;
   1.226  
   1.227      return nr_consumed;
   1.228  }
   1.229  
   1.230 -static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op)
   1.231 -{
   1.232 -    int i;
   1.233 -    struct blkif_request *req;
   1.234 -    int notify;
   1.235 -
   1.236 -    blkfront_wait_slot(dev);
   1.237 -    i = dev->ring.req_prod_pvt;
   1.238 -    req = RING_GET_REQUEST(&dev->ring, i);
   1.239 -    req->operation = op;
   1.240 -    req->nr_segments = 0;
   1.241 -    req->handle = dev->handle;
   1.242 -    /* Not used */
   1.243 -    req->id = 0;
   1.244 -    /* Not needed anyway, but the backend will check it */
   1.245 -    req->sector_number = 0;
   1.246 -    dev->ring.req_prod_pvt = i + 1;
   1.247 -    wmb();
   1.248 -    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
   1.249 -    if (notify) notify_remote_via_evtchn(dev->evtchn);
   1.250 -}
   1.251 -
   1.252 -void blkfront_sync(struct blkfront_dev *dev)
   1.253 -{
   1.254 -    unsigned long flags;
   1.255 -
   1.256 -    if (dev->mode == O_RDWR) {
   1.257 -        if (dev->barrier == 1)
   1.258 -            blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER);
   1.259 -
   1.260 -        if (dev->flush == 1)
   1.261 -            blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE);
   1.262 -    }
   1.263 -
   1.264 -    /* Note: This won't finish if another thread enqueues requests.  */
   1.265 -    local_irq_save(flags);
   1.266 -    DEFINE_WAIT(w);
   1.267 -    while (1) {
   1.268 -	blkfront_aio_poll(dev);
   1.269 -	if (RING_FREE_REQUESTS(&dev->ring) == RING_SIZE(&dev->ring))
   1.270 -	    break;
   1.271 -
   1.272 -	add_waiter(w, blkfront_queue);
   1.273 -	local_irq_restore(flags);
   1.274 -	schedule();
   1.275 -	local_irq_save(flags);
   1.276 -    }
   1.277 -    remove_waiter(w);
   1.278 -    local_irq_restore(flags);
   1.279 -}
   1.280 -
   1.281  #ifdef HAVE_LIBC
   1.282  int blkfront_open(struct blkfront_dev *dev)
   1.283  {
     2.1 --- a/extras/mini-os/include/blkfront.h	Sat Apr 05 22:19:02 2008 +0100
     2.2 +++ b/extras/mini-os/include/blkfront.h	Sat Apr 05 22:20:25 2008 +0100
     2.3 @@ -15,13 +15,23 @@ struct blkfront_aiocb
     2.4  
     2.5      void (*aio_cb)(struct blkfront_aiocb *aiocb, int ret);
     2.6  };
     2.7 -struct blkfront_dev *init_blkfront(char *nodename, uint64_t *sectors, unsigned *sector_size, int *mode, int *info);
     2.8 +struct blkfront_info
     2.9 +{
    2.10 +    uint64_t sectors;
    2.11 +    unsigned sector_size;
    2.12 +    int mode;
    2.13 +    int info;
    2.14 +    int barrier;
    2.15 +    int flush;
    2.16 +};
    2.17 +struct blkfront_dev *init_blkfront(char *nodename, struct blkfront_info *info);
    2.18  #ifdef HAVE_LIBC
    2.19  int blkfront_open(struct blkfront_dev *dev);
    2.20  #endif
    2.21  void blkfront_aio(struct blkfront_aiocb *aiocbp, int write);
    2.22  void blkfront_aio_read(struct blkfront_aiocb *aiocbp);
    2.23  void blkfront_aio_write(struct blkfront_aiocb *aiocbp);
    2.24 +void blkfront_aio_push_operation(struct blkfront_aiocb *aiocbp, uint8_t op);
    2.25  int blkfront_aio_poll(struct blkfront_dev *dev);
    2.26  void blkfront_sync(struct blkfront_dev *dev);
    2.27  void shutdown_blkfront(struct blkfront_dev *dev);
     3.1 --- a/extras/mini-os/kernel.c	Sat Apr 05 22:19:02 2008 +0100
     3.2 +++ b/extras/mini-os/kernel.c	Sat Apr 05 22:20:25 2008 +0100
     3.3 @@ -91,9 +91,7 @@ static void netfront_thread(void *p)
     3.4  }
     3.5  
     3.6  static struct blkfront_dev *blk_dev;
     3.7 -static uint64_t blk_sectors;
     3.8 -static unsigned blk_sector_size;
     3.9 -static int blk_mode;
    3.10 +static struct blkfront_info blk_info;
    3.11  static uint64_t blk_size_read;
    3.12  static uint64_t blk_size_write;
    3.13  
    3.14 @@ -111,9 +109,9 @@ static struct blk_req *blk_alloc_req(uin
    3.15  {
    3.16      struct blk_req *req = xmalloc(struct blk_req);
    3.17      req->aiocb.aio_dev = blk_dev;
    3.18 -    req->aiocb.aio_buf = _xmalloc(blk_sector_size, blk_sector_size);
    3.19 -    req->aiocb.aio_nbytes = blk_sector_size;
    3.20 -    req->aiocb.aio_offset = sector * blk_sector_size;
    3.21 +    req->aiocb.aio_buf = _xmalloc(blk_info.sector_size, blk_info.sector_size);
    3.22 +    req->aiocb.aio_nbytes = blk_info.sector_size;
    3.23 +    req->aiocb.aio_offset = sector * blk_info.sector_size;
    3.24      req->aiocb.data = req;
    3.25      req->next = NULL;
    3.26      return req;
    3.27 @@ -125,7 +123,7 @@ static void blk_read_completed(struct bl
    3.28      if (ret)
    3.29          printk("got error code %d when reading at offset %ld\n", ret, aiocb->aio_offset);
    3.30      else
    3.31 -        blk_size_read += blk_sector_size;
    3.32 +        blk_size_read += blk_info.sector_size;
    3.33      free(aiocb->aio_buf);
    3.34      free(req);
    3.35  }
    3.36 @@ -154,10 +152,10 @@ static void blk_write_read_completed(str
    3.37          free(req);
    3.38          return;
    3.39      }
    3.40 -    blk_size_read += blk_sector_size;
    3.41 +    blk_size_read += blk_info.sector_size;
    3.42      buf = (int*) aiocb->aio_buf;
    3.43      rand_value = req->rand_value;
    3.44 -    for (i = 0; i < blk_sector_size / sizeof(int); i++) {
    3.45 +    for (i = 0; i < blk_info.sector_size / sizeof(int); i++) {
    3.46          if (buf[i] != rand_value) {
    3.47              printk("bogus data at offset %ld\n", aiocb->aio_offset + i);
    3.48              break;
    3.49 @@ -177,7 +175,7 @@ static void blk_write_completed(struct b
    3.50          free(req);
    3.51          return;
    3.52      }
    3.53 -    blk_size_write += blk_sector_size;
    3.54 +    blk_size_write += blk_info.sector_size;
    3.55      /* Push write check */
    3.56      req->next = blk_to_read;
    3.57      blk_to_read = req;
    3.58 @@ -195,7 +193,7 @@ static void blk_write_sector(uint64_t se
    3.59      req->rand_value = rand_value = rand();
    3.60  
    3.61      buf = (int*) req->aiocb.aio_buf;
    3.62 -    for (i = 0; i < blk_sector_size / sizeof(int); i++) {
    3.63 +    for (i = 0; i < blk_info.sector_size / sizeof(int); i++) {
    3.64          buf[i] = rand_value;
    3.65          rand_value *= RAND_MIX;
    3.66      }
    3.67 @@ -207,35 +205,34 @@ static void blk_write_sector(uint64_t se
    3.68  static void blkfront_thread(void *p)
    3.69  {
    3.70      time_t lasttime = 0;
    3.71 -    int blk_info;
    3.72  
    3.73 -    blk_dev = init_blkfront(NULL, &blk_sectors, &blk_sector_size, &blk_mode, &blk_info);
    3.74 +    blk_dev = init_blkfront(NULL, &blk_info);
    3.75      if (!blk_dev)
    3.76          return;
    3.77  
    3.78 -    if (blk_info & VDISK_CDROM)
    3.79 +    if (blk_info.info & VDISK_CDROM)
    3.80          printk("Block device is a CDROM\n");
    3.81 -    if (blk_info & VDISK_REMOVABLE)
    3.82 +    if (blk_info.info & VDISK_REMOVABLE)
    3.83          printk("Block device is removable\n");
    3.84 -    if (blk_info & VDISK_READONLY)
    3.85 +    if (blk_info.info & VDISK_READONLY)
    3.86          printk("Block device is read-only\n");
    3.87  
    3.88  #ifdef BLKTEST_WRITE
    3.89 -    if (blk_mode == O_RDWR) {
    3.90 +    if (blk_info.mode == O_RDWR) {
    3.91          blk_write_sector(0);
    3.92 -        blk_write_sector(blk_sectors-1);
    3.93 +        blk_write_sector(blk_info.sectors-1);
    3.94      } else
    3.95  #endif
    3.96      {
    3.97          blk_read_sector(0);
    3.98 -        blk_read_sector(blk_sectors-1);
    3.99 +        blk_read_sector(blk_info.sectors-1);
   3.100      }
   3.101  
   3.102      while (1) {
   3.103 -        uint64_t sector = rand() % blk_sectors;
   3.104 +        uint64_t sector = rand() % blk_info.sectors;
   3.105          struct timeval tv;
   3.106  #ifdef BLKTEST_WRITE
   3.107 -        if (blk_mode == O_RDWR)
   3.108 +        if (blk_info.mode == O_RDWR)
   3.109              blk_write_sector(sector);
   3.110          else
   3.111  #endif
     4.1 --- a/tools/ioemu/block-vbd.c	Sat Apr 05 22:19:02 2008 +0100
     4.2 +++ b/tools/ioemu/block-vbd.c	Sat Apr 05 22:20:25 2008 +0100
     4.3 @@ -49,11 +49,7 @@
     4.4  typedef struct BDRVVbdState {
     4.5      struct blkfront_dev *dev;
     4.6      int fd;
     4.7 -    int type;
     4.8 -    int mode;
     4.9 -    int info;
    4.10 -    uint64_t sectors;
    4.11 -    unsigned sector_size;
    4.12 +    struct blkfront_info info;
    4.13      QEMU_LIST_ENTRY(BDRVVbdState) list;
    4.14  } BDRVVbdState;
    4.15  
    4.16 @@ -81,13 +77,13 @@ static int vbd_open(BlockDriverState *bs
    4.17      //handy to test posix access
    4.18      //return -EIO;
    4.19  
    4.20 -    s->dev = init_blkfront((char *) filename, &s->sectors, &s->sector_size, &s->mode, &s->info);
    4.21 +    s->dev = init_blkfront((char *) filename, &s->info);
    4.22  
    4.23      if (!s->dev)
    4.24  	return -EIO;
    4.25  
    4.26 -    if (SECTOR_SIZE % s->sector_size) {
    4.27 -	printf("sector size is %d, we only support sector sizes that divide %d\n", s->sector_size, SECTOR_SIZE);
    4.28 +    if (SECTOR_SIZE % s->info.sector_size) {
    4.29 +	printf("sector size is %d, we only support sector sizes that divide %d\n", s->info.sector_size, SECTOR_SIZE);
    4.30  	return -EIO;
    4.31      }
    4.32  
    4.33 @@ -267,6 +263,32 @@ static void vbd_aio_cancel(BlockDriverAI
    4.34      // Try to cancel. If can't, wait for it, drop the callback and call qemu_aio_release(acb)
    4.35  }
    4.36  
    4.37 +static void vbd_nop_cb(void *opaque, int ret)
    4.38 +{
    4.39 +}
    4.40 +
    4.41 +static BlockDriverAIOCB *vbd_aio_flush(BlockDriverState *bs,
    4.42 +        BlockDriverCompletionFunc *cb, void *opaque)
    4.43 +{
    4.44 +    BDRVVbdState *s = bs->opaque;
    4.45 +    VbdAIOCB *acb = NULL;
    4.46 +
    4.47 +    if (s->info.barrier == 1) {
    4.48 +        acb = vbd_aio_setup(bs, 0, NULL, 0,
    4.49 +                s->info.flush == 1 ? vbd_nop_cb : cb, opaque);
    4.50 +        if (!acb)
    4.51 +            return NULL;
    4.52 +        blkfront_aio_push_operation(&acb->aiocb, BLKIF_OP_WRITE_BARRIER);
    4.53 +    }
    4.54 +    if (s->info.flush == 1) {
    4.55 +        acb = vbd_aio_setup(bs, 0, NULL, 0, cb, opaque);
    4.56 +        if (!acb)
    4.57 +            return NULL;
    4.58 +        blkfront_aio_push_operation(&acb->aiocb, BLKIF_OP_FLUSH_DISKCACHE);
    4.59 +    }
    4.60 +    return &acb->common;
    4.61 +}
    4.62 +
    4.63  static void vbd_close(BlockDriverState *bs)
    4.64  {
    4.65      BDRVVbdState *s = bs->opaque;
    4.66 @@ -282,13 +304,14 @@ static void vbd_close(BlockDriverState *
    4.67  static int64_t  vbd_getlength(BlockDriverState *bs)
    4.68  {
    4.69      BDRVVbdState *s = bs->opaque;
    4.70 -    return s->sectors * s->sector_size;
    4.71 +    return s->info.sectors * s->info.sector_size;
    4.72  }
    4.73  
    4.74 -static void vbd_flush(BlockDriverState *bs)
    4.75 +static int vbd_flush(BlockDriverState *bs)
    4.76  {
    4.77      BDRVVbdState *s = bs->opaque;
    4.78      blkfront_sync(s->dev);
    4.79 +    return 0;
    4.80  }
    4.81  
    4.82  /***********************************************/
    4.83 @@ -333,6 +356,7 @@ BlockDriver bdrv_vbd = {
    4.84      .bdrv_aio_read = vbd_aio_read,
    4.85      .bdrv_aio_write = vbd_aio_write,
    4.86      .bdrv_aio_cancel = vbd_aio_cancel,
    4.87 +    .bdrv_aio_flush = vbd_aio_flush,
    4.88      .aiocb_size = sizeof(VbdAIOCB),
    4.89      .bdrv_read = vbd_read,
    4.90      .bdrv_write = vbd_write,