bitkeeper revision 1.1159.258.56 (4236f0d8NTb8nv3JBClhBcw3-6u3oQ)
authorvh249@arcadians.cl.cam.ac.uk <vh249@arcadians.cl.cam.ac.uk>
Tue, 15 Mar 2005 14:27:36 +0000 (14:27 +0000)
committervh249@arcadians.cl.cam.ac.uk <vh249@arcadians.cl.cam.ac.uk>
Tue, 15 Mar 2005 14:27:36 +0000 (14:27 +0000)
update code for having dynamic update of vbd for blkfront driver on 2.6
add some protection for kmalloc failure on 2.4 and 2.6

Signed-off-by: Vincent Hanquez <vincent@xensource.com>
BitKeeper/etc/logging_ok
linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c
linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c
linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c

index 05d987fd88a68b384cc456b56aed003366445330..e671b4583f9e5a888f9e1efb2f9b36880dcd3414 100644 (file)
@@ -66,4 +66,5 @@ tlh20@labyrinth.cl.cam.ac.uk
 tw275@labyrinth.cl.cam.ac.uk
 tw275@striker.cl.cam.ac.uk
 vh249@airwolf.cl.cam.ac.uk
+vh249@arcadians.cl.cam.ac.uk
 xenbk@gandalf.hpl.hp.com
index 74a43cdd4aef535abacd2389620985ab98445a69..81a873e4e070e83f6463d287039ed0a25e38c0b7 100644 (file)
@@ -442,11 +442,11 @@ void xlvbd_update_vbds(void)
     old_nr   = nr_vbds;
 
     new_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
-    if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
-    {
-        kfree(new_info);
+    if (!new_info)
         return;
-    }
+
+    if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
+        goto out;
 
     /*
      * Final list maximum size is old list + new list. This occurs only when
@@ -454,6 +454,8 @@ void xlvbd_update_vbds(void)
      * VBDs in the old list because the usage counts are busy.
      */
     merged_info = kmalloc((old_nr + new_nr) * sizeof(vdisk_t), GFP_KERNEL);
+    if (!merged_info)
+        goto out;
 
     /* @i tracks old list; @j tracks new list; @k tracks merged list. */
     i = j = k = 0;
@@ -500,6 +502,7 @@ void xlvbd_update_vbds(void)
     nr_vbds  = k;
 
     kfree(old_info);
+out:
     kfree(new_info);
 }
 
@@ -543,6 +546,9 @@ int xlvbd_init(void)
     }
 
     vbd_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
+    if (!vbd_info)
+        return -ENOMEM;
+
     nr_vbds  = xlvbd_get_vbd_info(vbd_info);
 
     if ( nr_vbds < 0 )
index e28db67411cd8075ee51ffbacec35d3612d93251..c6035b7b4d4fddae6c5fe575daac3440806f8256 100644 (file)
@@ -170,8 +170,15 @@ static inline void flush_requests(void)
 module_init(xlblk_init);
 
 #if ENABLE_VBD_UPDATE
+static void update_vbds_task(void *unused)
+{ 
+    xlvbd_update_vbds();
+}
+
 static void vbd_update(void)
 {
+    static DECLARE_WORK(update_tq, update_vbds_task, NULL);
+    schedule_work(&update_tq);
 }
 #endif /* ENABLE_VBD_UPDATE */
 
index 8050e756ca6b800a9a53ca7ef1f6ca2cb8b106b7..95f2bd4b3b6cfa295368b75eae37111dc3c479c6 100644 (file)
@@ -354,7 +354,6 @@ static int xlvbd_init_device(vdisk_t *xd)
     return err;
 }
 
-#if 0
 /*
  * xlvbd_remove_device - remove a device node if possible
  * @device:       numeric device ID
@@ -364,14 +363,16 @@ static int xlvbd_init_device(vdisk_t *xd)
  * This is OK for now but in future, should perhaps consider where this should
  * deallocate gendisks / unregister devices.
  */
