SCSI: fix race in device_create

There is a race from when a device is created with device_create() and
then the drvdata is set with a call to dev_set_drvdata() in which a
sysfs file could be open, yet the drvdata will be NULL, causing all
sorts of bad things to happen.

This patch fixes the problem by using the new function,
device_create_drvdata().  It fixes the problem in all of the scsi
drivers that need it.

Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: Doug Gilbert <dgilbert@interlog.com>
Cc: James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Greg Kroah-Hartman 2008-05-16 17:55:12 -07:00
parent c013d040b7
commit 24b42566c3
4 changed files with 17 additions and 16 deletions

View File

@ -910,9 +910,9 @@ static int ch_probe(struct device *dev)
ch->minor = minor;
sprintf(ch->name,"ch%d",ch->minor);
class_dev = device_create(ch_sysfs_class, dev,
MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
"s%s", ch->name);
class_dev = device_create_drvdata(ch_sysfs_class, dev,
MKDEV(SCSI_CHANGER_MAJOR, ch->minor),
ch, "s%s", ch->name);
if (IS_ERR(class_dev)) {
printk(KERN_WARNING "ch%d: device_create failed\n",
ch->minor);
@ -926,7 +926,6 @@ static int ch_probe(struct device *dev)
if (init)
ch_init_elem(ch);
dev_set_drvdata(dev, ch);
sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);
return 0;

View File

@ -5695,13 +5695,12 @@ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * S
struct device *osst_member;
int err;
osst_member = device_create(osst_sysfs_class, device, dev, "%s", name);
osst_member = device_create_drvdata(osst_sysfs_class, device, dev, STp, "%s", name);
if (IS_ERR(osst_member)) {
printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
return PTR_ERR(osst_member);
}
dev_set_drvdata(osst_member, STp);
err = device_create_file(osst_member, &dev_attr_ADR_rev);
if (err)
goto err_out;

View File

@ -1441,17 +1441,18 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
if (sg_sysfs_valid) {
struct device *sg_class_member;
sg_class_member = device_create(sg_sysfs_class, cl_dev->parent,
MKDEV(SCSI_GENERIC_MAJOR,
sdp->index),
"%s", disk->disk_name);
sg_class_member = device_create_drvdata(sg_sysfs_class,
cl_dev->parent,
MKDEV(SCSI_GENERIC_MAJOR,
sdp->index),
sdp,
"%s", disk->disk_name);
if (IS_ERR(sg_class_member)) {
printk(KERN_ERR "sg_add: "
"device_create failed\n");
error = PTR_ERR(sg_class_member);
goto cdev_add_err;
}
dev_set_drvdata(sg_class_member, sdp);
error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
&sg_class_member->kobj, "generic");
if (error)

View File

@ -4424,17 +4424,19 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
snprintf(name, 10, "%s%s%s", rew ? "n" : "",
STp->disk->disk_name, st_formats[i]);
st_class_member =
device_create(st_sysfs_class, &STp->device->sdev_gendev,
MKDEV(SCSI_TAPE_MAJOR,
TAPE_MINOR(dev_num, mode, rew)),
"%s", name);
device_create_drvdata(st_sysfs_class,
&STp->device->sdev_gendev,
MKDEV(SCSI_TAPE_MAJOR,
TAPE_MINOR(dev_num,
mode, rew)),
&STp->modes[mode],
"%s", name);
if (IS_ERR(st_class_member)) {
printk(KERN_WARNING "st%d: device_create failed\n",
dev_num);
error = PTR_ERR(st_class_member);
goto out;
}
dev_set_drvdata(st_class_member, &STp->modes[mode]);
error = device_create_file(st_class_member,
&dev_attr_defined);