in https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt it says: - show() must not use snprintf() when formatting the value to be returned to user space. If you can guarantee that an overflow will never happen you can use sprintf() otherwise you must use scnprintf(). > -----Original Message----- > From: linux-scsi-owner@xxxxxxxxxxxxxxx [mailto:linux-scsi- > owner@xxxxxxxxxxxxxxx] On Behalf Of Hannes Reinecke > Sent: Tuesday, March 01, 2016 3:56 PM > To: Martin K. Petersen > Cc: Christoph Hellwig; Ewan Milne; Bart van Assche; James Bottomley; linux- > scsi@xxxxxxxxxxxxxxx; Hannes Reinecke > Subject: [PATCH 1/6] scsi: Add 'access_state' and 'preferred_path' attribute > > Add an 'access_state' field to struct scsi_device and display them in sysfs as > 'access_state' and 'preferred_path' attribute. > > Signed-off-by: Hannes Reinecke <hare@xxxxxxx> > --- > drivers/scsi/scsi_sysfs.c | 74 > ++++++++++++++++++++++++++++++++++++++++++++++ > include/scsi/scsi_device.h | 1 + > include/scsi/scsi_proto.h | 12 ++++++++ > 3 files changed, 87 insertions(+) > > diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index > d8b275b..b6a1af8 100644 > --- a/drivers/scsi/scsi_sysfs.c > +++ b/drivers/scsi/scsi_sysfs.c > @@ -81,6 +81,33 @@ const char *scsi_host_state_name(enum > scsi_host_state state) > return name; > } > > +static const struct { > + unsigned char value; > + char *name; > +} sdev_access_states[] = { > + { SCSI_ACCESS_STATE_OPTIMAL, "active/optimized" }, > + { SCSI_ACCESS_STATE_ACTIVE, "active/non-optimized" }, > + { SCSI_ACCESS_STATE_STANDBY, "standby" }, > + { SCSI_ACCESS_STATE_UNAVAILABLE, "unavailable" }, > + { SCSI_ACCESS_STATE_LBA, "lba-dependent" }, > + { SCSI_ACCESS_STATE_OFFLINE, "offline" }, > + { SCSI_ACCESS_STATE_TRANSITIONING, "transitioning" }, }; > + > +const char *scsi_access_state_name(unsigned char state) { > + int i; > + char *name = NULL; > + > + for (i = 0; i < ARRAY_SIZE(sdev_access_states); i++) { > + if (sdev_access_states[i].value == state) { > + name = sdev_access_states[i].name; > + break; > + } > + } > + return name; > +} > + > static int check_set(unsigned long long *val, char *src) { > char *last; > @@ -973,6 +1000,43 @@ sdev_store_dh_state(struct device *dev, struct > device_attribute *attr, > > static DEVICE_ATTR(dh_state, S_IRUGO | S_IWUSR, sdev_show_dh_state, > sdev_store_dh_state); > + > +static ssize_t > +sdev_show_access_state(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct scsi_device *sdev = to_scsi_device(dev); > + unsigned char access_state; > + const char *access_state_name; > + > + if (!sdev->handler) > + return -EINVAL; > + > + access_state = (sdev->access_state & SCSI_ACCESS_STATE_MASK); > + access_state_name = scsi_access_state_name(access_state); > + > + return snprintf(buf, 32, "%s\n", > + access_state_name ? access_state_name : > "unknown"); } static > +DEVICE_ATTR(access_state, S_IRUGO, sdev_show_access_state, NULL); > + > +static ssize_t > +sdev_show_preferred_path(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct scsi_device *sdev = to_scsi_device(dev); > + > + if (!sdev->handler) > + return -EINVAL; > + > + if (sdev->access_state & SCSI_ACCESS_STATE_PREFERRED) > + return snprintf(buf,2, "1\n"); > + else > + return snprintf(buf, 2, "0\n"); > +} > +static DEVICE_ATTR(preferred_path, S_IRUGO, > sdev_show_preferred_path, > +NULL); > #endif > > static ssize_t > @@ -1020,6 +1084,14 @@ static umode_t scsi_sdev_attr_is_visible(struct > kobject *kobj, > !sdev->host->hostt->change_queue_depth) > return 0; > > +#ifdef CONFIG_SCSI_DH > + if (attr == &dev_attr_access_state.attr && > + !sdev->handler) > + return 0; > + if (attr == &dev_attr_preferred_path.attr && > + !sdev->handler) > + return 0; > +#endif > return attr->mode; > } > > @@ -1069,6 +1141,8 @@ static struct attribute *scsi_sdev_attrs[] = { > &dev_attr_wwid.attr, > #ifdef CONFIG_SCSI_DH > &dev_attr_dh_state.attr, > + &dev_attr_access_state.attr, > + &dev_attr_preferred_path.attr, > #endif > &dev_attr_queue_ramp_up_period.attr, > REF_EVT(media_change), > diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index > 4af2b24..c067019 100644 > --- a/include/scsi/scsi_device.h > +++ b/include/scsi/scsi_device.h > @@ -201,6 +201,7 @@ struct scsi_device { > struct scsi_device_handler *handler; > void *handler_data; > > + unsigned char access_state; > enum scsi_device_state sdev_state; > unsigned long sdev_data[0]; > } __attribute__((aligned(sizeof(unsigned long)))); diff --git > a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h index > a9fbf1b..c2ae21c 100644 > --- a/include/scsi/scsi_proto.h > +++ b/include/scsi/scsi_proto.h > @@ -277,5 +277,17 @@ struct scsi_lun { > __u8 scsi_lun[8]; > }; > > +/* SPC asymmetric access states */ > +#define SCSI_ACCESS_STATE_OPTIMAL 0x00 > +#define SCSI_ACCESS_STATE_ACTIVE 0x01 > +#define SCSI_ACCESS_STATE_STANDBY 0x02 > +#define SCSI_ACCESS_STATE_UNAVAILABLE 0x03 > +#define SCSI_ACCESS_STATE_LBA 0x04 > +#define SCSI_ACCESS_STATE_OFFLINE 0x0e > +#define SCSI_ACCESS_STATE_TRANSITIONING 0x0f > + > +/* Values for REPORT TARGET GROUP STATES */ > +#define SCSI_ACCESS_STATE_MASK 0x0f > +#define SCSI_ACCESS_STATE_PREFERRED 0x80 > > #endif /* _SCSI_PROTO_H_ */ > -- > 2.6.2 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the > body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at > http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html