ia64/xen-unstable

view linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c @ 4243:e07b3423bc48

bitkeeper revision 1.1159.272.6 (423ef7cda7Kpa_XoIQvmnA23rDLP2Q)

remove some bogus test while removing device

Signed-off-by: Vincent Hanquez <vincent@xensource.com>
author vh249@arcadians.cl.cam.ac.uk
date Mon Mar 21 16:35:25 2005 +0000 (2005-03-21)
parents 6ac7c6ea6fc2
children bc658811e45d 2fa2e30bcbde
line source
1 /******************************************************************************
2 * vbd.c
3 *
4 * XenLinux virtual block-device driver (xvd).
5 *
6 * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
7 * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
8 * Copyright (c) 2004-2005, Christian Limpach
9 *
10 * This file may be distributed separately from the Linux kernel, or
11 * incorporated into other software packages, subject to the following license:
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this source file (the "Software"), to deal in the Software without
15 * restriction, including without limitation the rights to use, copy, modify,
16 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
17 * and to permit persons to whom the Software is furnished to do so, subject to
18 * the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 * IN THE SOFTWARE.
30 */
32 #include "block.h"
33 #include <linux/blkdev.h>
35 /*
36 * For convenience we distinguish between ide, scsi and 'other' (i.e.
37 * potentially combinations of the two) in the naming scheme and in a few
38 * other places (like default readahead, etc).
39 */
41 #define NUM_IDE_MAJORS 10
42 #define NUM_SCSI_MAJORS 9
43 #define NUM_VBD_MAJORS 1
45 static struct xlbd_type_info xlbd_ide_type = {
46 .partn_shift = 6,
47 .partn_per_major = 2,
48 // XXXcl todo blksize_size[major] = 1024;
49 .hardsect_size = 512,
50 .max_sectors = 128, /* 'hwif->rqsize' if we knew it */
51 // XXXcl todo read_ahead[major] = 8; /* from drivers/ide/ide-probe.c */
52 .devname = "ide",
53 .diskname = "hd",
54 };
56 static struct xlbd_type_info xlbd_scsi_type = {
57 .partn_shift = 4,
58 .partn_per_major = 16,
59 // XXXcl todo blksize_size[major] = 1024; /* XXX 512; */
60 .hardsect_size = 512,
61 .max_sectors = 128*8, /* XXX 128; */
62 // XXXcl todo read_ahead[major] = 0; /* XXX 8; -- guessing */
63 .devname = "sd",
64 .diskname = "sd",
65 };
67 static struct xlbd_type_info xlbd_vbd_type = {
68 .partn_shift = 4,
69 .partn_per_major = 16,
70 // XXXcl todo blksize_size[major] = 512;
71 .hardsect_size = 512,
72 .max_sectors = 128,
73 // XXXcl todo read_ahead[major] = 8;
74 .devname = "xvd",
75 .diskname = "xvd",
76 };
78 static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
79 NUM_VBD_MAJORS];
81 /* Information about our VBDs. */
82 #define MAX_VBDS 64
83 static int nr_vbds;
84 static vdisk_t *vbd_info;
86 struct request_queue *xlbd_blk_queue = NULL;
88 #define MAJOR_XEN(dev) ((dev)>>8)
89 #define MINOR_XEN(dev) ((dev) & 0xff)
91 static struct block_device_operations xlvbd_block_fops =
92 {
93 .owner = THIS_MODULE,
94 .open = blkif_open,
95 .release = blkif_release,
96 .ioctl = blkif_ioctl,
97 #if 0
98 check_media_change: blkif_check,
99 revalidate: blkif_revalidate,
100 #endif
101 };
103 spinlock_t blkif_io_lock = SPIN_LOCK_UNLOCKED;
105 static int xlvbd_get_vbd_info(vdisk_t *disk_info)
106 {
107 vdisk_t *buf = (vdisk_t *)__get_free_page(GFP_KERNEL);
108 blkif_request_t req;
109 blkif_response_t rsp;
110 int nr;
112 memset(&req, 0, sizeof(req));
113 req.operation = BLKIF_OP_PROBE;
114 req.nr_segments = 1;
115 req.frame_and_sects[0] = virt_to_machine(buf) | 7;
117 blkif_control_send(&req, &rsp);
119 if ( rsp.status <= 0 )
120 {
121 printk(KERN_ALERT "Could not probe disks (%d)\n", rsp.status);
122 return -1;
123 }
125 if ( (nr = rsp.status) > MAX_VBDS )
126 nr = MAX_VBDS;
127 memcpy(disk_info, buf, nr * sizeof(vdisk_t));
129 free_page((unsigned long)buf);
131 return nr;
132 }
134 static struct xlbd_major_info *xlbd_get_major_info(int xd_device, int *minor)
135 {
136 int mi_idx, new_major;
137 int xd_major = MAJOR_XEN(xd_device);
138 int xd_minor = MINOR_XEN(xd_device);
140 *minor = xd_minor;
142 switch (xd_major) {
143 case IDE0_MAJOR: mi_idx = 0; new_major = IDE0_MAJOR; break;
144 case IDE1_MAJOR: mi_idx = 1; new_major = IDE1_MAJOR; break;
145 case IDE2_MAJOR: mi_idx = 2; new_major = IDE2_MAJOR; break;
146 case IDE3_MAJOR: mi_idx = 3; new_major = IDE3_MAJOR; break;
147 case IDE4_MAJOR: mi_idx = 4; new_major = IDE4_MAJOR; break;
148 case IDE5_MAJOR: mi_idx = 5; new_major = IDE5_MAJOR; break;
149 case IDE6_MAJOR: mi_idx = 6; new_major = IDE6_MAJOR; break;
150 case IDE7_MAJOR: mi_idx = 7; new_major = IDE7_MAJOR; break;
151 case IDE8_MAJOR: mi_idx = 8; new_major = IDE8_MAJOR; break;
152 case IDE9_MAJOR: mi_idx = 9; new_major = IDE9_MAJOR; break;
153 case SCSI_DISK0_MAJOR: mi_idx = 10; new_major = SCSI_DISK0_MAJOR; break;
154 case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
155 mi_idx = 11 + xd_major - SCSI_DISK1_MAJOR;
156 new_major = SCSI_DISK1_MAJOR + xd_major - SCSI_DISK1_MAJOR;
157 break;
158 case SCSI_CDROM_MAJOR: mi_idx = 18; new_major = SCSI_CDROM_MAJOR; break;
159 default: mi_idx = 19; new_major = 0;/* XXXcl notyet */ break;
160 }
162 if (major_info[mi_idx])
163 return major_info[mi_idx];
165 major_info[mi_idx] = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
166 if (major_info[mi_idx] == NULL)
167 return NULL;
169 memset(major_info[mi_idx], 0, sizeof(struct xlbd_major_info));
171 switch (mi_idx) {
172 case 0 ... (NUM_IDE_MAJORS - 1):
173 major_info[mi_idx]->type = &xlbd_ide_type;
174 major_info[mi_idx]->index = mi_idx;
175 break;
176 case NUM_IDE_MAJORS ... (NUM_IDE_MAJORS + NUM_SCSI_MAJORS - 1):
177 major_info[mi_idx]->type = &xlbd_scsi_type;
178 major_info[mi_idx]->index = mi_idx - NUM_IDE_MAJORS;
179 break;
180 case (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) ...
181 (NUM_IDE_MAJORS + NUM_SCSI_MAJORS + NUM_VBD_MAJORS - 1):
182 major_info[mi_idx]->type = &xlbd_vbd_type;
183 major_info[mi_idx]->index = mi_idx -
184 (NUM_IDE_MAJORS + NUM_SCSI_MAJORS);
185 break;
186 }
187 major_info[mi_idx]->major = new_major;
189 if (register_blkdev(major_info[mi_idx]->major, major_info[mi_idx]->type->devname)) {
190 printk(KERN_ALERT "XL VBD: can't get major %d with name %s\n",
191 major_info[mi_idx]->major, major_info[mi_idx]->type->devname);
192 goto out;
193 }
195 devfs_mk_dir(major_info[mi_idx]->type->devname);
197 return major_info[mi_idx];
199 out:
200 kfree(major_info[mi_idx]);
201 major_info[mi_idx] = NULL;
202 return NULL;
203 }
205 static struct gendisk *xlvbd_get_gendisk(struct xlbd_major_info *mi,
206 int xd_minor, vdisk_t *xd)
207 {
208 struct gendisk *gd;
209 struct xlbd_disk_info *di;
210 int device, partno;
212 device = MKDEV(mi->major, xd_minor);
213 gd = get_gendisk(device, &partno);
214 if ( gd != NULL )
215 return gd;
217 di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL);
218 if ( di == NULL )
219 return NULL;
220 di->mi = mi;
221 di->xd_device = xd->device;
223 /* Construct an appropriate gendisk structure. */
224 gd = alloc_disk(1);
225 if ( gd == NULL )
226 goto out;
228 gd->major = mi->major;
229 gd->first_minor = xd_minor;
230 gd->fops = &xlvbd_block_fops;
231 gd->private_data = di;
232 sprintf(gd->disk_name, "%s%c%d", mi->type->diskname,
233 'a' + mi->index * mi->type->partn_per_major +
234 (xd_minor >> mi->type->partn_shift),
235 xd_minor & ((1 << mi->type->partn_shift) - 1));
237 set_capacity(gd, xd->capacity);
239 if ( xlbd_blk_queue == NULL )
240 {
241 xlbd_blk_queue = blk_init_queue(do_blkif_request,
242 &blkif_io_lock);
243 if ( xlbd_blk_queue == NULL )
244 goto out;
245 elevator_init(xlbd_blk_queue, "noop");
247 /*
248 * Turn off barking 'headactive' mode. We dequeue
249 * buffer heads as soon as we pass them to back-end
250 * driver.
251 */
252 blk_queue_headactive(xlbd_blk_queue, 0);
254 /* Hard sector size and max sectors impersonate the equiv. hardware. */
255 blk_queue_hardsect_size(
256 xlbd_blk_queue, mi->type->hardsect_size);
257 blk_queue_max_sectors(
258 xlbd_blk_queue, mi->type->max_sectors);
260 /* Each segment in a request is up to an aligned page in size. */
261 blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1);
262 blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE);
264 /* Ensure a merged request will fit in a single I/O ring slot. */
265 blk_queue_max_phys_segments(
266 xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
267 blk_queue_max_hw_segments(
268 xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
270 /* Make sure buffer addresses are sector-aligned. */
271 blk_queue_dma_alignment(xlbd_blk_queue, 511);
272 }
273 gd->queue = xlbd_blk_queue;
275 add_disk(gd);
277 return gd;
279 out:
280 if ( gd != NULL )
281 del_gendisk(gd);
282 kfree(di);
283 return NULL;
284 }
286 /*
287 * xlvbd_init_device - initialise a VBD device
288 * @disk: a vdisk_t describing the VBD
289 *
290 * Takes a vdisk_t * that describes a VBD the domain has access to.
291 * Performs appropriate initialisation and registration of the device.
292 *
293 * Care needs to be taken when making re-entrant calls to ensure that
294 * corruption does not occur. Also, devices that are in use should not have
295 * their details updated. This is the caller's responsibility.
296 */
297 static int xlvbd_init_device(vdisk_t *xd)
298 {
299 struct block_device *bd;
300 struct gendisk *gd;
301 struct xlbd_major_info *mi;
302 int device;
303 int minor;
305 int err = -ENOMEM;
307 mi = xlbd_get_major_info(xd->device, &minor);
308 if (mi == NULL)
309 return -EPERM;
311 device = MKDEV(mi->major, minor);
313 if ((bd = bdget(device)) == NULL)
314 return -EPERM;
316 /*
317 * Update of partition info, and check of usage count, is protected
318 * by the per-block-device semaphore.
319 */
320 down(&bd->bd_sem);
322 gd = xlvbd_get_gendisk(mi, minor, xd);
323 if (gd == NULL) {
324 err = -EPERM;
325 goto out;
326 }
328 if (VDISK_READONLY(xd->info))
329 set_disk_ro(gd, 1);
331 /* Some final fix-ups depending on the device type */
332 switch (VDISK_TYPE(xd->info)) {
333 case VDISK_TYPE_CDROM:
334 gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD;
335 /* FALLTHROUGH */
336 case VDISK_TYPE_FLOPPY:
337 case VDISK_TYPE_TAPE:
338 gd->flags |= GENHD_FL_REMOVABLE;
339 break;
341 case VDISK_TYPE_DISK:
342 break;
344 default:
345 printk(KERN_ALERT "XenLinux: unknown device type %d\n",
346 VDISK_TYPE(xd->info));
347 break;
348 }
350 err = 0;
351 out:
352 up(&bd->bd_sem);
353 bdput(bd);
354 return err;
355 }
357 /*
358 * xlvbd_remove_device - remove a device node if possible
359 * @device: numeric device ID
360 *
361 * Updates the gendisk structure and invalidates devices.
362 *
363 * This is OK for now but in future, should perhaps consider where this should
364 * deallocate gendisks / unregister devices.
365 */
366 static int xlvbd_remove_device(int dev16)
367 {
368 int i, rc = 0;
369 struct gendisk *gd;
370 struct block_device *bd;
371 struct xlbd_disk_info *di;
372 dev_t device = MKDEV(MAJOR_XEN(dev16), MINOR_XEN(dev16));
374 bd = bdget(device);
375 if (!bd)
376 return -1;
378 /*
379 * Update of partition info, and check of usage count, is protected
380 * by the per-block-device semaphore.
381 */
382 down(&bd->bd_sem);
384 gd = get_gendisk(device, &i);
385 BUG_ON(gd == NULL);
386 di = (struct xlbd_disk_info *) gd->private_data;
387 BUG_ON(di == NULL);
389 if ( di->mi->usage != 0 )
390 {
391 printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device);
392 rc = -1;
393 goto out;
394 }
396 /* The VBD is mapped to an entire unit. */
398 invalidate_partition(gd, 0);
399 set_capacity(gd, 0);
401 out:
402 up(&bd->bd_sem);
403 bdput(bd);
404 return rc;
405 }
407 /*
408 * xlvbd_update_vbds - reprobes the VBD status and performs updates driver
409 * state. The VBDs need to be updated in this way when the domain is
410 * initialised and also each time we receive an XLBLK_UPDATE event.
411 */
412 void xlvbd_update_vbds(void)
413 {
414 int i, j, k, old_nr, new_nr;
415 vdisk_t *old_info, *new_info, *merged_info;
417 old_info = vbd_info;
418 old_nr = nr_vbds;
420 new_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
421 if (!new_info)
422 return;
424 if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
425 goto out;
427 /*
428 * Final list maximum size is old list + new list. This occurs only when
429 * old list and new list do not overlap at all, and we cannot yet destroy
430 * VBDs in the old list because the usage counts are busy.
431 */
432 merged_info = kmalloc((old_nr + new_nr) * sizeof(vdisk_t), GFP_KERNEL);
433 if (!merged_info)
434 goto out;
436 /* @i tracks old list; @j tracks new list; @k tracks merged list. */
437 i = j = k = 0;
439 while ( (i < old_nr) && (j < new_nr) )
440 {
441 if ( old_info[i].device < new_info[j].device )
442 {
443 if ( xlvbd_remove_device(old_info[i].device) != 0 )
444 memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
445 i++;
446 }
447 else if ( old_info[i].device > new_info[j].device )
448 {
449 if ( xlvbd_init_device(&new_info[j]) == 0 )
450 memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
451 j++;
452 }
453 else
454 {
455 if ( ((old_info[i].capacity == new_info[j].capacity) &&
456 (old_info[i].info == new_info[j].info)) ||
457 (xlvbd_remove_device(old_info[i].device) != 0) )
458 memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
459 else if ( xlvbd_init_device(&new_info[j]) == 0 )
460 memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
461 i++; j++;
462 }
463 }
465 for ( ; i < old_nr; i++ )
466 {
467 if ( xlvbd_remove_device(old_info[i].device) != 0 )
468 memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
469 }
471 for ( ; j < new_nr; j++ )
472 {
473 if ( xlvbd_init_device(&new_info[j]) == 0 )
474 memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
475 }
477 vbd_info = merged_info;
478 nr_vbds = k;
480 kfree(old_info);
481 out:
482 kfree(new_info);
483 }
485 /*
486 * Set up all the linux device goop for the virtual block devices
487 * (vbd's) that we know about. Note that although from the backend
488 * driver's p.o.v. VBDs are addressed simply an opaque 16-bit device
489 * number, the domain creation tools conventionally allocate these
490 * numbers to correspond to those used by 'real' linux -- this is just
491 * for convenience as it means e.g. that the same /etc/fstab can be
492 * used when booting with or without Xen.
493 */
494 int xlvbd_init(void)
495 {
496 int i;
498 memset(major_info, 0, sizeof(major_info));
500 vbd_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
501 if (vbd_info == NULL) {
502 printk(KERN_ALERT "Failed to allocate memory for disk info.\n");
503 nr_vbds = 0;
504 return 0;
505 }
507 nr_vbds = xlvbd_get_vbd_info(vbd_info);
508 if (nr_vbds < 0) {
509 kfree(vbd_info);
510 vbd_info = NULL;
511 nr_vbds = 0;
512 } else {
513 for (i = 0; i < nr_vbds; i++)
514 xlvbd_init_device(&vbd_info[i]);
515 }
517 return 0;
518 }