Skip to content

Commit

Permalink
block: don't block events on excl write for non-optical devices
Browse files Browse the repository at this point in the history
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: [email protected]
Signed-off-by: Tejun Heo <[email protected]>
Reported-by: Kay Sievers <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
htejun authored and Jens Axboe committed Apr 21, 2011
1 parent 1196f8b commit d4dc210
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 10 deletions.
1 change: 1 addition & 0 deletions drivers/block/paride/pcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/cdrom/viocd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/ide/ide-cd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1781,7 +1781,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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/sr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 10 additions & 7 deletions fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,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);
Expand All @@ -1263,15 +1265,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);
Expand Down
1 change: 1 addition & 0 deletions include/linux/genhd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit d4dc210

Please sign in to comment.