struct alua_port_group {
        struct kref             kref;
        struct list_head        node;
+       unsigned char           device_id_str[256];
+       int                     device_id_len;
        int                     group_id;
        int                     tpgs;
        int                     state;
                                      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
  * @sdev: scsi device
 struct alua_port_group *alua_alloc_pg(struct scsi_device *sdev,
                                      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);
        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->tpgs = tpgs;
        pg->state = TPGS_STATE_OPTIMIZED;
        kref_init(&pg->kref);
+
        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);
        spin_unlock(&port_group_lock);
 
        h->group_id = group_id;
 
        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);
 
        return 0;
                goto out;
 
        h->pg = alua_alloc_pg(sdev, h->group_id, tpgs);
-       if (!h->pg) {
-               err = SCSI_DH_NOMEM;
+       if (IS_ERR(h->pg)) {
+               if (PTR_ERR(h->pg) == -ENOMEM)
+                       err = SCSI_DH_NOMEM;
                goto out;
        }
        kref_get(&h->pg->kref);