Commit 1a5dc166 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen

scsi_dh_rdac: update 'access_state' field

Track attached SCSI devices and update the 'access_state' whenever the
path state of the device changes.
Signed-off-by: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent cb0a168c
...@@ -165,6 +165,7 @@ struct rdac_controller { ...@@ -165,6 +165,7 @@ struct rdac_controller {
struct work_struct ms_work; struct work_struct ms_work;
struct scsi_device *ms_sdev; struct scsi_device *ms_sdev;
struct list_head ms_head; struct list_head ms_head;
struct list_head dh_list;
}; };
struct c2_inquiry { struct c2_inquiry {
...@@ -181,7 +182,9 @@ struct c2_inquiry { ...@@ -181,7 +182,9 @@ struct c2_inquiry {
}; };
struct rdac_dh_data { struct rdac_dh_data {
struct list_head node;
struct rdac_controller *ctlr; struct rdac_controller *ctlr;
struct scsi_device *sdev;
#define UNINITIALIZED_LUN (1 << 8) #define UNINITIALIZED_LUN (1 << 8)
unsigned lun; unsigned lun;
...@@ -392,6 +395,7 @@ static struct rdac_controller *get_controller(int index, char *array_name, ...@@ -392,6 +395,7 @@ static struct rdac_controller *get_controller(int index, char *array_name,
INIT_WORK(&ctlr->ms_work, send_mode_select); INIT_WORK(&ctlr->ms_work, send_mode_select);
INIT_LIST_HEAD(&ctlr->ms_head); INIT_LIST_HEAD(&ctlr->ms_head);
list_add(&ctlr->node, &ctlr_list); list_add(&ctlr->node, &ctlr_list);
INIT_LIST_HEAD(&ctlr->dh_list);
return ctlr; return ctlr;
} }
...@@ -455,7 +459,8 @@ static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h, ...@@ -455,7 +459,8 @@ static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h,
static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h) static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
{ {
int err; int err, access_state;
struct rdac_dh_data *tmp;
struct c9_inquiry *inqp; struct c9_inquiry *inqp;
h->state = RDAC_STATE_ACTIVE; h->state = RDAC_STATE_ACTIVE;
...@@ -471,19 +476,31 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h) ...@@ -471,19 +476,31 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
h->mode = RDAC_MODE; /* LUN in RDAC mode */ h->mode = RDAC_MODE; /* LUN in RDAC mode */
/* Update ownership */ /* Update ownership */
if (inqp->avte_cvp & 0x1) if (inqp->avte_cvp & 0x1) {
h->lun_state = RDAC_LUN_OWNED; h->lun_state = RDAC_LUN_OWNED;
else { access_state = SCSI_ACCESS_STATE_OPTIMAL;
} else {
h->lun_state = RDAC_LUN_UNOWNED; h->lun_state = RDAC_LUN_UNOWNED;
if (h->mode == RDAC_MODE) if (h->mode == RDAC_MODE) {
h->state = RDAC_STATE_PASSIVE; h->state = RDAC_STATE_PASSIVE;
access_state = SCSI_ACCESS_STATE_STANDBY;
} else
access_state = SCSI_ACCESS_STATE_ACTIVE;
} }
/* Update path prio*/ /* Update path prio*/
if (inqp->path_prio & 0x1) if (inqp->path_prio & 0x1) {
h->preferred = RDAC_PREFERRED; h->preferred = RDAC_PREFERRED;
else access_state |= SCSI_ACCESS_STATE_PREFERRED;
} else
h->preferred = RDAC_NON_PREFERRED; h->preferred = RDAC_NON_PREFERRED;
rcu_read_lock();
list_for_each_entry_rcu(tmp, &h->ctlr->dh_list, node) {
/* h->sdev should always be valid */
BUG_ON(!tmp->sdev);
tmp->sdev->access_state = access_state;
}
rcu_read_unlock();
} }
return err; return err;
...@@ -508,6 +525,10 @@ static int initialize_controller(struct scsi_device *sdev, ...@@ -508,6 +525,10 @@ static int initialize_controller(struct scsi_device *sdev,
h->ctlr = get_controller(index, array_name, array_id, sdev); h->ctlr = get_controller(index, array_name, array_id, sdev);
if (!h->ctlr) if (!h->ctlr)
err = SCSI_DH_RES_TEMP_UNAVAIL; err = SCSI_DH_RES_TEMP_UNAVAIL;
else {
list_add_rcu(&h->node, &h->ctlr->dh_list);
h->sdev = sdev;
}
spin_unlock(&list_lock); spin_unlock(&list_lock);
} }
return err; return err;
...@@ -829,8 +850,11 @@ static void rdac_bus_detach( struct scsi_device *sdev ) ...@@ -829,8 +850,11 @@ static void rdac_bus_detach( struct scsi_device *sdev )
flush_workqueue(kmpath_rdacd); flush_workqueue(kmpath_rdacd);
spin_lock(&list_lock); spin_lock(&list_lock);
if (h->ctlr) if (h->ctlr) {
list_del_rcu(&h->node);
h->sdev = NULL;
kref_put(&h->ctlr->kref, release_controller); kref_put(&h->ctlr->kref, release_controller);
}
spin_unlock(&list_lock); spin_unlock(&list_lock);
sdev->handler_data = NULL; sdev->handler_data = NULL;
kfree(h); kfree(h);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment