]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
block: don't block events on excl write for non-optical devices
authorTejun Heo <tj@kernel.org>
Thu, 21 Apr 2011 18:54:46 +0000 (20:54 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 3 Jun 2011 01:33:43 +0000 (10:33 +0900)
commit d4dc210f69bcb0b4bef5a83b1c323817be89bad1 upstream.

Disk event code automatically blocks events on excl write.  This is
primarily to avoid issuing polling commands while burning is in
progress.  This behavior doesn't fit other types of devices with
removeable media where polling commands don't have adverse side
effects and door locking usually doesn't exist.

This patch introduces new genhd flag which controls the auto-blocking
behavior and uses it to enable auto-blocking only on optical devices.

Note for stable: 2.6.38 and later only

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/block/paride/pcd.c
drivers/cdrom/viocd.c
drivers/ide/ide-cd.c
drivers/scsi/sr.c
fs/block_dev.c
include/linux/genhd.h

index 2f2ccf6862519c4bb44493ccab140cbbdab37a93..a0aabd904a51294605a20e39de391660bff77e90 100644 (file)
@@ -320,6 +320,7 @@ static void pcd_init_units(void)
                disk->first_minor = unit;
                strcpy(disk->disk_name, cd->name);      /* umm... */
                disk->fops = &pcd_bdops;
+               disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
                disk->events = DISK_EVENT_MEDIA_CHANGE;
        }
 }
index 4e874c5fa60595036a7e10b26257384715b06b56..ae15a4ddaa9b0a3d7ff172e737dbaafd9fe8ac46 100644 (file)
@@ -625,7 +625,8 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        blk_queue_max_hw_sectors(q, 4096 / 512);
        gendisk->queue = q;
        gendisk->fops = &viocd_fops;
-       gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE;
+       gendisk->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE |
+                        GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
        gendisk->events = DISK_EVENT_MEDIA_CHANGE;
        set_capacity(gendisk, 0);
        gendisk->private_data = d;
index a2e29099ee0c1b22339452e76c9150bac827ce7b..413e4ef60356e3d6a4945fb8f42a875949f018d8 100644 (file)
@@ -1790,7 +1790,7 @@ static int ide_cd_probe(ide_drive_t *drive)
 
        ide_cd_read_toc(drive, &sense);
        g->fops = &idecd_ops;
-       g->flags |= GENHD_FL_REMOVABLE;
+       g->flags |= GENHD_FL_REMOVABLE | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
        g->events = DISK_EVENT_MEDIA_CHANGE;
        add_disk(g);
        return 0;
index aefadc6a1607231173f7126a3e4bac44b16f583e..464ee7ba95b7e1bf7056380c28d8cf22a71957e3 100644 (file)
@@ -636,7 +636,7 @@ static int sr_probe(struct device *dev)
        disk->first_minor = minor;
        sprintf(disk->disk_name, "sr%d", minor);
        disk->fops = &sr_bdops;
-       disk->flags = GENHD_FL_CD;
+       disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
        disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST;
 
        blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
index 0920e7cfde5acad3a0f1c531849fb102fa5ef9fc..59277ba8d2903fd8214278f0bc2243c7d282e6e1 100644 (file)
@@ -1233,6 +1233,8 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
        res = __blkdev_get(bdev, mode, 0);
 
        if (whole) {
+               struct gendisk *disk = whole->bd_disk;
+
                /* finish claiming */
                mutex_lock(&bdev->bd_mutex);
                spin_lock(&bdev_lock);
@@ -1259,15 +1261,16 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
                spin_unlock(&bdev_lock);
 
                /*
-                * Block event polling for write claims.  Any write
-                * holder makes the write_holder state stick until all
-                * are released.  This is good enough and tracking
-                * individual writeable reference is too fragile given
-                * the way @mode is used in blkdev_get/put().
+                * Block event polling for write claims if requested.  Any
+                * write holder makes the write_holder state stick until
+                * all are released.  This is good enough and tracking
+                * individual writeable reference is too fragile given the
+                * way @mode is used in blkdev_get/put().
                 */
-               if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) {
+               if ((disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE) &&
+                   !res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) {
                        bdev->bd_write_holder = true;
-                       disk_block_events(bdev->bd_disk);
+                       disk_block_events(disk);
                }
 
                mutex_unlock(&bdev->bd_mutex);
index c0d5f6945c1ebffcccc452da109e353b646a4b0c..035bc67051ce59c7fe1741e697cedf80e4518174 100644 (file)
@@ -127,6 +127,7 @@ struct hd_struct {
 #define GENHD_FL_SUPPRESS_PARTITION_INFO       32
 #define GENHD_FL_EXT_DEVT                      64 /* allow extended devt */
 #define GENHD_FL_NATIVE_CAPACITY               128
+#define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE    256
 
 enum {
        DISK_EVENT_MEDIA_CHANGE                 = 1 << 0, /* media changed */