Commit a2b9c1f6 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block

* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
  block: don't delay blk_run_queue_async
  scsi: remove performance regression due to async queue run
  blk-throttle: Use task_subsys_state() to determine a task's blkio_cgroup
  block: rescan partitions on invalidated devices on -ENOMEDIA too
  cdrom: always check_disk_change() on open
  block: unexport DISK_EVENT_MEDIA_CHANGE for legacy/fringe drivers
parents 2e9521fd 3ec717b7
...@@ -114,6 +114,13 @@ struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup) ...@@ -114,6 +114,13 @@ struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup)
} }
EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup); EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup);
struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk)
{
return container_of(task_subsys_state(tsk, blkio_subsys_id),
struct blkio_cgroup, css);
}
EXPORT_SYMBOL_GPL(task_blkio_cgroup);
static inline void static inline void
blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight) blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
{ {
......
...@@ -291,6 +291,7 @@ static inline void blkiocg_set_start_empty_time(struct blkio_group *blkg) {} ...@@ -291,6 +291,7 @@ static inline void blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
extern struct blkio_cgroup blkio_root_cgroup; extern struct blkio_cgroup blkio_root_cgroup;
extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup); extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
extern struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk);
extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
struct blkio_group *blkg, void *key, dev_t dev, struct blkio_group *blkg, void *key, dev_t dev,
enum blkio_policy_id plid); enum blkio_policy_id plid);
...@@ -314,6 +315,8 @@ void blkiocg_update_io_remove_stats(struct blkio_group *blkg, ...@@ -314,6 +315,8 @@ void blkiocg_update_io_remove_stats(struct blkio_group *blkg,
struct cgroup; struct cgroup;
static inline struct blkio_cgroup * static inline struct blkio_cgroup *
cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; } cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
static inline struct blkio_cgroup *
task_blkio_cgroup(struct task_struct *tsk) { return NULL; }
static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
struct blkio_group *blkg, void *key, dev_t dev, struct blkio_group *blkg, void *key, dev_t dev,
......
...@@ -316,8 +316,10 @@ EXPORT_SYMBOL(__blk_run_queue); ...@@ -316,8 +316,10 @@ EXPORT_SYMBOL(__blk_run_queue);
*/ */
void blk_run_queue_async(struct request_queue *q) void blk_run_queue_async(struct request_queue *q)
{ {
if (likely(!blk_queue_stopped(q))) if (likely(!blk_queue_stopped(q))) {
__cancel_delayed_work(&q->delay_work);
queue_delayed_work(kblockd_workqueue, &q->delay_work, 0); queue_delayed_work(kblockd_workqueue, &q->delay_work, 0);
}
} }
EXPORT_SYMBOL(blk_run_queue_async); EXPORT_SYMBOL(blk_run_queue_async);
......
...@@ -160,9 +160,8 @@ static void throtl_put_tg(struct throtl_grp *tg) ...@@ -160,9 +160,8 @@ static void throtl_put_tg(struct throtl_grp *tg)
} }
static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td, static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
struct cgroup *cgroup) struct blkio_cgroup *blkcg)
{ {
struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
struct throtl_grp *tg = NULL; struct throtl_grp *tg = NULL;
void *key = td; void *key = td;
struct backing_dev_info *bdi = &td->queue->backing_dev_info; struct backing_dev_info *bdi = &td->queue->backing_dev_info;
...@@ -229,12 +228,12 @@ static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td, ...@@ -229,12 +228,12 @@ static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
static struct throtl_grp * throtl_get_tg(struct throtl_data *td) static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
{ {
struct cgroup *cgroup;
struct throtl_grp *tg = NULL; struct throtl_grp *tg = NULL;
struct blkio_cgroup *blkcg;
rcu_read_lock(); rcu_read_lock();
cgroup = task_cgroup(current, blkio_subsys_id); blkcg = task_blkio_cgroup(current);
tg = throtl_find_alloc_tg(td, cgroup); tg = throtl_find_alloc_tg(td, blkcg);
if (!tg) if (!tg)
tg = &td->root_tg; tg = &td->root_tg;
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -1014,10 +1014,9 @@ void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg, ...@@ -1014,10 +1014,9 @@ void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
cfqg->needs_update = true; cfqg->needs_update = true;
} }
static struct cfq_group * static struct cfq_group * cfq_find_alloc_cfqg(struct cfq_data *cfqd,
cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create) struct blkio_cgroup *blkcg, int create)
{ {
struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
struct cfq_group *cfqg = NULL; struct cfq_group *cfqg = NULL;
void *key = cfqd; void *key = cfqd;
int i, j; int i, j;
...@@ -1079,12 +1078,12 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create) ...@@ -1079,12 +1078,12 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
*/ */
static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create) static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create)
{ {
struct cgroup *cgroup; struct blkio_cgroup *blkcg;
struct cfq_group *cfqg = NULL; struct cfq_group *cfqg = NULL;
rcu_read_lock(); rcu_read_lock();
cgroup = task_cgroup(current, blkio_subsys_id); blkcg = task_blkio_cgroup(current);
cfqg = cfq_find_alloc_cfqg(cfqd, cgroup, create); cfqg = cfq_find_alloc_cfqg(cfqd, blkcg, create);
if (!cfqg && create) if (!cfqg && create)
cfqg = &cfqd->root_group; cfqg = &cfqd->root_group;
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -2547,7 +2547,6 @@ static bool DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) ...@@ -2547,7 +2547,6 @@ static bool DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
disk->major = MajorNumber; disk->major = MajorNumber;
disk->first_minor = n << DAC960_MaxPartitionsBits; disk->first_minor = n << DAC960_MaxPartitionsBits;
disk->fops = &DAC960_BlockDeviceOperations; disk->fops = &DAC960_BlockDeviceOperations;
disk->events = DISK_EVENT_MEDIA_CHANGE;
} }
/* /*
Indicate the Block Device Registration completed successfully, Indicate the Block Device Registration completed successfully,
......
...@@ -1736,7 +1736,6 @@ static int __init fd_probe_drives(void) ...@@ -1736,7 +1736,6 @@ static int __init fd_probe_drives(void)
disk->major = FLOPPY_MAJOR; disk->major = FLOPPY_MAJOR;
disk->first_minor = drive; disk->first_minor = drive;
disk->fops = &floppy_fops; disk->fops = &floppy_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
sprintf(disk->disk_name, "fd%d", drive); sprintf(disk->disk_name, "fd%d", drive);
disk->private_data = &unit[drive]; disk->private_data = &unit[drive];
set_capacity(disk, 880*2); set_capacity(disk, 880*2);
......
...@@ -1964,7 +1964,6 @@ static int __init atari_floppy_init (void) ...@@ -1964,7 +1964,6 @@ static int __init atari_floppy_init (void)
unit[i].disk->first_minor = i; unit[i].disk->first_minor = i;
sprintf(unit[i].disk->disk_name, "fd%d", i); sprintf(unit[i].disk->disk_name, "fd%d", i);
unit[i].disk->fops = &floppy_fops; unit[i].disk->fops = &floppy_fops;
unit[i].disk->events = DISK_EVENT_MEDIA_CHANGE;
unit[i].disk->private_data = &unit[i]; unit[i].disk->private_data = &unit[i];
unit[i].disk->queue = blk_init_queue(do_fd_request, unit[i].disk->queue = blk_init_queue(do_fd_request,
&ataflop_lock); &ataflop_lock);
......
...@@ -4205,7 +4205,6 @@ static int __init floppy_init(void) ...@@ -4205,7 +4205,6 @@ static int __init floppy_init(void)
disks[dr]->major = FLOPPY_MAJOR; disks[dr]->major = FLOPPY_MAJOR;
disks[dr]->first_minor = TOMINOR(dr); disks[dr]->first_minor = TOMINOR(dr);
disks[dr]->fops = &floppy_fops; disks[dr]->fops = &floppy_fops;
disks[dr]->events = DISK_EVENT_MEDIA_CHANGE;
sprintf(disks[dr]->disk_name, "fd%d", dr); sprintf(disks[dr]->disk_name, "fd%d", dr);
init_timer(&motor_off_timer[dr]); init_timer(&motor_off_timer[dr]);
......
...@@ -320,7 +320,6 @@ static void pcd_init_units(void) ...@@ -320,7 +320,6 @@ 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->events = DISK_EVENT_MEDIA_CHANGE;
} }
} }
......
...@@ -837,7 +837,6 @@ static void pd_probe_drive(struct pd_unit *disk) ...@@ -837,7 +837,6 @@ static void pd_probe_drive(struct pd_unit *disk)
p->fops = &pd_fops; p->fops = &pd_fops;
p->major = major; p->major = major;
p->first_minor = (disk - pd) << PD_BITS; p->first_minor = (disk - pd) << PD_BITS;
p->events = DISK_EVENT_MEDIA_CHANGE;
disk->gd = p; disk->gd = p;
p->private_data = disk; p->private_data = disk;
p->queue = pd_queue; p->queue = pd_queue;
......
...@@ -294,7 +294,6 @@ static void __init pf_init_units(void) ...@@ -294,7 +294,6 @@ static void __init pf_init_units(void)
disk->first_minor = unit; disk->first_minor = unit;
strcpy(disk->disk_name, pf->name); strcpy(disk->disk_name, pf->name);
disk->fops = &pf_fops; disk->fops = &pf_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
if (!(*drives[unit])[D_PRT]) if (!(*drives[unit])[D_PRT])
pf_drive_count++; pf_drive_count++;
} }
......
...@@ -858,7 +858,6 @@ static int __devinit swim_floppy_init(struct swim_priv *swd) ...@@ -858,7 +858,6 @@ static int __devinit swim_floppy_init(struct swim_priv *swd)
swd->unit[drive].disk->first_minor = drive; swd->unit[drive].disk->first_minor = drive;
sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive); sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive);
swd->unit[drive].disk->fops = &floppy_fops; swd->unit[drive].disk->fops = &floppy_fops;
swd->unit[drive].disk->events = DISK_EVENT_MEDIA_CHANGE;
swd->unit[drive].disk->private_data = &swd->unit[drive]; swd->unit[drive].disk->private_data = &swd->unit[drive];
swd->unit[drive].disk->queue = swd->queue; swd->unit[drive].disk->queue = swd->queue;
set_capacity(swd->unit[drive].disk, 2880); set_capacity(swd->unit[drive].disk, 2880);
......
...@@ -1163,7 +1163,6 @@ static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device ...@@ -1163,7 +1163,6 @@ static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device
disk->major = FLOPPY_MAJOR; disk->major = FLOPPY_MAJOR;
disk->first_minor = i; disk->first_minor = i;
disk->fops = &floppy_fops; disk->fops = &floppy_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->private_data = &floppy_states[i]; disk->private_data = &floppy_states[i];
disk->queue = swim3_queue; disk->queue = swim3_queue;
disk->flags |= GENHD_FL_REMOVABLE; disk->flags |= GENHD_FL_REMOVABLE;
......
...@@ -2334,7 +2334,6 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) ...@@ -2334,7 +2334,6 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
disk->major = UB_MAJOR; disk->major = UB_MAJOR;
disk->first_minor = lun->id * UB_PARTS_PER_LUN; disk->first_minor = lun->id * UB_PARTS_PER_LUN;
disk->fops = &ub_bd_fops; disk->fops = &ub_bd_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->private_data = lun; disk->private_data = lun;
disk->driverfs_dev = &sc->intf->dev; disk->driverfs_dev = &sc->intf->dev;
......
...@@ -1005,7 +1005,6 @@ static int __devinit ace_setup(struct ace_device *ace) ...@@ -1005,7 +1005,6 @@ static int __devinit ace_setup(struct ace_device *ace)
ace->gd->major = ace_major; ace->gd->major = ace_major;
ace->gd->first_minor = ace->id * ACE_NUM_MINORS; ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
ace->gd->fops = &ace_fops; ace->gd->fops = &ace_fops;
ace->gd->events = DISK_EVENT_MEDIA_CHANGE;
ace->gd->queue = ace->queue; ace->gd->queue = ace->queue;
ace->gd->private_data = ace; ace->gd->private_data = ace;
snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a'); snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
......
...@@ -986,6 +986,9 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t ...@@ -986,6 +986,9 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t
cdinfo(CD_OPEN, "entering cdrom_open\n"); cdinfo(CD_OPEN, "entering cdrom_open\n");
/* open is event synchronization point, check events first */
check_disk_change(bdev);
/* if this was a O_NONBLOCK open and we should honor the flags, /* if this was a O_NONBLOCK open and we should honor the flags,
* do a quick open without drive/disc integrity checks. */ * do a quick open without drive/disc integrity checks. */
cdi->use_count++; cdi->use_count++;
...@@ -1012,9 +1015,6 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t ...@@ -1012,9 +1015,6 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t
cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
cdi->name, cdi->use_count); cdi->name, cdi->use_count);
/* Do this on open. Don't wait for mount, because they might
not be mounting, but opening with O_NONBLOCK */
check_disk_change(bdev);
return 0; return 0;
err_release: err_release:
if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
......
...@@ -803,7 +803,6 @@ static int __devinit probe_gdrom(struct platform_device *devptr) ...@@ -803,7 +803,6 @@ static int __devinit probe_gdrom(struct platform_device *devptr)
goto probe_fail_cdrom_register; goto probe_fail_cdrom_register;
} }
gd.disk->fops = &gdrom_bdops; gd.disk->fops = &gdrom_bdops;
gd.disk->events = DISK_EVENT_MEDIA_CHANGE;
/* latch on to the interrupt */ /* latch on to the interrupt */
err = gdrom_set_interrupt_handlers(); err = gdrom_set_interrupt_handlers();
if (err) if (err)
......
...@@ -626,7 +626,6 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) ...@@ -626,7 +626,6 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
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;
gendisk->events = DISK_EVENT_MEDIA_CHANGE;
set_capacity(gendisk, 0); set_capacity(gendisk, 0);
gendisk->private_data = d; gendisk->private_data = d;
d->viocd_disk = gendisk; d->viocd_disk = gendisk;
......
...@@ -1000,7 +1000,6 @@ static struct i2o_block_device *i2o_block_device_alloc(void) ...@@ -1000,7 +1000,6 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
gd->major = I2O_MAJOR; gd->major = I2O_MAJOR;
gd->queue = queue; gd->queue = queue;
gd->fops = &i2o_block_fops; gd->fops = &i2o_block_fops;
gd->events = DISK_EVENT_MEDIA_CHANGE;
gd->private_data = dev; gd->private_data = dev;
dev->gd = gd; dev->gd = gd;
......
...@@ -236,7 +236,6 @@ tapeblock_setup_device(struct tape_device * device) ...@@ -236,7 +236,6 @@ tapeblock_setup_device(struct tape_device * device)
disk->major = tapeblock_major; disk->major = tapeblock_major;
disk->first_minor = device->first_minor; disk->first_minor = device->first_minor;
disk->fops = &tapeblock_fops; disk->fops = &tapeblock_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->private_data = tape_get_device(device); disk->private_data = tape_get_device(device);
disk->queue = blkdat->request_queue; disk->queue = blkdat->request_queue;
set_capacity(disk, 0); set_capacity(disk, 0);
......
...@@ -74,8 +74,6 @@ struct kmem_cache *scsi_sdb_cache; ...@@ -74,8 +74,6 @@ struct kmem_cache *scsi_sdb_cache;
*/ */
#define SCSI_QUEUE_DELAY 3 #define SCSI_QUEUE_DELAY 3
static void scsi_run_queue(struct request_queue *q);
/* /*
* Function: scsi_unprep_request() * Function: scsi_unprep_request()
* *
...@@ -161,7 +159,7 @@ static int __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) ...@@ -161,7 +159,7 @@ static int __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
blk_requeue_request(q, cmd->request); blk_requeue_request(q, cmd->request);
spin_unlock_irqrestore(q->queue_lock, flags); spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q); kblockd_schedule_work(q, &device->requeue_work);
return 0; return 0;
} }
...@@ -438,7 +436,11 @@ static void scsi_run_queue(struct request_queue *q) ...@@ -438,7 +436,11 @@ static void scsi_run_queue(struct request_queue *q)
continue; continue;
} }
blk_run_queue_async(sdev->request_queue); spin_unlock(shost->host_lock);
spin_lock(sdev->request_queue->queue_lock);
__blk_run_queue(sdev->request_queue);
spin_unlock(sdev->request_queue->queue_lock);
spin_lock(shost->host_lock);
} }
/* put any unprocessed entries back */ /* put any unprocessed entries back */
list_splice(&starved_list, &shost->starved_list); list_splice(&starved_list, &shost->starved_list);
...@@ -447,6 +449,16 @@ static void scsi_run_queue(struct request_queue *q) ...@@ -447,6 +449,16 @@ static void scsi_run_queue(struct request_queue *q)
blk_run_queue(q); blk_run_queue(q);
} }
void scsi_requeue_run_queue(struct work_struct *work)
{
struct scsi_device *sdev;
struct request_queue *q;
sdev = container_of(work, struct scsi_device, requeue_work);
q = sdev->request_queue;
scsi_run_queue(q);
}
/* /*
* Function: scsi_requeue_command() * Function: scsi_requeue_command()
* *
......
...@@ -242,6 +242,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, ...@@ -242,6 +242,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
int display_failure_msg = 1, ret; int display_failure_msg = 1, ret;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
extern void scsi_evt_thread(struct work_struct *work); extern void scsi_evt_thread(struct work_struct *work);
extern void scsi_requeue_run_queue(struct work_struct *work);
sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
GFP_ATOMIC); GFP_ATOMIC);
...@@ -264,6 +265,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, ...@@ -264,6 +265,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
INIT_LIST_HEAD(&sdev->event_list); INIT_LIST_HEAD(&sdev->event_list);
spin_lock_init(&sdev->list_lock); spin_lock_init(&sdev->list_lock);
INIT_WORK(&sdev->event_work, scsi_evt_thread); INIT_WORK(&sdev->event_work, scsi_evt_thread);
INIT_WORK(&sdev->requeue_work, scsi_requeue_run_queue);
sdev->sdev_gendev.parent = get_device(&starget->dev); sdev->sdev_gendev.parent = get_device(&starget->dev);
sdev->sdev_target = starget; sdev->sdev_target = starget;
......
...@@ -1102,6 +1102,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) ...@@ -1102,6 +1102,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (!bdev->bd_part) if (!bdev->bd_part)
goto out_clear; goto out_clear;
ret = 0;
if (disk->fops->open) { if (disk->fops->open) {
ret = disk->fops->open(bdev, mode); ret = disk->fops->open(bdev, mode);
if (ret == -ERESTARTSYS) { if (ret == -ERESTARTSYS) {
...@@ -1118,9 +1119,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) ...@@ -1118,9 +1119,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
put_disk(disk); put_disk(disk);
goto restart; goto restart;
} }
if (ret)
goto out_clear;
} }
/*
* If the device is invalidated, rescan partition
* if open succeeded or failed with -ENOMEDIUM.
* The latter is necessary to prevent ghost
* partitions on a removed medium.
*/
if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
rescan_partitions(disk, bdev);
if (ret)
goto out_clear;
if (!bdev->bd_openers) { if (!bdev->bd_openers) {
bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
bdi = blk_get_backing_dev_info(bdev); bdi = blk_get_backing_dev_info(bdev);
...@@ -1128,8 +1138,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) ...@@ -1128,8 +1138,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
bdi = &default_backing_dev_info; bdi = &default_backing_dev_info;
bdev_inode_switch_bdi(bdev->bd_inode, bdi); bdev_inode_switch_bdi(bdev->bd_inode, bdi);
} }
if (bdev->bd_invalidated)
rescan_partitions(disk, bdev);
} else { } else {
struct block_device *whole; struct block_device *whole;
whole = bdget_disk(disk, 0); whole = bdget_disk(disk, 0);
...@@ -1153,13 +1161,14 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) ...@@ -1153,13 +1161,14 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
} }
} else { } else {
if (bdev->bd_contains == bdev) { if (bdev->bd_contains == bdev) {
if (bdev->bd_disk->fops->open) { ret = 0;
if (bdev->bd_disk->fops->open)
ret = bdev->bd_disk->fops->open(bdev, mode); ret = bdev->bd_disk->fops->open(bdev, mode);
if (ret) /* the same as first opener case, read comment there */
goto out_unlock_bdev; if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
}
if (bdev->bd_invalidated)
rescan_partitions(bdev->bd_disk, bdev); rescan_partitions(bdev->bd_disk, bdev);
if (ret)
goto out_unlock_bdev;
} }
/* only one opener holds refs to the module and disk */ /* only one opener holds refs to the module and disk */
module_put(disk->fops->owner); module_put(disk->fops->owner);
......
...@@ -169,6 +169,7 @@ struct scsi_device { ...@@ -169,6 +169,7 @@ struct scsi_device {
sdev_dev; sdev_dev;
struct execute_work ew; /* used to get process context on put */ struct execute_work ew; /* used to get process context on put */
struct work_struct requeue_work;
struct scsi_dh_data *scsi_dh_data; struct scsi_dh_data *scsi_dh_data;
enum scsi_device_state sdev_state; enum scsi_device_state sdev_state;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment