1 /******************************************************************************
4 * Routines for managing virtual block devices (VBDs).
6 * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation; or, when distributed
11 * separately from the Linux kernel or incorporated into other
12 * software packages, subject to the following license:
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this source file (the "Software"), to deal in the Software without
16 * restriction, including without limitation the rights to use, copy, modify,
17 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18 * and to permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
35 #define vbd_sz(_v) ((_v)->bdev->bd_part ? \
36 (_v)->bdev->bd_part->nr_sects : get_capacity((_v)->bdev->bd_disk))
38 unsigned long long vbd_size(struct vbd *vbd)
40 return vbd->bdev ? vbd_sz(vbd) : 0;
43 unsigned long vbd_secsize(struct vbd *vbd)
45 return vbd->bdev ? bdev_logical_block_size(vbd->bdev) : 0;
48 int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
49 unsigned minor, fmode_t mode, bool cdrom)
52 struct block_device *bdev;
53 struct request_queue *q;
58 vbd->type = cdrom ? VDISK_CDROM : 0;
60 if (!(mode & FMODE_WRITE)) {
61 mode &= ~FMODE_EXCL; /* xend doesn't even allow mode="r!" */
62 vbd->type |= VDISK_READONLY;
66 vbd->pdevice = MKDEV(major, minor);
68 bdev = blkdev_get_by_dev(vbd->pdevice, mode, blkif);
71 if (PTR_ERR(bdev) != -ENOMEDIUM) {
72 DPRINTK("vbd_creat: device %08x could not be opened\n",
77 DPRINTK("vbd_creat: device %08x has no medium\n",
82 bdev = blkdev_get_by_dev(vbd->pdevice, mode | FMODE_NDELAY,
88 if (bdev->bd_disk->flags & GENHD_FL_CD)
89 vbd->type |= VDISK_CDROM;
90 if (bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
91 vbd->type |= VDISK_REMOVABLE;
94 blkdev_put(bdev, mode);
100 if (vbd->bdev->bd_disk == NULL) {
101 DPRINTK("vbd_creat: device %08x doesn't exist.\n",
107 vbd->size = vbd_size(vbd);
109 if (bdev->bd_disk->flags & GENHD_FL_CD)
110 vbd->type |= VDISK_CDROM;
111 if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
112 vbd->type |= VDISK_REMOVABLE;
114 q = bdev_get_queue(bdev);
115 if (q && q->flush_flags)
116 vbd->flush_support = true;
118 if (q && blk_queue_secdiscard(q))
119 vbd->discard_secure = true;
121 DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
122 handle, blkif->domid);
126 void vbd_free(struct vbd *vbd)
129 blkdev_put(vbd->bdev, vbd->mode);
133 int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation)
135 struct vbd *vbd = &blkif->vbd;
138 if ((operation != READ) && !(vbd->mode & FMODE_WRITE))
141 if (vbd->bdev == NULL) {
146 if (likely(req->nr_sects)) {
147 blkif_sector_t end = req->sector_number + req->nr_sects;
149 if (unlikely(end < req->sector_number))
151 if (unlikely(end > vbd_sz(vbd)))
155 req->dev = vbd->pdevice;
156 req->bdev = vbd->bdev;
163 void vbd_resize(blkif_t *blkif)
165 struct vbd *vbd = &blkif->vbd;
166 struct xenbus_transaction xbt;
168 struct xenbus_device *dev = blkif->be->dev;
169 unsigned long long new_size = vbd_size(vbd);
171 pr_info("VBD Resize: new size %Lu\n", new_size);
172 vbd->size = new_size;
174 err = xenbus_transaction_start(&xbt);
176 pr_warning("Error %d starting transaction", err);
179 err = xenbus_printf(xbt, dev->nodename, "sectors", "%Lu",
182 pr_warning("Error %d writing new size", err);
186 err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu",
189 pr_warning("Error writing new sector size");
194 * Write the current state; we will use this to synchronize
195 * the front-end. If the current state is "connected" the
196 * front-end will get the new size information online.
198 err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state);
200 pr_warning("Error %d writing the state", err);
204 err = xenbus_transaction_end(xbt, 0);
208 pr_warning("Error %d ending transaction", err);
211 xenbus_transaction_end(xbt, 1);