scsi_dh_alua: use unique device id
Use scsi_vpd_lun_id() to assign a unique device identification to the alua port group structure. Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
43394c67f8
commit
0047220c6c
1 changed files with 50 additions and 5 deletions
|
@ -70,6 +70,8 @@ static DEFINE_SPINLOCK(port_group_lock);
|
||||||
struct alua_port_group {
|
struct alua_port_group {
|
||||||
struct kref kref;
|
struct kref kref;
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
|
unsigned char device_id_str[256];
|
||||||
|
int device_id_len;
|
||||||
int group_id;
|
int group_id;
|
||||||
int tpgs;
|
int tpgs;
|
||||||
int state;
|
int state;
|
||||||
|
@ -162,6 +164,26 @@ static int submit_stpg(struct scsi_device *sdev, int group_id,
|
||||||
ALUA_FAILOVER_RETRIES, NULL, req_flags);
|
ALUA_FAILOVER_RETRIES, NULL, req_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size,
|
||||||
|
int group_id)
|
||||||
|
{
|
||||||
|
struct alua_port_group *pg;
|
||||||
|
|
||||||
|
list_for_each_entry(pg, &port_group_list, node) {
|
||||||
|
if (pg->group_id != group_id)
|
||||||
|
continue;
|
||||||
|
if (pg->device_id_len != id_size)
|
||||||
|
continue;
|
||||||
|
if (strncmp(pg->device_id_str, id_str, id_size))
|
||||||
|
continue;
|
||||||
|
if (!kref_get_unless_zero(&pg->kref))
|
||||||
|
continue;
|
||||||
|
return pg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* alua_alloc_pg - Allocate a new port_group structure
|
* alua_alloc_pg - Allocate a new port_group structure
|
||||||
* @sdev: scsi device
|
* @sdev: scsi device
|
||||||
|
@ -174,17 +196,39 @@ static int submit_stpg(struct scsi_device *sdev, int group_id,
|
||||||
struct alua_port_group *alua_alloc_pg(struct scsi_device *sdev,
|
struct alua_port_group *alua_alloc_pg(struct scsi_device *sdev,
|
||||||
int group_id, int tpgs)
|
int group_id, int tpgs)
|
||||||
{
|
{
|
||||||
struct alua_port_group *pg;
|
struct alua_port_group *pg, *tmp_pg;
|
||||||
|
|
||||||
pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL);
|
pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL);
|
||||||
if (!pg)
|
if (!pg)
|
||||||
return NULL;
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
pg->device_id_len = scsi_vpd_lun_id(sdev, pg->device_id_str,
|
||||||
|
sizeof(pg->device_id_str));
|
||||||
|
if (pg->device_id_len <= 0) {
|
||||||
|
/*
|
||||||
|
* Internal error: TPGS supported but no device
|
||||||
|
* identifcation found. Disable ALUA support.
|
||||||
|
*/
|
||||||
|
kfree(pg);
|
||||||
|
sdev_printk(KERN_INFO, sdev,
|
||||||
|
"%s: No device descriptors found\n",
|
||||||
|
ALUA_DH_NAME);
|
||||||
|
return ERR_PTR(-ENXIO);
|
||||||
|
}
|
||||||
pg->group_id = group_id;
|
pg->group_id = group_id;
|
||||||
pg->tpgs = tpgs;
|
pg->tpgs = tpgs;
|
||||||
pg->state = TPGS_STATE_OPTIMIZED;
|
pg->state = TPGS_STATE_OPTIMIZED;
|
||||||
kref_init(&pg->kref);
|
kref_init(&pg->kref);
|
||||||
|
|
||||||
spin_lock(&port_group_lock);
|
spin_lock(&port_group_lock);
|
||||||
|
tmp_pg = alua_find_get_pg(pg->device_id_str, pg->device_id_len,
|
||||||
|
group_id);
|
||||||
|
if (tmp_pg) {
|
||||||
|
spin_unlock(&port_group_lock);
|
||||||
|
kfree(pg);
|
||||||
|
return tmp_pg;
|
||||||
|
}
|
||||||
|
|
||||||
list_add(&pg->node, &port_group_list);
|
list_add(&pg->node, &port_group_list);
|
||||||
spin_unlock(&port_group_lock);
|
spin_unlock(&port_group_lock);
|
||||||
|
|
||||||
|
@ -269,7 +313,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h)
|
||||||
h->group_id = group_id;
|
h->group_id = group_id;
|
||||||
|
|
||||||
sdev_printk(KERN_INFO, sdev,
|
sdev_printk(KERN_INFO, sdev,
|
||||||
"%s: port group %02x rel port %02x\n",
|
"%s: port group %x rel port %x\n",
|
||||||
ALUA_DH_NAME, h->group_id, h->rel_port);
|
ALUA_DH_NAME, h->group_id, h->rel_port);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -597,8 +641,9 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
h->pg = alua_alloc_pg(sdev, h->group_id, tpgs);
|
h->pg = alua_alloc_pg(sdev, h->group_id, tpgs);
|
||||||
if (!h->pg) {
|
if (IS_ERR(h->pg)) {
|
||||||
err = SCSI_DH_NOMEM;
|
if (PTR_ERR(h->pg) == -ENOMEM)
|
||||||
|
err = SCSI_DH_NOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
kref_get(&h->pg->kref);
|
kref_get(&h->pg->kref);
|
||||||
|
|
Loading…
Reference in a new issue