ia64/xen-unstable
changeset 4424:a6d955deec8e
bitkeeper revision 1.1236.1.185 (424d4eb3GRbQvjFst4j4MoRRngC5dg)
Merge arcadians.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into arcadians.cl.cam.ac.uk:/local/scratch-2/vh249/xen-unstable.bk
Merge arcadians.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into arcadians.cl.cam.ac.uk:/local/scratch-2/vh249/xen-unstable.bk
author | vh249@arcadians.cl.cam.ac.uk |
---|---|
date | Fri Apr 01 13:37:55 2005 +0000 (2005-04-01) |
parents | 09485b0bafad 50ec7eded8a9 |
children | 5396c1c1d634 e89596d1bfb4 |
files | linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xend/server/blkif.py tools/python/xen/xm/main.py |
line diff
1.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c Fri Apr 01 13:17:52 2005 +0000 1.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c Fri Apr 01 13:37:55 2005 +0000 1.3 @@ -31,6 +31,7 @@ 1.4 1.5 #include "block.h" 1.6 #include <linux/blkdev.h> 1.7 +#include <linux/list.h> 1.8 1.9 /* 1.10 * For convenience we distinguish between ide, scsi and 'other' (i.e., 1.11 @@ -42,6 +43,14 @@ 1.12 #define NUM_SCSI_MAJORS 9 1.13 #define NUM_VBD_MAJORS 1 1.14 1.15 +struct lvdisk 1.16 +{ 1.17 + blkif_sector_t capacity; /* 0: Size in terms of 512-byte sectors. */ 1.18 + blkif_vdev_t device; /* 8: Device number (opaque 16 bit value). */ 1.19 + u16 info; 1.20 + struct list_head list; 1.21 +}; 1.22 + 1.23 static struct xlbd_type_info xlbd_ide_type = { 1.24 .partn_shift = 6, 1.25 .partn_per_major = 2, 1.26 @@ -66,10 +75,17 @@ static struct xlbd_type_info xlbd_vbd_ty 1.27 static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS + 1.28 NUM_VBD_MAJORS]; 1.29 1.30 +#define XLBD_MAJOR_IDE_START 0 1.31 +#define XLBD_MAJOR_SCSI_START (NUM_IDE_MAJORS) 1.32 +#define XLBD_MAJOR_VBD_START (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) 1.33 + 1.34 +#define XLBD_MAJOR_IDE_RANGE XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1 1.35 +#define XLBD_MAJOR_SCSI_RANGE XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1 1.36 +#define XLBD_MAJOR_VBD_RANGE XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1 1.37 + 1.38 /* Information about our VBDs. */ 1.39 #define MAX_VBDS 64 1.40 -static int nr_vbds; 1.41 -static vdisk_t *vbd_info; 1.42 +struct list_head vbds_list; 1.43 1.44 struct request_queue *xlbd_blk_queue = NULL; 1.45 1.46 @@ -82,310 +98,376 @@ static struct block_device_operations xl 1.47 .open = blkif_open, 1.48 .release = blkif_release, 1.49 .ioctl = blkif_ioctl, 1.50 -#if 0 1.51 - check_media_change: blkif_check, 1.52 - revalidate: blkif_revalidate, 1.53 -#endif 1.54 }; 1.55 1.56 spinlock_t blkif_io_lock = SPIN_LOCK_UNLOCKED; 1.57 1.58 -static int xlvbd_get_vbd_info(vdisk_t *disk_info) 1.59 +static struct lvdisk * xlvbd_device_alloc(void) 1.60 +{ 1.61 + struct lvdisk *ret; 1.62 + 1.63 + ret = kmalloc(sizeof(struct lvdisk), GFP_KERNEL); 1.64 + if ( ret ) { 1.65 + memset(ret, '\0', 0); 1.66 + INIT_LIST_HEAD(&ret->list); 1.67 + } 1.68 + return ret; 1.69 +} 1.70 + 1.71 +static void xlvbd_device_free(struct lvdisk *disk) 1.72 { 1.73 - vdisk_t *buf = (vdisk_t *)__get_free_page(GFP_KERNEL); 1.74 - blkif_request_t req; 1.75 + list_del(&disk->list); 1.76 + kfree(disk); 1.77 +} 1.78 + 1.79 +static vdisk_t * xlvbd_probe(int *ret) 1.80 +{ 1.81 blkif_response_t rsp; 1.82 - int nr; 1.83 + blkif_request_t req; 1.84 + vdisk_t *disk_info = NULL; 1.85 + unsigned long buf; 1.86 + int nr; 1.87 + 1.88 + buf = __get_free_page(GFP_KERNEL); 1.89 + if ( !buf ) 1.90 + goto out; 1.91 1.92 memset(&req, 0, sizeof(req)); 1.93 - req.operation = BLKIF_OP_PROBE; 1.94 + req.operation = BLKIF_OP_PROBE; 1.95 req.nr_segments = 1; 1.96 req.frame_and_sects[0] = virt_to_machine(buf) | 7; 1.97 1.98 blkif_control_send(&req, &rsp); 1.99 - 1.100 - if ( rsp.status <= 0 ) 1.101 - { 1.102 + if ( rsp.status <= 0 ) { 1.103 printk(KERN_ALERT "Could not probe disks (%d)\n", rsp.status); 1.104 - return -1; 1.105 + goto out; 1.106 } 1.107 + nr = rsp.status; 1.108 + if ( nr > MAX_VBDS ) 1.109 + nr = MAX_VBDS; 1.110 1.111 - if ( (nr = rsp.status) > MAX_VBDS ) 1.112 - nr = MAX_VBDS; 1.113 - memcpy(disk_info, buf, nr * sizeof(vdisk_t)); 1.114 - 1.115 - free_page((unsigned long)buf); 1.116 - 1.117 - return nr; 1.118 + disk_info = kmalloc(nr * sizeof(vdisk_t), GFP_KERNEL); 1.119 + if ( disk_info ) 1.120 + memcpy(disk_info, (void *) buf, nr * sizeof(vdisk_t)); 1.121 + if ( ret ) 1.122 + *ret = nr; 1.123 +out: 1.124 + free_page(buf); 1.125 + return disk_info; 1.126 } 1.127 1.128 -static struct xlbd_major_info *xlbd_get_major_info(int xd_device, int *minor) 1.129 +static struct xlbd_major_info *xlbd_alloc_major_info(int major, int minor, int index) 1.130 { 1.131 - int mi_idx, new_major; 1.132 - int xd_major = MAJOR_XEN(xd_device); 1.133 - int xd_minor = MINOR_XEN(xd_device); 1.134 + struct xlbd_major_info *ptr; 1.135 1.136 - *minor = xd_minor; 1.137 + ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL); 1.138 + if ( !ptr ) 1.139 + return NULL; 1.140 + 1.141 + memset(ptr, 0, sizeof(struct xlbd_major_info)); 1.142 + 1.143 + ptr->major = major; 1.144 1.145 - switch (xd_major) { 1.146 - case IDE0_MAJOR: mi_idx = 0; new_major = IDE0_MAJOR; break; 1.147 - case IDE1_MAJOR: mi_idx = 1; new_major = IDE1_MAJOR; break; 1.148 - case IDE2_MAJOR: mi_idx = 2; new_major = IDE2_MAJOR; break; 1.149 - case IDE3_MAJOR: mi_idx = 3; new_major = IDE3_MAJOR; break; 1.150 - case IDE4_MAJOR: mi_idx = 4; new_major = IDE4_MAJOR; break; 1.151 - case IDE5_MAJOR: mi_idx = 5; new_major = IDE5_MAJOR; break; 1.152 - case IDE6_MAJOR: mi_idx = 6; new_major = IDE6_MAJOR; break; 1.153 - case IDE7_MAJOR: mi_idx = 7; new_major = IDE7_MAJOR; break; 1.154 - case IDE8_MAJOR: mi_idx = 8; new_major = IDE8_MAJOR; break; 1.155 - case IDE9_MAJOR: mi_idx = 9; new_major = IDE9_MAJOR; break; 1.156 - case SCSI_DISK0_MAJOR: mi_idx = 10; new_major = SCSI_DISK0_MAJOR; break; 1.157 - case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR: 1.158 - mi_idx = 11 + xd_major - SCSI_DISK1_MAJOR; 1.159 - new_major = SCSI_DISK1_MAJOR + xd_major - SCSI_DISK1_MAJOR; 1.160 + switch (index) { 1.161 + case XLBD_MAJOR_IDE_RANGE: 1.162 + ptr->type = &xlbd_ide_type; 1.163 + ptr->index = index - XLBD_MAJOR_IDE_START; 1.164 + break; 1.165 + case XLBD_MAJOR_SCSI_RANGE: 1.166 + ptr->type = &xlbd_scsi_type; 1.167 + ptr->index = index - XLBD_MAJOR_SCSI_START; 1.168 break; 1.169 - case SCSI_CDROM_MAJOR: mi_idx = 18; new_major = SCSI_CDROM_MAJOR; break; 1.170 - default: mi_idx = 19; new_major = 0;/* XXXcl notyet */ break; 1.171 + case XLBD_MAJOR_VBD_RANGE: 1.172 + ptr->type = &xlbd_vbd_type; 1.173 + ptr->index = index - XLBD_MAJOR_VBD_START; 1.174 + break; 1.175 + } 1.176 + 1.177 + if ( register_blkdev(ptr->major, ptr->type->devname) ) { 1.178 + printk(KERN_ALERT "XL VBD: can't get major %d with name %s\n", 1.179 + ptr->major, ptr->type->devname); 1.180 + kfree(ptr); 1.181 + return NULL; 1.182 } 1.183 1.184 - if (major_info[mi_idx]) 1.185 - return major_info[mi_idx]; 1.186 + devfs_mk_dir(ptr->type->devname); 1.187 + major_info[index] = ptr; 1.188 + return ptr; 1.189 +} 1.190 1.191 - major_info[mi_idx] = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL); 1.192 - if (major_info[mi_idx] == NULL) 1.193 - return NULL; 1.194 +static struct xlbd_major_info *xlbd_get_major_info(int device) 1.195 +{ 1.196 + int major, minor, index; 1.197 + 1.198 + major = MAJOR_XEN(device); 1.199 + minor = MINOR_XEN(device); 1.200 1.201 - memset(major_info[mi_idx], 0, sizeof(struct xlbd_major_info)); 1.202 - 1.203 - switch (mi_idx) { 1.204 - case 0 ... (NUM_IDE_MAJORS - 1): 1.205 - major_info[mi_idx]->type = &xlbd_ide_type; 1.206 - major_info[mi_idx]->index = mi_idx; 1.207 + switch (major) { 1.208 + case IDE0_MAJOR: index = 0; break; 1.209 + case IDE1_MAJOR: index = 1; break; 1.210 + case IDE2_MAJOR: index = 2; break; 1.211 + case IDE3_MAJOR: index = 3; break; 1.212 + case IDE4_MAJOR: index = 4; break; 1.213 + case IDE5_MAJOR: index = 5; break; 1.214 + case IDE6_MAJOR: index = 6; break; 1.215 + case IDE7_MAJOR: index = 7; break; 1.216 + case IDE8_MAJOR: index = 8; break; 1.217 + case IDE9_MAJOR: index = 9; break; 1.218 + case SCSI_DISK0_MAJOR: index = 10; break; 1.219 + case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR: 1.220 + index = 11 + major - SCSI_DISK1_MAJOR; 1.221 break; 1.222 - case NUM_IDE_MAJORS ... (NUM_IDE_MAJORS + NUM_SCSI_MAJORS - 1): 1.223 - major_info[mi_idx]->type = &xlbd_scsi_type; 1.224 - major_info[mi_idx]->index = mi_idx - NUM_IDE_MAJORS; 1.225 - break; 1.226 - case (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) ... 1.227 - (NUM_IDE_MAJORS + NUM_SCSI_MAJORS + NUM_VBD_MAJORS - 1): 1.228 - major_info[mi_idx]->type = &xlbd_vbd_type; 1.229 - major_info[mi_idx]->index = mi_idx - 1.230 - (NUM_IDE_MAJORS + NUM_SCSI_MAJORS); 1.231 - break; 1.232 - } 1.233 - major_info[mi_idx]->major = new_major; 1.234 - 1.235 - if (register_blkdev(major_info[mi_idx]->major, major_info[mi_idx]->type->devname)) { 1.236 - printk(KERN_ALERT "XL VBD: can't get major %d with name %s\n", 1.237 - major_info[mi_idx]->major, major_info[mi_idx]->type->devname); 1.238 - goto out; 1.239 + case SCSI_CDROM_MAJOR: index = 18; break; 1.240 + default: index = 19; break; 1.241 } 1.242 1.243 - devfs_mk_dir(major_info[mi_idx]->type->devname); 1.244 - 1.245 - return major_info[mi_idx]; 1.246 - 1.247 - out: 1.248 - kfree(major_info[mi_idx]); 1.249 - major_info[mi_idx] = NULL; 1.250 - return NULL; 1.251 + return major_info[index] 1.252 + ? major_info[index] 1.253 + : xlbd_alloc_major_info(major, minor, index); 1.254 } 1.255 1.256 -static struct gendisk *xlvbd_get_gendisk(struct xlbd_major_info *mi, 1.257 - int xd_minor, vdisk_t *xd) 1.258 +static int xlvbd_blk_queue_alloc(struct xlbd_type_info *type) 1.259 +{ 1.260 + xlbd_blk_queue = blk_init_queue(do_blkif_request, &blkif_io_lock); 1.261 + if ( !xlbd_blk_queue ) 1.262 + return -1; 1.263 + 1.264 + elevator_init(xlbd_blk_queue, "noop"); 1.265 + 1.266 + /* 1.267 + * Turn off barking 'headactive' mode. We dequeue 1.268 + * buffer heads as soon as we pass them to back-end 1.269 + * driver. 1.270 + */ 1.271 + blk_queue_headactive(xlbd_blk_queue, 0); 1.272 + 1.273 + /* Hard sector size and max sectors impersonate the equiv. hardware. */ 1.274 + blk_queue_hardsect_size(xlbd_blk_queue, 512); 1.275 + blk_queue_max_sectors(xlbd_blk_queue, 512); 1.276 + 1.277 + /* Each segment in a request is up to an aligned page in size. */ 1.278 + blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1); 1.279 + blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE); 1.280 + 1.281 + /* Ensure a merged request will fit in a single I/O ring slot. */ 1.282 + blk_queue_max_phys_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); 1.283 + blk_queue_max_hw_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); 1.284 + 1.285 + /* Make sure buffer addresses are sector-aligned. */ 1.286 + blk_queue_dma_alignment(xlbd_blk_queue, 511); 1.287 + return 0; 1.288 +} 1.289 + 1.290 +struct gendisk *xlvbd_alloc_gendisk(struct xlbd_major_info *mi, int minor, 1.291 + vdisk_t *disk) 1.292 { 1.293 struct gendisk *gd; 1.294 struct xlbd_disk_info *di; 1.295 - int device, partno; 1.296 - 1.297 - device = MKDEV(mi->major, xd_minor); 1.298 - gd = get_gendisk(device, &partno); 1.299 - if ( gd != NULL ) 1.300 - return gd; 1.301 + int nb_minors; 1.302 1.303 di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL); 1.304 - if ( di == NULL ) 1.305 - return NULL; 1.306 + if ( !di ) 1.307 + goto out; 1.308 di->mi = mi; 1.309 - di->xd_device = xd->device; 1.310 + di->xd_device = disk->device; 1.311 1.312 - /* Construct an appropriate gendisk structure. */ 1.313 - gd = alloc_disk(1); 1.314 - if ( gd == NULL ) 1.315 + nb_minors = ((minor & ((1 << mi->type->partn_shift) - 1)) == 0) 1.316 + ? mi->type->partn_per_major 1.317 + : 1; 1.318 + 1.319 + gd = alloc_disk(nb_minors); 1.320 + if ( !gd ) 1.321 goto out; 1.322 1.323 + if ( nb_minors > 1 ) 1.324 + sprintf(gd->disk_name, "%s%c", mi->type->diskname, 1.325 + 'a' + mi->index * mi->type->partn_per_major + 1.326 + (minor >> mi->type->partn_shift)); 1.327 + else 1.328 + sprintf(gd->disk_name, "%s%c%d", mi->type->diskname, 1.329 + 'a' + mi->index * mi->type->partn_per_major + 1.330 + (minor >> mi->type->partn_shift), 1.331 + minor & ((1 << mi->type->partn_shift) - 1)); 1.332 + 1.333 gd->major = mi->major; 1.334 - gd->first_minor = xd_minor; 1.335 + gd->first_minor = minor; 1.336 gd->fops = &xlvbd_block_fops; 1.337 gd->private_data = di; 1.338 - sprintf(gd->disk_name, "%s%c%d", mi->type->diskname, 1.339 - 'a' + mi->index * mi->type->partn_per_major + 1.340 - (xd_minor >> mi->type->partn_shift), 1.341 - xd_minor & ((1 << mi->type->partn_shift) - 1)); 1.342 - 1.343 - set_capacity(gd, xd->capacity); 1.344 + set_capacity(gd, disk->capacity); 1.345 1.346 - if ( xlbd_blk_queue == NULL ) 1.347 - { 1.348 - xlbd_blk_queue = blk_init_queue(do_blkif_request, 1.349 - &blkif_io_lock); 1.350 - if ( xlbd_blk_queue == NULL ) 1.351 - goto out; 1.352 - elevator_init(xlbd_blk_queue, "noop"); 1.353 - 1.354 - /* 1.355 - * Turn off barking 'headactive' mode. We dequeue buffer heads as soon 1.356 - * as we pass them to back-end driver. 1.357 - */ 1.358 - blk_queue_headactive(xlbd_blk_queue, 0); 1.359 + if ( !xlbd_blk_queue ) 1.360 + if ( xlvbd_blk_queue_alloc(mi->type) ) 1.361 + goto out_gendisk; 1.362 1.363 - blk_queue_hardsect_size(xlbd_blk_queue, 512); 1.364 - blk_queue_max_sectors(xlbd_blk_queue, 512); 1.365 - 1.366 - /* Each segment in a request is up to an aligned page in size. */ 1.367 - blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1); 1.368 - blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE); 1.369 - 1.370 - /* Ensure a merged request will fit in a single I/O ring slot. */ 1.371 - blk_queue_max_phys_segments( 1.372 - xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); 1.373 - blk_queue_max_hw_segments( 1.374 - xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); 1.375 - 1.376 - /* Make sure buffer addresses are sector-aligned. */ 1.377 - blk_queue_dma_alignment(xlbd_blk_queue, 511); 1.378 - } 1.379 gd->queue = xlbd_blk_queue; 1.380 - 1.381 add_disk(gd); 1.382 - 1.383 return gd; 1.384 - 1.385 - out: 1.386 - if ( gd != NULL ) 1.387 - del_gendisk(gd); 1.388 +out_gendisk: 1.389 + printk(KERN_ALERT "error gendisk\n"); 1.390 + del_gendisk(gd); 1.391 +out: 1.392 + printk(KERN_ALERT "error out\n"); 1.393 kfree(di); 1.394 return NULL; 1.395 } 1.396 1.397 -/* 1.398 - * xlvbd_init_device - initialise a VBD device 1.399 - * @disk: a vdisk_t describing the VBD 1.400 - * 1.401 - * Takes a vdisk_t * that describes a VBD the domain has access to. 1.402 - * Performs appropriate initialisation and registration of the device. 1.403 - * 1.404 - * Care needs to be taken when making re-entrant calls to ensure that 1.405 - * corruption does not occur. Also, devices that are in use should not have 1.406 - * their details updated. This is the caller's responsibility. 1.407 - */ 1.408 -static int xlvbd_init_device(vdisk_t *xd) 1.409 +static int xlvbd_device_add(struct list_head *list, vdisk_t *disk) 1.410 { 1.411 + struct lvdisk *new; 1.412 + int minor; 1.413 + dev_t device; 1.414 struct block_device *bd; 1.415 struct gendisk *gd; 1.416 struct xlbd_major_info *mi; 1.417 - int device; 1.418 - int minor; 1.419 1.420 - int err = -ENOMEM; 1.421 - 1.422 - mi = xlbd_get_major_info(xd->device, &minor); 1.423 - if (mi == NULL) 1.424 + mi = xlbd_get_major_info(disk->device); 1.425 + if ( !mi ) 1.426 return -EPERM; 1.427 1.428 + new = xlvbd_device_alloc(); 1.429 + if ( !new ) 1.430 + return -1; 1.431 + new->capacity = disk->capacity; 1.432 + new->device = disk->device; 1.433 + new->info = disk->info; 1.434 + 1.435 + minor = MINOR_XEN(disk->device); 1.436 device = MKDEV(mi->major, minor); 1.437 - 1.438 - if ((bd = bdget(device)) == NULL) 1.439 - return -EPERM; 1.440 - 1.441 - /* 1.442 - * Update of partition info, and check of usage count, is protected 1.443 - * by the per-block-device semaphore. 1.444 - */ 1.445 + 1.446 + bd = bdget(device); 1.447 + if ( !bd ) 1.448 + goto out; 1.449 + 1.450 down(&bd->bd_sem); 1.451 1.452 - gd = xlvbd_get_gendisk(mi, minor, xd); 1.453 - if (gd == NULL) { 1.454 - err = -EPERM; 1.455 + gd = xlvbd_alloc_gendisk(mi, minor, disk); 1.456 + if ( !gd ) 1.457 + goto out_bd; 1.458 + 1.459 + if ( VDISK_READONLY(disk->info) ) 1.460 + set_disk_ro(gd, 1); 1.461 + 1.462 + switch (VDISK_TYPE(disk->info)) { 1.463 + case VDISK_TYPE_CDROM: 1.464 + gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD; 1.465 + break; 1.466 + case VDISK_TYPE_FLOPPY: 1.467 + case VDISK_TYPE_TAPE: 1.468 + gd->flags |= GENHD_FL_REMOVABLE; 1.469 + break; 1.470 + case VDISK_TYPE_DISK: 1.471 + break; 1.472 + default: 1.473 + printk(KERN_ALERT "XenLinux: unknown device type %d\n", 1.474 + VDISK_TYPE(disk->info)); 1.475 + break; 1.476 + } 1.477 + 1.478 + list_add(&new->list, list); 1.479 +out_bd: 1.480 + up(&bd->bd_sem); 1.481 + bdput(bd); 1.482 +out: 1.483 + return 0; 1.484 +} 1.485 + 1.486 +static int xlvbd_device_del(struct lvdisk *disk) 1.487 +{ 1.488 + dev_t device; 1.489 + struct block_device *bd; 1.490 + struct gendisk *gd; 1.491 + struct xlbd_disk_info *di; 1.492 + int ret = 0, unused; 1.493 + 1.494 + device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device)); 1.495 + 1.496 + bd = bdget(device); 1.497 + if ( !bd ) 1.498 + return -1; 1.499 + 1.500 + down(&bd->bd_sem); 1.501 + 1.502 + gd = get_gendisk(device, &unused); 1.503 + di = gd->private_data; 1.504 + 1.505 + if ( di->mi->usage != 0 ) { 1.506 + printk(KERN_ALERT "VBD removal failed: used [dev=%x]\n", device); 1.507 + ret = -1; 1.508 goto out; 1.509 } 1.510 1.511 - if (VDISK_READONLY(xd->info)) 1.512 - set_disk_ro(gd, 1); 1.513 - 1.514 - /* Some final fix-ups depending on the device type */ 1.515 - switch (VDISK_TYPE(xd->info)) { 1.516 - case VDISK_TYPE_CDROM: 1.517 - gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD; 1.518 - /* FALLTHROUGH */ 1.519 - case VDISK_TYPE_FLOPPY: 1.520 - case VDISK_TYPE_TAPE: 1.521 - gd->flags |= GENHD_FL_REMOVABLE; 1.522 - break; 1.523 - 1.524 - case VDISK_TYPE_DISK: 1.525 - break; 1.526 - 1.527 - default: 1.528 - printk(KERN_ALERT "XenLinux: unknown device type %d\n", 1.529 - VDISK_TYPE(xd->info)); 1.530 - break; 1.531 - } 1.532 - 1.533 - err = 0; 1.534 - out: 1.535 - up(&bd->bd_sem); 1.536 - bdput(bd); 1.537 - return err; 1.538 -} 1.539 + del_gendisk(gd); 1.540 1.541 -/* 1.542 - * xlvbd_remove_device - remove a device node if possible 1.543 - * @device: numeric device ID 1.544 - * 1.545 - * Updates the gendisk structure and invalidates devices. 1.546 - * 1.547 - * This is OK for now but in future, should perhaps consider where this should 1.548 - * deallocate gendisks / unregister devices. 1.549 - */ 1.550 -static int xlvbd_remove_device(int dev16) 1.551 -{ 1.552 - int i, rc = 0; 1.553 - struct gendisk *gd; 1.554 - struct block_device *bd; 1.555 - struct xlbd_disk_info *di; 1.556 - dev_t device = MKDEV(MAJOR_XEN(dev16), MINOR_XEN(dev16)); 1.557 - 1.558 - bd = bdget(device); 1.559 - if (!bd) 1.560 - return -1; 1.561 - 1.562 - /* 1.563 - * Update of partition info, and check of usage count, is protected 1.564 - * by the per-block-device semaphore. 1.565 - */ 1.566 - down(&bd->bd_sem); 1.567 - 1.568 - gd = get_gendisk(device, &i); 1.569 - BUG_ON(gd == NULL); 1.570 - di = (struct xlbd_disk_info *) gd->private_data; 1.571 - BUG_ON(di == NULL); 1.572 - 1.573 - if ( di->mi->usage != 0 ) 1.574 - { 1.575 - printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device); 1.576 - rc = -1; 1.577 - goto out; 1.578 - } 1.579 - 1.580 - /* The VBD is mapped to an entire unit. */ 1.581 - 1.582 - invalidate_partition(gd, 0); 1.583 - set_capacity(gd, 0); 1.584 - 1.585 + xlvbd_device_free(disk); 1.586 out: 1.587 up(&bd->bd_sem); 1.588 bdput(bd); 1.589 - return rc; 1.590 + return ret; 1.591 +} 1.592 + 1.593 +static int xlvbd_device_update(struct lvdisk *ldisk, vdisk_t *disk) 1.594 +{ 1.595 + dev_t device; 1.596 + struct block_device *bd; 1.597 + struct gendisk *gd; 1.598 + int unused; 1.599 + 1.600 + if ( ldisk->capacity == disk->capacity && ldisk->info == disk->info ) 1.601 + return 0; 1.602 + 1.603 + device = MKDEV(MAJOR_XEN(ldisk->device), MINOR_XEN(ldisk->device)); 1.604 + 1.605 + bd = bdget(device); 1.606 + if ( !bd ) 1.607 + return -1; 1.608 + 1.609 + down(&bd->bd_sem); 1.610 + 1.611 + gd = get_gendisk(device, &unused); 1.612 + set_capacity(gd, disk->capacity); 1.613 + ldisk->capacity = disk->capacity; 1.614 + 1.615 + up(&bd->bd_sem); 1.616 + bdput(bd); 1.617 + 1.618 + return 0; 1.619 +} 1.620 + 1.621 +void xlvbd_refresh(void) 1.622 +{ 1.623 + vdisk_t *newdisks; 1.624 + struct list_head *tmp, *tmp2; 1.625 + struct lvdisk *disk; 1.626 + int i, nr; 1.627 + 1.628 + newdisks = xlvbd_probe(&nr); 1.629 + if ( !newdisks ) { 1.630 + printk(KERN_ALERT "failed to probe\n"); 1.631 + return; 1.632 + } 1.633 + 1.634 + i = 0; 1.635 + list_for_each_safe(tmp, tmp2, &vbds_list) { 1.636 + disk = list_entry(tmp, struct lvdisk, list); 1.637 + 1.638 + for (i = 0; i < nr; i++) { 1.639 + if ( !newdisks[i].device ) 1.640 + continue; 1.641 + if ( disk->device == newdisks[i].device ) { 1.642 + xlvbd_device_update(disk, &newdisks[i]); 1.643 + newdisks[i].device = 0; 1.644 + break; 1.645 + } 1.646 + } 1.647 + if ( i == nr ) { 1.648 + xlvbd_device_del(disk); 1.649 + newdisks[i].device = 0; 1.650 + } 1.651 + } 1.652 + for (i = 0; i < nr; i++) 1.653 + if ( newdisks[i].device ) 1.654 + xlvbd_device_add(&vbds_list, &newdisks[i]); 1.655 + kfree(newdisks); 1.656 } 1.657 1.658 /* 1.659 @@ -395,75 +477,7 @@ out: 1.660 */ 1.661 void xlvbd_update_vbds(void) 1.662 { 1.663 - int i, j, k, old_nr, new_nr; 1.664 - vdisk_t *old_info, *new_info, *merged_info; 1.665 - 1.666 - old_info = vbd_info; 1.667 - old_nr = nr_vbds; 1.668 - 1.669 - new_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL); 1.670 - if (!new_info) 1.671 - return; 1.672 - 1.673 - if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 ) 1.674 - goto out; 1.675 - 1.676 - /* 1.677 - * Final list maximum size is old list + new list. This occurs only when 1.678 - * old list and new list do not overlap at all, and we cannot yet destroy 1.679 - * VBDs in the old list because the usage counts are busy. 1.680 - */ 1.681 - merged_info = kmalloc((old_nr + new_nr) * sizeof(vdisk_t), GFP_KERNEL); 1.682 - if (!merged_info) 1.683 - goto out; 1.684 - 1.685 - /* @i tracks old list; @j tracks new list; @k tracks merged list. */ 1.686 - i = j = k = 0; 1.687 - 1.688 - while ( (i < old_nr) && (j < new_nr) ) 1.689 - { 1.690 - if ( old_info[i].device < new_info[j].device ) 1.691 - { 1.692 - if ( xlvbd_remove_device(old_info[i].device) != 0 ) 1.693 - memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t)); 1.694 - i++; 1.695 - } 1.696 - else if ( old_info[i].device > new_info[j].device ) 1.697 - { 1.698 - if ( xlvbd_init_device(&new_info[j]) == 0 ) 1.699 - memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t)); 1.700 - j++; 1.701 - } 1.702 - else 1.703 - { 1.704 - if ( ((old_info[i].capacity == new_info[j].capacity) && 1.705 - (old_info[i].info == new_info[j].info)) || 1.706 - (xlvbd_remove_device(old_info[i].device) != 0) ) 1.707 - memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t)); 1.708 - else if ( xlvbd_init_device(&new_info[j]) == 0 ) 1.709 - memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t)); 1.710 - i++; j++; 1.711 - } 1.712 - } 1.713 - 1.714 - for ( ; i < old_nr; i++ ) 1.715 - { 1.716 - if ( xlvbd_remove_device(old_info[i].device) != 0 ) 1.717 - memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t)); 1.718 - } 1.719 - 1.720 - for ( ; j < new_nr; j++ ) 1.721 - { 1.722 - if ( xlvbd_init_device(&new_info[j]) == 0 ) 1.723 - memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t)); 1.724 - } 1.725 - 1.726 - vbd_info = merged_info; 1.727 - nr_vbds = k; 1.728 - 1.729 - kfree(old_info); 1.730 -out: 1.731 - kfree(new_info); 1.732 + xlvbd_refresh(); 1.733 } 1.734 1.735 /* 1.736 @@ -477,26 +491,21 @@ out: 1.737 */ 1.738 int xlvbd_init(void) 1.739 { 1.740 - int i; 1.741 + int i, nr; 1.742 + vdisk_t *disks; 1.743 + 1.744 + INIT_LIST_HEAD(&vbds_list); 1.745 1.746 memset(major_info, 0, sizeof(major_info)); 1.747 - 1.748 - vbd_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL); 1.749 - if (vbd_info == NULL) { 1.750 - printk(KERN_ALERT "Failed to allocate memory for disk info.\n"); 1.751 - nr_vbds = 0; 1.752 - return 0; 1.753 + 1.754 + disks = xlvbd_probe(&nr); 1.755 + if ( !disks ) { 1.756 + printk(KERN_ALERT "failed to probe\n"); 1.757 + return -1; 1.758 } 1.759 1.760 - nr_vbds = xlvbd_get_vbd_info(vbd_info); 1.761 - if (nr_vbds < 0) { 1.762 - kfree(vbd_info); 1.763 - vbd_info = NULL; 1.764 - nr_vbds = 0; 1.765 - } else { 1.766 - for (i = 0; i < nr_vbds; i++) 1.767 - xlvbd_init_device(&vbd_info[i]); 1.768 - } 1.769 - 1.770 + for (i = 0; i < nr; i++) 1.771 + xlvbd_device_add(&vbds_list, &disks[i]); 1.772 + kfree(disks); 1.773 return 0; 1.774 }
2.1 --- a/tools/python/xen/xend/XendClient.py Fri Apr 01 13:17:52 2005 +0000 2.2 +++ b/tools/python/xen/xend/XendClient.py Fri Apr 01 13:37:55 2005 +0000 2.3 @@ -308,6 +308,12 @@ class Xend: 2.4 {'op' : 'device_create', 2.5 'config' : fileof(config) }) 2.6 2.7 + def xend_domain_device_refresh(self, id, type, idx): 2.8 + return self.xendPost(self.domainurl(id), 2.9 + {'op' : 'device_refresh', 2.10 + 'type' : type, 2.11 + 'idx' : idx }) 2.12 + 2.13 def xend_domain_device_destroy(self, id, type, idx): 2.14 return self.xendPost(self.domainurl(id), 2.15 {'op' : 'device_destroy',
3.1 --- a/tools/python/xen/xend/XendDomain.py Fri Apr 01 13:17:52 2005 +0000 3.2 +++ b/tools/python/xen/xend/XendDomain.py Fri Apr 01 13:37:55 2005 +0000 3.3 @@ -687,6 +687,18 @@ class XendDomain: 3.4 self.update_domain(dominfo.id) 3.5 return val 3.6 3.7 + def domain_device_refresh(self, id, type, idx): 3.8 + """Refresh a device. 3.9 + 3.10 + @param id: domain id 3.11 + @param idx: device index 3.12 + @param type: device type 3.13 + """ 3.14 + dominfo = self.domain_lookup(id) 3.15 + self.refresh_schedule() 3.16 + val = dominfo.device_refresh(type, idx) 3.17 + self.update_domain(dominfo.id) 3.18 + return val 3.19 3.20 def domain_device_destroy(self, id, type, idx): 3.21 """Destroy a device.
4.1 --- a/tools/python/xen/xend/XendDomainInfo.py Fri Apr 01 13:17:52 2005 +0000 4.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Apr 01 13:37:55 2005 +0000 4.3 @@ -551,6 +551,16 @@ class XendDomainInfo: 4.4 dl.append(dev) 4.5 self.devices[type] = dl 4.6 4.7 + def refresh_device(self, type, dev): 4.8 + """Refresh a device to a virtual machine. 4.9 + 4.10 + @param type: device type 4.11 + @param dev: device 4.12 + """ 4.13 + dl = self.devices.get(type, []) 4.14 + if dev in dl: 4.15 + dl.refresh(dev) 4.16 + 4.17 def remove_device(self, type, dev): 4.18 """Remove a device from a virtual machine. 4.19 4.20 @@ -912,6 +922,19 @@ class XendDomainInfo: 4.21 old_index = self.config.index(old_full_config) 4.22 self.config[old_index] = new_full_config 4.23 return new_config 4.24 + 4.25 + def device_refresh(self, type, idx): 4.26 + """Refresh a device. 4.27 + 4.28 + @param type: device type 4.29 + @param idx: device index 4.30 + """ 4.31 + dev = self.get_device_by_index(type, idx) 4.32 + if not dev: 4.33 + raise VmError('invalid device: %s %s' % (type, idx)) 4.34 + devs = self.devices.get(type) 4.35 + dev.refresh() 4.36 + #self.refresh_device(type, dev) 4.37 4.38 def device_destroy(self, type, idx): 4.39 """Destroy a device.
5.1 --- a/tools/python/xen/xend/server/SrvDomain.py Fri Apr 01 13:17:52 2005 +0000 5.2 +++ b/tools/python/xen/xend/server/SrvDomain.py Fri Apr 01 13:37:55 2005 +0000 5.3 @@ -131,6 +131,14 @@ class SrvDomain(SrvDir): 5.4 d = fn(req.args, {'dom': self.dom.id}) 5.5 return d 5.6 5.7 + def op_device_refresh(self, op, req): 5.8 + fn = FormFn(self.xd.domain_device_refresh, 5.9 + [['dom', 'str'], 5.10 + ['type', 'str'], 5.11 + ['idx', 'str']]) 5.12 + val = fn(req.args, {'dom': self.dom.id}) 5.13 + return val 5.14 + 5.15 def op_device_destroy(self, op, req): 5.16 fn = FormFn(self.xd.domain_device_destroy, 5.17 [['dom', 'str'],
6.1 --- a/tools/python/xen/xend/server/blkif.py Fri Apr 01 13:17:52 2005 +0000 6.2 +++ b/tools/python/xen/xend/server/blkif.py Fri Apr 01 13:37:55 2005 +0000 6.3 @@ -414,6 +414,10 @@ class BlkDev(controller.SplitDev): 6.4 val.append(['index', self.index]) 6.5 return val 6.6 6.7 + def refresh(self): 6.8 + log.debug("Refreshing vbd domain=%d idx=%s", self.controller.dom, self.idx) 6.9 + self.interfaceChanged() 6.10 + 6.11 def destroy(self, change=0): 6.12 """Destroy the device. If 'change' is true notify the front-end interface. 6.13
7.1 --- a/tools/python/xen/xm/main.py Fri Apr 01 13:17:52 2005 +0000 7.2 +++ b/tools/python/xen/xm/main.py Fri Apr 01 13:37:55 2005 +0000 7.3 @@ -800,6 +800,28 @@ Create a virtual block device for a doma 7.4 7.5 xm.prog(ProgVbdCreate) 7.6 7.7 +class ProgVbdRefresh(Prog): 7.8 + group = 'vbd' 7.9 + name = 'vbd-refresh' 7.10 + info = """Refresh a virtual block device for a domain""" 7.11 + 7.12 + def help(self, args): 7.13 + print args[0], "DOM DEV" 7.14 + print """ 7.15 +Refresh a virtual block device for a domain. 7.16 + 7.17 + DEV - idx field in the device information 7.18 +""" 7.19 + 7.20 + def main(self, args): 7.21 + if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0]) 7.22 + dom = args[1] 7.23 + dev = args[2] 7.24 + server.xend_domain_device_refresh(dom, 'vbd', dev) 7.25 + 7.26 +xm.prog(ProgVbdRefresh) 7.27 + 7.28 + 7.29 class ProgVbdDestroy(Prog): 7.30 group = 'vbd' 7.31 name = 'vbd-destroy'