Skip to content

Commit 77c9df9

Browse files
hreineckemartinkpetersen
authored andcommitted
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@suse.de> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Reviewed-by: Bart van Assche <bart.vanassche@sandisk.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 7e47976 commit 77c9df9

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

drivers/scsi/scsi_sysfs.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,33 @@ const char *scsi_host_state_name(enum scsi_host_state state)
8181
return name;
8282
}
8383

84+
static const struct {
85+
unsigned char value;
86+
char *name;
87+
} sdev_access_states[] = {
88+
{ SCSI_ACCESS_STATE_OPTIMAL, "active/optimized" },
89+
{ SCSI_ACCESS_STATE_ACTIVE, "active/non-optimized" },
90+
{ SCSI_ACCESS_STATE_STANDBY, "standby" },
91+
{ SCSI_ACCESS_STATE_UNAVAILABLE, "unavailable" },
92+
{ SCSI_ACCESS_STATE_LBA, "lba-dependent" },
93+
{ SCSI_ACCESS_STATE_OFFLINE, "offline" },
94+
{ SCSI_ACCESS_STATE_TRANSITIONING, "transitioning" },
95+
};
96+
97+
const char *scsi_access_state_name(unsigned char state)
98+
{
99+
int i;
100+
char *name = NULL;
101+
102+
for (i = 0; i < ARRAY_SIZE(sdev_access_states); i++) {
103+
if (sdev_access_states[i].value == state) {
104+
name = sdev_access_states[i].name;
105+
break;
106+
}
107+
}
108+
return name;
109+
}
110+
84111
static int check_set(unsigned long long *val, char *src)
85112
{
86113
char *last;
@@ -973,6 +1000,43 @@ sdev_store_dh_state(struct device *dev, struct device_attribute *attr,
9731000

9741001
static DEVICE_ATTR(dh_state, S_IRUGO | S_IWUSR, sdev_show_dh_state,
9751002
sdev_store_dh_state);
1003+
1004+
static ssize_t
1005+
sdev_show_access_state(struct device *dev,
1006+
struct device_attribute *attr,
1007+
char *buf)
1008+
{
1009+
struct scsi_device *sdev = to_scsi_device(dev);
1010+
unsigned char access_state;
1011+
const char *access_state_name;
1012+
1013+
if (!sdev->handler)
1014+
return -EINVAL;
1015+
1016+
access_state = (sdev->access_state & SCSI_ACCESS_STATE_MASK);
1017+
access_state_name = scsi_access_state_name(access_state);
1018+
1019+
return sprintf(buf, "%s\n",
1020+
access_state_name ? access_state_name : "unknown");
1021+
}
1022+
static DEVICE_ATTR(access_state, S_IRUGO, sdev_show_access_state, NULL);
1023+
1024+
static ssize_t
1025+
sdev_show_preferred_path(struct device *dev,
1026+
struct device_attribute *attr,
1027+
char *buf)
1028+
{
1029+
struct scsi_device *sdev = to_scsi_device(dev);
1030+
1031+
if (!sdev->handler)
1032+
return -EINVAL;
1033+
1034+
if (sdev->access_state & SCSI_ACCESS_STATE_PREFERRED)
1035+
return sprintf(buf, "1\n");
1036+
else
1037+
return sprintf(buf, "0\n");
1038+
}
1039+
static DEVICE_ATTR(preferred_path, S_IRUGO, sdev_show_preferred_path, NULL);
9761040
#endif
9771041

9781042
static ssize_t
@@ -1020,6 +1084,14 @@ static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
10201084
!sdev->host->hostt->change_queue_depth)
10211085
return 0;
10221086

1087+
#ifdef CONFIG_SCSI_DH
1088+
if (attr == &dev_attr_access_state.attr &&
1089+
!sdev->handler)
1090+
return 0;
1091+
if (attr == &dev_attr_preferred_path.attr &&
1092+
!sdev->handler)
1093+
return 0;
1094+
#endif
10231095
return attr->mode;
10241096
}
10251097

@@ -1063,6 +1135,8 @@ static struct attribute *scsi_sdev_attrs[] = {
10631135
&dev_attr_wwid.attr,
10641136
#ifdef CONFIG_SCSI_DH
10651137
&dev_attr_dh_state.attr,
1138+
&dev_attr_access_state.attr,
1139+
&dev_attr_preferred_path.attr,
10661140
#endif
10671141
&dev_attr_queue_ramp_up_period.attr,
10681142
REF_EVT(media_change),

include/scsi/scsi_device.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ struct scsi_device {
201201
struct scsi_device_handler *handler;
202202
void *handler_data;
203203

204+
unsigned char access_state;
204205
enum scsi_device_state sdev_state;
205206
unsigned long sdev_data[0];
206207
} __attribute__((aligned(sizeof(unsigned long))));

include/scsi/scsi_proto.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,5 +277,17 @@ struct scsi_lun {
277277
__u8 scsi_lun[8];
278278
};
279279

280+
/* SPC asymmetric access states */
281+
#define SCSI_ACCESS_STATE_OPTIMAL 0x00
282+
#define SCSI_ACCESS_STATE_ACTIVE 0x01
283+
#define SCSI_ACCESS_STATE_STANDBY 0x02
284+
#define SCSI_ACCESS_STATE_UNAVAILABLE 0x03
285+
#define SCSI_ACCESS_STATE_LBA 0x04
286+
#define SCSI_ACCESS_STATE_OFFLINE 0x0e
287+
#define SCSI_ACCESS_STATE_TRANSITIONING 0x0f
288+
289+
/* Values for REPORT TARGET GROUP STATES */
290+
#define SCSI_ACCESS_STATE_MASK 0x0f
291+
#define SCSI_ACCESS_STATE_PREFERRED 0x80
280292

281293
#endif /* _SCSI_PROTO_H_ */

0 commit comments

Comments
 (0)