ia64/xen-unstable

changeset 5036:664508b09c16

bitkeeper revision 1.1159.258.141 (428de6e3qI6WPj3ZDv-N9guEb9d7uA)

Blkfront cleanups and fix whole-device mapping.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri May 20 13:32:19 2005 +0000 (2005-05-20)
parents 829173784dc1
children 08bcb94afa37 7693dd47436e
files linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c
line diff
     1.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri May 20 01:00:03 2005 +0000
     1.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri May 20 13:32:19 2005 +0000
     1.3 @@ -60,8 +60,6 @@ static void vbd_update(void){};
     1.4  #define BLKIF_STATE_DISCONNECTED 1
     1.5  #define BLKIF_STATE_CONNECTED    2
     1.6  
     1.7 -#define WPRINTK(fmt, args...) printk(KERN_WARNING "xen_blk: " fmt, ##args)
     1.8 -
     1.9  static int blkif_handle = 0;
    1.10  static unsigned int blkif_state = BLKIF_STATE_CLOSED;
    1.11  static unsigned int blkif_evtchn = 0;
    1.12 @@ -694,7 +692,7 @@ int blkif_ioctl(struct inode *inode, str
    1.13          return -ENOSYS;
    1.14  
    1.15      default:
    1.16 -        printk(KERN_ALERT "ioctl %08x not supported by XL blkif\n", command);
    1.17 +        WPRINTK("ioctl %08x not supported by XL blkif\n", command);
    1.18          return -ENOSYS;
    1.19      }
    1.20      
    1.21 @@ -1206,7 +1204,7 @@ static void blkif_connect(blkif_fe_inter
    1.22      err = request_irq(blkif_irq, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL);
    1.23      if ( err )
    1.24      {
    1.25 -        printk(KERN_ALERT "xen_blk: request_irq failed (err=%d)\n", err);
    1.26 +        WPRINTK("request_irq failed (err=%d)\n", err);
    1.27          return;
    1.28      }
    1.29  
    1.30 @@ -1353,7 +1351,7 @@ int wait_for_blkif(void)
    1.31  
    1.32      if ( blkif_state != BLKIF_STATE_CONNECTED )
    1.33      {
    1.34 -        printk(KERN_INFO "xen_blk: Timeout connecting to device!\n");
    1.35 +        WPRINTK("Timeout connecting to device!\n");
    1.36          err = -ENOSYS;
    1.37      }
    1.38      return err;
    1.39 @@ -1367,7 +1365,7 @@ int __init xlblk_init(void)
    1.40           (xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
    1.41          return 0;
    1.42  
    1.43 -    printk(KERN_INFO "xen_blk: Initialising virtual block device driver\n");
    1.44 +    IPRINTK("Initialising virtual block device driver\n");
    1.45  
    1.46      rec_ring_free = 0;
    1.47      for ( i = 0; i < BLKIF_RING_SIZE; i++ )
     2.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h	Fri May 20 01:00:03 2005 +0000
     2.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h	Fri May 20 13:32:19 2005 +0000
     2.3 @@ -50,6 +50,11 @@
     2.4  #include <asm/atomic.h>
     2.5  #include <asm/uaccess.h>
     2.6  
     2.7 +#define IPRINTK(fmt, args...) \
     2.8 +    printk(KERN_INFO "xen_blk: " fmt, ##args)
     2.9 +#define WPRINTK(fmt, args...) \
    2.10 +    printk(KERN_WARNING "xen_blk: " fmt, ##args)
    2.11 +
    2.12  #if 0
    2.13  #define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a )
    2.14  #else
    2.15 @@ -64,8 +69,7 @@
    2.16  
    2.17  struct xlbd_type_info {
    2.18      int partn_shift;
    2.19 -    int partn_per_major;
    2.20 -    int devs_per_major;
    2.21 +    int disks_per_major;
    2.22      char *devname;
    2.23      char *diskname;
    2.24  };
     3.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c	Fri May 20 01:00:03 2005 +0000
     3.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c	Fri May 20 13:32:19 2005 +0000
     3.3 @@ -31,6 +31,7 @@
     3.4  
     3.5  #include "block.h"
     3.6  #include <linux/blkdev.h>
     3.7 +#include <linux/list.h>
     3.8  
     3.9  /*
    3.10   * For convenience we distinguish between ide, scsi and 'other' (i.e.,
    3.11 @@ -42,23 +43,31 @@
    3.12  #define NUM_SCSI_MAJORS 9
    3.13  #define NUM_VBD_MAJORS 1
    3.14  
    3.15 +struct lvdisk
    3.16 +{
    3.17 +    blkif_sector_t capacity; /*  0: Size in terms of 512-byte sectors.   */
    3.18 +    blkif_vdev_t   device;   /*  8: Device number (opaque 16 bit value). */
    3.19 +    u16            info; 
    3.20 +    struct list_head list;
    3.21 +};
    3.22 +
    3.23  static struct xlbd_type_info xlbd_ide_type = {
    3.24      .partn_shift = 6,
    3.25 -    .partn_per_major = 2,
    3.26 +    .disks_per_major = 2,
    3.27      .devname = "ide",
    3.28      .diskname = "hd",
    3.29  };
    3.30  
    3.31  static struct xlbd_type_info xlbd_scsi_type = {
    3.32      .partn_shift = 4,
    3.33 -    .partn_per_major = 16,
    3.34 +    .disks_per_major = 16,
    3.35      .devname = "sd",
    3.36      .diskname = "sd",
    3.37  };
    3.38  
    3.39  static struct xlbd_type_info xlbd_vbd_type = {
    3.40      .partn_shift = 4,
    3.41 -    .partn_per_major = 16,
    3.42 +    .disks_per_major = 16,
    3.43      .devname = "xvd",
    3.44      .diskname = "xvd",
    3.45  };
    3.46 @@ -66,10 +75,17 @@ static struct xlbd_type_info xlbd_vbd_ty
    3.47  static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
    3.48                                           NUM_VBD_MAJORS];
    3.49  
    3.50 +#define XLBD_MAJOR_IDE_START    0
    3.51 +#define XLBD_MAJOR_SCSI_START   (NUM_IDE_MAJORS)
    3.52 +#define XLBD_MAJOR_VBD_START    (NUM_IDE_MAJORS + NUM_SCSI_MAJORS)
    3.53 +
    3.54 +#define XLBD_MAJOR_IDE_RANGE    XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1
    3.55 +#define XLBD_MAJOR_SCSI_RANGE   XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1
    3.56 +#define XLBD_MAJOR_VBD_RANGE    XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1
    3.57 +
    3.58  /* Information about our VBDs. */
    3.59  #define MAX_VBDS 64
    3.60 -static int nr_vbds;
    3.61 -static vdisk_t *vbd_info;
    3.62 +struct list_head vbds_list;
    3.63  
    3.64  struct request_queue *xlbd_blk_queue = NULL;
    3.65  
    3.66 @@ -82,310 +98,371 @@ static struct block_device_operations xl
    3.67      .open  = blkif_open,
    3.68      .release = blkif_release,
    3.69      .ioctl  = blkif_ioctl,
    3.70 -#if 0
    3.71 -    check_media_change: blkif_check,
    3.72 -    revalidate:         blkif_revalidate,
    3.73 -#endif
    3.74  };
    3.75  
    3.76  spinlock_t blkif_io_lock = SPIN_LOCK_UNLOCKED;
    3.77  
    3.78 -static int xlvbd_get_vbd_info(vdisk_t *disk_info)
    3.79 +static struct lvdisk *xlvbd_device_alloc(void)
    3.80 +{
    3.81 +    struct lvdisk *disk;
    3.82 +
    3.83 +    disk = kmalloc(sizeof(*disk), GFP_KERNEL);
    3.84 +    if (disk != NULL) {
    3.85 +        memset(disk, 0, sizeof(*disk));
    3.86 +        INIT_LIST_HEAD(&disk->list);
    3.87 +    }
    3.88 +    return disk;
    3.89 +}
    3.90 +
    3.91 +static void xlvbd_device_free(struct lvdisk *disk)
    3.92  {
    3.93 -    vdisk_t         *buf = (vdisk_t *)__get_free_page(GFP_KERNEL);
    3.94 -    blkif_request_t  req;
    3.95 +    list_del(&disk->list);
    3.96 +    kfree(disk);
    3.97 +}
    3.98 +
    3.99 +static vdisk_t *xlvbd_probe(int *ret)
   3.100 +{
   3.101      blkif_response_t rsp;
   3.102 -    int              nr;
   3.103 +    blkif_request_t req;
   3.104 +    vdisk_t *disk_info = NULL;
   3.105 +    unsigned long buf;
   3.106 +    int nr;
   3.107 +
   3.108 +    buf = __get_free_page(GFP_KERNEL);
   3.109 +    if ((void *)buf == NULL)
   3.110 +        goto out;
   3.111  
   3.112      memset(&req, 0, sizeof(req));
   3.113 -    req.operation   = BLKIF_OP_PROBE;
   3.114 +    req.operation = BLKIF_OP_PROBE;
   3.115      req.nr_segments = 1;
   3.116 +#ifdef CONFIG_XEN_BLKDEV_GRANT
   3.117 +    blkif_control_probe_send(&req, &rsp,
   3.118 +                             (unsigned long)(virt_to_machine(buf)));
   3.119 +#else
   3.120      req.frame_and_sects[0] = virt_to_machine(buf) | 7;
   3.121  
   3.122      blkif_control_send(&req, &rsp);
   3.123 -
   3.124 -    if ( rsp.status <= 0 )
   3.125 -    {
   3.126 -        printk(KERN_ALERT "Could not probe disks (%d)\n", rsp.status);
   3.127 -        return -1;
   3.128 +#endif
   3.129 +    if ( rsp.status <= 0 ) {
   3.130 +        WPRINTK("Could not probe disks (%d)\n", rsp.status);
   3.131 +        goto out;
   3.132      }
   3.133 +    nr = rsp.status;
   3.134 +    if ( nr > MAX_VBDS )
   3.135 +        nr = MAX_VBDS;
   3.136  
   3.137 -    if ( (nr = rsp.status) > MAX_VBDS )
   3.138 -        nr = MAX_VBDS;
   3.139 -    memcpy(disk_info, buf, nr * sizeof(vdisk_t));
   3.140 +    disk_info = kmalloc(nr * sizeof(vdisk_t), GFP_KERNEL);
   3.141 +    if (disk_info != NULL)
   3.142 +        memcpy(disk_info, (void *) buf, nr * sizeof(vdisk_t));
   3.143  
   3.144 -    free_page((unsigned long)buf);
   3.145 +    if (ret != NULL)
   3.146 +        *ret = nr;
   3.147  
   3.148 -    return nr;
   3.149 +out:
   3.150 +    free_page(buf);
   3.151 +    return disk_info;
   3.152  }
   3.153  
   3.154 -static struct xlbd_major_info *xlbd_get_major_info(int xd_device, int *minor)
   3.155 +static struct xlbd_major_info *xlbd_alloc_major_info(
   3.156 +    int major, int minor, int index)
   3.157  {
   3.158 -    int mi_idx, new_major;
   3.159 -    int xd_major = MAJOR_XEN(xd_device); 
   3.160 -    int xd_minor = MINOR_XEN(xd_device);
   3.161 +    struct xlbd_major_info *ptr;
   3.162  
   3.163 -    *minor = xd_minor;
   3.164 +    ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
   3.165 +    if (ptr == NULL)
   3.166 +        return NULL;
   3.167 +
   3.168 +    memset(ptr, 0, sizeof(struct xlbd_major_info));
   3.169 +
   3.170 +    ptr->major = major;
   3.171  
   3.172 -    switch (xd_major) {
   3.173 -    case IDE0_MAJOR: mi_idx = 0; new_major = IDE0_MAJOR; break;
   3.174 -    case IDE1_MAJOR: mi_idx = 1; new_major = IDE1_MAJOR; break;
   3.175 -    case IDE2_MAJOR: mi_idx = 2; new_major = IDE2_MAJOR; break;
   3.176 -    case IDE3_MAJOR: mi_idx = 3; new_major = IDE3_MAJOR; break;
   3.177 -    case IDE4_MAJOR: mi_idx = 4; new_major = IDE4_MAJOR; break;
   3.178 -    case IDE5_MAJOR: mi_idx = 5; new_major = IDE5_MAJOR; break;
   3.179 -    case IDE6_MAJOR: mi_idx = 6; new_major = IDE6_MAJOR; break;
   3.180 -    case IDE7_MAJOR: mi_idx = 7; new_major = IDE7_MAJOR; break;
   3.181 -    case IDE8_MAJOR: mi_idx = 8; new_major = IDE8_MAJOR; break;
   3.182 -    case IDE9_MAJOR: mi_idx = 9; new_major = IDE9_MAJOR; break;
   3.183 -    case SCSI_DISK0_MAJOR: mi_idx = 10; new_major = SCSI_DISK0_MAJOR; break;
   3.184 -    case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
   3.185 -        mi_idx = 11 + xd_major - SCSI_DISK1_MAJOR;
   3.186 -        new_major = SCSI_DISK1_MAJOR + xd_major - SCSI_DISK1_MAJOR;
   3.187 +    switch (index) {
   3.188 +    case XLBD_MAJOR_IDE_RANGE:
   3.189 +        ptr->type = &xlbd_ide_type;
   3.190 +        ptr->index = index - XLBD_MAJOR_IDE_START;
   3.191 +        break;
   3.192 +    case XLBD_MAJOR_SCSI_RANGE:
   3.193 +        ptr->type = &xlbd_scsi_type;
   3.194 +        ptr->index = index - XLBD_MAJOR_SCSI_START;
   3.195          break;
   3.196 -    case SCSI_CDROM_MAJOR: mi_idx = 18; new_major = SCSI_CDROM_MAJOR; break;
   3.197 -    default: mi_idx = 19; new_major = 0;/* XXXcl notyet */ break;
   3.198 +    case XLBD_MAJOR_VBD_RANGE:
   3.199 +        ptr->type = &xlbd_vbd_type;
   3.200 +        ptr->index = index - XLBD_MAJOR_VBD_START;
   3.201 +        break;
   3.202 +    }
   3.203 +    
   3.204 +    if (register_blkdev(ptr->major, ptr->type->devname)) {
   3.205 +        WPRINTK("can't get major %d with name %s\n",
   3.206 +                ptr->major, ptr->type->devname);
   3.207 +        kfree(ptr);
   3.208 +        return NULL;
   3.209      }
   3.210  
   3.211 -    if (major_info[mi_idx])
   3.212 -        return major_info[mi_idx];
   3.213 +    devfs_mk_dir(ptr->type->devname);
   3.214 +    major_info[index] = ptr;
   3.215 +    return ptr;
   3.216 +}
   3.217  
   3.218 -    major_info[mi_idx] = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
   3.219 -    if (major_info[mi_idx] == NULL)
   3.220 -        return NULL;
   3.221 +static struct xlbd_major_info *xlbd_get_major_info(int device)
   3.222 +{
   3.223 +    int major, minor, index;
   3.224 +
   3.225 +    major = MAJOR_XEN(device);
   3.226 +    minor = MINOR_XEN(device);
   3.227  
   3.228 -    memset(major_info[mi_idx], 0, sizeof(struct xlbd_major_info));
   3.229 -
   3.230 -    switch (mi_idx) {
   3.231 -    case 0 ... (NUM_IDE_MAJORS - 1):
   3.232 -        major_info[mi_idx]->type = &xlbd_ide_type;
   3.233 -        major_info[mi_idx]->index = mi_idx;
   3.234 +    switch (major) {
   3.235 +    case IDE0_MAJOR: index = 0; break;
   3.236 +    case IDE1_MAJOR: index = 1; break;
   3.237 +    case IDE2_MAJOR: index = 2; break;
   3.238 +    case IDE3_MAJOR: index = 3; break;
   3.239 +    case IDE4_MAJOR: index = 4; break;
   3.240 +    case IDE5_MAJOR: index = 5; break;
   3.241 +    case IDE6_MAJOR: index = 6; break;
   3.242 +    case IDE7_MAJOR: index = 7; break;
   3.243 +    case IDE8_MAJOR: index = 8; break;
   3.244 +    case IDE9_MAJOR: index = 9; break;
   3.245 +    case SCSI_DISK0_MAJOR: index = 10; break;
   3.246 +    case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
   3.247 +        index = 11 + major - SCSI_DISK1_MAJOR;
   3.248          break;
   3.249 -    case NUM_IDE_MAJORS ... (NUM_IDE_MAJORS + NUM_SCSI_MAJORS - 1):
   3.250 -        major_info[mi_idx]->type = &xlbd_scsi_type;
   3.251 -        major_info[mi_idx]->index = mi_idx - NUM_IDE_MAJORS;
   3.252 -        break;
   3.253 -        case (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) ...
   3.254 -            (NUM_IDE_MAJORS + NUM_SCSI_MAJORS + NUM_VBD_MAJORS - 1):
   3.255 -                major_info[mi_idx]->type = &xlbd_vbd_type;
   3.256 -        major_info[mi_idx]->index = mi_idx -
   3.257 -            (NUM_IDE_MAJORS + NUM_SCSI_MAJORS);
   3.258 -        break;
   3.259 -    }
   3.260 -    major_info[mi_idx]->major = new_major;
   3.261 -
   3.262 -    if (register_blkdev(major_info[mi_idx]->major, major_info[mi_idx]->type->devname)) {
   3.263 -        printk(KERN_ALERT "XL VBD: can't get major %d with name %s\n",
   3.264 -               major_info[mi_idx]->major, major_info[mi_idx]->type->devname);
   3.265 -        goto out;
   3.266 +    case SCSI_CDROM_MAJOR: index = 18; break;
   3.267 +    default: index = 19; break;
   3.268      }
   3.269  
   3.270 -    devfs_mk_dir(major_info[mi_idx]->type->devname);
   3.271 -
   3.272 -    return major_info[mi_idx];
   3.273 -
   3.274 - out:
   3.275 -    kfree(major_info[mi_idx]);
   3.276 -    major_info[mi_idx] = NULL;
   3.277 -    return NULL;
   3.278 +    return ((major_info[index] != NULL) ? major_info[index] :
   3.279 +            xlbd_alloc_major_info(major, minor, index));
   3.280  }
   3.281  
   3.282 -static struct gendisk *xlvbd_get_gendisk(struct xlbd_major_info *mi,
   3.283 -                                         int xd_minor, vdisk_t *xd)
   3.284 +static int xlvbd_blk_queue_alloc(struct xlbd_type_info *type)
   3.285 +{
   3.286 +    xlbd_blk_queue = blk_init_queue(do_blkif_request, &blkif_io_lock);
   3.287 +    if (xlbd_blk_queue == NULL)
   3.288 +        return -1;
   3.289 +
   3.290 +    elevator_init(xlbd_blk_queue, "noop");
   3.291 +
   3.292 +    /*
   3.293 +    * Turn off barking 'headactive' mode. We dequeue
   3.294 +    * buffer heads as soon as we pass them to back-end
   3.295 +    * driver.
   3.296 +    */
   3.297 +    blk_queue_headactive(xlbd_blk_queue, 0);
   3.298 +
   3.299 +    /* Hard sector size and max sectors impersonate the equiv. hardware. */
   3.300 +    blk_queue_hardsect_size(xlbd_blk_queue, 512);
   3.301 +    blk_queue_max_sectors(xlbd_blk_queue, 512);
   3.302 +
   3.303 +    /* Each segment in a request is up to an aligned page in size. */
   3.304 +    blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1);
   3.305 +    blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE);
   3.306 +
   3.307 +    /* Ensure a merged request will fit in a single I/O ring slot. */
   3.308 +    blk_queue_max_phys_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
   3.309 +    blk_queue_max_hw_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
   3.310 +
   3.311 +    /* Make sure buffer addresses are sector-aligned. */
   3.312 +    blk_queue_dma_alignment(xlbd_blk_queue, 511);
   3.313 +    return 0;
   3.314 +}
   3.315 +
   3.316 +struct gendisk *xlvbd_alloc_gendisk(
   3.317 +    struct xlbd_major_info *mi, int minor, vdisk_t *disk)
   3.318  {
   3.319      struct gendisk *gd;
   3.320      struct xlbd_disk_info *di;
   3.321 -    int device, partno;
   3.322 -
   3.323 -    device = MKDEV(mi->major, xd_minor);
   3.324 -    gd = get_gendisk(device, &partno);
   3.325 -    if ( gd != NULL )
   3.326 -        return gd;
   3.327 +    int nr_minors = 1;
   3.328  
   3.329      di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL);
   3.330 -    if ( di == NULL )
   3.331 -        return NULL;
   3.332 +    if (di == NULL)
   3.333 +        goto out;
   3.334      di->mi = mi;
   3.335 -    di->xd_device = xd->device;
   3.336 +    di->xd_device = disk->device;
   3.337  
   3.338 -    /* Construct an appropriate gendisk structure. */
   3.339 -    gd = alloc_disk(1);
   3.340 -    if ( gd == NULL )
   3.341 +    /* Full disk rather than a single partition? */
   3.342 +    if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
   3.343 +        nr_minors = 1 << mi->type->partn_shift;
   3.344 +
   3.345 +    gd = alloc_disk(nr_minors);
   3.346 +    if ( !gd )
   3.347          goto out;
   3.348  
   3.349 +    if ( nr_minors > 1 ) /* full disk? */
   3.350 +        sprintf(gd->disk_name, "%s%c", mi->type->diskname,
   3.351 +                'a' + mi->index * mi->type->disks_per_major +
   3.352 +                    (minor >> mi->type->partn_shift));
   3.353 +    else
   3.354 +        sprintf(gd->disk_name, "%s%c%d", mi->type->diskname,
   3.355 +                'a' + mi->index * mi->type->disks_per_major +
   3.356 +                (minor >> mi->type->partn_shift),
   3.357 +                minor & ((1 << mi->type->partn_shift) - 1));
   3.358 +
   3.359      gd->major = mi->major;
   3.360 -    gd->first_minor = xd_minor;
   3.361 +    gd->first_minor = minor;
   3.362      gd->fops = &xlvbd_block_fops;
   3.363      gd->private_data = di;
   3.364 -    sprintf(gd->disk_name, "%s%c%d", mi->type->diskname,
   3.365 -            'a' + mi->index * mi->type->partn_per_major +
   3.366 -            (xd_minor >> mi->type->partn_shift),
   3.367 -            xd_minor & ((1 << mi->type->partn_shift) - 1));
   3.368 -
   3.369 -    set_capacity(gd, xd->capacity);
   3.370 -
   3.371 -    if ( xlbd_blk_queue == NULL )
   3.372 -    {
   3.373 -        xlbd_blk_queue = blk_init_queue(do_blkif_request,
   3.374 -                                        &blkif_io_lock);
   3.375 -        if ( xlbd_blk_queue == NULL )
   3.376 -            goto out;
   3.377 -        elevator_init(xlbd_blk_queue, "noop");
   3.378 -
   3.379 -        /*
   3.380 -         * Turn off barking 'headactive' mode. We dequeue buffer heads as soon 
   3.381 -         * as we pass them to back-end driver.
   3.382 -         */
   3.383 -        blk_queue_headactive(xlbd_blk_queue, 0);
   3.384 +    set_capacity(gd, disk->capacity);
   3.385  
   3.386 -        blk_queue_hardsect_size(xlbd_blk_queue, 512);
   3.387 -        blk_queue_max_sectors(xlbd_blk_queue, 512);
   3.388 -
   3.389 -        /* Each segment in a request is up to an aligned page in size. */
   3.390 -        blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1);
   3.391 -        blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE);
   3.392 +    if ((xlbd_blk_queue == NULL) && xlvbd_blk_queue_alloc(mi->type))
   3.393 +            goto out_gendisk;
   3.394  
   3.395 -        /* Ensure a merged request will fit in a single I/O ring slot. */
   3.396 -        blk_queue_max_phys_segments(
   3.397 -            xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
   3.398 -        blk_queue_max_hw_segments(
   3.399 -            xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
   3.400 -
   3.401 -        /* Make sure buffer addresses are sector-aligned. */
   3.402 -        blk_queue_dma_alignment(xlbd_blk_queue, 511);
   3.403 -    }
   3.404      gd->queue = xlbd_blk_queue;
   3.405 -
   3.406      add_disk(gd);
   3.407 -
   3.408      return gd;
   3.409  
   3.410 - out:
   3.411 -    if ( gd != NULL )
   3.412 -        del_gendisk(gd);
   3.413 +out_gendisk:
   3.414 +    del_gendisk(gd);
   3.415 +out:
   3.416      kfree(di);
   3.417      return NULL;
   3.418  }
   3.419  
   3.420 -/*
   3.421 - * xlvbd_init_device - initialise a VBD device
   3.422 - * @disk:              a vdisk_t describing the VBD
   3.423 - *
   3.424 - * Takes a vdisk_t * that describes a VBD the domain has access to.
   3.425 - * Performs appropriate initialisation and registration of the device.
   3.426 - *
   3.427 - * Care needs to be taken when making re-entrant calls to ensure that
   3.428 - * corruption does not occur.  Also, devices that are in use should not have
   3.429 - * their details updated.  This is the caller's responsibility.
   3.430 - */
   3.431 -static int xlvbd_init_device(vdisk_t *xd)
   3.432 +static int xlvbd_device_add(struct list_head *list, vdisk_t *disk)
   3.433  {
   3.434 +    struct lvdisk *new;
   3.435 +    int minor;
   3.436 +    dev_t device;
   3.437      struct block_device *bd;
   3.438      struct gendisk *gd;
   3.439      struct xlbd_major_info *mi;
   3.440 -    int device;
   3.441 -    int minor;
   3.442  
   3.443 -    int err = -ENOMEM;
   3.444 -
   3.445 -    mi = xlbd_get_major_info(xd->device, &minor);
   3.446 +    mi = xlbd_get_major_info(disk->device);
   3.447      if (mi == NULL)
   3.448          return -EPERM;
   3.449  
   3.450 +    new = xlvbd_device_alloc();
   3.451 +    if (new == NULL)
   3.452 +        return -1;
   3.453 +    new->capacity = disk->capacity;
   3.454 +    new->device = disk->device;
   3.455 +    new->info = disk->info;
   3.456 +    
   3.457 +    minor = MINOR_XEN(disk->device);
   3.458      device = MKDEV(mi->major, minor);
   3.459 +    
   3.460 +    bd = bdget(device);
   3.461 +    if (bd == NULL)
   3.462 +        goto out;
   3.463 +    
   3.464 +    gd = xlvbd_alloc_gendisk(mi, minor, disk);
   3.465 +    if (gd == NULL)
   3.466 +        goto out_bd;
   3.467  
   3.468 -    if ((bd = bdget(device)) == NULL)
   3.469 -        return -EPERM;
   3.470 +    if (VDISK_READONLY(disk->info))
   3.471 +        set_disk_ro(gd, 1);
   3.472  
   3.473 -    /*
   3.474 -     * Update of partition info, and check of usage count, is protected
   3.475 -     * by the per-block-device semaphore.
   3.476 -     */
   3.477 -    down(&bd->bd_sem);
   3.478 +    switch (VDISK_TYPE(disk->info)) {
   3.479 +    case VDISK_TYPE_CDROM:
   3.480 +        gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD;
   3.481 +        break;
   3.482 +    case VDISK_TYPE_FLOPPY: 
   3.483 +    case VDISK_TYPE_TAPE:
   3.484 +        gd->flags |= GENHD_FL_REMOVABLE;
   3.485 +        break;
   3.486 +    case VDISK_TYPE_DISK:
   3.487 +        break;
   3.488 +    default:
   3.489 +        WPRINTK("unknown device type %d\n", VDISK_TYPE(disk->info));
   3.490 +        break;
   3.491 +    }    
   3.492  
   3.493 -    gd = xlvbd_get_gendisk(mi, minor, xd);
   3.494 -    if (gd == NULL) {
   3.495 -        err = -EPERM;
   3.496 +    list_add(&new->list, list);
   3.497 +out_bd:
   3.498 +    bdput(bd);
   3.499 +out:
   3.500 +    return 0;
   3.501 +}
   3.502 +
   3.503 +static int xlvbd_device_del(struct lvdisk *disk)
   3.504 +{
   3.505 +    dev_t device;
   3.506 +    struct block_device *bd;
   3.507 +    struct gendisk *gd;
   3.508 +    struct xlbd_disk_info *di;
   3.509 +    int ret = 0, unused;
   3.510 +
   3.511 +    device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device));
   3.512 +
   3.513 +    bd = bdget(device);
   3.514 +    if (bd == NULL)
   3.515 +        return -1;
   3.516 +
   3.517 +    gd = get_gendisk(device, &unused);
   3.518 +    di = gd->private_data;
   3.519 +
   3.520 +    if (di->mi->usage != 0) {
   3.521 +        WPRINTK("disk removal failed: used [dev=%x]\n", device);
   3.522 +        ret = -1;
   3.523          goto out;
   3.524      }
   3.525  
   3.526 -    if (VDISK_READONLY(xd->info))
   3.527 -        set_disk_ro(gd, 1); 
   3.528 +    del_gendisk(gd);
   3.529  
   3.530 -    /* Some final fix-ups depending on the device type */
   3.531 -    switch (VDISK_TYPE(xd->info)) { 
   3.532 -    case VDISK_TYPE_CDROM:
   3.533 -        gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD; 
   3.534 -        /* FALLTHROUGH */
   3.535 -    case VDISK_TYPE_FLOPPY: 
   3.536 -    case VDISK_TYPE_TAPE:
   3.537 -        gd->flags |= GENHD_FL_REMOVABLE; 
   3.538 -        break; 
   3.539 +    xlvbd_device_free(disk);
   3.540 +out:
   3.541 +    bdput(bd);
   3.542 +    return ret;
   3.543 +}
   3.544 +
   3.545 +static int xlvbd_device_update(struct lvdisk *ldisk, vdisk_t *disk)
   3.546 +{
   3.547 +    dev_t device;
   3.548 +    struct block_device *bd;
   3.549 +    struct gendisk *gd;
   3.550 +    int unused;
   3.551  
   3.552 -    case VDISK_TYPE_DISK:
   3.553 -        break; 
   3.554 +    if ((ldisk->capacity == disk->capacity) && (ldisk->info == disk->info))
   3.555 +        return 0;    
   3.556 +
   3.557 +    device = MKDEV(MAJOR_XEN(ldisk->device), MINOR_XEN(ldisk->device));
   3.558  
   3.559 -    default:
   3.560 -        printk(KERN_ALERT "XenLinux: unknown device type %d\n", 
   3.561 -               VDISK_TYPE(xd->info)); 
   3.562 -        break; 
   3.563 -    }
   3.564 +    bd = bdget(device);
   3.565 +    if (bd == NULL)
   3.566 +        return -1;
   3.567  
   3.568 -    err = 0;
   3.569 - out:
   3.570 -    up(&bd->bd_sem);
   3.571 -    bdput(bd);    
   3.572 -    return err;
   3.573 +    gd = get_gendisk(device, &unused);
   3.574 +    set_capacity(gd, disk->capacity);    
   3.575 +    ldisk->capacity = disk->capacity;
   3.576 +
   3.577 +    bdput(bd);
   3.578 +
   3.579 +    return 0;
   3.580  }
   3.581  
   3.582 -/*
   3.583 - * xlvbd_remove_device - remove a device node if possible
   3.584 - * @device:       numeric device ID
   3.585 - *
   3.586 - * Updates the gendisk structure and invalidates devices.
   3.587 - *
   3.588 - * This is OK for now but in future, should perhaps consider where this should
   3.589 - * deallocate gendisks / unregister devices.
   3.590 - */
   3.591 -static int xlvbd_remove_device(int dev16)
   3.592 +void xlvbd_refresh(void)
   3.593  {
   3.594 -    int i, rc = 0;
   3.595 -    struct gendisk *gd;
   3.596 -    struct block_device *bd;
   3.597 -    struct xlbd_disk_info *di;
   3.598 -    dev_t device = MKDEV(MAJOR_XEN(dev16), MINOR_XEN(dev16));
   3.599 -
   3.600 -    bd = bdget(device);
   3.601 -    if (!bd)
   3.602 -        return -1;
   3.603 +    vdisk_t *newdisks;
   3.604 +    struct list_head *tmp, *tmp2;
   3.605 +    struct lvdisk *disk;
   3.606 +    int i, nr;
   3.607  
   3.608 -    /*
   3.609 -     * Update of partition info, and check of usage count, is protected
   3.610 -     * by the per-block-device semaphore.
   3.611 -     */
   3.612 -    down(&bd->bd_sem);
   3.613 -
   3.614 -    gd = get_gendisk(device, &i);
   3.615 -    BUG_ON(gd == NULL);
   3.616 -    di = (struct xlbd_disk_info *) gd->private_data;
   3.617 -    BUG_ON(di == NULL);
   3.618 -
   3.619 -    if ( di->mi->usage != 0 )
   3.620 -    {
   3.621 -        printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device);
   3.622 -        rc = -1;
   3.623 -        goto out;
   3.624 +    newdisks = xlvbd_probe(&nr);
   3.625 +    if (newdisks == NULL) {
   3.626 +        WPRINTK("failed to probe\n");
   3.627 +        return;
   3.628      }
   3.629 -
   3.630 -    /* The VBD is mapped to an entire unit. */
   3.631      
   3.632 -    invalidate_partition(gd, 0);
   3.633 -    set_capacity(gd, 0);
   3.634 -
   3.635 -out:
   3.636 -    up(&bd->bd_sem);
   3.637 -    bdput(bd);
   3.638 -    return rc;
   3.639 +    i = 0;
   3.640 +    list_for_each_safe(tmp, tmp2, &vbds_list) {
   3.641 +        disk = list_entry(tmp, struct lvdisk, list);
   3.642 +        
   3.643 +        for (i = 0; i < nr; i++) {
   3.644 +            if ( !newdisks[i].device )
   3.645 +                continue;
   3.646 +            if ( disk->device == newdisks[i].device ) {
   3.647 +                xlvbd_device_update(disk, &newdisks[i]);
   3.648 +                newdisks[i].device = 0;
   3.649 +                break;
   3.650 +            }
   3.651 +        }
   3.652 +        if (i == nr) {
   3.653 +            xlvbd_device_del(disk);
   3.654 +            newdisks[i].device = 0;
   3.655 +        }
   3.656 +    }
   3.657 +    for (i = 0; i < nr; i++)
   3.658 +        if ( newdisks[i].device )
   3.659 +            xlvbd_device_add(&vbds_list, &newdisks[i]);
   3.660 +    kfree(newdisks);
   3.661  }
   3.662  
   3.663  /*
   3.664 @@ -395,75 +472,7 @@ out:
   3.665   */
   3.666  void xlvbd_update_vbds(void)
   3.667  {
   3.668 -    int i, j, k, old_nr, new_nr;
   3.669 -    vdisk_t *old_info, *new_info, *merged_info;
   3.670 -
   3.671 -    old_info = vbd_info;
   3.672 -    old_nr   = nr_vbds;
   3.673 -
   3.674 -    new_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
   3.675 -    if (!new_info)
   3.676 -        return;
   3.677 -
   3.678 -    if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
   3.679 -        goto out;
   3.680 -
   3.681 -    /*
   3.682 -     * Final list maximum size is old list + new list. This occurs only when
   3.683 -     * old list and new list do not overlap at all, and we cannot yet destroy
   3.684 -     * VBDs in the old list because the usage counts are busy.
   3.685 -     */
   3.686 -    merged_info = kmalloc((old_nr + new_nr) * sizeof(vdisk_t), GFP_KERNEL);
   3.687 -    if (!merged_info)
   3.688 -        goto out;
   3.689 -
   3.690 -    /* @i tracks old list; @j tracks new list; @k tracks merged list. */
   3.691 -    i = j = k = 0;
   3.692 -
   3.693 -    while ( (i < old_nr) && (j < new_nr) )
   3.694 -    {
   3.695 -        if ( old_info[i].device < new_info[j].device )
   3.696 -        {
   3.697 -            if ( xlvbd_remove_device(old_info[i].device) != 0 )
   3.698 -                memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
   3.699 -            i++;
   3.700 -        }
   3.701 -        else if ( old_info[i].device > new_info[j].device )
   3.702 -        {
   3.703 -            if ( xlvbd_init_device(&new_info[j]) == 0 )
   3.704 -                memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
   3.705 -            j++;
   3.706 -        }
   3.707 -        else
   3.708 -        {
   3.709 -            if ( ((old_info[i].capacity == new_info[j].capacity) &&
   3.710 -                  (old_info[i].info == new_info[j].info)) ||
   3.711 -                 (xlvbd_remove_device(old_info[i].device) != 0) )
   3.712 -                memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
   3.713 -            else if ( xlvbd_init_device(&new_info[j]) == 0 )
   3.714 -                memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
   3.715 -            i++; j++;
   3.716 -        }
   3.717 -    }
   3.718 -
   3.719 -    for ( ; i < old_nr; i++ )
   3.720 -    {
   3.721 -        if ( xlvbd_remove_device(old_info[i].device) != 0 )
   3.722 -            memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
   3.723 -    }
   3.724 -
   3.725 -    for ( ; j < new_nr; j++ )
   3.726 -    {
   3.727 -        if ( xlvbd_init_device(&new_info[j]) == 0 )
   3.728 -            memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
   3.729 -    }
   3.730 -
   3.731 -    vbd_info = merged_info;
   3.732 -    nr_vbds  = k;
   3.733 -
   3.734 -    kfree(old_info);
   3.735 -out:
   3.736 -    kfree(new_info);
   3.737 +    xlvbd_refresh();
   3.738  }
   3.739  
   3.740  /*
   3.741 @@ -477,26 +486,22 @@ out:
   3.742   */
   3.743  int xlvbd_init(void)
   3.744  {
   3.745 -    int i;
   3.746 +    int i, nr;
   3.747 +    vdisk_t *disks;
   3.748 +
   3.749 +    INIT_LIST_HEAD(&vbds_list);
   3.750  
   3.751      memset(major_info, 0, sizeof(major_info));
   3.752 -
   3.753 -    vbd_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
   3.754 -    if (vbd_info == NULL) {
   3.755 -        printk(KERN_ALERT "Failed to allocate memory for disk info.\n");
   3.756 -        nr_vbds = 0;
   3.757 -        return 0;
   3.758 +    
   3.759 +    disks = xlvbd_probe(&nr);
   3.760 +    if (disks == NULL) {
   3.761 +        WPRINTK("failed to probe\n");
   3.762 +        return -1;
   3.763      }
   3.764  
   3.765 -    nr_vbds  = xlvbd_get_vbd_info(vbd_info);
   3.766 -    if (nr_vbds < 0) {
   3.767 -        kfree(vbd_info);
   3.768 -        vbd_info = NULL;
   3.769 -        nr_vbds  = 0;
   3.770 -    } else {
   3.771 -        for (i = 0; i < nr_vbds; i++)
   3.772 -            xlvbd_init_device(&vbd_info[i]);
   3.773 -    }
   3.774 +    for (i = 0; i < nr; i++)
   3.775 +        xlvbd_device_add(&vbds_list, &disks[i]);
   3.776  
   3.777 +    kfree(disks);
   3.778      return 0;
   3.779  }