aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2014-03-15 04:51:47 -0400
committerJames Bottomley <JBottomley@Parallels.com>2014-03-19 18:22:39 -0400
commit276b20d09be7a1c260f0a94880d33e0850efe200 (patch)
treed2f87fd172c04197f473235815eb18a01bf0b586 /drivers/scsi
parent9a993302cc7a2e0a22e0851122dcfb59b56abd7a (diff)
[SCSI] scsi_sysfs: Implement 'is_visible' callback
Instead of modifying attributes after the device has been created we should be using the 'is_visible' callback to avoid races. Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_sysfs.c184
1 files changed, 93 insertions, 91 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 8dab6ddf8222..85098222a9e8 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -576,7 +576,6 @@ static int scsi_sdev_check_buf_bit(const char *buf)
576 * Create the actual show/store functions and data structures. 576 * Create the actual show/store functions and data structures.
577 */ 577 */
578sdev_rd_attr (device_blocked, "%d\n"); 578sdev_rd_attr (device_blocked, "%d\n");
579sdev_rd_attr (queue_depth, "%d\n");
580sdev_rd_attr (device_busy, "%d\n"); 579sdev_rd_attr (device_busy, "%d\n");
581sdev_rd_attr (type, "%d\n"); 580sdev_rd_attr (type, "%d\n");
582sdev_rd_attr (scsi_level, "%d\n"); 581sdev_rd_attr (scsi_level, "%d\n");
@@ -720,7 +719,37 @@ show_queue_type_field(struct device *dev, struct device_attribute *attr,
720 return snprintf(buf, 20, "%s\n", name); 719 return snprintf(buf, 20, "%s\n", name);
721} 720}
722 721
723static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL); 722static ssize_t
723store_queue_type_field(struct device *dev, struct device_attribute *attr,
724 const char *buf, size_t count)
725{
726 struct scsi_device *sdev = to_scsi_device(dev);
727 struct scsi_host_template *sht = sdev->host->hostt;
728 int tag_type = 0, retval;
729 int prev_tag_type = scsi_get_tag_type(sdev);
730
731 if (!sdev->tagged_supported || !sht->change_queue_type)
732 return -EINVAL;
733
734 if (strncmp(buf, "ordered", 7) == 0)
735 tag_type = MSG_ORDERED_TAG;
736 else if (strncmp(buf, "simple", 6) == 0)
737 tag_type = MSG_SIMPLE_TAG;
738 else if (strncmp(buf, "none", 4) != 0)
739 return -EINVAL;
740
741 if (tag_type == prev_tag_type)
742 return count;
743
744 retval = sht->change_queue_type(sdev, tag_type);
745 if (retval < 0)
746 return retval;
747
748 return count;
749}
750
751static DEVICE_ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
752 store_queue_type_field);
724 753
725static ssize_t 754static ssize_t
726show_iostat_counterbits(struct device *dev, struct device_attribute *attr, char *buf) 755show_iostat_counterbits(struct device *dev, struct device_attribute *attr, char *buf)
@@ -794,46 +823,9 @@ DECLARE_EVT(soft_threshold_reached, SOFT_THRESHOLD_REACHED_REPORTED)
794DECLARE_EVT(mode_parameter_change_reported, MODE_PARAMETER_CHANGE_REPORTED) 823DECLARE_EVT(mode_parameter_change_reported, MODE_PARAMETER_CHANGE_REPORTED)
795DECLARE_EVT(lun_change_reported, LUN_CHANGE_REPORTED) 824DECLARE_EVT(lun_change_reported, LUN_CHANGE_REPORTED)
796 825
797/* Default template for device attributes. May NOT be modified */
798static struct attribute *scsi_sdev_attrs[] = {
799 &dev_attr_device_blocked.attr,
800 &dev_attr_type.attr,
801 &dev_attr_scsi_level.attr,
802 &dev_attr_device_busy.attr,
803 &dev_attr_vendor.attr,
804 &dev_attr_model.attr,
805 &dev_attr_rev.attr,
806 &dev_attr_rescan.attr,
807 &dev_attr_delete.attr,
808 &dev_attr_state.attr,
809 &dev_attr_timeout.attr,
810 &dev_attr_eh_timeout.attr,
811 &dev_attr_iocounterbits.attr,
812 &dev_attr_iorequest_cnt.attr,
813 &dev_attr_iodone_cnt.attr,
814 &dev_attr_ioerr_cnt.attr,
815 &dev_attr_modalias.attr,
816 REF_EVT(media_change),
817 REF_EVT(inquiry_change_reported),
818 REF_EVT(capacity_change_reported),
819 REF_EVT(soft_threshold_reached),
820 REF_EVT(mode_parameter_change_reported),
821 REF_EVT(lun_change_reported),
822 NULL
823};
824
825static struct attribute_group scsi_sdev_attr_group = {
826 .attrs = scsi_sdev_attrs,
827};
828
829static const struct attribute_group *scsi_sdev_attr_groups[] = {
830 &scsi_sdev_attr_group,
831 NULL
832};
833
834static ssize_t 826static ssize_t
835sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr, 827sdev_store_queue_depth(struct device *dev, struct device_attribute *attr,
836 const char *buf, size_t count) 828 const char *buf, size_t count)
837{ 829{
838 int depth, retval; 830 int depth, retval;
839 struct scsi_device *sdev = to_scsi_device(dev); 831 struct scsi_device *sdev = to_scsi_device(dev);
@@ -856,10 +848,10 @@ sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr,
856 848
857 return count; 849 return count;
858} 850}
851sdev_show_function(queue_depth, "%d\n");
859 852
860static struct device_attribute sdev_attr_queue_depth_rw = 853static DEVICE_ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
861 __ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth, 854 sdev_store_queue_depth);
862 sdev_store_queue_depth_rw);
863 855
864static ssize_t 856static ssize_t
865sdev_show_queue_ramp_up_period(struct device *dev, 857sdev_show_queue_ramp_up_period(struct device *dev,
@@ -887,40 +879,73 @@ sdev_store_queue_ramp_up_period(struct device *dev,
887 return period; 879 return period;
888} 880}
889 881
890static struct device_attribute sdev_attr_queue_ramp_up_period = 882static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR,
891 __ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, 883 sdev_show_queue_ramp_up_period,
892 sdev_show_queue_ramp_up_period, 884 sdev_store_queue_ramp_up_period);
893 sdev_store_queue_ramp_up_period);
894 885
895static ssize_t 886static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
896sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr, 887 struct attribute *attr, int i)
897 const char *buf, size_t count)
898{ 888{
889 struct device *dev = container_of(kobj, struct device, kobj);
899 struct scsi_device *sdev = to_scsi_device(dev); 890 struct scsi_device *sdev = to_scsi_device(dev);
900 struct scsi_host_template *sht = sdev->host->hostt;
901 int tag_type = 0, retval;
902 int prev_tag_type = scsi_get_tag_type(sdev);
903 891
904 if (!sdev->tagged_supported || !sht->change_queue_type)
905 return -EINVAL;
906 892
907 if (strncmp(buf, "ordered", 7) == 0) 893 if (attr == &dev_attr_queue_depth.attr &&
908 tag_type = MSG_ORDERED_TAG; 894 !sdev->host->hostt->change_queue_depth)
909 else if (strncmp(buf, "simple", 6) == 0) 895 return S_IRUGO;
910 tag_type = MSG_SIMPLE_TAG;
911 else if (strncmp(buf, "none", 4) != 0)
912 return -EINVAL;
913 896
914 if (tag_type == prev_tag_type) 897 if (attr == &dev_attr_queue_ramp_up_period.attr &&
915 return count; 898 !sdev->host->hostt->change_queue_depth)
899 return 0;
916 900
917 retval = sht->change_queue_type(sdev, tag_type); 901 if (attr == &dev_attr_queue_type.attr &&
918 if (retval < 0) 902 !sdev->host->hostt->change_queue_type)
919 return retval; 903 return S_IRUGO;
920 904
921 return count; 905 return attr->mode;
922} 906}
923 907
908/* Default template for device attributes. May NOT be modified */
909static struct attribute *scsi_sdev_attrs[] = {
910 &dev_attr_device_blocked.attr,
911 &dev_attr_type.attr,
912 &dev_attr_scsi_level.attr,
913 &dev_attr_device_busy.attr,
914 &dev_attr_vendor.attr,
915 &dev_attr_model.attr,
916 &dev_attr_rev.attr,
917 &dev_attr_rescan.attr,
918 &dev_attr_delete.attr,
919 &dev_attr_state.attr,
920 &dev_attr_timeout.attr,
921 &dev_attr_eh_timeout.attr,
922 &dev_attr_iocounterbits.attr,
923 &dev_attr_iorequest_cnt.attr,
924 &dev_attr_iodone_cnt.attr,
925 &dev_attr_ioerr_cnt.attr,
926 &dev_attr_modalias.attr,
927 &dev_attr_queue_depth.attr,
928 &dev_attr_queue_type.attr,
929 &dev_attr_queue_ramp_up_period.attr,
930 REF_EVT(media_change),
931 REF_EVT(inquiry_change_reported),
932 REF_EVT(capacity_change_reported),
933 REF_EVT(soft_threshold_reached),
934 REF_EVT(mode_parameter_change_reported),
935 REF_EVT(lun_change_reported),
936 NULL
937};
938
939static struct attribute_group scsi_sdev_attr_group = {
940 .attrs = scsi_sdev_attrs,
941 .is_visible = scsi_sdev_attr_is_visible,
942};
943
944static const struct attribute_group *scsi_sdev_attr_groups[] = {
945 &scsi_sdev_attr_group,
946 NULL
947};
948
924static int scsi_target_add(struct scsi_target *starget) 949static int scsi_target_add(struct scsi_target *starget)
925{ 950{
926 int error; 951 int error;
@@ -943,10 +968,6 @@ static int scsi_target_add(struct scsi_target *starget)
943 return 0; 968 return 0;
944} 969}
945 970
946static struct device_attribute sdev_attr_queue_type_rw =
947 __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
948 sdev_store_queue_type_rw);
949
950/** 971/**
951 * scsi_sysfs_add_sdev - add scsi device to sysfs 972 * scsi_sysfs_add_sdev - add scsi device to sysfs
952 * @sdev: scsi_device to add 973 * @sdev: scsi_device to add
@@ -1000,25 +1021,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
1000 transport_add_device(&sdev->sdev_gendev); 1021 transport_add_device(&sdev->sdev_gendev);
1001 sdev->is_visible = 1; 1022 sdev->is_visible = 1;
1002 1023
1003 /* create queue files, which may be writable, depending on the host */
1004 if (sdev->host->hostt->change_queue_depth) {
1005 error = device_create_file(&sdev->sdev_gendev,
1006 &sdev_attr_queue_depth_rw);
1007 error = device_create_file(&sdev->sdev_gendev,
1008 &sdev_attr_queue_ramp_up_period);
1009 }
1010 else
1011 error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
1012 if (error)
1013 return error;
1014
1015 if (sdev->host->hostt->change_queue_type)
1016 error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw);
1017 else
1018 error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_type);
1019 if (error)
1020 return error;
1021
1022 error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL); 1024 error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
1023 1025
1024 if (error) 1026 if (error)