1 /******************************************************************************
2 * Routines for managing virtual block devices (VBDs).
4 * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation; or, when distributed
9 * separately from the Linux kernel or incorporated into other
10 * software packages, subject to the following license:
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this source file (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use, copy, modify,
15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16 * and to permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 #define vbd_sz(_v) ((_v)->bdev->bd_part ? \
34 (_v)->bdev->bd_part->nr_sects : get_capacity((_v)->bdev->bd_disk))
36 unsigned long long vbd_size(struct vbd
*vbd
)
41 unsigned int vbd_info(struct vbd
*vbd
)
43 return vbd
->type
| (vbd
->readonly
?VDISK_READONLY
:0);
46 unsigned long vbd_secsize(struct vbd
*vbd
)
48 return bdev_logical_block_size(vbd
->bdev
);
51 int vbd_create(blkif_t
*blkif
, blkif_vdev_t handle
, unsigned major
,
52 unsigned minor
, int readonly
, int cdrom
)
55 struct block_device
*bdev
;
59 vbd
->readonly
= readonly
;
62 vbd
->pdevice
= MKDEV(major
, minor
);
64 bdev
= blkdev_get_by_dev(vbd
->pdevice
, vbd
->readonly
?
65 FMODE_READ
: FMODE_WRITE
, NULL
);
68 DPRINTK("vbd_creat: device %08x could not be opened.\n",
74 vbd
->size
= vbd_size(vbd
);
76 if (vbd
->bdev
->bd_disk
== NULL
) {
77 DPRINTK("vbd_creat: device %08x doesn't exist.\n",
83 if (vbd
->bdev
->bd_disk
->flags
& GENHD_FL_CD
|| cdrom
)
84 vbd
->type
|= VDISK_CDROM
;
85 if (vbd
->bdev
->bd_disk
->flags
& GENHD_FL_REMOVABLE
)
86 vbd
->type
|= VDISK_REMOVABLE
;
88 DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
89 handle
, blkif
->domid
);
93 void vbd_free(struct vbd
*vbd
)
96 blkdev_put(vbd
->bdev
, vbd
->readonly
? FMODE_READ
: FMODE_WRITE
);
100 int vbd_translate(struct phys_req
*req
, blkif_t
*blkif
, int operation
)
102 struct vbd
*vbd
= &blkif
->vbd
;
105 if ((operation
!= READ
) && vbd
->readonly
)
108 if (unlikely((req
->sector_number
+ req
->nr_sects
) > vbd_sz(vbd
)))
111 req
->dev
= vbd
->pdevice
;
112 req
->bdev
= vbd
->bdev
;
119 void vbd_resize(blkif_t
*blkif
)
121 struct vbd
*vbd
= &blkif
->vbd
;
122 struct xenbus_transaction xbt
;
124 struct xenbus_device
*dev
= blkback_xenbus(blkif
->be
);
125 unsigned long long new_size
= vbd_size(vbd
);
127 printk(KERN_INFO
"VBD Resize: Domid: %d, Device: (%d, %d)\n",
128 blkif
->domid
, MAJOR(vbd
->pdevice
), MINOR(vbd
->pdevice
));
129 printk(KERN_INFO
"VBD Resize: new size %Lu\n", new_size
);
130 vbd
->size
= new_size
;
132 err
= xenbus_transaction_start(&xbt
);
134 printk(KERN_WARNING
"Error starting transaction");
137 err
= xenbus_printf(xbt
, dev
->nodename
, "sectors", "%Lu",
140 printk(KERN_WARNING
"Error writing new size");
144 * Write the current state; we will use this to synchronize
145 * the front-end. If the current state is "connected" the
146 * front-end will get the new size information online.
148 err
= xenbus_printf(xbt
, dev
->nodename
, "state", "%d", dev
->state
);
150 printk(KERN_WARNING
"Error writing the state");
154 err
= xenbus_transaction_end(xbt
, 0);
158 printk(KERN_WARNING
"Error ending transaction");
160 xenbus_transaction_end(xbt
, 1);