ia64/xen-unstable

changeset 6356:827a3c3524b3

Use a block interface for each device.
Lots of code cleanups, incl. a couple of bug fixes.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Mon Aug 22 20:59:00 2005 +0000 (2005-08-22)
parents 6078dc5f7ea1
children 2d3a7be68ba3
files linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6-xen-sparse/drivers/xen/blkfront/block.h linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Aug 22 20:57:26 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Aug 22 20:59:00 2005 +0000
     1.3 @@ -58,39 +58,21 @@
     1.4  #include <asm-xen/xen-public/grant_table.h>
     1.5  #include <asm-xen/gnttab.h>
     1.6  
     1.7 -struct blkfront_info
     1.8 -{
     1.9 -	/* We watch the backend */
    1.10 -	struct xenbus_watch watch;
    1.11 -	int vdevice;
    1.12 -	u16 handle;
    1.13 -	int connected;
    1.14 -	struct xenbus_device *dev;
    1.15 -	char *backend;
    1.16 -	int backend_id;
    1.17 -	int grant_id;
    1.18 -	blkif_front_ring_t ring;
    1.19 -	unsigned int evtchn;
    1.20 -};
    1.21 -
    1.22  typedef unsigned char byte; /* from linux/ide.h */
    1.23  
    1.24  /* Control whether runtime update of vbds is enabled. */
    1.25  #define ENABLE_VBD_UPDATE 1
    1.26  
    1.27 -#define BLKIF_STATE_CLOSED       0
    1.28 -#define BLKIF_STATE_DISCONNECTED 1
    1.29 -#define BLKIF_STATE_CONNECTED    2
    1.30 +#define BLKIF_STATE_DISCONNECTED 0
    1.31 +#define BLKIF_STATE_CONNECTED    1
    1.32  
    1.33 -static unsigned int blkif_state = BLKIF_STATE_CLOSED;
    1.34 -static unsigned int blkif_vbds_connected = 0;
    1.35 +static unsigned int blkif_state = BLKIF_STATE_DISCONNECTED;
    1.36  
    1.37  #define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
    1.38  
    1.39  #define MAXIMUM_OUTSTANDING_BLOCK_REQS \
    1.40      (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE)
    1.41  #define GRANTREF_INVALID (1<<15)
    1.42 -static grant_ref_t gref_head, gref_terminal;
    1.43  
    1.44  static struct blk_shadow {
    1.45      blkif_request_t req;
    1.46 @@ -101,7 +83,7 @@ unsigned long blk_shadow_free;
    1.47  
    1.48  static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */
    1.49  
    1.50 -static void kick_pending_request_queues(void);
    1.51 +static void kick_pending_request_queues(struct blkfront_info *info);
    1.52  
    1.53  static int __init xlblk_init(void);
    1.54  
    1.55 @@ -128,7 +110,7 @@ static inline void ADD_ID_TO_FREELIST(un
    1.56  
    1.57  /* Kernel-specific definitions used in the common code */
    1.58  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
    1.59 -#define DISABLE_SCATTERGATHER() 
    1.60 +#define DISABLE_SCATTERGATHER()
    1.61  #else
    1.62  static int sg_operation = -1;
    1.63  #define DISABLE_SCATTERGATHER() (sg_operation = -1)
    1.64 @@ -161,30 +143,34 @@ static inline void flush_requests(struct
    1.65  
    1.66  module_init(xlblk_init);
    1.67  
    1.68 -static struct xlbd_disk_info *head_waiting = NULL;
    1.69 -static void kick_pending_request_queues(void)
    1.70 +static void kick_pending_request_queues(struct blkfront_info *info)
    1.71  {
    1.72 -    struct xlbd_disk_info *di;
    1.73 -    while ( ((di = head_waiting) != NULL) && !RING_FULL(&di->info->ring) )
    1.74 -    {
    1.75 -        head_waiting = di->next_waiting;
    1.76 -        di->next_waiting = NULL;
    1.77 -        /* Re-enable calldowns. */
    1.78 -        blk_start_queue(di->rq);
    1.79 -        /* Kick things off immediately. */
    1.80 -        do_blkif_request(di->rq);
    1.81 -    }
    1.82 +	if (!RING_FULL(&info->ring)) {
    1.83 +		/* Re-enable calldowns. */
    1.84 +		blk_start_queue(info->rq);
    1.85 +		/* Kick things off immediately. */
    1.86 +		do_blkif_request(info->rq);
    1.87 +	}
    1.88 +}
    1.89 +
    1.90 +static void blkif_restart_queue(void *arg)
    1.91 +{
    1.92 +	struct blkfront_info *info = (struct blkfront_info *)arg;
    1.93 +	spin_lock_irq(&blkif_io_lock);
    1.94 +	info->callback.work = NULL;
    1.95 +	kick_pending_request_queues(info);
    1.96 +	spin_unlock_irq(&blkif_io_lock);
    1.97  }
    1.98  
    1.99  int blkif_open(struct inode *inode, struct file *filep)
   1.100  {
   1.101 -    struct gendisk *gd = inode->i_bdev->bd_disk;
   1.102 -    struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data;
   1.103 +	// struct gendisk *gd = inode->i_bdev->bd_disk;
   1.104 +	// struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data;
   1.105  
   1.106 -    /* Update of usage count is protected by per-device semaphore. */
   1.107 -    di->mi->usage++;
   1.108 -    
   1.109 -    return 0;
   1.110 +	/* Update of usage count is protected by per-device semaphore. */
   1.111 +	// di->mi->usage++;
   1.112 +
   1.113 +	return 0;
   1.114  }
   1.115  
   1.116  
   1.117 @@ -201,8 +187,8 @@ int blkif_ioctl(struct inode *inode, str
   1.118      int i;
   1.119  
   1.120      DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
   1.121 -                  command, (long)argument, inode->i_rdev); 
   1.122 -  
   1.123 +                  command, (long)argument, inode->i_rdev);
   1.124 +
   1.125      switch ( command )
   1.126      {
   1.127      case HDIO_GETGEO:
   1.128 @@ -228,7 +214,7 @@ int blkif_ioctl(struct inode *inode, str
   1.129  /*
   1.130   * blkif_queue_request
   1.131   *
   1.132 - * request block io 
   1.133 + * request block io
   1.134   * 
   1.135   * id: for guest use only.
   1.136   * operation: BLKIF_OP_{READ,WRITE,PROBE}
   1.137 @@ -237,7 +223,7 @@ int blkif_ioctl(struct inode *inode, str
   1.138   */
   1.139  static int blkif_queue_request(struct request *req)
   1.140  {
   1.141 -    struct xlbd_disk_info *di = req->rq_disk->private_data;
   1.142 +    struct blkfront_info *info = req->rq_disk->private_data;
   1.143      unsigned long buffer_ma;
   1.144      blkif_request_t *ring_req;
   1.145      struct bio *bio;
   1.146 @@ -246,20 +232,29 @@ static int blkif_queue_request(struct re
   1.147      unsigned long id;
   1.148      unsigned int fsect, lsect;
   1.149      int ref;
   1.150 +    grant_ref_t gref_head, gref_terminal;
   1.151  
   1.152 -    if ( unlikely(blkif_state != BLKIF_STATE_CONNECTED) )
   1.153 +    if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
   1.154          return 1;
   1.155  
   1.156 +    if (gnttab_alloc_grant_references(BLKIF_MAX_SEGMENTS_PER_REQUEST,
   1.157 +				      &gref_head, &gref_terminal) < 0) {
   1.158 +	    if (info->callback.work)
   1.159 +		    return 1;
   1.160 +	    INIT_WORK(&info->work, blkif_restart_queue, (void *)info);
   1.161 +	    gnttab_request_free_callback(&info->callback, &info->work);
   1.162 +	    return 1;
   1.163 +    }
   1.164 +
   1.165      /* Fill out a communications ring structure. */
   1.166 -    ring_req = RING_GET_REQUEST(&di->info->ring, di->info->ring.req_prod_pvt);
   1.167 +    ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
   1.168      id = GET_ID_FROM_FREELIST();
   1.169      blk_shadow[id].request = (unsigned long)req;
   1.170  
   1.171      ring_req->id = id;
   1.172 -    ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE :
   1.173 -        BLKIF_OP_READ;
   1.174 +    ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ;
   1.175      ring_req->sector_number = (blkif_sector_t)req->sector;
   1.176 -    ring_req->handle = di->handle;
   1.177 +    ring_req->handle = info->handle;
   1.178  
   1.179      ring_req->nr_segments = 0;
   1.180      rq_for_each_bio(bio, req)
   1.181 @@ -277,44 +272,47 @@ static int blkif_queue_request(struct re
   1.182  
   1.183              gnttab_grant_foreign_access_ref(
   1.184                          ref,
   1.185 -                        di->info->backend_id,
   1.186 +                        info->backend_id,
   1.187                          buffer_ma >> PAGE_SHIFT,
   1.188                          rq_data_dir(req) );
   1.189  
   1.190              blk_shadow[id].frame[ring_req->nr_segments] =
   1.191                  buffer_ma >> PAGE_SHIFT;
   1.192  
   1.193 -            ring_req->frame_and_sects[ring_req->nr_segments++] =
   1.194 +            ring_req->frame_and_sects[ring_req->nr_segments] =
   1.195                  blkif_fas_from_gref(ref, fsect, lsect);
   1.196 +
   1.197 +	    ring_req->nr_segments++;
   1.198          }
   1.199      }
   1.200  
   1.201 -    di->info->ring.req_prod_pvt++;
   1.202 -    
   1.203 +    info->ring.req_prod_pvt++;
   1.204 +
   1.205      /* Keep a private copy so we can reissue requests when recovering. */
   1.206      pickle_request(&blk_shadow[id], ring_req);
   1.207  
   1.208 +    gnttab_free_grant_references(&gref_head, gref_terminal);
   1.209 +
   1.210      return 0;
   1.211  }
   1.212  
   1.213 -
   1.214  /*
   1.215   * do_blkif_request
   1.216   *  read a block; request is in a request queue
   1.217   */
   1.218  void do_blkif_request(request_queue_t *rq)
   1.219  {
   1.220 -    struct xlbd_disk_info *di = NULL;
   1.221 +    struct blkfront_info *info = NULL;
   1.222      struct request *req;
   1.223      int queued;
   1.224  
   1.225 -    DPRINTK("Entered do_blkif_request\n"); 
   1.226 +    DPRINTK("Entered do_blkif_request\n");
   1.227  
   1.228      queued = 0;
   1.229  
   1.230      while ( (req = elv_next_request(rq)) != NULL )
   1.231      {
   1.232 -	di = req->rq_disk->private_data;
   1.233 +	info = req->rq_disk->private_data;
   1.234  
   1.235          if ( !blk_fs_request(req) )
   1.236          {
   1.237 @@ -322,8 +320,8 @@ void do_blkif_request(request_queue_t *r
   1.238              continue;
   1.239          }
   1.240  
   1.241 -        if ( RING_FULL(&di->info->ring) )
   1.242 -            goto wait;
   1.243 +	if (RING_FULL(&info->ring))
   1.244 +		goto wait;
   1.245  
   1.246          DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n",
   1.247                  req, req->cmd, req->sector, req->current_nr_sectors,
   1.248 @@ -331,24 +329,19 @@ void do_blkif_request(request_queue_t *r
   1.249                  rq_data_dir(req) ? "write" : "read");
   1.250  
   1.251          blkdev_dequeue_request(req);
   1.252 -        if ( blkif_queue_request(req) )
   1.253 -        {
   1.254 +        if (blkif_queue_request(req)) {
   1.255 +		blk_requeue_request(rq, req);
   1.256          wait:
   1.257 -            if ( di->next_waiting == NULL )
   1.258 -            {
   1.259 -                di->next_waiting = head_waiting;
   1.260 -                head_waiting = di;
   1.261 -                /* Avoid pointless unplugs. */
   1.262 -                blk_stop_queue(rq);
   1.263 -            }
   1.264 -            break;
   1.265 +		/* Avoid pointless unplugs. */
   1.266 +		blk_stop_queue(rq);
   1.267 +		break;
   1.268          }
   1.269  
   1.270          queued++;
   1.271      }
   1.272  
   1.273      if ( queued != 0 )
   1.274 -        flush_requests(di->info);
   1.275 +        flush_requests(info);
   1.276  }
   1.277  
   1.278  
   1.279 @@ -359,16 +352,14 @@ static irqreturn_t blkif_int(int irq, vo
   1.280      RING_IDX i, rp;
   1.281      unsigned long flags;
   1.282      struct blkfront_info *info = (struct blkfront_info *)dev_id;
   1.283 -    
   1.284 -    spin_lock_irqsave(&blkif_io_lock, flags);     
   1.285  
   1.286 -    if ( unlikely(blkif_state == BLKIF_STATE_CLOSED) || 
   1.287 -         unlikely(recovery) )
   1.288 -    {
   1.289 +    spin_lock_irqsave(&blkif_io_lock, flags);
   1.290 +
   1.291 +    if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) {
   1.292          spin_unlock_irqrestore(&blkif_io_lock, flags);
   1.293          return IRQ_HANDLED;
   1.294      }
   1.295 -    
   1.296 +
   1.297      rp = info->ring.sring->rsp_prod;
   1.298      rmb(); /* Ensure we see queued responses up to 'rp'. */
   1.299  
   1.300 @@ -393,7 +384,7 @@ static irqreturn_t blkif_int(int irq, vo
   1.301                          bret->status);
   1.302  
   1.303              if ( unlikely(end_that_request_first
   1.304 -                          (req, 
   1.305 +                          (req,
   1.306                             (bret->status == BLKIF_RSP_OKAY),
   1.307                             req->hard_nr_sectors)) )
   1.308                  BUG();
   1.309 @@ -407,7 +398,7 @@ static irqreturn_t blkif_int(int irq, vo
   1.310  
   1.311      info->ring.rsp_cons = i;
   1.312  
   1.313 -    kick_pending_request_queues();
   1.314 +    kick_pending_request_queues(info);
   1.315  
   1.316      spin_unlock_irqrestore(&blkif_io_lock, flags);
   1.317  
   1.318 @@ -436,7 +427,7 @@ static int nr_pending;
   1.319  static void kick_pending_request_queues(void)
   1.320  {
   1.321      /* We kick pending request queues if the ring is reasonably empty. */
   1.322 -    if ( (nr_pending != 0) && 
   1.323 +    if ( (nr_pending != 0) &&
   1.324           (RING_PENDING_REQUESTS(&info->ring) < (BLK_RING_SIZE >> 1)) )
   1.325      {
   1.326          /* Attempt to drain the queue, but bail if the ring becomes full. */
   1.327 @@ -447,20 +438,20 @@ static void kick_pending_request_queues(
   1.328  
   1.329  int blkif_open(struct inode *inode, struct file *filep)
   1.330  {
   1.331 -    short xldev = inode->i_rdev; 
   1.332 +    short xldev = inode->i_rdev;
   1.333      struct gendisk *gd = get_gendisk(xldev);
   1.334      xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
   1.335 -    short minor = MINOR(xldev); 
   1.336 +    short minor = MINOR(xldev);
   1.337  
   1.338      if ( gd->part[minor].nr_sects == 0 )
   1.339 -    { 
   1.340 +    {
   1.341          /*
   1.342           * Device either doesn't exist, or has zero capacity; we use a few
   1.343           * cheesy heuristics to return the relevant error code
   1.344           */
   1.345          if ( (gd->sizes[minor >> gd->minor_shift] != 0) ||
   1.346               ((minor & (gd->max_p - 1)) != 0) )
   1.347 -        { 
   1.348 +        {
   1.349              /*
   1.350               * We have a real device, but no such partition, or we just have a
   1.351               * partition number so guess this is the problem.
   1.352 @@ -469,16 +460,16 @@ int blkif_open(struct inode *inode, stru
   1.353          }
   1.354          else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE )
   1.355          {
   1.356 -            /* This is a removable device => assume that media is missing. */ 
   1.357 +            /* This is a removable device => assume that media is missing. */
   1.358              return -ENOMEDIUM; /* media not present (this is a guess) */
   1.359 -        } 
   1.360 +        }
   1.361          else
   1.362 -        { 
   1.363 +        {
   1.364              /* Just go for the general 'no such device' error. */
   1.365              return -ENODEV;    /* no such device */
   1.366          }
   1.367      }
   1.368 -    
   1.369 +
   1.370      /* Update of usage count is protected by per-device semaphore. */
   1.371      disk->usage++;
   1.372  
   1.373 @@ -507,24 +498,24 @@ int blkif_ioctl(struct inode *inode, str
   1.374  {
   1.375      kdev_t dev = inode->i_rdev;
   1.376      struct hd_geometry *geo = (struct hd_geometry *)argument;
   1.377 -    struct gendisk *gd;     
   1.378 -    struct hd_struct *part; 
   1.379 +    struct gendisk *gd;
   1.380 +    struct hd_struct *part;
   1.381      int i;
   1.382      unsigned short cylinders;
   1.383      byte heads, sectors;
   1.384  
   1.385      /* NB. No need to check permissions. That is done for us. */
   1.386 -    
   1.387 +
   1.388      DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
   1.389 -                  command, (long) argument, dev); 
   1.390 -  
   1.391 +                  command, (long) argument, dev);
   1.392 +
   1.393      gd = get_gendisk(dev);
   1.394 -    part = &gd->part[MINOR(dev)]; 
   1.395 +    part = &gd->part[MINOR(dev)];
   1.396  
   1.397      switch ( command )
   1.398      {
   1.399      case BLKGETSIZE:
   1.400 -        DPRINTK_IOCTL("   BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); 
   1.401 +        DPRINTK_IOCTL("   BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects);
   1.402          return put_user(part->nr_sects, (unsigned long *) argument);
   1.403  
   1.404      case BLKGETSIZE64:
   1.405 @@ -537,7 +528,7 @@ int blkif_ioctl(struct inode *inode, str
   1.406          return blkif_revalidate(dev);
   1.407  
   1.408      case BLKSSZGET:
   1.409 -        return hardsect_size[MAJOR(dev)][MINOR(dev)]; 
   1.410 +        return hardsect_size[MAJOR(dev)][MINOR(dev)];
   1.411  
   1.412      case BLKBSZGET:                                        /* get block size */
   1.413          DPRINTK_IOCTL("   BLKBSZGET: %x\n", BLKBSZGET);
   1.414 @@ -563,7 +554,7 @@ int blkif_ioctl(struct inode *inode, str
   1.415             values consistent with the size of the device */
   1.416  
   1.417          heads = 0xff;
   1.418 -        sectors = 0x3f; 
   1.419 +        sectors = 0x3f;
   1.420          cylinders = part->nr_sects / (heads * sectors);
   1.421  
   1.422          if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
   1.423 @@ -573,7 +564,7 @@ int blkif_ioctl(struct inode *inode, str
   1.424  
   1.425          return 0;
   1.426  
   1.427 -    case HDIO_GETGEO_BIG: 
   1.428 +    case HDIO_GETGEO_BIG:
   1.429          DPRINTK_IOCTL("   HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
   1.430          if (!argument) return -EINVAL;
   1.431  
   1.432 @@ -581,7 +572,7 @@ int blkif_ioctl(struct inode *inode, str
   1.433             values consistent with the size of the device */
   1.434  
   1.435          heads = 0xff;
   1.436 -        sectors = 0x3f; 
   1.437 +        sectors = 0x3f;
   1.438          cylinders = part->nr_sects / (heads * sectors);
   1.439  
   1.440          if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
   1.441 @@ -605,7 +596,7 @@ int blkif_ioctl(struct inode *inode, str
   1.442          WPRINTK("ioctl %08x not supported by XL blkif\n", command);
   1.443          return -ENOSYS;
   1.444      }
   1.445 -    
   1.446 +
   1.447      return 0;
   1.448  }
   1.449  
   1.450 @@ -625,7 +616,7 @@ int blkif_revalidate(kdev_t dev)
   1.451      xl_disk_t *disk;
   1.452      unsigned long capacity;
   1.453      int i, rc = 0;
   1.454 -    
   1.455 +
   1.456      if ( (bd = bdget(dev)) == NULL )
   1.457          return -EINVAL;
   1.458  
   1.459 @@ -673,7 +664,7 @@ int blkif_revalidate(kdev_t dev)
   1.460  /*
   1.461   * blkif_queue_request
   1.462   *
   1.463 - * request block io 
   1.464 + * request block io
   1.465   * 
   1.466   * id: for guest use only.
   1.467   * operation: BLKIF_OP_{READ,WRITE,PROBE}
   1.468 @@ -707,7 +698,7 @@ static int blkif_queue_request(unsigned 
   1.469  
   1.470      buffer_ma &= PAGE_MASK;
   1.471  
   1.472 -    if ( unlikely(blkif_state != BLKIF_STATE_CONNECTED) )
   1.473 +    if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
   1.474          return 1;
   1.475  
   1.476      switch ( operation )
   1.477 @@ -715,7 +706,7 @@ static int blkif_queue_request(unsigned 
   1.478  
   1.479      case BLKIF_OP_READ:
   1.480      case BLKIF_OP_WRITE:
   1.481 -        gd = get_gendisk(device); 
   1.482 +        gd = get_gendisk(device);
   1.483  
   1.484          /*
   1.485           * Update the sector_number we'll pass down as appropriate; note that
   1.486 @@ -725,10 +716,10 @@ static int blkif_queue_request(unsigned 
   1.487          sector_number += gd->part[MINOR(device)].start_sect;
   1.488  
   1.489          /*
   1.490 -         * If this unit doesn't consist of virtual partitions then we clear 
   1.491 +         * If this unit doesn't consist of virtual partitions then we clear
   1.492           * the partn bits from the device number.
   1.493           */
   1.494 -        if ( !(gd->flags[MINOR(device)>>gd->minor_shift] & 
   1.495 +        if ( !(gd->flags[MINOR(device)>>gd->minor_shift] &
   1.496                 GENHD_FL_VIRT_PARTNS) )
   1.497              device &= ~(gd->max_p - 1);
   1.498  
   1.499 @@ -736,10 +727,10 @@ static int blkif_queue_request(unsigned 
   1.500               (sg_dev == device) &&
   1.501               (sg_next_sect == sector_number) )
   1.502          {
   1.503 -            req = RING_GET_REQUEST(&info->ring, 
   1.504 +            req = RING_GET_REQUEST(&info->ring,
   1.505                                     info->ring.req_prod_pvt - 1);
   1.506              bh = (struct buffer_head *)id;
   1.507 -     
   1.508 +
   1.509              bh->b_reqnext = (struct buffer_head *)blk_shadow[req->id].request;
   1.510              blk_shadow[req->id].request = (unsigned long)id;
   1.511  
   1.512 @@ -793,7 +784,7 @@ static int blkif_queue_request(unsigned 
   1.513      req->id            = xid;
   1.514      req->operation     = operation;
   1.515      req->sector_number = (blkif_sector_t)sector_number;
   1.516 -    req->handle        = handle; 
   1.517 +    req->handle        = handle;
   1.518      req->nr_segments   = 1;
   1.519      /* install a grant reference. */
   1.520      ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
   1.521 @@ -809,11 +800,11 @@ static int blkif_queue_request(unsigned 
   1.522  
   1.523      req->frame_and_sects[0] = blkif_fas_from_gref(ref, fsect, lsect);
   1.524  
   1.525 -    /* Keep a private copy so we can reissue requests when recovering. */    
   1.526 +    /* Keep a private copy so we can reissue requests when recovering. */
   1.527      pickle_request(&blk_shadow[xid], req);
   1.528  
   1.529      info->ring.req_prod_pvt++;
   1.530 -    
   1.531 +
   1.532      return 0;
   1.533  }
   1.534  
   1.535 @@ -828,13 +819,13 @@ void do_blkif_request(request_queue_t *r
   1.536      struct buffer_head *bh, *next_bh;
   1.537      int rw, nsect, full, queued = 0;
   1.538  
   1.539 -    DPRINTK("Entered do_blkif_request\n"); 
   1.540 +    DPRINTK("Entered do_blkif_request\n");
   1.541  
   1.542      while ( !rq->plugged && !list_empty(&rq->queue_head))
   1.543      {
   1.544 -        if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) 
   1.545 +        if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL )
   1.546              goto out;
   1.547 -  
   1.548 +
   1.549          DPRINTK("do_blkif_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
   1.550                  req, req->cmd, req->sector,
   1.551                  req->current_nr_sectors, req->nr_sectors, req->bh);
   1.552 @@ -855,16 +846,16 @@ void do_blkif_request(request_queue_t *r
   1.553  
   1.554              full = blkif_queue_request(
   1.555                  (unsigned long)bh,
   1.556 -                (rw == READ) ? BLKIF_OP_READ : BLKIF_OP_WRITE, 
   1.557 +                (rw == READ) ? BLKIF_OP_READ : BLKIF_OP_WRITE,
   1.558                  bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev);
   1.559  
   1.560              if ( full )
   1.561 -            { 
   1.562 +            {
   1.563                  bh->b_reqnext = next_bh;
   1.564                  pending_queues[nr_pending++] = rq;
   1.565                  if ( unlikely(nr_pending >= MAX_PENDING) )
   1.566                      BUG();
   1.567 -                goto out; 
   1.568 +                goto out;
   1.569              }
   1.570  
   1.571              queued++;
   1.572 @@ -872,7 +863,7 @@ void do_blkif_request(request_queue_t *r
   1.573              /* Dequeue the buffer head from the request. */
   1.574              nsect = bh->b_size >> 9;
   1.575              bh = req->bh = next_bh;
   1.576 -            
   1.577 +
   1.578              if ( bh != NULL )
   1.579              {
   1.580                  /* There's another buffer head to do. Update the request. */
   1.581 @@ -902,13 +893,13 @@ void do_blkif_request(request_queue_t *r
   1.582  
   1.583  static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
   1.584  {
   1.585 -    RING_IDX i, rp; 
   1.586 -    unsigned long flags; 
   1.587 +    RING_IDX i, rp;
   1.588 +    unsigned long flags;
   1.589      struct buffer_head *bh, *next_bh;
   1.590 -    
   1.591 -    spin_lock_irqsave(&io_request_lock, flags);     
   1.592  
   1.593 -    if ( unlikely(blkif_state == BLKIF_STATE_CLOSED || recovery) )
   1.594 +    spin_lock_irqsave(&io_request_lock, flags);
   1.595 +
   1.596 +    if ( unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery) )
   1.597      {
   1.598          spin_unlock_irqrestore(&io_request_lock, flags);
   1.599          return;
   1.600 @@ -921,7 +912,7 @@ static void blkif_int(int irq, void *dev
   1.601      {
   1.602          unsigned long id;
   1.603          blkif_response_t *bret;
   1.604 -        
   1.605 +
   1.606          bret = RING_GET_RESPONSE(&info->ring, i);
   1.607          id = bret->id;
   1.608          bh = (struct buffer_head *)blk_shadow[id].request;
   1.609 @@ -955,7 +946,7 @@ static void blkif_int(int irq, void *dev
   1.610  
   1.611      }
   1.612      info->ring.rsp_cons = i;
   1.613 -    
   1.614 +
   1.615      kick_pending_request_queues();
   1.616  
   1.617      spin_unlock_irqrestore(&io_request_lock, flags);
   1.618 @@ -969,7 +960,7 @@ static void blkif_free(struct blkfront_i
   1.619  {
   1.620      /* Prevent new requests being issued until we fix things up. */
   1.621      spin_lock_irq(&blkif_io_lock);
   1.622 -    blkif_state = BLKIF_STATE_DISCONNECTED;
   1.623 +    info->connected = BLKIF_STATE_DISCONNECTED;
   1.624      spin_unlock_irq(&blkif_io_lock);
   1.625  
   1.626      /* Free resources associated with old device channel. */
   1.627 @@ -1045,7 +1036,7 @@ static void blkif_recover(struct blkfron
   1.628      flush_requests(info);
   1.629  
   1.630      /* Now safe to left other people use the interface. */
   1.631 -    blkif_state = BLKIF_STATE_CONNECTED;
   1.632 +    info->connected = BLKIF_STATE_CONNECTED;
   1.633  }
   1.634  
   1.635  static void blkif_connect(struct blkfront_info *info, u16 evtchn)
   1.636 @@ -1080,31 +1071,29 @@ static void watch_for_status(struct xenb
   1.637  	node += strlen(watch->node);
   1.638  
   1.639  	/* FIXME: clean up when error on the other end. */
   1.640 -	if (info->connected)
   1.641 +	if (info->connected == BLKIF_STATE_CONNECTED)
   1.642  		return;
   1.643  
   1.644 -	err = xenbus_gather(watch->node, 
   1.645 +	err = xenbus_gather(watch->node,
   1.646  			    "sectors", "%lu", &sectors,
   1.647  			    "info", "%u", &binfo,
   1.648  			    "sector-size", "%lu", &sector_size,
   1.649  			    NULL);
   1.650  	if (err) {
   1.651 -		xenbus_dev_error(info->dev, err, "reading backend fields");
   1.652 +		xenbus_dev_error(info->xbdev, err, "reading backend fields");
   1.653  		return;
   1.654  	}
   1.655  
   1.656 -	xlvbd_add(sectors, info->vdevice, info->handle, binfo, sector_size, info);
   1.657 -	info->connected = 1;
   1.658 +	xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
   1.659 +	info->connected = BLKIF_STATE_CONNECTED;
   1.660  
   1.661 -	/* First to connect?  blkif is now connected. */
   1.662 -	if (blkif_vbds_connected++ == 0)
   1.663 -		blkif_state = BLKIF_STATE_CONNECTED;
   1.664 +	blkif_state = BLKIF_STATE_CONNECTED;
   1.665  
   1.666 -	xenbus_dev_ok(info->dev);
   1.667 +	xenbus_dev_ok(info->xbdev);
   1.668  
   1.669  	/* Kick pending requests. */
   1.670  	spin_lock_irq(&blkif_io_lock);
   1.671 -	kick_pending_request_queues();
   1.672 +	kick_pending_request_queues(info);
   1.673  	spin_unlock_irq(&blkif_io_lock);
   1.674  }
   1.675  
   1.676 @@ -1122,17 +1111,20 @@ static int setup_blkring(struct xenbus_d
   1.677  	SHARED_RING_INIT(sring);
   1.678  	FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
   1.679  
   1.680 -	info->grant_id = gnttab_claim_grant_reference(&gref_head,
   1.681 -						      gref_terminal);
   1.682 -	ASSERT(info->grant_id != -ENOSPC);
   1.683 -	gnttab_grant_foreign_access_ref(info->grant_id,
   1.684 -					info->backend_id,
   1.685 -					virt_to_mfn(info->ring.sring),
   1.686 -					0);
   1.687 +	err = gnttab_grant_foreign_access(info->backend_id,
   1.688 +					  virt_to_mfn(info->ring.sring), 0);
   1.689 +	if (err == -ENOSPC) {
   1.690 +		free_page((unsigned long)info->ring.sring);
   1.691 +		info->ring.sring = 0;
   1.692 +		xenbus_dev_error(dev, err, "granting access to ring page");
   1.693 +		return err;
   1.694 +	}
   1.695 +	info->grant_id = err;
   1.696  
   1.697  	op.u.alloc_unbound.dom = info->backend_id;
   1.698  	err = HYPERVISOR_event_channel_op(&op);
   1.699  	if (err) {
   1.700 +		gnttab_end_foreign_access(info->grant_id, 0);
   1.701  		free_page((unsigned long)info->ring.sring);
   1.702  		info->ring.sring = 0;
   1.703  		xenbus_dev_error(dev, err, "allocating event channel");
   1.704 @@ -1246,9 +1238,10 @@ static int blkfront_probe(struct xenbus_
   1.705  		xenbus_dev_error(dev, err, "allocating info structure");
   1.706  		return err;
   1.707  	}
   1.708 -	info->dev = dev;
   1.709 +	info->xbdev = dev;
   1.710  	info->vdevice = vdevice;
   1.711 -	info->connected = 0;
   1.712 +	info->connected = BLKIF_STATE_DISCONNECTED;
   1.713 +	info->mi = NULL;
   1.714  
   1.715  	/* Front end dir is a number, which is used as the id. */
   1.716  	info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
   1.717 @@ -1272,10 +1265,8 @@ static int blkfront_remove(struct xenbus
   1.718  	if (info->backend)
   1.719  		unregister_xenbus_watch(&info->watch);
   1.720  
   1.721 -	if (info->connected) {
   1.722 -		xlvbd_del(info->handle);
   1.723 -		blkif_vbds_connected--;
   1.724 -	}
   1.725 +	if (info->mi)
   1.726 +		xlvbd_del(info);
   1.727  
   1.728  	blkif_free(info);
   1.729  
   1.730 @@ -1359,11 +1350,6 @@ static int __init xlblk_init(void)
   1.731           (xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
   1.732          return 0;
   1.733  
   1.734 -    /* A grant for every ring slot, plus one for the ring itself. */
   1.735 -    if (gnttab_alloc_grant_references(MAXIMUM_OUTSTANDING_BLOCK_REQS + 1,
   1.736 -				      &gref_head, &gref_terminal) < 0)
   1.737 -        return 1;
   1.738 -
   1.739      IPRINTK("Initialising virtual block device driver\n");
   1.740  
   1.741      blk_shadow_free = 0;
   1.742 @@ -1383,6 +1369,6 @@ static void blkif_completion(struct blk_
   1.743  {
   1.744      int i;
   1.745      for ( i = 0; i < s->req.nr_segments; i++ )
   1.746 -        gnttab_release_grant_reference(
   1.747 -            &gref_head, blkif_gref_from_fas(s->req.frame_and_sects[i]));
   1.748 +        gnttab_free_grant_reference(
   1.749 +		blkif_gref_from_fas(s->req.frame_and_sects[i]));
   1.750  }
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h	Mon Aug 22 20:57:26 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h	Mon Aug 22 20:59:00 2005 +0000
     2.3 @@ -46,6 +46,7 @@
     2.4  #include <linux/major.h>
     2.5  #include <linux/devfs_fs_kernel.h>
     2.6  #include <asm-xen/hypervisor.h>
     2.7 +#include <asm-xen/xenbus.h>
     2.8  #include <asm-xen/xen-public/xen.h>
     2.9  #include <asm-xen/xen-public/io/blkif.h>
    2.10  #include <asm-xen/xen-public/io/ring.h>
    2.11 @@ -79,13 +80,20 @@
    2.12  #define DPRINTK_IOCTL(_f, _a...) ((void)0)
    2.13  #endif
    2.14  
    2.15 -struct blkfront_info;
    2.16 +struct xlbd_type_info
    2.17 +{
    2.18 +	int partn_shift;
    2.19 +	int disks_per_major;
    2.20 +	char *devname;
    2.21 +	char *diskname;
    2.22 +};
    2.23  
    2.24 -struct xlbd_type_info {
    2.25 -    int partn_shift;
    2.26 -    int disks_per_major;
    2.27 -    char *devname;
    2.28 -    char *diskname;
    2.29 +struct xlbd_major_info
    2.30 +{
    2.31 +	int major;
    2.32 +	int index;
    2.33 +	int usage;
    2.34 +	struct xlbd_type_info *type;
    2.35  };
    2.36  
    2.37  /*
    2.38 @@ -93,28 +101,28 @@ struct xlbd_type_info {
    2.39   * hang in private_data off the gendisk structure. We may end up
    2.40   * putting all kinds of interesting stuff here :-)
    2.41   */
    2.42 -struct xlbd_major_info {
    2.43 -    int major;
    2.44 -    int index;
    2.45 -    int usage;
    2.46 -    struct xlbd_type_info *type;
    2.47 +struct blkfront_info
    2.48 +{
    2.49 +	struct xenbus_device *xbdev;
    2.50 +	/* We watch the backend */
    2.51 +	struct xenbus_watch watch;
    2.52 +	dev_t dev;
    2.53 +	int vdevice;
    2.54 +	blkif_vdev_t handle;
    2.55 +	int connected;
    2.56 +	char *backend;
    2.57 +	int backend_id;
    2.58 +	int grant_id;
    2.59 +	blkif_front_ring_t ring;
    2.60 +	unsigned int evtchn;
    2.61 +	struct xlbd_major_info *mi;
    2.62 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
    2.63 +	request_queue_t *rq;
    2.64 +#endif
    2.65 +	struct work_struct work;
    2.66 +	struct gnttab_free_callback callback;
    2.67  };
    2.68  
    2.69 -struct xlbd_disk_info {
    2.70 -    int xd_device;
    2.71 -    blkif_vdev_t handle;
    2.72 -    struct xlbd_major_info *mi;
    2.73 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
    2.74 -    struct xlbd_disk_info  *next_waiting;
    2.75 -    request_queue_t        *rq;
    2.76 -#endif
    2.77 -    struct blkfront_info *info;
    2.78 -};
    2.79 -
    2.80 -typedef struct xen_block {
    2.81 -    int usage;
    2.82 -} xen_block_t;
    2.83 -
    2.84  extern spinlock_t blkif_io_lock;
    2.85  
    2.86  extern int blkif_open(struct inode *inode, struct file *filep);
    2.87 @@ -126,7 +134,7 @@ extern int blkif_revalidate(dev_t dev);
    2.88  extern void do_blkif_request (request_queue_t *rq); 
    2.89  
    2.90  /* Virtual block-device subsystem. */
    2.91 -int xlvbd_add(blkif_sector_t capacity, int device, blkif_vdev_t handle,
    2.92 +int xlvbd_add(blkif_sector_t capacity, int device,
    2.93  	      u16 vdisk_info, u16 sector_size, struct blkfront_info *info);
    2.94 -void xlvbd_del(blkif_vdev_t handle);
    2.95 +void xlvbd_del(struct blkfront_info *info);
    2.96  #endif /* __XEN_DRIVERS_BLOCK_H__ */
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c	Mon Aug 22 20:57:26 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c	Mon Aug 22 20:59:00 2005 +0000
     3.3 @@ -43,46 +43,37 @@
     3.4  #define NUM_SCSI_MAJORS 9
     3.5  #define NUM_VBD_MAJORS 1
     3.6  
     3.7 -struct lvdisk
     3.8 -{
     3.9 -    blkif_sector_t capacity; /*  0: Size in terms of 512-byte sectors.   */
    3.10 -    blkif_vdev_t   handle;   /*  8: Device number (opaque 16 bit value). */
    3.11 -    u16            info;
    3.12 -    dev_t          dev;
    3.13 -    struct list_head list;
    3.14 -};
    3.15 -
    3.16  static struct xlbd_type_info xlbd_ide_type = {
    3.17 -    .partn_shift = 6,
    3.18 -    .disks_per_major = 2,
    3.19 -    .devname = "ide",
    3.20 -    .diskname = "hd",
    3.21 +	.partn_shift = 6,
    3.22 +	.disks_per_major = 2,
    3.23 +	.devname = "ide",
    3.24 +	.diskname = "hd",
    3.25  };
    3.26  
    3.27  static struct xlbd_type_info xlbd_scsi_type = {
    3.28 -    .partn_shift = 4,
    3.29 -    .disks_per_major = 16,
    3.30 -    .devname = "sd",
    3.31 -    .diskname = "sd",
    3.32 +	.partn_shift = 4,
    3.33 +	.disks_per_major = 16,
    3.34 +	.devname = "sd",
    3.35 +	.diskname = "sd",
    3.36  };
    3.37  
    3.38  static struct xlbd_type_info xlbd_vbd_type = {
    3.39 -    .partn_shift = 4,
    3.40 -    .disks_per_major = 16,
    3.41 -    .devname = "xvd",
    3.42 -    .diskname = "xvd",
    3.43 +	.partn_shift = 4,
    3.44 +	.disks_per_major = 16,
    3.45 +	.devname = "xvd",
    3.46 +	.diskname = "xvd",
    3.47  };
    3.48  
    3.49  static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
    3.50 -                                         NUM_VBD_MAJORS];
    3.51 +					  NUM_VBD_MAJORS];
    3.52  
    3.53 -#define XLBD_MAJOR_IDE_START    0
    3.54 -#define XLBD_MAJOR_SCSI_START   (NUM_IDE_MAJORS)
    3.55 -#define XLBD_MAJOR_VBD_START    (NUM_IDE_MAJORS + NUM_SCSI_MAJORS)
    3.56 +#define XLBD_MAJOR_IDE_START	0
    3.57 +#define XLBD_MAJOR_SCSI_START	(NUM_IDE_MAJORS)
    3.58 +#define XLBD_MAJOR_VBD_START	(NUM_IDE_MAJORS + NUM_SCSI_MAJORS)
    3.59  
    3.60 -#define XLBD_MAJOR_IDE_RANGE    XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1
    3.61 -#define XLBD_MAJOR_SCSI_RANGE   XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1
    3.62 -#define XLBD_MAJOR_VBD_RANGE    XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1
    3.63 +#define XLBD_MAJOR_IDE_RANGE	XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1
    3.64 +#define XLBD_MAJOR_SCSI_RANGE	XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1
    3.65 +#define XLBD_MAJOR_VBD_RANGE	XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1
    3.66  
    3.67  /* Information about our VBDs. */
    3.68  #define MAX_VBDS 64
    3.69 @@ -91,279 +82,233 @@ static LIST_HEAD(vbds_list);
    3.70  #define MAJOR_XEN(dev) ((dev)>>8)
    3.71  #define MINOR_XEN(dev) ((dev) & 0xff)
    3.72  
    3.73 -static struct block_device_operations xlvbd_block_fops = 
    3.74 +static struct block_device_operations xlvbd_block_fops =
    3.75  {
    3.76 -    .owner  = THIS_MODULE,
    3.77 -    .open  = blkif_open,
    3.78 -    .release = blkif_release,
    3.79 -    .ioctl  = blkif_ioctl,
    3.80 +	.owner = THIS_MODULE,
    3.81 +	.open = blkif_open,
    3.82 +	.release = blkif_release,
    3.83 +	.ioctl  = blkif_ioctl,
    3.84  };
    3.85  
    3.86  spinlock_t blkif_io_lock = SPIN_LOCK_UNLOCKED;
    3.87  
    3.88 -static struct lvdisk *xlvbd_device_alloc(void)
    3.89 -{
    3.90 -    struct lvdisk *disk;
    3.91 -
    3.92 -    disk = kmalloc(sizeof(*disk), GFP_KERNEL);
    3.93 -    if (disk != NULL) {
    3.94 -        memset(disk, 0, sizeof(*disk));
    3.95 -        INIT_LIST_HEAD(&disk->list);
    3.96 -    }
    3.97 -    return disk;
    3.98 -}
    3.99 -
   3.100 -static void xlvbd_device_free(struct lvdisk *disk)
   3.101 +static struct xlbd_major_info *
   3.102 +xlbd_alloc_major_info(int major, int minor, int index)
   3.103  {
   3.104 -    list_del(&disk->list);
   3.105 -    kfree(disk);
   3.106 -}
   3.107 +	struct xlbd_major_info *ptr;
   3.108  
   3.109 -static struct xlbd_major_info *xlbd_alloc_major_info(
   3.110 -    int major, int minor, int index)
   3.111 -{
   3.112 -    struct xlbd_major_info *ptr;
   3.113 +	ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
   3.114 +	if (ptr == NULL)
   3.115 +		return NULL;
   3.116  
   3.117 -    ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
   3.118 -    if (ptr == NULL)
   3.119 -        return NULL;
   3.120 +	memset(ptr, 0, sizeof(struct xlbd_major_info));
   3.121  
   3.122 -    memset(ptr, 0, sizeof(struct xlbd_major_info));
   3.123 +	ptr->major = major;
   3.124  
   3.125 -    ptr->major = major;
   3.126 +	switch (index) {
   3.127 +	case XLBD_MAJOR_IDE_RANGE:
   3.128 +		ptr->type = &xlbd_ide_type;
   3.129 +		ptr->index = index - XLBD_MAJOR_IDE_START;
   3.130 +		break;
   3.131 +	case XLBD_MAJOR_SCSI_RANGE:
   3.132 +		ptr->type = &xlbd_scsi_type;
   3.133 +		ptr->index = index - XLBD_MAJOR_SCSI_START;
   3.134 +		break;
   3.135 +	case XLBD_MAJOR_VBD_RANGE:
   3.136 +		ptr->type = &xlbd_vbd_type;
   3.137 +		ptr->index = index - XLBD_MAJOR_VBD_START;
   3.138 +		break;
   3.139 +	}
   3.140  
   3.141 -    switch (index) {
   3.142 -    case XLBD_MAJOR_IDE_RANGE:
   3.143 -        ptr->type = &xlbd_ide_type;
   3.144 -        ptr->index = index - XLBD_MAJOR_IDE_START;
   3.145 -        break;
   3.146 -    case XLBD_MAJOR_SCSI_RANGE:
   3.147 -        ptr->type = &xlbd_scsi_type;
   3.148 -        ptr->index = index - XLBD_MAJOR_SCSI_START;
   3.149 -        break;
   3.150 -    case XLBD_MAJOR_VBD_RANGE:
   3.151 -        ptr->type = &xlbd_vbd_type;
   3.152 -        ptr->index = index - XLBD_MAJOR_VBD_START;
   3.153 -        break;
   3.154 -    }
   3.155 -    
   3.156 -    printk("Registering block device major %i\n", ptr->major);
   3.157 -    if (register_blkdev(ptr->major, ptr->type->devname)) {
   3.158 -        WPRINTK("can't get major %d with name %s\n",
   3.159 -                ptr->major, ptr->type->devname);
   3.160 -        kfree(ptr);
   3.161 -        return NULL;
   3.162 -    }
   3.163 +	printk("Registering block device major %i\n", ptr->major);
   3.164 +	if (register_blkdev(ptr->major, ptr->type->devname)) {
   3.165 +		WPRINTK("can't get major %d with name %s\n",
   3.166 +			ptr->major, ptr->type->devname);
   3.167 +		kfree(ptr);
   3.168 +		return NULL;
   3.169 +	}
   3.170  
   3.171 -    devfs_mk_dir(ptr->type->devname);
   3.172 -    major_info[index] = ptr;
   3.173 -    return ptr;
   3.174 +	devfs_mk_dir(ptr->type->devname);
   3.175 +	major_info[index] = ptr;
   3.176 +	return ptr;
   3.177  }
   3.178  
   3.179 -static struct xlbd_major_info *xlbd_get_major_info(int device)
   3.180 +static struct xlbd_major_info *
   3.181 +xlbd_get_major_info(int vdevice)
   3.182  {
   3.183 -    int major, minor, index;
   3.184 +	struct xlbd_major_info *mi;
   3.185 +	int major, minor, index;
   3.186  
   3.187 -    major = MAJOR_XEN(device);
   3.188 -    minor = MINOR_XEN(device);
   3.189 +	major = MAJOR_XEN(vdevice);
   3.190 +	minor = MINOR_XEN(vdevice);
   3.191  
   3.192 -    switch (major) {
   3.193 -    case IDE0_MAJOR: index = 0; break;
   3.194 -    case IDE1_MAJOR: index = 1; break;
   3.195 -    case IDE2_MAJOR: index = 2; break;
   3.196 -    case IDE3_MAJOR: index = 3; break;
   3.197 -    case IDE4_MAJOR: index = 4; break;
   3.198 -    case IDE5_MAJOR: index = 5; break;
   3.199 -    case IDE6_MAJOR: index = 6; break;
   3.200 -    case IDE7_MAJOR: index = 7; break;
   3.201 -    case IDE8_MAJOR: index = 8; break;
   3.202 -    case IDE9_MAJOR: index = 9; break;
   3.203 -    case SCSI_DISK0_MAJOR: index = 10; break;
   3.204 -    case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
   3.205 -        index = 11 + major - SCSI_DISK1_MAJOR;
   3.206 -        break;
   3.207 -    case SCSI_CDROM_MAJOR: index = 18; break;
   3.208 -    default: index = 19; break;
   3.209 -    }
   3.210 +	switch (major) {
   3.211 +	case IDE0_MAJOR: index = 0; break;
   3.212 +	case IDE1_MAJOR: index = 1; break;
   3.213 +	case IDE2_MAJOR: index = 2; break;
   3.214 +	case IDE3_MAJOR: index = 3; break;
   3.215 +	case IDE4_MAJOR: index = 4; break;
   3.216 +	case IDE5_MAJOR: index = 5; break;
   3.217 +	case IDE6_MAJOR: index = 6; break;
   3.218 +	case IDE7_MAJOR: index = 7; break;
   3.219 +	case IDE8_MAJOR: index = 8; break;
   3.220 +	case IDE9_MAJOR: index = 9; break;
   3.221 +	case SCSI_DISK0_MAJOR: index = 10; break;
   3.222 +	case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
   3.223 +		index = 11 + major - SCSI_DISK1_MAJOR;
   3.224 +		break;
   3.225 +	case SCSI_CDROM_MAJOR: index = 18; break;
   3.226 +	default: index = 19; break;
   3.227 +	}
   3.228  
   3.229 -    return ((major_info[index] != NULL) ? major_info[index] :
   3.230 -            xlbd_alloc_major_info(major, minor, index));
   3.231 +	mi = ((major_info[index] != NULL) ? major_info[index] :
   3.232 +	      xlbd_alloc_major_info(major, minor, index));
   3.233 +	mi->usage++;
   3.234 +	return mi;
   3.235  }
   3.236  
   3.237 -static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
   3.238 +static void
   3.239 +xlbd_put_major_info(struct xlbd_major_info *mi)
   3.240  {
   3.241 -    request_queue_t *rq;
   3.242 -
   3.243 -    rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
   3.244 -    if (rq == NULL)
   3.245 -        return -1;
   3.246 -
   3.247 -    elevator_init(rq, "noop");
   3.248 -
   3.249 -    /* Hard sector size and max sectors impersonate the equiv. hardware. */
   3.250 -    blk_queue_hardsect_size(rq, sector_size);
   3.251 -    blk_queue_max_sectors(rq, 512);
   3.252 -
   3.253 -    /* Each segment in a request is up to an aligned page in size. */
   3.254 -    blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
   3.255 -    blk_queue_max_segment_size(rq, PAGE_SIZE);
   3.256 -
   3.257 -    /* Ensure a merged request will fit in a single I/O ring slot. */
   3.258 -    blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
   3.259 -    blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
   3.260 -
   3.261 -    /* Make sure buffer addresses are sector-aligned. */
   3.262 -    blk_queue_dma_alignment(rq, 511);
   3.263 -
   3.264 -    gd->queue = rq;
   3.265 -
   3.266 -    return 0;
   3.267 +	mi->usage--;
   3.268 +	/* XXX: release major if 0 */
   3.269  }
   3.270  
   3.271 -static struct gendisk *xlvbd_alloc_gendisk(
   3.272 -    struct xlbd_major_info *mi, int minor, blkif_sector_t capacity,
   3.273 -    int device, blkif_vdev_t handle, u16 vdisk_info, u16 sector_size,
   3.274 -    struct blkfront_info *info)
   3.275 +static int
   3.276 +xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
   3.277  {
   3.278 -    struct gendisk *gd;
   3.279 -    struct xlbd_disk_info *di;
   3.280 -    int nr_minors = 1;
   3.281 +	request_queue_t *rq;
   3.282  
   3.283 -    di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL);
   3.284 -    if (di == NULL)
   3.285 -        return NULL;
   3.286 -    memset(di, 0, sizeof(*di));
   3.287 -    di->mi = mi;
   3.288 -    di->xd_device = device;
   3.289 -    di->handle = handle;
   3.290 -    di->info = info;
   3.291 +	rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
   3.292 +	if (rq == NULL)
   3.293 +		return -1;
   3.294  
   3.295 -    if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
   3.296 -        nr_minors = 1 << mi->type->partn_shift;
   3.297 +	elevator_init(rq, "noop");
   3.298  
   3.299 -    gd = alloc_disk(nr_minors);
   3.300 -    if (gd == NULL)
   3.301 -        goto out;
   3.302 +	/* Hard sector size and max sectors impersonate the equiv. hardware. */
   3.303 +	blk_queue_hardsect_size(rq, sector_size);
   3.304 +	blk_queue_max_sectors(rq, 512);
   3.305  
   3.306 -    if (nr_minors > 1)
   3.307 -        sprintf(gd->disk_name, "%s%c", mi->type->diskname,
   3.308 -                'a' + mi->index * mi->type->disks_per_major +
   3.309 -                    (minor >> mi->type->partn_shift));
   3.310 -    else
   3.311 -        sprintf(gd->disk_name, "%s%c%d", mi->type->diskname,
   3.312 -                'a' + mi->index * mi->type->disks_per_major +
   3.313 -                (minor >> mi->type->partn_shift),
   3.314 -                minor & ((1 << mi->type->partn_shift) - 1));
   3.315 -
   3.316 -    gd->major = mi->major;
   3.317 -    gd->first_minor = minor;
   3.318 -    gd->fops = &xlvbd_block_fops;
   3.319 -    gd->private_data = di;
   3.320 -    set_capacity(gd, capacity);
   3.321 +	/* Each segment in a request is up to an aligned page in size. */
   3.322 +	blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
   3.323 +	blk_queue_max_segment_size(rq, PAGE_SIZE);
   3.324  
   3.325 -    if (xlvbd_init_blk_queue(gd, sector_size)) {
   3.326 -        del_gendisk(gd);
   3.327 -        goto out;
   3.328 -    }
   3.329 -
   3.330 -    di->rq = gd->queue;
   3.331 -
   3.332 -    if (vdisk_info & VDISK_READONLY)
   3.333 -        set_disk_ro(gd, 1);
   3.334 +	/* Ensure a merged request will fit in a single I/O ring slot. */
   3.335 +	blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
   3.336 +	blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
   3.337  
   3.338 -    if (vdisk_info & VDISK_REMOVABLE)
   3.339 -        gd->flags |= GENHD_FL_REMOVABLE;
   3.340 -
   3.341 -    if (vdisk_info & VDISK_CDROM)
   3.342 -        gd->flags |= GENHD_FL_CD;
   3.343 +	/* Make sure buffer addresses are sector-aligned. */
   3.344 +	blk_queue_dma_alignment(rq, 511);
   3.345  
   3.346 -    add_disk(gd);
   3.347 -
   3.348 -    return gd;
   3.349 +	gd->queue = rq;
   3.350  
   3.351 -out:
   3.352 -    kfree(di);
   3.353 -    return NULL;
   3.354 +	return 0;
   3.355  }
   3.356  
   3.357 -int xlvbd_add(blkif_sector_t capacity, int device, blkif_vdev_t handle,
   3.358 -	      u16 vdisk_info, u16 sector_size, struct blkfront_info *info)
   3.359 +static int
   3.360 +xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity, int vdevice,
   3.361 +		    u16 vdisk_info, u16 sector_size,
   3.362 +		    struct blkfront_info *info)
   3.363  {
   3.364 -    struct lvdisk *new;
   3.365 -    struct block_device *bd;
   3.366 -    struct gendisk *gd;
   3.367 -    struct xlbd_major_info *mi;
   3.368 +	struct gendisk *gd;
   3.369 +	struct xlbd_major_info *mi;
   3.370 +	int nr_minors = 1;
   3.371 +	int err = -ENODEV;
   3.372  
   3.373 -    mi = xlbd_get_major_info(device);
   3.374 -    if (mi == NULL)
   3.375 -        return -EPERM;
   3.376 +	mi = xlbd_get_major_info(vdevice);
   3.377 +	if (mi == NULL)
   3.378 +		goto out;
   3.379 +	info->mi = mi;
   3.380 +
   3.381 +	if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
   3.382 +		nr_minors = 1 << mi->type->partn_shift;
   3.383 +
   3.384 +	gd = alloc_disk(nr_minors);
   3.385 +	if (gd == NULL)
   3.386 +		goto out;
   3.387  
   3.388 -    new = xlvbd_device_alloc();
   3.389 -    if (new == NULL)
   3.390 -        return -ENOMEM;
   3.391 -    new->capacity = capacity;
   3.392 -    new->info = vdisk_info;
   3.393 -    new->handle = handle;
   3.394 -    new->dev = MKDEV(MAJOR_XEN(device), MINOR_XEN(device));
   3.395 +	if (nr_minors > 1)
   3.396 +		sprintf(gd->disk_name, "%s%c", mi->type->diskname,
   3.397 +			'a' + mi->index * mi->type->disks_per_major +
   3.398 +			(minor >> mi->type->partn_shift));
   3.399 +	else
   3.400 +		sprintf(gd->disk_name, "%s%c%d", mi->type->diskname,
   3.401 +			'a' + mi->index * mi->type->disks_per_major +
   3.402 +			(minor >> mi->type->partn_shift),
   3.403 +			minor & ((1 << mi->type->partn_shift) - 1));
   3.404 +
   3.405 +	gd->major = mi->major;
   3.406 +	gd->first_minor = minor;
   3.407 +	gd->fops = &xlvbd_block_fops;
   3.408 +	gd->private_data = info;
   3.409 +	set_capacity(gd, capacity);
   3.410  
   3.411 -    bd = bdget(new->dev);
   3.412 -    if (bd == NULL)
   3.413 -        goto out;
   3.414 -    
   3.415 -    gd = xlvbd_alloc_gendisk(mi, MINOR_XEN(device), capacity, device, handle,
   3.416 -			     vdisk_info, sector_size, info);
   3.417 -    if (gd == NULL)
   3.418 -        goto out_bd;
   3.419 +	if (xlvbd_init_blk_queue(gd, sector_size)) {
   3.420 +		del_gendisk(gd);
   3.421 +		goto out;
   3.422 +	}
   3.423 +
   3.424 +	info->rq = gd->queue;
   3.425 +
   3.426 +	if (vdisk_info & VDISK_READONLY)
   3.427 +		set_disk_ro(gd, 1);
   3.428  
   3.429 -    list_add(&new->list, &vbds_list);
   3.430 -out_bd:
   3.431 -    bdput(bd);
   3.432 -out:
   3.433 -    return 0;
   3.434 +	if (vdisk_info & VDISK_REMOVABLE)
   3.435 +		gd->flags |= GENHD_FL_REMOVABLE;
   3.436 +
   3.437 +	if (vdisk_info & VDISK_CDROM)
   3.438 +		gd->flags |= GENHD_FL_CD;
   3.439 +
   3.440 +	add_disk(gd);
   3.441 +
   3.442 +	return 0;
   3.443 +
   3.444 + out:
   3.445 +	if (mi)
   3.446 +		xlbd_put_major_info(mi);
   3.447 +	return err;
   3.448  }
   3.449  
   3.450 -static int xlvbd_device_del(struct lvdisk *disk)
   3.451 +int
   3.452 +xlvbd_add(blkif_sector_t capacity, int vdevice, u16 vdisk_info,
   3.453 +	  u16 sector_size, struct blkfront_info *info)
   3.454  {
   3.455 -    struct block_device *bd;
   3.456 -    struct gendisk *gd;
   3.457 -    struct xlbd_disk_info *di;
   3.458 -    int ret = 0, unused;
   3.459 -    request_queue_t *rq;
   3.460 +	struct block_device *bd;
   3.461 +	int err = 0;
   3.462  
   3.463 -    bd = bdget(disk->dev);
   3.464 -    if (bd == NULL)
   3.465 -        return -1;
   3.466 -
   3.467 -    gd = get_gendisk(disk->dev, &unused);
   3.468 -    di = gd->private_data;
   3.469 +	info->dev = MKDEV(MAJOR_XEN(vdevice), MINOR_XEN(vdevice));
   3.470  
   3.471 -#if 0 /* This is wrong: hda and hdb share same major, for example. */
   3.472 -    if (di->mi->usage != 0) {
   3.473 -        WPRINTK("disk removal failed: used [dev=%x]\n", disk->dev);
   3.474 -        ret = -1;
   3.475 -        goto out;
   3.476 -    }
   3.477 -#endif
   3.478 +	bd = bdget(info->dev);
   3.479 +	if (bd == NULL)
   3.480 +		return -ENODEV;
   3.481  
   3.482 -    rq = gd->queue;
   3.483 -    del_gendisk(gd);
   3.484 -    put_disk(gd);
   3.485 -    blk_cleanup_queue(rq);
   3.486 +	err = xlvbd_alloc_gendisk(MINOR_XEN(vdevice), capacity, vdevice,
   3.487 +				  vdisk_info, sector_size, info);
   3.488  
   3.489 -    xlvbd_device_free(disk);
   3.490 -    bdput(bd);
   3.491 -    return ret;
   3.492 +	bdput(bd);
   3.493 +	return err;
   3.494  }
   3.495  
   3.496 -void xlvbd_del(blkif_vdev_t handle)
   3.497 +void
   3.498 +xlvbd_del(struct blkfront_info *info)
   3.499  {
   3.500 -	struct lvdisk *i;
   3.501 +	struct block_device *bd;
   3.502 +	struct gendisk *gd;
   3.503 +	int unused;
   3.504 +	request_queue_t *rq;
   3.505 +
   3.506 +	bd = bdget(info->dev);
   3.507 +	if (bd == NULL)
   3.508 +		return;
   3.509  
   3.510 -	list_for_each_entry(i, &vbds_list, list) {
   3.511 -		if (i->handle == handle) {
   3.512 -			xlvbd_device_del(i);
   3.513 -			return;
   3.514 -		}
   3.515 -	}
   3.516 -	BUG();
   3.517 +	gd = get_gendisk(info->dev, &unused);
   3.518 +	rq = gd->queue;
   3.519 +
   3.520 +	del_gendisk(gd);
   3.521 +	put_disk(gd);
   3.522 +	xlbd_put_major_info(info->mi);
   3.523 +	info->mi = NULL;
   3.524 +	blk_cleanup_queue(rq);
   3.525 +
   3.526 +	bdput(bd);
   3.527  }