]> git.ipfire.org Git - thirdparty/kernel/stable.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 00:32:50 +0000 (09:32 +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 8690e31d993287e16a68caca0e2125c0c7e6bdb0..46b8136c31bbe4aab3bccee9923ca755f6833ea8 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;
        }
 }
 
index e427fbe459994a8491945a65fd085201f40ed01f..7878da89d29e2afef850461254f43ab4ae58722e 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;
        set_capacity(gendisk, 0);
        gendisk->private_data = d;
        d->viocd_disk = gendisk;
index a5ec5a7cb381bbffac45a13c9e2cdccfd0a7d8b0..95608228b981ab1252801e972ed04af838b9245b 100644 (file)
@@ -1773,7 +1773,8 @@ static int ide_cd_probe(ide_drive_t *drive)
 
        g->minors = 1;
        g->driverfs_dev = &drive->gendev;
-       g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
+       g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE |
+                  GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
        if (ide_cdrom_setup(drive)) {
                put_device(&info->dev);
                goto failed;
index 95019c747cc17cad69ed22c9091c2228b914c23b..4778e27071689593ec4fdffdd1107018c2f7ebe6 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 bf9c7a72037179c7ad524c439f1735a98ef5fda3..1f2b1997833340fc4e80b0c5a3c115a7f949fd15 100644 (file)
@@ -1238,6 +1238,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);
@@ -1264,15 +1266,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 d764a426e9fdbf5b5086542e3eeb6c6a2e6d3c8a..300d7582006e49f6ea08a3df09fc9070748c5256 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 */