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>
This commit is contained in:
Родитель
1196f8b814
Коммит
d4dc210f69
|
@ -320,6 +320,7 @@ static void pcd_init_units(void)
|
||||||
disk->first_minor = unit;
|
disk->first_minor = unit;
|
||||||
strcpy(disk->disk_name, cd->name); /* umm... */
|
strcpy(disk->disk_name, cd->name); /* umm... */
|
||||||
disk->fops = &pcd_bdops;
|
disk->fops = &pcd_bdops;
|
||||||
|
disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
|
||||||
disk->events = DISK_EVENT_MEDIA_CHANGE;
|
disk->events = DISK_EVENT_MEDIA_CHANGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
blk_queue_max_hw_sectors(q, 4096 / 512);
|
||||||
gendisk->queue = q;
|
gendisk->queue = q;
|
||||||
gendisk->fops = &viocd_fops;
|
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;
|
gendisk->events = DISK_EVENT_MEDIA_CHANGE;
|
||||||
set_capacity(gendisk, 0);
|
set_capacity(gendisk, 0);
|
||||||
gendisk->private_data = d;
|
gendisk->private_data = d;
|
||||||
|
|
|
@ -1781,7 +1781,7 @@ static int ide_cd_probe(ide_drive_t *drive)
|
||||||
|
|
||||||
ide_cd_read_toc(drive, &sense);
|
ide_cd_read_toc(drive, &sense);
|
||||||
g->fops = &idecd_ops;
|
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;
|
g->events = DISK_EVENT_MEDIA_CHANGE;
|
||||||
add_disk(g);
|
add_disk(g);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -636,7 +636,7 @@ static int sr_probe(struct device *dev)
|
||||||
disk->first_minor = minor;
|
disk->first_minor = minor;
|
||||||
sprintf(disk->disk_name, "sr%d", minor);
|
sprintf(disk->disk_name, "sr%d", minor);
|
||||||
disk->fops = &sr_bdops;
|
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;
|
disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST;
|
||||||
|
|
||||||
blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
|
blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
|
||||||
|
|
|
@ -1237,6 +1237,8 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
|
||||||
res = __blkdev_get(bdev, mode, 0);
|
res = __blkdev_get(bdev, mode, 0);
|
||||||
|
|
||||||
if (whole) {
|
if (whole) {
|
||||||
|
struct gendisk *disk = whole->bd_disk;
|
||||||
|
|
||||||
/* finish claiming */
|
/* finish claiming */
|
||||||
mutex_lock(&bdev->bd_mutex);
|
mutex_lock(&bdev->bd_mutex);
|
||||||
spin_lock(&bdev_lock);
|
spin_lock(&bdev_lock);
|
||||||
|
@ -1263,15 +1265,16 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
|
||||||
spin_unlock(&bdev_lock);
|
spin_unlock(&bdev_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Block event polling for write claims. Any write
|
* Block event polling for write claims if requested. Any
|
||||||
* holder makes the write_holder state stick until all
|
* write holder makes the write_holder state stick until
|
||||||
* are released. This is good enough and tracking
|
* all are released. This is good enough and tracking
|
||||||
* individual writeable reference is too fragile given
|
* individual writeable reference is too fragile given the
|
||||||
* the way @mode is used in blkdev_get/put().
|
* 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;
|
bdev->bd_write_holder = true;
|
||||||
disk_block_events(bdev->bd_disk);
|
disk_block_events(disk);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&bdev->bd_mutex);
|
mutex_unlock(&bdev->bd_mutex);
|
||||||
|
|
|
@ -127,6 +127,7 @@ struct hd_struct {
|
||||||
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
|
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
|
||||||
#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
|
#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
|
||||||
#define GENHD_FL_NATIVE_CAPACITY 128
|
#define GENHD_FL_NATIVE_CAPACITY 128
|
||||||
|
#define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE 256
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */
|
DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче