char *nodename;
char *backend;
- unsigned sector_size;
- unsigned sectors;
- int mode;
- int barrier;
- int flush;
+ struct blkfront_info info;
#ifdef HAVE_LIBC
int fd;
wake_up(&blkfront_queue);
}
-struct blkfront_dev *init_blkfront(char *nodename, uint64_t *sectors, unsigned *sector_size, int *mode, int *info)
+struct blkfront_dev *init_blkfront(char *nodename, struct blkfront_info *info)
{
xenbus_transaction_t xbt;
char* err;
return NULL;
}
if (*c == 'w')
- *mode = dev->mode = O_RDWR;
+ dev->info.mode = O_RDWR;
else
- *mode = dev->mode = O_RDONLY;
+ dev->info.mode = O_RDONLY;
free(c);
snprintf(path, sizeof(path), "%s/state", dev->backend);
xenbus_unwatch_path(XBT_NIL, path);
snprintf(path, sizeof(path), "%s/info", dev->backend);
- *info = xenbus_read_integer(path);
+ dev->info.info = xenbus_read_integer(path);
snprintf(path, sizeof(path), "%s/sectors", dev->backend);
// FIXME: read_integer returns an int, so disk size limited to 1TB for now
- *sectors = dev->sectors = xenbus_read_integer(path);
+ dev->info.sectors = xenbus_read_integer(path);
snprintf(path, sizeof(path), "%s/sector-size", dev->backend);
- *sector_size = dev->sector_size = xenbus_read_integer(path);
+ dev->info.sector_size = xenbus_read_integer(path);
snprintf(path, sizeof(path), "%s/feature-barrier", dev->backend);
- dev->barrier = xenbus_read_integer(path);
+ dev->info.barrier = xenbus_read_integer(path);
snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend);
- dev->flush = xenbus_read_integer(path);
+ dev->info.flush = xenbus_read_integer(path);
+
+ *info = dev->info;
}
unmask_evtchn(dev->evtchn);
- printk("%u sectors of %u bytes\n", dev->sectors, dev->sector_size);
+ printk("%u sectors of %u bytes\n", dev->info.sectors, dev->info.sector_size);
printk("**************************\n");
return dev;
uintptr_t start, end;
// Can't io at non-sector-aligned location
- ASSERT(!(aiocbp->aio_offset & (dev->sector_size-1)));
+ ASSERT(!(aiocbp->aio_offset & (dev->info.sector_size-1)));
// Can't io non-sector-sized amounts
- ASSERT(!(aiocbp->aio_nbytes & (dev->sector_size-1)));
+ ASSERT(!(aiocbp->aio_nbytes & (dev->info.sector_size-1)));
// Can't io non-sector-aligned buffer
- ASSERT(!((uintptr_t) aiocbp->aio_buf & (dev->sector_size-1)));
+ ASSERT(!((uintptr_t) aiocbp->aio_buf & (dev->info.sector_size-1)));
start = (uintptr_t)aiocbp->aio_buf & PAGE_MASK;
end = ((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes + PAGE_SIZE - 1) & PAGE_MASK;
req->nr_segments = n;
req->handle = dev->handle;
req->id = (uintptr_t) aiocbp;
- req->sector_number = aiocbp->aio_offset / dev->sector_size;
+ req->sector_number = aiocbp->aio_offset / dev->info.sector_size;
for (j = 0; j < n; j++) {
uintptr_t data = start + j * PAGE_SIZE;
aiocbp->gref[j] = req->seg[j].gref =
gnttab_grant_access(dev->dom, virtual_to_mfn(data), write);
req->seg[j].first_sect = 0;
- req->seg[j].last_sect = PAGE_SIZE / dev->sector_size - 1;
+ req->seg[j].last_sect = PAGE_SIZE / dev->info.sector_size - 1;
}
- req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / dev->sector_size;
- req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / dev->sector_size;
+ req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / dev->info.sector_size;
+ req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / dev->info.sector_size;
dev->ring.req_prod_pvt = i + 1;
blkfront_aio(aiocbp, 0);
}
+static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op, uint64_t id)
+{
+ int i;
+ struct blkif_request *req;
+ int notify;
+
+ blkfront_wait_slot(dev);
+ i = dev->ring.req_prod_pvt;
+ req = RING_GET_REQUEST(&dev->ring, i);
+ req->operation = op;
+ req->nr_segments = 0;
+ req->handle = dev->handle;
+ req->id = id;
+ /* Not needed anyway, but the backend will check it */
+ req->sector_number = 0;
+ dev->ring.req_prod_pvt = i + 1;
+ wmb();
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
+ if (notify) notify_remote_via_evtchn(dev->evtchn);
+}
+
+void blkfront_aio_push_operation(struct blkfront_aiocb *aiocbp, uint8_t op)
+{
+ struct blkfront_dev *dev = aiocbp->aio_dev;
+ blkfront_push_operation(dev, op, (uintptr_t) aiocbp);
+}
+
+void blkfront_sync(struct blkfront_dev *dev)
+{
+ unsigned long flags;
+
+ if (dev->info.mode == O_RDWR) {
+ if (dev->info.barrier == 1)
+ blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER, 0);
+
+ if (dev->info.flush == 1)
+ blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
+ }
+
+ /* Note: This won't finish if another thread enqueues requests. */
+ local_irq_save(flags);
+ DEFINE_WAIT(w);
+ while (1) {
+ blkfront_aio_poll(dev);
+ if (RING_FREE_REQUESTS(&dev->ring) == RING_SIZE(&dev->ring))
+ break;
+
+ add_waiter(w, blkfront_queue);
+ local_irq_restore(flags);
+ schedule();
+ local_irq_save(flags);
+ }
+ remove_waiter(w);
+ local_irq_restore(flags);
+}
+
int blkfront_aio_poll(struct blkfront_dev *dev)
{
RING_IDX rp, cons;
rsp = RING_GET_RESPONSE(&dev->ring, cons);
nr_consumed++;
- if (rsp->status != BLKIF_RSP_OKAY)
- printk("block error %d for op %d\n", rsp->status, rsp->operation);
+ struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id;
+ int status = rsp->status;
+
+ if (status != BLKIF_RSP_OKAY)
+ printk("block error %d for op %d\n", status, rsp->operation);
switch (rsp->operation) {
case BLKIF_OP_READ:
case BLKIF_OP_WRITE:
{
- struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id;
- int status = rsp->status;
int j;
for (j = 0; j < aiocbp->n; j++)
gnttab_end_access(aiocbp->gref[j]);
- dev->ring.rsp_cons = ++cons;
- /* Nota: callback frees aiocbp itself */
- aiocbp->aio_cb(aiocbp, status ? -EIO : 0);
- if (dev->ring.rsp_cons != cons)
- /* We reentered, we must not continue here */
- goto out;
break;
}
- default:
- printk("unrecognized block operation %d response\n", rsp->operation);
+
case BLKIF_OP_WRITE_BARRIER:
case BLKIF_OP_FLUSH_DISKCACHE:
- dev->ring.rsp_cons = ++cons;
break;
+
+ default:
+ printk("unrecognized block operation %d response\n", rsp->operation);
}
+
+ dev->ring.rsp_cons = ++cons;
+ /* Nota: callback frees aiocbp itself */
+ if (aiocbp && aiocbp->aio_cb)
+ aiocbp->aio_cb(aiocbp, status ? -EIO : 0);
+ if (dev->ring.rsp_cons != cons)
+ /* We reentered, we must not continue here */
+ break;
}
-out:
RING_FINAL_CHECK_FOR_RESPONSES(&dev->ring, more);
if (more) goto moretodo;
return nr_consumed;
}
-static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op)
-{
- int i;
- struct blkif_request *req;
- int notify;
-
- blkfront_wait_slot(dev);
- i = dev->ring.req_prod_pvt;
- req = RING_GET_REQUEST(&dev->ring, i);
- req->operation = op;
- req->nr_segments = 0;
- req->handle = dev->handle;
- /* Not used */
- req->id = 0;
- /* Not needed anyway, but the backend will check it */
- req->sector_number = 0;
- dev->ring.req_prod_pvt = i + 1;
- wmb();
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
- if (notify) notify_remote_via_evtchn(dev->evtchn);
-}
-
-void blkfront_sync(struct blkfront_dev *dev)
-{
- unsigned long flags;
-
- if (dev->mode == O_RDWR) {
- if (dev->barrier == 1)
- blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER);
-
- if (dev->flush == 1)
- blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE);
- }
-
- /* Note: This won't finish if another thread enqueues requests. */
- local_irq_save(flags);
- DEFINE_WAIT(w);
- while (1) {
- blkfront_aio_poll(dev);
- if (RING_FREE_REQUESTS(&dev->ring) == RING_SIZE(&dev->ring))
- break;
-
- add_waiter(w, blkfront_queue);
- local_irq_restore(flags);
- schedule();
- local_irq_save(flags);
- }
- remove_waiter(w);
- local_irq_restore(flags);
-}
-
#ifdef HAVE_LIBC
int blkfront_open(struct blkfront_dev *dev)
{
}
static struct blkfront_dev *blk_dev;
-static uint64_t blk_sectors;
-static unsigned blk_sector_size;
-static int blk_mode;
+static struct blkfront_info blk_info;
static uint64_t blk_size_read;
static uint64_t blk_size_write;
{
struct blk_req *req = xmalloc(struct blk_req);
req->aiocb.aio_dev = blk_dev;
- req->aiocb.aio_buf = _xmalloc(blk_sector_size, blk_sector_size);
- req->aiocb.aio_nbytes = blk_sector_size;
- req->aiocb.aio_offset = sector * blk_sector_size;
+ req->aiocb.aio_buf = _xmalloc(blk_info.sector_size, blk_info.sector_size);
+ req->aiocb.aio_nbytes = blk_info.sector_size;
+ req->aiocb.aio_offset = sector * blk_info.sector_size;
req->aiocb.data = req;
req->next = NULL;
return req;
if (ret)
printk("got error code %d when reading at offset %ld\n", ret, aiocb->aio_offset);
else
- blk_size_read += blk_sector_size;
+ blk_size_read += blk_info.sector_size;
free(aiocb->aio_buf);
free(req);
}
free(req);
return;
}
- blk_size_read += blk_sector_size;
+ blk_size_read += blk_info.sector_size;
buf = (int*) aiocb->aio_buf;
rand_value = req->rand_value;
- for (i = 0; i < blk_sector_size / sizeof(int); i++) {
+ for (i = 0; i < blk_info.sector_size / sizeof(int); i++) {
if (buf[i] != rand_value) {
printk("bogus data at offset %ld\n", aiocb->aio_offset + i);
break;
free(req);
return;
}
- blk_size_write += blk_sector_size;
+ blk_size_write += blk_info.sector_size;
/* Push write check */
req->next = blk_to_read;
blk_to_read = req;
req->rand_value = rand_value = rand();
buf = (int*) req->aiocb.aio_buf;
- for (i = 0; i < blk_sector_size / sizeof(int); i++) {
+ for (i = 0; i < blk_info.sector_size / sizeof(int); i++) {
buf[i] = rand_value;
rand_value *= RAND_MIX;
}
static void blkfront_thread(void *p)
{
time_t lasttime = 0;
- int blk_info;
- blk_dev = init_blkfront(NULL, &blk_sectors, &blk_sector_size, &blk_mode, &blk_info);
+ blk_dev = init_blkfront(NULL, &blk_info);
if (!blk_dev)
return;
- if (blk_info & VDISK_CDROM)
+ if (blk_info.info & VDISK_CDROM)
printk("Block device is a CDROM\n");
- if (blk_info & VDISK_REMOVABLE)
+ if (blk_info.info & VDISK_REMOVABLE)
printk("Block device is removable\n");
- if (blk_info & VDISK_READONLY)
+ if (blk_info.info & VDISK_READONLY)
printk("Block device is read-only\n");
#ifdef BLKTEST_WRITE
- if (blk_mode == O_RDWR) {
+ if (blk_info.mode == O_RDWR) {
blk_write_sector(0);
- blk_write_sector(blk_sectors-1);
+ blk_write_sector(blk_info.sectors-1);
} else
#endif
{
blk_read_sector(0);
- blk_read_sector(blk_sectors-1);
+ blk_read_sector(blk_info.sectors-1);
}
while (1) {
- uint64_t sector = rand() % blk_sectors;
+ uint64_t sector = rand() % blk_info.sectors;
struct timeval tv;
#ifdef BLKTEST_WRITE
- if (blk_mode == O_RDWR)
+ if (blk_info.mode == O_RDWR)
blk_write_sector(sector);
else
#endif