Commit 24b42566c3fcbb5a9011d1446783d0f5844ccd45
1 parent
c013d040b7
Exists in
master
and in
7 other branches
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>
Showing 4 changed files with 17 additions and 16 deletions Side-by-side Diff
drivers/scsi/ch.c
... | ... | @@ -910,9 +910,9 @@ |
910 | 910 | ch->minor = minor; |
911 | 911 | sprintf(ch->name,"ch%d",ch->minor); |
912 | 912 | |
913 | - class_dev = device_create(ch_sysfs_class, dev, | |
914 | - MKDEV(SCSI_CHANGER_MAJOR,ch->minor), | |
915 | - "s%s", ch->name); | |
913 | + class_dev = device_create_drvdata(ch_sysfs_class, dev, | |
914 | + MKDEV(SCSI_CHANGER_MAJOR, ch->minor), | |
915 | + ch, "s%s", ch->name); | |
916 | 916 | if (IS_ERR(class_dev)) { |
917 | 917 | printk(KERN_WARNING "ch%d: device_create failed\n", |
918 | 918 | ch->minor); |
... | ... | @@ -926,7 +926,6 @@ |
926 | 926 | if (init) |
927 | 927 | ch_init_elem(ch); |
928 | 928 | |
929 | - dev_set_drvdata(dev, ch); | |
930 | 929 | sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name); |
931 | 930 | |
932 | 931 | return 0; |
drivers/scsi/osst.c
... | ... | @@ -5695,13 +5695,12 @@ |
5695 | 5695 | struct device *osst_member; |
5696 | 5696 | int err; |
5697 | 5697 | |
5698 | - osst_member = device_create(osst_sysfs_class, device, dev, "%s", name); | |
5698 | + osst_member = device_create_drvdata(osst_sysfs_class, device, dev, STp, "%s", name); | |
5699 | 5699 | if (IS_ERR(osst_member)) { |
5700 | 5700 | printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name); |
5701 | 5701 | return PTR_ERR(osst_member); |
5702 | 5702 | } |
5703 | 5703 | |
5704 | - dev_set_drvdata(osst_member, STp); | |
5705 | 5704 | err = device_create_file(osst_member, &dev_attr_ADR_rev); |
5706 | 5705 | if (err) |
5707 | 5706 | goto err_out; |
drivers/scsi/sg.c
... | ... | @@ -1441,17 +1441,18 @@ |
1441 | 1441 | if (sg_sysfs_valid) { |
1442 | 1442 | struct device *sg_class_member; |
1443 | 1443 | |
1444 | - sg_class_member = device_create(sg_sysfs_class, cl_dev->parent, | |
1445 | - MKDEV(SCSI_GENERIC_MAJOR, | |
1446 | - sdp->index), | |
1447 | - "%s", disk->disk_name); | |
1444 | + sg_class_member = device_create_drvdata(sg_sysfs_class, | |
1445 | + cl_dev->parent, | |
1446 | + MKDEV(SCSI_GENERIC_MAJOR, | |
1447 | + sdp->index), | |
1448 | + sdp, | |
1449 | + "%s", disk->disk_name); | |
1448 | 1450 | if (IS_ERR(sg_class_member)) { |
1449 | 1451 | printk(KERN_ERR "sg_add: " |
1450 | 1452 | "device_create failed\n"); |
1451 | 1453 | error = PTR_ERR(sg_class_member); |
1452 | 1454 | goto cdev_add_err; |
1453 | 1455 | } |
1454 | - dev_set_drvdata(sg_class_member, sdp); | |
1455 | 1456 | error = sysfs_create_link(&scsidp->sdev_gendev.kobj, |
1456 | 1457 | &sg_class_member->kobj, "generic"); |
1457 | 1458 | if (error) |
drivers/scsi/st.c
... | ... | @@ -4424,17 +4424,19 @@ |
4424 | 4424 | snprintf(name, 10, "%s%s%s", rew ? "n" : "", |
4425 | 4425 | STp->disk->disk_name, st_formats[i]); |
4426 | 4426 | st_class_member = |
4427 | - device_create(st_sysfs_class, &STp->device->sdev_gendev, | |
4428 | - MKDEV(SCSI_TAPE_MAJOR, | |
4429 | - TAPE_MINOR(dev_num, mode, rew)), | |
4430 | - "%s", name); | |
4427 | + device_create_drvdata(st_sysfs_class, | |
4428 | + &STp->device->sdev_gendev, | |
4429 | + MKDEV(SCSI_TAPE_MAJOR, | |
4430 | + TAPE_MINOR(dev_num, | |
4431 | + mode, rew)), | |
4432 | + &STp->modes[mode], | |
4433 | + "%s", name); | |
4431 | 4434 | if (IS_ERR(st_class_member)) { |
4432 | 4435 | printk(KERN_WARNING "st%d: device_create failed\n", |
4433 | 4436 | dev_num); |
4434 | 4437 | error = PTR_ERR(st_class_member); |
4435 | 4438 | goto out; |
4436 | 4439 | } |
4437 | - dev_set_drvdata(st_class_member, &STp->modes[mode]); | |
4438 | 4440 | |
4439 | 4441 | error = device_create_file(st_class_member, |
4440 | 4442 | &dev_attr_defined); |