From: Keir Fraser Date: Mon, 1 Mar 2010 09:56:15 +0000 (+0000) Subject: blktap2: Fix queue restart, racing block device removal. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=9314b05952dbd570b3d0ab00411ac48efa3d9e98;p=legacy%2Flinux-2.6.18-xen.git blktap2: Fix queue restart, racing block device removal. Makes tapdisk context test dev->gd before attempting a queue restart, with the device lock held. Fixes a race lost against device destruction, which may issued anywhere on the control path. Signed-off-by: Daniel Stodden Signed-off-by: Jan Beulich --- diff --git a/drivers/xen/blktap2/device.c b/drivers/xen/blktap2/device.c index eb21e968..f15c7230 100644 --- a/drivers/xen/blktap2/device.c +++ b/drivers/xen/blktap2/device.c @@ -951,8 +951,6 @@ blktap_device_restart(struct blktap *tap) struct blktap_device *dev; dev = &tap->device; - if (!dev->gd || !dev->gd->queue) - return; if (blktap_active(tap) && RING_FULL(&tap->ring.ring)) { blktap_defer(tap); @@ -968,11 +966,15 @@ blktap_device_restart(struct blktap *tap) spin_lock_irq(&dev->lock); /* Re-enable calldowns. */ - if (blk_queue_stopped(dev->gd->queue)) - blk_start_queue(dev->gd->queue); + if (dev->gd) { + struct request_queue *rq = dev->gd->queue; + + if (blk_queue_stopped(rq)) + blk_start_queue(rq); - /* Kick things off immediately. */ - blktap_device_do_request(dev->gd->queue); + /* Kick things off immediately. */ + blktap_device_do_request(rq); + } spin_unlock_irq(&dev->lock); } @@ -1061,6 +1063,7 @@ int blktap_device_destroy(struct blktap *tap) { struct blktap_device *dev = &tap->device; + struct gendisk *gd = dev->gd; if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse)) return 0; @@ -1072,8 +1075,9 @@ blktap_device_destroy(struct blktap *tap) spin_lock_irq(&dev->lock); /* No more blktap_device_do_request(). */ - blk_stop_queue(dev->gd->queue); + blk_stop_queue(gd->queue); clear_bit(BLKTAP_DEVICE, &tap->dev_inuse); + dev->gd = NULL; spin_unlock_irq(&dev->lock); #ifdef ENABLE_PASSTHROUGH @@ -1081,11 +1085,9 @@ blktap_device_destroy(struct blktap *tap) blktap_device_close_bdev(tap); #endif - del_gendisk(dev->gd); - blk_cleanup_queue(dev->gd->queue); - put_disk(dev->gd); - - dev->gd = NULL; + del_gendisk(gd); + blk_cleanup_queue(gd->queue); + put_disk(gd); wake_up(&tap->wq);