static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, unsigned major, unsigned minor, int readonly, int cdrom) { struct xen_vbd *vbd; struct block_device *bdev; struct request_queue *q; vbd = &blkif->vbd; vbd->handle = handle; vbd->readonly = readonly; vbd->type = 0; vbd->pdevice = MKDEV(major, minor); bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ? FMODE_READ : FMODE_WRITE, NULL); if (IS_ERR(bdev)) { DPRINTK("xen_vbd_create: device %08x could not be opened.\n", vbd->pdevice); return -ENOENT; } vbd->bdev = bdev; if (vbd->bdev->bd_disk == NULL) { DPRINTK("xen_vbd_create: device %08x doesn't exist.\n", vbd->pdevice); xen_vbd_free(vbd); return -ENOENT; } vbd->size = vbd_sz(vbd); if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom) vbd->type |= VDISK_CDROM; if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) vbd->type |= VDISK_REMOVABLE; q = bdev_get_queue(bdev); if (q && q->flush_flags) vbd->flush_support = true; if (q && blk_queue_secdiscard(q)) vbd->discard_secure = true; DPRINTK("Successful creation of handle=%04x (dom=%u)\n", handle, blkif->domid); return 0; }
int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation) { struct vbd *vbd = &blkif->vbd; int rc = -EACCES; if ((operation != READ) && vbd->readonly) goto out; if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) goto out; req->dev = vbd->pdevice; req->bdev = vbd->bdev; rc = 0; out: return rc; }
/* * Write the physical details regarding the block device to the store, and * switch to Connected state. */ static void connect(struct backend_info *be) { struct xenbus_transaction xbt; int err; struct xenbus_device *dev = be->dev; DPRINTK("%s", dev->otherend); /* Supply the information about the device the frontend needs */ again: err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); return; } err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support); if (err) goto abort; err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", (unsigned long long)vbd_sz(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sectors", dev->nodename); goto abort; } /* FIXME: use a typename instead */ err = xenbus_printf(xbt, dev->nodename, "info", "%u", be->blkif->vbd.type | (be->blkif->vbd.readonly ? VDISK_READONLY : 0)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/info", dev->nodename); goto abort; } err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu", (unsigned long) bdev_logical_block_size(be->blkif->vbd.bdev)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sector-size", dev->nodename); goto abort; } err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) xenbus_dev_fatal(dev, err, "ending transaction"); err = xenbus_switch_state(dev, XenbusStateConnected); if (err) xenbus_dev_fatal(dev, err, "switching to Connected state", dev->nodename); return; abort: xenbus_transaction_end(xbt, 1); }
unsigned long long vbd_size(struct vbd *vbd) { return vbd_sz(vbd); }