-static int xlvbd_remove_device(int device)
+static int xlvbd_remove_device(int dev16)
 {
-    int i, rc = 0, minor = MINOR(device);
+    int i, rc = 0, minor = MINOR(dev16);
     struct gendisk *gd;
     struct block_device *bd;
-    xen_block_t *disk = NULL;
+    struct xlbd_disk_info *di;
+    dev_t device = MKDEV(MAJOR_XEN(dev16), MINOR_XEN(dev16));
 
-    if ( (bd = bdget(device)) == NULL )
+    bd = bdget(device);
+    if (!bd)
         return -1;
 
     /*
@@ -380,67 +381,25 @@ static int xlvbd_remove_device(int device)
      */
     down(&bd->bd_sem);
 
-    if ( ((gd = get_gendisk(device)) == NULL) ||
-         ((disk = xldev_to_xldisk(device)) == NULL) )
-        BUG();
+    gd = get_gendisk(device, &i);
+    BUG_ON(gd == NULL);
+    di = (struct xlbd_disk_info *) gd->private_data;
+    BUG_ON(di == NULL);
 
-    if ( disk->usage != 0 )
+    if ( di->mi->usage != 0 )
     {
         printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device);
         rc = -1;
         goto out;
     }
-    if ( (minor & (gd->max_p-1)) != 0 )
-    {
-        /* 1: The VBD is mapped to a partition rather than a whole unit. */
-        invalidate_device(device, 1);
-        gd->part[minor].start_sect = 0;
-        gd->part[minor].nr_sects   = 0;
-        gd->sizes[minor]           = 0;
-
-        /* Clear the consists-of-virtual-partitions flag if possible. */
-        gd->flags[minor >> gd->minor_shift] &= ~GENHD_FL_VIRT_PARTNS;
-        for ( i = 1; i < gd->max_p; i++ )
-            if ( gd->sizes[(minor & ~(gd->max_p-1)) + i] != 0 )
-                gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS;
 
-        /*
-         * If all virtual partitions are now gone, and a 'whole unit' VBD is
-         * present, then we can try to grok the unit's real partition table.
-         */
-        if ( !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) &&
-             (gd->sizes[minor & ~(gd->max_p-1)] != 0) &&
-             !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE) )
-        {
-            register_disk(gd,
-                          device&~(gd->max_p-1), 
-                          gd->max_p, 
-                          &xlvbd_block_fops,
-                          gd->part[minor&~(gd->max_p-1)].nr_sects);
-        }
-    }
-    else
-    {
-        /*
-         * 2: The VBD is mapped to an entire 'unit'. Clear all partitions.
-         * NB. The partition entries are only cleared if there are no VBDs
-         * mapped to individual partitions on this unit.
-         */
-        i = gd->max_p - 1; /* Default: clear subpartitions as well. */
-        if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS )
-            i = 0; /* 'Virtual' mode: only clear the 'whole unit' entry. */
-        while ( i >= 0 )
-        {
-            invalidate_device(device+i, 1);
-            gd->part[minor+i].start_sect = 0;
-            gd->part[minor+i].nr_sects   = 0;
-            gd->sizes[minor+i]           = 0;
-            i--;
-        }
-    }
+    BUG_ON(minor != gd->first_minor);
+    /* The VBD is mapped to an entire unit. */
+    
+    invalidate_partition(gd, 0);
+    set_capacity(gd, 0);
 
- out:
+out:
     up(&bd->bd_sem);
     bdput(bd);
     return rc;
@@ -460,11 +419,11 @@ void xlvbd_update_vbds(void)
     old_nr   = nr_vbds;
 
     new_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
-    if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
-    {
-        kfree(new_info);
+    if (!new_info)
         return;
-    }
+
+    if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
+        goto out;
 
     /*
      * Final list maximum size is old list + new list. This occurs only when
@@ -472,6 +431,8 @@ void xlvbd_update_vbds(void)
      * VBDs in the old list because the usage counts are busy.
      */
     merged_info = kmalloc((old_nr + new_nr) * sizeof(vdisk_t), GFP_KERNEL);
+    if (!merged_info)
+        goto out;
 
     /* @i tracks old list; @j tracks new list; @k tracks merged list. */
     i = j = k = 0;
@@ -518,9 +479,9 @@ void xlvbd_update_vbds(void)
     nr_vbds  = k;
 
     kfree(old_info);
+out:
     kfree(new_info);
 }
-#endif
 
 /*
  * Set up all the linux device goop for the virtual block devices