debuggers.hg

view linux-2.6.10-xen-sparse/drivers/xen/blkfront/vbd.c @ 3636:f86bdb0a8573

bitkeeper revision 1.1159.223.55 (41fffadb9KX8y2tjTwUVGZRrZQdJ2g)

Fix incorrect result-check in xlvbd_init_device

Signed-off-by: Jody Belka <knew-xen@pimb.org>
Signed-off-by: ian.pratt@cl.cam.ac.uk
author iap10@labyrinth.cl.cam.ac.uk
date Tue Feb 01 21:55:39 2005 +0000 (2005-02-01)
parents ea428d76cfb3
children 11b95fad5f5d a63c03fcda8f
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, 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 .name = "hd",
53 };
55 static struct xlbd_type_info xlbd_scsi_type = {
56 .partn_shift = 4,
57 .partn_per_major = 16,
58 // XXXcl todo blksize_size[major] = 1024; /* XXX 512; */
59 .hardsect_size = 512,
60 .max_sectors = 128*8, /* XXX 128; */
61 // XXXcl todo read_ahead[major] = 0; /* XXX 8; -- guessing */
62 .name = "sd",
63 };
65 static struct xlbd_type_info xlbd_vbd_type = {
66 .partn_shift = 4,
67 .partn_per_major = 16,
68 // XXXcl todo blksize_size[major] = 512;
69 .hardsect_size = 512,
70 .max_sectors = 128,
71 // XXXcl todo read_ahead[major] = 8;
72 .name = "xvd",
73 };
75 static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
76 NUM_VBD_MAJORS];
78 /* Information about our VBDs. */
79 #define MAX_VBDS 64
80 static int nr_vbds;
81 static vdisk_t *vbd_info;
83 struct request_queue *xlbd_blk_queue = NULL;
85 #define MAJOR_XEN(dev) ((dev)>>8)
86 #define MINOR_XEN(dev) ((dev) & 0xff)
88 static struct block_device_operations xlvbd_block_fops =
89 {
90 .owner = THIS_MODULE,
91 .open = blkif_open,
92 .release = blkif_release,
93 .ioctl = blkif_ioctl,
94 #if 0
95 check_media_change: blkif_check,
96 revalidate: blkif_revalidate,
97 #endif
98 };
100 spinlock_t blkif_io_lock = SPIN_LOCK_UNLOCKED;
102 static int xlvbd_get_vbd_info(vdisk_t *disk_info)
103 {
104 vdisk_t *buf = (vdisk_t *)__get_free_page(GFP_KERNEL);
105 blkif_request_t req;
106 blkif_response_t rsp;
107 int nr;
109 memset(&req, 0, sizeof(req));
110 req.operation = BLKIF_OP_PROBE;
111 req.nr_segments = 1;
112 req.frame_and_sects[0] = virt_to_machine(buf) | 7;
114 blkif_control_send(&req, &rsp);
116 if ( rsp.status <= 0 )
117 {
118 printk(KERN_ALERT "Could not probe disks (%d)\n", rsp.status);
119 return -1;
120 }
122 if ( (nr = rsp.status) > MAX_VBDS )
123 nr = MAX_VBDS;
124 memcpy(disk_info, buf, nr * sizeof(vdisk_t));
126 free_page((unsigned long)buf);
128 return nr;
129 }
131 static struct xlbd_major_info *xlbd_get_major_info(int xd_device, int *minor)
132 {
133 int mi_idx, new_major;
134 int xd_major = MAJOR_XEN(xd_device);
135 int xd_minor = MINOR_XEN(xd_device);
137 *minor = xd_minor;
139 switch (xd_major) {
140 case IDE0_MAJOR: mi_idx = 0; new_major = IDE0_MAJOR; break;
141 case IDE1_MAJOR: mi_idx = 1; new_major = IDE1_MAJOR; break;
142 case IDE2_MAJOR: mi_idx = 2; new_major = IDE2_MAJOR; break;
143 case IDE3_MAJOR: mi_idx = 3; new_major = IDE3_MAJOR; break;
144 case IDE4_MAJOR: mi_idx = 4; new_major = IDE4_MAJOR; break;
145 case IDE5_MAJOR: mi_idx = 5; new_major = IDE5_MAJOR; break;
146 case IDE6_MAJOR: mi_idx = 6; new_major = IDE6_MAJOR; break;
147 case IDE7_MAJOR: mi_idx = 7; new_major = IDE7_MAJOR; break;
148 case IDE8_MAJOR: mi_idx = 8; new_major = IDE8_MAJOR; break;
149 case IDE9_MAJOR: mi_idx = 9; new_major = IDE9_MAJOR; break;
150 case SCSI_DISK0_MAJOR: mi_idx = 10; new_major = SCSI_DISK0_MAJOR; break;
151 case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
152 mi_idx = 11 + xd_major - SCSI_DISK1_MAJOR;
153 new_major = SCSI_DISK1_MAJOR + xd_major - SCSI_DISK1_MAJOR;
154 break;
155 case SCSI_CDROM_MAJOR: mi_idx = 18; new_major = SCSI_CDROM_MAJOR; break;
156 default: mi_idx = 19; new_major = 0;/* XXXcl notyet */ break;
157 }
159 if (major_info[mi_idx])
160 return major_info[mi_idx];
162 major_info[mi_idx] = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
163 if (major_info[mi_idx] == NULL)
164 return NULL;
166 memset(major_info[mi_idx], 0, sizeof(struct xlbd_major_info));
168 switch (mi_idx) {
169 case 0 ... (NUM_IDE_MAJORS - 1):
170 major_info[mi_idx]->type = &xlbd_ide_type;
171 major_info[mi_idx]->index = mi_idx;
172 break;
173 case NUM_IDE_MAJORS ... (NUM_IDE_MAJORS + NUM_SCSI_MAJORS - 1):
174 major_info[mi_idx]->type = &xlbd_scsi_type;
175 major_info[mi_idx]->index = mi_idx - NUM_IDE_MAJORS;
176 break;
177 case (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) ...
178 (NUM_IDE_MAJORS + NUM_SCSI_MAJORS + NUM_VBD_MAJORS - 1):
179 major_info[mi_idx]->type = &xlbd_vbd_type;
180 major_info[mi_idx]->index = mi_idx -
181 (NUM_IDE_MAJORS + NUM_SCSI_MAJORS);
182 break;
183 }
184 major_info[mi_idx]->major = new_major;
186 if (register_blkdev(major_info[mi_idx]->major, major_info[mi_idx]->type->name)) {
187 printk(KERN_ALERT "XL VBD: can't get major %d with name %s\n",
188 major_info[mi_idx]->major, major_info[mi_idx]->type->name);
189 goto out;
190 }
192 devfs_mk_dir(major_info[mi_idx]->type->name);
194 return major_info[mi_idx];
196 out:
197 kfree(major_info[mi_idx]);
198 major_info[mi_idx] = NULL;
199 return NULL;
200 }
202 static struct gendisk *xlvbd_get_gendisk(struct xlbd_major_info *mi,
203 int xd_minor, vdisk_t *xd)
204 {
205 struct gendisk *gd;
206 struct xlbd_disk_info *di;
207 int device, partno;
209 device = MKDEV(mi->major, xd_minor);
210 gd = get_gendisk(device, &partno);
211 if ( gd != NULL )
212 return gd;
214 di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL);
215 if ( di == NULL )
216 return NULL;
217 di->mi = mi;
218 di->xd_device = xd->device;
220 /* Construct an appropriate gendisk structure. */
221 gd = alloc_disk(1);
222 if ( gd == NULL )
223 goto out;
225 gd->major = mi->major;
226 gd->first_minor = xd_minor;
227 gd->fops = &xlvbd_block_fops;
228 gd->private_data = di;
229 sprintf(gd->disk_name, "%s%c%d", mi->type->name,
230 'a' + mi->index * mi->type->partn_per_major +
231 (xd_minor >> mi->type->partn_shift),
232 xd_minor & ((1 << mi->type->partn_shift) - 1));
234 set_capacity(gd, xd->capacity);
236 if ( xlbd_blk_queue == NULL )
237 {
238 xlbd_blk_queue = blk_init_queue(do_blkif_request,
239 &blkif_io_lock);
240 if ( xlbd_blk_queue == NULL )
241 goto out;
242 elevator_init(xlbd_blk_queue, "noop");
244 /*
245 * Turn off barking 'headactive' mode. We dequeue
246 * buffer heads as soon as we pass them to back-end
247 * driver.
248 */
249 blk_queue_headactive(xlbd_blk_queue, 0);
251 /* Hard sector size and max sectors impersonate the equiv. hardware. */
252 blk_queue_hardsect_size(
253 xlbd_blk_queue, mi->type->hardsect_size);
254 blk_queue_max_sectors(
255 xlbd_blk_queue, mi->type->max_sectors);
257 /* Each segment in a request is up to an aligned page in size. */
258 blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1);
259 blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE);
261 /* Ensure a merged request will fit in a single I/O ring slot. */
262 blk_queue_max_phys_segments(
263 xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
264 blk_queue_max_hw_segments(
265 xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
267 /* Make sure buffer addresses are sector-aligned. */
268 blk_queue_dma_alignment(xlbd_blk_queue, 511);
269 }
270 gd->queue = xlbd_blk_queue;
272 add_disk(gd);
274 return gd;
276 out:
277 if ( gd != NULL )
278 del_gendisk(gd);
279 kfree(di);
280 return NULL;
281 }
283 /*
284 * xlvbd_init_device - initialise a VBD device
285 * @disk: a vdisk_t describing the VBD
286 *
287 * Takes a vdisk_t * that describes a VBD the domain has access to.
288 * Performs appropriate initialisation and registration of the device.
289 *
290 * Care needs to be taken when making re-entrant calls to ensure that
291 * corruption does not occur. Also, devices that are in use should not have
292 * their details updated. This is the caller's responsibility.
293 */
294 static int xlvbd_init_device(vdisk_t *xd)
295 {
296 struct block_device *bd;
297 struct gendisk *gd;
298 struct xlbd_major_info *mi;
299 int device;
300 int minor;
302 int err = -ENOMEM;
304 mi = xlbd_get_major_info(xd->device, &minor);
305 if (mi == NULL)
306 return -EPERM;
308 device = MKDEV(mi->major, minor);
310 if ((bd = bdget(device)) == NULL)
311 return -EPERM;
313 /*
314 * Update of partition info, and check of usage count, is protected
315 * by the per-block-device semaphore.
316 */
317 down(&bd->bd_sem);
319 gd = xlvbd_get_gendisk(mi, minor, xd);
320 if (gd == NULL) {
321 err = -EPERM;
322 goto out;
323 }
325 if (VDISK_READONLY(xd->info))
326 set_disk_ro(gd, 1);
328 /* Some final fix-ups depending on the device type */
329 switch (VDISK_TYPE(xd->info)) {
330 case VDISK_TYPE_CDROM:
331 gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD;
332 /* FALLTHROUGH */
333 case VDISK_TYPE_FLOPPY:
334 case VDISK_TYPE_TAPE:
335 gd->flags |= GENHD_FL_REMOVABLE;
336 break;
338 case VDISK_TYPE_DISK:
339 break;
341 default:
342 printk(KERN_ALERT "XenLinux: unknown device type %d\n",
343 VDISK_TYPE(xd->info));
344 break;
345 }
347 err = 0;
348 out:
349 up(&bd->bd_sem);
350 bdput(bd);
351 return err;
352 }
354 #if 0
355 /*
356 * xlvbd_remove_device - remove a device node if possible
357 * @device: numeric device ID
358 *
359 * Updates the gendisk structure and invalidates devices.
360 *
361 * This is OK for now but in future, should perhaps consider where this should
362 * deallocate gendisks / unregister devices.
363 */
364 static int xlvbd_remove_device(int device)
365 {
366 int i, rc = 0, minor = MINOR(device);
367 struct gendisk *gd;
368 struct block_device *bd;
369 xen_block_t *disk = NULL;
371 if ( (bd = bdget(device)) == NULL )
372 return -1;
374 /*
375 * Update of partition info, and check of usage count, is protected
376 * by the per-block-device semaphore.
377 */
378 down(&bd->bd_sem);
380 if ( ((gd = get_gendisk(device)) == NULL) ||
381 ((disk = xldev_to_xldisk(device)) == NULL) )
382 BUG();
384 if ( disk->usage != 0 )
385 {
386 printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device);
387 rc = -1;
388 goto out;
389 }
391 if ( (minor & (gd->max_p-1)) != 0 )
392 {
393 /* 1: The VBD is mapped to a partition rather than a whole unit. */
394 invalidate_device(device, 1);
395 gd->part[minor].start_sect = 0;
396 gd->part[minor].nr_sects = 0;
397 gd->sizes[minor] = 0;
399 /* Clear the consists-of-virtual-partitions flag if possible. */
400 gd->flags[minor >> gd->minor_shift] &= ~GENHD_FL_VIRT_PARTNS;
401 for ( i = 1; i < gd->max_p; i++ )
402 if ( gd->sizes[(minor & ~(gd->max_p-1)) + i] != 0 )
403 gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS;
405 /*
406 * If all virtual partitions are now gone, and a 'whole unit' VBD is
407 * present, then we can try to grok the unit's real partition table.
408 */
409 if ( !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) &&
410 (gd->sizes[minor & ~(gd->max_p-1)] != 0) &&
411 !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE) )
412 {
413 register_disk(gd,
414 device&~(gd->max_p-1),
415 gd->max_p,
416 &xlvbd_block_fops,
417 gd->part[minor&~(gd->max_p-1)].nr_sects);
418 }
419 }
420 else
421 {
422 /*
423 * 2: The VBD is mapped to an entire 'unit'. Clear all partitions.
424 * NB. The partition entries are only cleared if there are no VBDs
425 * mapped to individual partitions on this unit.
426 */
427 i = gd->max_p - 1; /* Default: clear subpartitions as well. */
428 if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS )
429 i = 0; /* 'Virtual' mode: only clear the 'whole unit' entry. */
430 while ( i >= 0 )
431 {
432 invalidate_device(device+i, 1);
433 gd->part[minor+i].start_sect = 0;
434 gd->part[minor+i].nr_sects = 0;
435 gd->sizes[minor+i] = 0;
436 i--;
437 }
438 }
440 out:
441 up(&bd->bd_sem);
442 bdput(bd);
443 return rc;
444 }
446 /*
447 * xlvbd_update_vbds - reprobes the VBD status and performs updates driver
448 * state. The VBDs need to be updated in this way when the domain is
449 * initialised and also each time we receive an XLBLK_UPDATE event.
450 */
451 void xlvbd_update_vbds(void)
452 {
453 int i, j, k, old_nr, new_nr;
454 vdisk_t *old_info, *new_info, *merged_info;
456 old_info = vbd_info;
457 old_nr = nr_vbds;
459 new_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
460 if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
461 {
462 kfree(new_info);
463 return;
464 }
466 /*
467 * Final list maximum size is old list + new list. This occurs only when
468 * old list and new list do not overlap at all, and we cannot yet destroy
469 * VBDs in the old list because the usage counts are busy.
470 */
471 merged_info = kmalloc((old_nr + new_nr) * sizeof(vdisk_t), GFP_KERNEL);
473 /* @i tracks old list; @j tracks new list; @k tracks merged list. */
474 i = j = k = 0;
476 while ( (i < old_nr) && (j < new_nr) )
477 {
478 if ( old_info[i].device < new_info[j].device )
479 {
480 if ( xlvbd_remove_device(old_info[i].device) != 0 )
481 memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
482 i++;
483 }
484 else if ( old_info[i].device > new_info[j].device )
485 {
486 if ( xlvbd_init_device(&new_info[j]) == 0 )
487 memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
488 j++;
489 }
490 else
491 {
492 if ( ((old_info[i].capacity == new_info[j].capacity) &&
493 (old_info[i].info == new_info[j].info)) ||
494 (xlvbd_remove_device(old_info[i].device) != 0) )
495 memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
496 else if ( xlvbd_init_device(&new_info[j]) == 0 )
497 memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
498 i++; j++;
499 }
500 }
502 for ( ; i < old_nr; i++ )
503 {
504 if ( xlvbd_remove_device(old_info[i].device) != 0 )
505 memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
506 }
508 for ( ; j < new_nr; j++ )
509 {
510 if ( xlvbd_init_device(&new_info[j]) == 0 )
511 memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
512 }
514 vbd_info = merged_info;
515 nr_vbds = k;
517 kfree(old_info);
518 kfree(new_info);
519 }
520 #endif
522 /*
523 * Set up all the linux device goop for the virtual block devices
524 * (vbd's) that we know about. Note that although from the backend
525 * driver's p.o.v. VBDs are addressed simply an opaque 16-bit device
526 * number, the domain creation tools conventionally allocate these
527 * numbers to correspond to those used by 'real' linux -- this is just
528 * for convenience as it means e.g. that the same /etc/fstab can be
529 * used when booting with or without Xen.
530 */
531 int xlvbd_init(void)
532 {
533 int i;
535 /*
536 * If compiled as a module, we don't support unloading yet. We
537 * therefore permanently increment the reference count to
538 * disallow it.
539 */
540 /* MOD_INC_USE_COUNT; */
542 memset(major_info, 0, sizeof(major_info));
544 for (i = 0; i < sizeof(major_info) / sizeof(major_info[0]); i++) {
545 }
547 vbd_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
548 nr_vbds = xlvbd_get_vbd_info(vbd_info);
550 if (nr_vbds < 0) {
551 kfree(vbd_info);
552 vbd_info = NULL;
553 nr_vbds = 0;
554 } else {
555 for (i = 0; i < nr_vbds; i++)
556 xlvbd_init_device(&vbd_info[i]);
557 }
559 return 0;
560 }