aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-04-21 14:54:46 -0400
committerJens Axboe <jaxboe@fusionio.com>2011-04-21 14:54:46 -0400
commitd4dc210f69bcb0b4bef5a83b1c323817be89bad1 (patch)
tree58774a27fa6faff1260a416a86d2c121f0013431
parent1196f8b814f32cd04df334abf47648c2a9fd8324 (diff)
block: don't block events on excl write for non-optical devices
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 Cc: stable@kernel.org Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r--drivers/block/paride/pcd.c1
-rw-r--r--drivers/cdrom/viocd.c3
-rw-r--r--drivers/ide/ide-cd.c2
-rw-r--r--drivers/scsi/sr.c2
-rw-r--r--fs/block_dev.c17
-rw-r--r--include/linux/genhd.h1
6 files changed, 16 insertions, 10 deletions
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 2f2ccf686251..a0aabd904a51 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -320,6 +320,7 @@ static void pcd_init_units(void)
320 disk->first_minor = unit; 320 disk->first_minor = unit;
321 strcpy(disk->disk_name, cd->name); /* umm... */ 321 strcpy(disk->disk_name, cd->name); /* umm... */
322 disk->fops = &pcd_bdops; 322 disk->fops = &pcd_bdops;
323 disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
323 disk->events = DISK_EVENT_MEDIA_CHANGE; 324 disk->events = DISK_EVENT_MEDIA_CHANGE;
324 } 325 }
325} 326}
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 4e874c5fa605..ae15a4ddaa9b 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -625,7 +625,8 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
625 blk_queue_max_hw_sectors(q, 4096 / 512); 625 blk_queue_max_hw_sectors(q, 4096 / 512);
626 gendisk->queue = q; 626 gendisk->queue = q;
627 gendisk->fops = &viocd_fops; 627 gendisk->fops = &viocd_fops;
628 gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE; 628 gendisk->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE |
629 GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
629 gendisk->events = DISK_EVENT_MEDIA_CHANGE; 630 gendisk->events = DISK_EVENT_MEDIA_CHANGE;
630 set_capacity(gendisk, 0); 631 set_capacity(gendisk, 0);
631 gendisk->private_data = d; 632 gendisk->private_data = d;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index fd1e11799137..6e5123b1d341 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1781,7 +1781,7 @@ static int ide_cd_probe(ide_drive_t *drive)
1781 1781
1782 ide_cd_read_toc(drive, &sense); 1782 ide_cd_read_toc(drive, &sense);
1783 g->fops = &idecd_ops; 1783 g->fops = &idecd_ops;
1784 g->flags |= GENHD_FL_REMOVABLE; 1784 g->flags |= GENHD_FL_REMOVABLE | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
1785 g->events = DISK_EVENT_MEDIA_CHANGE; 1785 g->events = DISK_EVENT_MEDIA_CHANGE;
1786 add_disk(g); 1786 add_disk(g);
1787 return 0; 1787 return 0;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 95019c747cc1..4778e2707168 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -636,7 +636,7 @@ static int sr_probe(struct device *dev)
636 disk->first_minor = minor; 636 disk->first_minor = minor;
637 sprintf(disk->disk_name, "sr%d", minor); 637 sprintf(disk->disk_name, "sr%d", minor);
638 disk->fops = &sr_bdops; 638 disk->fops = &sr_bdops;
639 disk->flags = GENHD_FL_CD; 639 disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
640 disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST; 640 disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST;
641 641
642 blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT); 642 blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 257b00e98428..d7c2e0fddc6f 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1237,6 +1237,8 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
1237 res = __blkdev_get(bdev, mode, 0); 1237 res = __blkdev_get(bdev, mode, 0);
1238 1238
1239 if (whole) { 1239 if (whole) {
1240 struct gendisk *disk = whole->bd_disk;
1241
1240 /* finish claiming */ 1242 /* finish claiming */
1241 mutex_lock(&bdev->bd_mutex); 1243 mutex_lock(&bdev->bd_mutex);
1242 spin_lock(&bdev_lock); 1244 spin_lock(&bdev_lock);
@@ -1263,15 +1265,16 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
1263 spin_unlock(&bdev_lock); 1265 spin_unlock(&bdev_lock);
1264 1266
1265 /* 1267 /*
1266 * Block event polling for write claims. Any write 1268 * Block event polling for write claims if requested. Any
1267 * holder makes the write_holder state stick until all 1269 * write holder makes the write_holder state stick until
1268 * are released. This is good enough and tracking 1270 * all are released. This is good enough and tracking
1269 * individual writeable reference is too fragile given 1271 * individual writeable reference is too fragile given the
1270 * the way @mode is used in blkdev_get/put(). 1272 * way @mode is used in blkdev_get/put().
1271 */ 1273 */
1272 if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) { 1274 if ((disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE) &&
1275 !res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) {
1273 bdev->bd_write_holder = true; 1276 bdev->bd_write_holder = true;
1274 disk_block_events(bdev->bd_disk); 1277 disk_block_events(disk);
1275 } 1278 }
1276 1279
1277 mutex_unlock(&bdev->bd_mutex); 1280 mutex_unlock(&bdev->bd_mutex);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index d764a426e9fd..300d7582006e 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -127,6 +127,7 @@ struct hd_struct {
127#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 127#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
128#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ 128#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
129#define GENHD_FL_NATIVE_CAPACITY 128 129#define GENHD_FL_NATIVE_CAPACITY 128
130#define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE 256
130 131
131enum { 132enum {
132 DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */ 133 DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */