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
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'