From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH] linux/blkfront: fixes for 'xm block-detach ... --force' Date: Mon, 18 Jan 2010 10:19:24 +0000 Message-ID: <4B5443BC020000780002A81E@vpn.id2.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartFED4ECBC.1__=" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com Cc: Jeremy Fitzhardinge List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartFED4ECBC.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Prevent prematurely freeing 'struct blkfront_info' instances (when the xenbus data structures are gone, but the Linux ones are still needed). Prevent adding a disk with the same (major, minor) [and hence the same name and sysfs entries, which leads to oopses] when the previous instance wasn't fully de-allocated yet. This still doesn't address all issues resulting from forced detach: I/O submitted after the detach still blocks forever, likely preventing subsequent un-mounting from completing. It's not clear to me (not knowing much about the block layer) how this can be avoided. This also doesn't address issues with duplicate device creation caused by re-using the hdXX and sdXX name spaces - this would require synchronization with the respective native code. As usual, written against 2.6.32.3 and made apply to the 2.6.18 tree without further testing. As I believe that pv-ops Xen has the same issue, I'm also attaching a respective (compile tested only) patch against 2.6.33-rc4. Signed-off-by: Jan Beulich --- sle11-2010-01-12.orig/drivers/xen/blkfront/blkfront.c 2009-06-04 = 10:47:04.000000000 +0200 +++ sle11-2010-01-12/drivers/xen/blkfront/blkfront.c 2010-01-15 = 16:47:42.000000000 +0100 @@ -426,7 +426,10 @@ static int blkfront_remove(struct xenbus =20 blkif_free(info, 0); =20 - kfree(info); + if(info->users =3D=3D 0) + kfree(info); + else + info->is_ready =3D -1; =20 return 0; } @@ -488,6 +491,9 @@ static void blkif_restart_queue_callback int blkif_open(struct inode *inode, struct file *filep) { struct blkfront_info *info =3D inode->i_bdev->bd_disk->private_data= ; + + if(info->is_ready < 0) + return -ENODEV; info->users++; return 0; } @@ -504,7 +510,10 @@ int blkif_release(struct inode *inode, s struct xenbus_device * dev =3D info->xbdev; enum xenbus_state state =3D xenbus_read_driver_state(dev->o= therend); =20 - if (state =3D=3D XenbusStateClosing && info->is_ready) + if(info->is_ready < 0) { + blkfront_closing(dev); + kfree(info); + } else if (state =3D=3D XenbusStateClosing && info->is_read= y) blkfront_closing(dev); } return 0; @@ -894,7 +903,7 @@ int blkfront_is_ready(struct xenbus_devi { struct blkfront_info *info =3D dev->dev.driver_data; =20 - return info->is_ready; + return info->is_ready > 0; } =20 =20 --- sle11-2010-01-12.orig/drivers/xen/blkfront/block.h 2009-06-04 = 10:47:04.000000000 +0200 +++ sle11-2010-01-12/drivers/xen/blkfront/block.h 2010-01-18 = 08:56:41.000000000 +0100 @@ -78,6 +78,7 @@ struct xlbd_major_info int index; int usage; struct xlbd_type_info *type; + struct xlbd_minor_state *minors; }; =20 struct blk_shadow { --- sle11-2010-01-12.orig/drivers/xen/blkfront/vbd.c 2009-06-04 = 10:47:04.000000000 +0200 +++ sle11-2010-01-12/drivers/xen/blkfront/vbd.c 2010-01-18 08:56:32.0000000= 00 +0100 @@ -48,6 +48,12 @@ #define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED)) #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) =20 +struct xlbd_minor_state { + unsigned int nr; + unsigned long *bitmap; + spinlock_t lock; +}; + /* * For convenience we distinguish between ide, scsi and 'other' (i.e., * potentially combinations of the two) in the naming scheme and in a few = other @@ -97,6 +103,8 @@ static struct xlbd_major_info *major_inf #define XLBD_MAJOR_SCSI_RANGE XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_ST= ART - 1 #define XLBD_MAJOR_VBD_RANGE XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_STA= RT + NUM_VBD_MAJORS - 1 =20 +#define XLBD_MAJOR_VBD_ALT(idx) ((idx) ^ XLBD_MAJOR_VBD_START ^ (XLBD_MAJO= R_VBD_START + 1)) + static struct block_device_operations xlvbd_block_fops =3D { .owner =3D THIS_MODULE, @@ -114,6 +122,7 @@ static struct xlbd_major_info * xlbd_alloc_major_info(int major, int minor, int index) { struct xlbd_major_info *ptr; + struct xlbd_minor_state *minors; int do_register; =20 ptr =3D kzalloc(sizeof(struct xlbd_major_info), GFP_KERNEL); @@ -121,6 +130,22 @@ xlbd_alloc_major_info(int major, int min return NULL; =20 ptr->major =3D major; + minors =3D kmalloc(sizeof(*minors), GFP_KERNEL); + if (minors =3D=3D NULL) { + kfree(ptr); + return NULL; + } + + minors->bitmap =3D kzalloc(BITS_TO_LONGS(256) * sizeof(*minors->bit= map), + GFP_KERNEL); + if (minors->bitmap =3D=3D NULL) { + kfree(minors); + kfree(ptr); + return NULL; + } + + spin_lock_init(&minors->lock); + minors->nr =3D 256; do_register =3D 1; =20 switch (index) { @@ -143,13 +168,19 @@ xlbd_alloc_major_info(int major, int min * if someone already registered block major 202, * don't try to register it again */ - if (major_info[XLBD_MAJOR_VBD_START] !=3D NULL) + if (major_info[XLBD_MAJOR_VBD_ALT(index)] !=3D NULL) { + kfree(minors->bitmap); + kfree(minors); + minors =3D major_info[XLBD_MAJOR_VBD_ALT(index)]->m= inors; do_register =3D 0; + } break; } =20 if (do_register) { if (register_blkdev(ptr->major, ptr->type->devname)) { + kfree(minors->bitmap); + kfree(minors); kfree(ptr); return NULL; } @@ -157,6 +188,7 @@ xlbd_alloc_major_info(int major, int min printk("xen-vbd: registered block device major %i\n", = ptr->major); } =20 + ptr->minors =3D minors; major_info[index] =3D ptr; return ptr; } @@ -209,6 +241,61 @@ xlbd_put_major_info(struct xlbd_major_in } =20 static int +xlbd_reserve_minors(struct xlbd_major_info *mi, unsigned int minor, + unsigned int nr_minors) +{ + struct xlbd_minor_state *ms =3D mi->minors; + unsigned int end =3D minor + nr_minors; + int rc; + + if (end > ms->nr) { + unsigned long *bitmap, *old; + + bitmap =3D kzalloc(BITS_TO_LONGS(end) * sizeof(*bitmap), + GFP_KERNEL); + if (bitmap =3D=3D NULL) + return -ENOMEM; + + spin_lock(&ms->lock); + if (end > ms->nr) { + old =3D ms->bitmap; + memcpy(bitmap, ms->bitmap, + BITS_TO_LONGS(ms->nr) * sizeof(*bitmap)); + ms->bitmap =3D bitmap; + ms->nr =3D BITS_TO_LONGS(end) * BITS_PER_LONG; + } else + old =3D bitmap; + spin_unlock(&ms->lock); + kfree(old); + } + + spin_lock(&ms->lock); + if (find_next_bit(ms->bitmap, end, minor) >=3D end) { + for (; minor < end; ++minor) + __set_bit(minor, ms->bitmap); + rc =3D 0; + } else + rc =3D -EBUSY; + spin_unlock(&ms->lock); + + return rc; +} + +static void +xlbd_release_minors(struct xlbd_major_info *mi, unsigned int minor, + unsigned int nr_minors) +{ + struct xlbd_minor_state *ms =3D mi->minors; + unsigned int end =3D minor + nr_minors; + + BUG_ON(end > ms->nr); + spin_lock(&ms->lock); + for (; minor < end; ++minor) + __clear_bit(minor, ms->bitmap); + spin_unlock(&ms->lock); +} + +static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) { request_queue_t *rq; @@ -285,9 +372,14 @@ xlvbd_add(blkif_sector_t capacity, int v if ((minor & ((1 << mi->type->partn_shift) - 1)) =3D=3D 0) nr_minors =3D 1 << mi->type->partn_shift; =20 + err =3D xlbd_reserve_minors(mi, minor, nr_minors); + if (err) + goto out; + err =3D -ENODEV; + gd =3D alloc_disk(nr_minors); if (gd =3D=3D NULL) - goto out; + goto release; =20 offset =3D mi->index * mi->type->disks_per_major + (minor >> mi->type->partn_shift); @@ -326,7 +418,7 @@ xlvbd_add(blkif_sector_t capacity, int v =20 if (xlvbd_init_blk_queue(gd, sector_size)) { del_gendisk(gd); - goto out; + goto release; } =20 info->rq =3D gd->queue; @@ -346,6 +438,8 @@ xlvbd_add(blkif_sector_t capacity, int v =20 return 0; =20 + release: + xlbd_release_minors(mi, minor, nr_minors); out: if (mi) xlbd_put_major_info(mi); @@ -356,14 +450,19 @@ xlvbd_add(blkif_sector_t capacity, int v void xlvbd_del(struct blkfront_info *info) { + unsigned int minor, nr_minors; + if (info->mi =3D=3D NULL) return; =20 BUG_ON(info->gd =3D=3D NULL); + minor =3D info->gd->first_minor; + nr_minors =3D info->gd->minors; del_gendisk(info->gd); put_disk(info->gd); info->gd =3D NULL; =20 + xlbd_release_minors(info->mi, minor, nr_minors); xlbd_put_major_info(info->mi); info->mi =3D NULL; =20 --=__PartFED4ECBC.1__= Content-Type: text/plain; name="xenlinux-blkfront-forced-detach.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="xenlinux-blkfront-forced-detach.patch" Subject: blkfront: fixes for 'xm block-detach ... --force'=0A=0APrevent = prematurely freeing 'struct blkfront_info' instances (when the=0Axenbus = data structures are gone, but the Linux ones are still needed).=0A=0APreven= t adding a disk with the same (major, minor) [and hence the same=0Aname = and sysfs entries, which leads to oopses] when the previous=0Ainstance = wasn't fully de-allocated yet.=0A=0AThis still doesn't address all issues = resulting from forced detach:=0AI/O submitted after the detach still = blocks forever, likely preventing=0Asubsequent un-mounting from completing.= It's not clear to me (not=0Aknowing much about the block layer) how this = can be avoided.=0A=0AThis also doesn't address issues with duplicate = device creation caused=0Aby re-using the hdXX and sdXX name spaces - this = would require=0Asynchronization with the respective native code.=0A=0AAs = usual, written against 2.6.32.3 and made apply to the 2.6.18=0Atree = without further testing.=0A=0ASigned-off-by: Jan Beulich =0A=0A--- sle11-2010-01-12.orig/drivers/xen/blkfront/blkfront.c = 2009-06-04 10:47:04.000000000 +0200=0A+++ sle11-2010-01-12/drivers/xen/blkf= ront/blkfront.c 2010-01-15 16:47:42.000000000 +0100=0A@@ -426,7 +426,10 @@ = static int blkfront_remove(struct xenbus=0A =0A blkif_free(info, = 0);=0A =0A- kfree(info);=0A+ if(info->users =3D=3D 0)=0A+ = kfree(info);=0A+ else=0A+ info->is_ready =3D -1;=0A = =0A return 0;=0A }=0A@@ -488,6 +491,9 @@ static void blkif_restart_queu= e_callback=0A int blkif_open(struct inode *inode, struct file *filep)=0A = {=0A struct blkfront_info *info =3D inode->i_bdev->bd_disk->private_data= ;=0A+=0A+ if(info->is_ready < 0)=0A+ return -ENODEV;=0A = info->users++;=0A return 0;=0A }=0A@@ -504,7 +510,10 @@ int = blkif_release(struct inode *inode, s=0A struct xenbus_devic= e * dev =3D info->xbdev;=0A enum xenbus_state state =3D = xenbus_read_driver_state(dev->otherend);=0A =0A- if (state = =3D=3D XenbusStateClosing && info->is_ready)=0A+ if(info->is= _ready < 0) {=0A+ blkfront_closing(dev);=0A+ = kfree(info);=0A+ } else if (state =3D=3D XenbusState= Closing && info->is_ready)=0A blkfront_closing(dev);=0A = }=0A return 0;=0A@@ -894,7 +903,7 @@ int blkfront_is_ready(struct = xenbus_devi=0A {=0A struct blkfront_info *info =3D dev->dev.driver_data= ;=0A =0A- return info->is_ready;=0A+ return info->is_ready > = 0;=0A }=0A =0A =0A--- sle11-2010-01-12.orig/drivers/xen/blkfront/block.h = 2009-06-04 10:47:04.000000000 +0200=0A+++ sle11-2010-01-12/drivers/xen/blkf= ront/block.h 2010-01-18 08:56:41.000000000 +0100=0A@@ -78,6 +78,7 @@ = struct xlbd_major_info=0A int index;=0A int usage;=0A struct = xlbd_type_info *type;=0A+ struct xlbd_minor_state *minors;=0A };=0A = =0A struct blk_shadow {=0A--- sle11-2010-01-12.orig/drivers/xen/blkfront/vb= d.c 2009-06-04 10:47:04.000000000 +0200=0A+++ sle11-2010-01-12/drivers/= xen/blkfront/vbd.c 2010-01-18 08:56:32.000000000 +0100=0A@@ -48,6 = +48,12 @@=0A #define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))=0A #define = BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))=0A =0A+struct xlbd_minor_state = {=0A+ unsigned int nr;=0A+ unsigned long *bitmap;=0A+ spinlock_t = lock;=0A+};=0A+=0A /*=0A * For convenience we distinguish between ide, = scsi and 'other' (i.e.,=0A * potentially combinations of the two) in the = naming scheme and in a few other=0A@@ -97,6 +103,8 @@ static struct = xlbd_major_info *major_inf=0A #define XLBD_MAJOR_SCSI_RANGE XLBD_MAJOR_= SCSI_START ... XLBD_MAJOR_VBD_START - 1=0A #define XLBD_MAJOR_VBD_RANGE = XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1=0A = =0A+#define XLBD_MAJOR_VBD_ALT(idx) ((idx) ^ XLBD_MAJOR_VBD_START ^ = (XLBD_MAJOR_VBD_START + 1))=0A+=0A static struct block_device_operations = xlvbd_block_fops =3D=0A {=0A .owner =3D THIS_MODULE,=0A@@ -114,6 +122,7 = @@ static struct xlbd_major_info *=0A xlbd_alloc_major_info(int major, int = minor, int index)=0A {=0A struct xlbd_major_info *ptr;=0A+ = struct xlbd_minor_state *minors;=0A int do_register;=0A =0A = ptr =3D kzalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);=0A@@ -121,6 = +130,22 @@ xlbd_alloc_major_info(int major, int min=0A return = NULL;=0A =0A ptr->major =3D major;=0A+ minors =3D kmalloc(sizeof(*= minors), GFP_KERNEL);=0A+ if (minors =3D=3D NULL) {=0A+ = kfree(ptr);=0A+ return NULL;=0A+ }=0A+=0A+ minors->bit= map =3D kzalloc(BITS_TO_LONGS(256) * sizeof(*minors->bitmap),=0A+ = GFP_KERNEL);=0A+ if (minors->bitmap =3D=3D NULL) = {=0A+ kfree(minors);=0A+ kfree(ptr);=0A+ = return NULL;=0A+ }=0A+=0A+ spin_lock_init(&minors->lock);=0A+ = minors->nr =3D 256;=0A do_register =3D 1;=0A =0A switch (index) = {=0A@@ -143,13 +168,19 @@ xlbd_alloc_major_info(int major, int min=0A = * if someone already registered block major 202,=0A * don't = try to register it again=0A */=0A- if (major_info[XLBD= _MAJOR_VBD_START] !=3D NULL)=0A+ if (major_info[XLBD_MAJOR_V= BD_ALT(index)] !=3D NULL) {=0A+ kfree(minors->bitmap);=0A+ = kfree(minors);=0A+ minors =3D = major_info[XLBD_MAJOR_VBD_ALT(index)]->minors;=0A = do_register =3D 0;=0A+ }=0A break;=0A }=0A =0A = if (do_register) {=0A if (register_blkdev(ptr->major, ptr->type->= devname)) {=0A+ kfree(minors->bitmap);=0A+ = kfree(minors);=0A kfree(ptr);=0A = return NULL;=0A }=0A@@ -157,6 +188,7 @@ xlbd_alloc_major_in= fo(int major, int min=0A printk("xen-vbd: registered block = device major %i\n", ptr->major);=0A }=0A =0A+ ptr->minors =3D = minors;=0A major_info[index] =3D ptr;=0A return ptr;=0A }=0A@@ = -209,6 +241,61 @@ xlbd_put_major_info(struct xlbd_major_in=0A }=0A =0A = static int=0A+xlbd_reserve_minors(struct xlbd_major_info *mi, unsigned int = minor,=0A+ unsigned int nr_minors)=0A+{=0A+ struct = xlbd_minor_state *ms =3D mi->minors;=0A+ unsigned int end =3D minor = + nr_minors;=0A+ int rc;=0A+=0A+ if (end > ms->nr) {=0A+ = unsigned long *bitmap, *old;=0A+=0A+ bitmap =3D kzalloc(BITS_TO_= LONGS(end) * sizeof(*bitmap),=0A+ GFP_KERNEL= );=0A+ if (bitmap =3D=3D NULL)=0A+ return = -ENOMEM;=0A+=0A+ spin_lock(&ms->lock);=0A+ if = (end > ms->nr) {=0A+ old =3D ms->bitmap;=0A+ = memcpy(bitmap, ms->bitmap,=0A+ BITS_TO_LONGS(ms->nr= ) * sizeof(*bitmap));=0A+ ms->bitmap =3D bitmap;=0A+ = ms->nr =3D BITS_TO_LONGS(end) * BITS_PER_LONG;=0A+ = } else=0A+ old =3D bitmap;=0A+ spin_unlock= (&ms->lock);=0A+ kfree(old);=0A+ }=0A+=0A+ spin_lock(&= ms->lock);=0A+ if (find_next_bit(ms->bitmap, end, minor) >=3D end) {=0A+ = for (; minor < end; ++minor)=0A+ __set_bit(m= inor, ms->bitmap);=0A+ rc =3D 0;=0A+ } else=0A+ rc = =3D -EBUSY;=0A+ spin_unlock(&ms->lock);=0A+=0A+ return rc;=0A+}=0A+=0A+stat= ic void=0A+xlbd_release_minors(struct xlbd_major_info *mi, unsigned int = minor,=0A+ unsigned int nr_minors)=0A+{=0A+ struct = xlbd_minor_state *ms =3D mi->minors;=0A+ unsigned int end =3D minor = + nr_minors;=0A+=0A+ BUG_ON(end > ms->nr);=0A+ spin_lock(&ms->lock= );=0A+ for (; minor < end; ++minor)=0A+ __clear_bit(minor, = ms->bitmap);=0A+ spin_unlock(&ms->lock);=0A+}=0A+=0A+static int=0A = xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)=0A {=0A = request_queue_t *rq;=0A@@ -285,9 +372,14 @@ xlvbd_add(blkif_sector_t = capacity, int v=0A if ((minor & ((1 << mi->type->partn_shift) - 1)) = =3D=3D 0)=0A nr_minors =3D 1 << mi->type->partn_shift;=0A =0A+ = err =3D xlbd_reserve_minors(mi, minor, nr_minors);=0A+ if (err)=0A+ = goto out;=0A+ err =3D -ENODEV;=0A+=0A gd =3D alloc_disk(nr_minors= );=0A if (gd =3D=3D NULL)=0A- goto out;=0A+ goto = release;=0A =0A offset =3D mi->index * mi->type->disks_per_major = +=0A (minor >> mi->type->partn_shift);=0A@@ -326,7 = +418,7 @@ xlvbd_add(blkif_sector_t capacity, int v=0A =0A if = (xlvbd_init_blk_queue(gd, sector_size)) {=0A del_gendisk(gd);=0A= - goto out;=0A+ goto release;=0A }=0A =0A = info->rq =3D gd->queue;=0A@@ -346,6 +438,8 @@ xlvbd_add(blkif_sector_t = capacity, int v=0A =0A return 0;=0A =0A+ release:=0A+ xlbd_release_minors= (mi, minor, nr_minors);=0A out:=0A if (mi)=0A xlbd_put_ma= jor_info(mi);=0A@@ -356,14 +450,19 @@ xlvbd_add(blkif_sector_t capacity, = int v=0A void=0A xlvbd_del(struct blkfront_info *info)=0A {=0A+ unsigned = int minor, nr_minors;=0A+=0A if (info->mi =3D=3D NULL)=0A = return;=0A =0A BUG_ON(info->gd =3D=3D NULL);=0A+ minor =3D = info->gd->first_minor;=0A+ nr_minors =3D info->gd->minors;=0A = del_gendisk(info->gd);=0A put_disk(info->gd);=0A info->gd =3D = NULL;=0A =0A+ xlbd_release_minors(info->mi, minor, nr_minors);=0A = xlbd_put_major_info(info->mi);=0A info->mi =3D NULL;=0A =0A --=__PartFED4ECBC.1__= Content-Type: text/plain; name="linux-2.6.33-rc4-xen-blkfront-forced-detach.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="linux-2.6.33-rc4-xen-blkfront-forced-detach.patch" Subject: blkfront: fixes for 'xm block-detach ... --force'=0A=0APrevent = prematurely freeing 'struct blkfront_info' instances (when the=0Axenbus = data structures are gone, but the Linux ones are still needed).=0A=0APreven= t adding a disk with the same (major, minor) [and hence the same=0Aname = and sysfs entries, which leads to oopses] when the previous=0Ainstance = wasn't fully de-allocated yet.=0A=0AThis still doesn't address all issues = resulting from forced detach:=0AI/O submitted after the detach still = blocks forever, likely preventing=0Asubsequent un-mounting from completing.= It's not clear to me (not=0Aknowing much about the block layer) how this = can be avoided.=0A=0ASigned-off-by: Jan Beulich =0A=0A= ---=0A drivers/block/xen-blkfront.c | 83 ++++++++++++++++++++++++++++++++= ++++++++---=0A 1 file changed, 78 insertions(+), 5 deletions(-)=0A=0A--- = linux-2.6.33-rc4/drivers/block/xen-blkfront.c 2010-01-18 10:43:21.0000000= 00 +0100=0A+++ 2.6.33-rc4-xen-blkfront-forced-detach/drivers/block/xen-blkf= ront.c 2010-01-18 11:14:20.000000000 +0100=0A@@ -103,6 +103,10 @@ struct = blkfront_info=0A =0A static DEFINE_SPINLOCK(blkif_io_lock);=0A =0A+static = unsigned int nr_minors;=0A+static unsigned long *minors;=0A+static = DEFINE_SPINLOCK(minor_lock);=0A+=0A #define MAXIMUM_OUTSTANDING_BLOCK_REQS = \=0A (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLK_RING_SIZE)=0A #define = GRANT_INVALID_REF 0=0A@@ -137,6 +141,55 @@ static void add_id_to_free= list(struct bl=0A info->shadow_free =3D id;=0A }=0A =0A+static int = xlbd_reserve_minors(unsigned int minor, unsigned int nr)=0A+{=0A+ = unsigned int end =3D minor + nr;=0A+ int rc;=0A+=0A+ if (end > = nr_minors) {=0A+ unsigned long *bitmap, *old;=0A+=0A+ = bitmap =3D kzalloc(BITS_TO_LONGS(end) * sizeof(*bitmap),=0A+ = GFP_KERNEL);=0A+ if (bitmap =3D=3D NULL)=0A+ = return -ENOMEM;=0A+=0A+ spin_lock(&minor_lock);=0A+ = if (end > nr_minors) {=0A+ old =3D minors;=0A+ = memcpy(bitmap, minors,=0A+ BITS_TO_LONG= S(nr_minors) * sizeof(*bitmap));=0A+ minors =3D = bitmap;=0A+ nr_minors =3D BITS_TO_LONGS(end) * = BITS_PER_LONG;=0A+ } else=0A+ old =3D = bitmap;=0A+ spin_unlock(&minor_lock);=0A+ kfree(old);= =0A+ }=0A+=0A+ spin_lock(&minor_lock);=0A+ if (find_next_bit(m= inors, end, minor) >=3D end) {=0A+ for (; minor < end; = ++minor)=0A+ __set_bit(minor, minors);=0A+ rc = =3D 0;=0A+ } else=0A+ rc =3D -EBUSY;=0A+ spin_unlock= (&minor_lock);=0A+=0A+ return rc;=0A+}=0A+=0A+static void xlbd_release_min= ors(unsigned int minor, unsigned int nr)=0A+{=0A+ unsigned int end = =3D minor + nr;=0A+=0A+ BUG_ON(end > nr_minors);=0A+ spin_lock(&minor_lo= ck);=0A+ for (; minor < end; ++minor)=0A+ __clear_bit= (minor, minors);=0A+ spin_unlock(&minor_lock);=0A+}=0A+=0A static void = blkif_restart_queue_callback(void *arg)=0A {=0A struct blkfront_inf= o *info =3D (struct blkfront_info *)arg;=0A@@ -417,9 +470,14 @@ static int = xlvbd_alloc_gendisk(blkif_sec=0A if ((minor % nr_parts) =3D=3D = 0)=0A nr_minors =3D nr_parts;=0A =0A+ err =3D xlbd_reserve_minors= (minor, nr_minors);=0A+ if (err)=0A+ goto out;=0A+ err =3D = -ENODEV;=0A+=0A gd =3D alloc_disk(nr_minors);=0A if (gd = =3D=3D NULL)=0A- goto out;=0A+ goto release;=0A = =0A offset =3D minor / nr_parts;=0A =0A@@ -450,7 +508,7 @@ static int = xlvbd_alloc_gendisk(blkif_sec=0A =0A if (xlvbd_init_blk_queue(gd, = sector_size)) {=0A del_gendisk(gd);=0A- goto = out;=0A+ goto release;=0A }=0A =0A info->rq = =3D gd->queue;=0A@@ -470,6 +528,8 @@ static int xlvbd_alloc_gendisk(blkif_s= ec=0A =0A return 0;=0A =0A+ release:=0A+ xlbd_release_minors(minor, = nr_minors);=0A out:=0A return err;=0A }=0A@@ -924,6 +984,7 @@ = static void blkfront_connect(struct blkf=0A static void blkfront_closing(st= ruct xenbus_device *dev)=0A {=0A struct blkfront_info *info =3D = dev_get_drvdata(&dev->dev);=0A+ unsigned int minor, nr_minors;=0A = unsigned long flags;=0A =0A dev_dbg(&dev->dev, "blkfront_closing: %s = removed\n", dev->nodename);=0A@@ -946,7 +1007,10 @@ static void blkfront_cl= osing(struct xenb=0A blk_cleanup_queue(info->rq);=0A info->rq = =3D NULL;=0A =0A+ minor =3D info->gd->first_minor;=0A+ nr_minors = =3D info->gd->minors;=0A del_gendisk(info->gd);=0A+ xlbd_releas= e_minors(minor, nr_minors);=0A =0A out:=0A xenbus_frontend_closed(dev)= ;=0A@@ -1004,7 +1068,10 @@ static int blkfront_remove(struct xenbus=0A =0A = blkif_free(info, 0);=0A =0A- kfree(info);=0A+ if(info->us= ers =3D=3D 0)=0A+ kfree(info);=0A+ else=0A+ = info->is_ready =3D -1;=0A =0A return 0;=0A }=0A@@ -1013,12 +1080,15 @@ = static int blkfront_is_ready(struct xenb=0A {=0A struct blkfront_inf= o *info =3D dev_get_drvdata(&dev->dev);=0A =0A- return info->is_ready;=0A+ = return info->is_ready > 0;=0A }=0A =0A static int blkif_open(struct = block_device *bdev, fmode_t mode)=0A {=0A struct blkfront_info *info = =3D bdev->bd_disk->private_data;=0A+=0A+ if(info->is_ready < 0)=0A+ = return -ENODEV;=0A info->users++;=0A return 0;=0A = }=0A@@ -1034,7 +1104,10 @@ static int blkif_release(struct gendisk =0A = struct xenbus_device *dev =3D info->xbdev;=0A enum xenbus_state = state =3D xenbus_read_driver_state(dev->otherend);=0A =0A- if = (state =3D=3D XenbusStateClosing && info->is_ready)=0A+ if(info->is= _ready < 0) {=0A+ blkfront_closing(dev);=0A+ = kfree(info);=0A+ } else if (state =3D=3D XenbusState= Closing && info->is_ready)=0A blkfront_closing(dev);=0A = }=0A return 0;=0A --=__PartFED4ECBC.1__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --=__PartFED4ECBC.1__=--