Commit 24b42566 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c013d040
...@@ -910,9 +910,9 @@ static int ch_probe(struct device *dev) ...@@ -910,9 +910,9 @@ static int ch_probe(struct device *dev)
ch->minor = minor; ch->minor = minor;
sprintf(ch->name,"ch%d",ch->minor); sprintf(ch->name,"ch%d",ch->minor);
class_dev = device_create(ch_sysfs_class, dev, class_dev = device_create_drvdata(ch_sysfs_class, dev,
MKDEV(SCSI_CHANGER_MAJOR,ch->minor), MKDEV(SCSI_CHANGER_MAJOR, ch->minor),
"s%s", ch->name); ch, "s%s", ch->name);
if (IS_ERR(class_dev)) { if (IS_ERR(class_dev)) {
printk(KERN_WARNING "ch%d: device_create failed\n", printk(KERN_WARNING "ch%d: device_create failed\n",
ch->minor); ch->minor);
...@@ -926,7 +926,6 @@ static int ch_probe(struct device *dev) ...@@ -926,7 +926,6 @@ static int ch_probe(struct device *dev)
if (init) if (init)
ch_init_elem(ch); ch_init_elem(ch);
dev_set_drvdata(dev, ch);
sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name); sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);
return 0; return 0;
......
...@@ -5695,13 +5695,12 @@ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * S ...@@ -5695,13 +5695,12 @@ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * S
struct device *osst_member; struct device *osst_member;
int err; 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)) { if (IS_ERR(osst_member)) {
printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name); printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
return PTR_ERR(osst_member); return PTR_ERR(osst_member);
} }
dev_set_drvdata(osst_member, STp);
err = device_create_file(osst_member, &dev_attr_ADR_rev); err = device_create_file(osst_member, &dev_attr_ADR_rev);
if (err) if (err)
goto err_out; goto err_out;
......
...@@ -1441,17 +1441,18 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) ...@@ -1441,17 +1441,18 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
if (sg_sysfs_valid) { if (sg_sysfs_valid) {
struct device *sg_class_member; struct device *sg_class_member;
sg_class_member = device_create(sg_sysfs_class, cl_dev->parent, sg_class_member = device_create_drvdata(sg_sysfs_class,
MKDEV(SCSI_GENERIC_MAJOR, cl_dev->parent,
sdp->index), MKDEV(SCSI_GENERIC_MAJOR,
"%s", disk->disk_name); sdp->index),
sdp,
"%s", disk->disk_name);
if (IS_ERR(sg_class_member)) { if (IS_ERR(sg_class_member)) {
printk(KERN_ERR "sg_add: " printk(KERN_ERR "sg_add: "
"device_create failed\n"); "device_create failed\n");
error = PTR_ERR(sg_class_member); error = PTR_ERR(sg_class_member);
goto cdev_add_err; goto cdev_add_err;
} }
dev_set_drvdata(sg_class_member, sdp);
error = sysfs_create_link(&scsidp->sdev_gendev.kobj, error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
&sg_class_member->kobj, "generic"); &sg_class_member->kobj, "generic");
if (error) if (error)
......
...@@ -4424,17 +4424,19 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) ...@@ -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" : "", snprintf(name, 10, "%s%s%s", rew ? "n" : "",
STp->disk->disk_name, st_formats[i]); STp->disk->disk_name, st_formats[i]);
st_class_member = st_class_member =
device_create(st_sysfs_class, &STp->device->sdev_gendev, device_create_drvdata(st_sysfs_class,
MKDEV(SCSI_TAPE_MAJOR, &STp->device->sdev_gendev,
TAPE_MINOR(dev_num, mode, rew)), MKDEV(SCSI_TAPE_MAJOR,
"%s", name); TAPE_MINOR(dev_num,
mode, rew)),
&STp->modes[mode],
"%s", name);
if (IS_ERR(st_class_member)) { if (IS_ERR(st_class_member)) {
printk(KERN_WARNING "st%d: device_create failed\n", printk(KERN_WARNING "st%d: device_create failed\n",
dev_num); dev_num);
error = PTR_ERR(st_class_member); error = PTR_ERR(st_class_member);
goto out; goto out;
} }
dev_set_drvdata(st_class_member, &STp->modes[mode]);
error = device_create_file(st_class_member, error = device_create_file(st_class_member,
&dev_attr_defined); &dev_attr_defined);
......
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