@@ -548,6 +548,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
unsigned err, retval;
unsigned int tpg_desc_tbl_off;
unsigned char orig_transition_tmo;
+ struct alua_port_group *tmp_pg;
+ unsigned long flags;
if (!pg->expiry) {
if (!pg->transition_tmo)
@@ -638,17 +640,35 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
else
tpg_desc_tbl_off = 4;
+ spin_lock_irqsave(&port_group_lock, flags);
for (k = tpg_desc_tbl_off, ucp = pg->buff + tpg_desc_tbl_off;
k < len;
k += off, ucp += off) {
- if (pg->group_id == (ucp[2] << 8) + ucp[3]) {
- pg->state = ucp[0] & 0x0f;
- pg->pref = ucp[0] >> 7;
- valid_states = ucp[1];
+ list_for_each_entry(tmp_pg, &port_group_list, node) {
+ u16 group_id = get_unaligned_be16(&ucp[2]);
+ if (tmp_pg->group_id != group_id)
+ continue;
+ if (tmp_pg->device_id_size != pg->device_id_size)
+ continue;
+ if (memcmp(tmp_pg->device_id, pg->device_id,
+ tmp_pg->device_id_size))
+ continue;
+ tmp_pg->state = ucp[0] & 0x0f;
+ tmp_pg->pref = ucp[0] >> 7;
+ sdev_printk(KERN_INFO, sdev,
+ "%s: device %s port group %02x "
+ "state %c %s\n", ALUA_DH_NAME,
+ tmp_pg->device_id_str, tmp_pg->group_id,
+ print_alua_state(tmp_pg->state),
+ tmp_pg->pref ?
+ "preferred" : "non-preferred");
+ if (tmp_pg == pg)
+ valid_states = ucp[1];
}
off = 8 + (ucp[7] * 4);
}
+ spin_unlock_irqrestore(&port_group_lock, flags);
sdev_printk(KERN_INFO, sdev,
"%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n",
When we read in the target port group state we should be updating all affected port groups, otherwise we risk running out of sync. Signed-off-by: Hannes Reinecke <hare@suse.de> --- drivers/scsi/device_handler/scsi_dh_alua.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)