[libvirt] [PATCH] storage: More uniquely identify NPIV LUNs

John Ferlan jferlan at redhat.com
Tue Jan 15 15:02:01 UTC 2019


ping^2?

Any brave soul want to take a look?

Tks -

John

On 1/5/19 9:56 AM, John Ferlan wrote:
> 
> ping?
> 
> Tks,
> 
> John
> 
> On 12/18/18 5:46 PM, John Ferlan wrote:
>> https://bugzilla.redhat.com/show_bug.cgi?id=1657468
>>
>> Commit be1bb6c95 changed the way volumes were stored from a forward
>> linked list to a hash table. In doing so, it required that each vol
>> object would have 3 unique values as keys into tables - key, name,
>> and path. Due to how vHBA/NPIV LUNs are created/used this resulted
>> in a failure to utilize all the LUN's found during processing.
>>
>> The virStorageBackendSCSINewLun uses virStorageBackendSCSISerial
>> in order to read/return the unique serial number of the LUN to be
>> used as a key for the volume.
>>
>> However, for NPIV based LUNs the logic results in usage of the
>> same serial value for each path to the LUN. For example,
>>
>> $ lsscsi -tg
>> ...
>> [4:0:3:13]   disk    fc:0x207800c0ffd79b2a0xeb02ef   /dev/sde   /dev/sg16
>> [4:0:4:0]    disk    fc:0x50060169446021980xeb1f00   /dev/sdf   /dev/sg17
>> [4:0:5:0]    disk    fc:0x50060161446021980xeb2000   /dev/sdg   /dev/sg18
>> ...
>>
>> /lib/udev/scsi_id --replace-whitespace --whitelisted --device /dev/sde
>> 3600c0ff000d7a2965c603e5401000000
>> /lib/udev/scsi_id --replace-whitespace --whitelisted --device /dev/sdf
>> 350060160c460219850060160c4602198
>> /lib/udev/scsi_id --replace-whitespace --whitelisted --device /dev/sdg
>> 350060160c460219850060160c4602198
>>
>> The /dev/sdf and /dev/sdg although separate LUNs would end up with the
>> same serial number used for the vol->key value. When attempting to add
>> the LUN via virStoragePoolObjAddVol, the hash table code will indicate
>> that we have a duplicate:
>>
>>     virHashAddOrUpdateEntry:341 : internal error: Duplicate key
>>
>> and thus the LUN is not added to the pool.
>>
>> Digging deeper into the scsi_id output using the --export option one
>> will find that the only difference between the two luns is:
>>
>>     ID_TARGET_PORT=1 for /dev/sdf
>>     ID_TARGET_PORT=2 for /dev/sdg
>>
>> So, let's use the ID_TARGET_PORT string value along with the serial
>> to generate a more unique key using "@serial_PORT at target_port", where
>> @target_port is just the value of the ID_TARGET_PORT for the LUN.
>>
>> Signed-off-by: John Ferlan <jferlan at redhat.com>
>> ---
>>  src/storage/storage_util.c | 61 +++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 60 insertions(+), 1 deletion(-)
>>
>> diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
>> index a84ee5b600..d6d441c06d 100644
>> --- a/src/storage/storage_util.c
>> +++ b/src/storage/storage_util.c
>> @@ -3755,6 +3755,49 @@ virStorageBackendRefreshLocal(virStoragePoolObjPtr pool)
>>  }
>>  
>>  
>> +static char *
>> +virStorageBackendSCSITargetPort(const char *dev)
>> +{
>> +    char *target_port = NULL;
>> +    const char *id;
>> +#ifdef WITH_UDEV
>> +    virCommandPtr cmd = virCommandNewArgList(
>> +        "/lib/udev/scsi_id",
>> +        "--replace-whitespace",
>> +        "--whitelisted",
>> +        "--export",
>> +        "--device", dev,
>> +        NULL
>> +        );
>> +
>> +    /* Run the program and capture its output */
>> +    virCommandSetOutputBuffer(cmd, &target_port);
>> +    if (virCommandRun(cmd, NULL) < 0)
>> +        goto cleanup;
>> +#endif
>> +
>> +    if (target_port && STRNEQ(target_port, "") &&
>> +        (id = strstr(target_port, "ID_TARGET_PORT="))) {
>> +        char *nl = strchr(id, '\n');
>> +        if (nl)
>> +            *nl = '\0';
>> +        id = strrchr(id, '=');
>> +        memmove(target_port, id + 1, strlen(id));
>> +    } else {
>> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>> +                       _("unable to uniquely identify target port for '%s'"),
>> +                       dev);
>> +    }
>> +
>> +#ifdef WITH_UDEV
>> + cleanup:
>> +    virCommandFree(cmd);
>> +#endif
>> +
>> +    return target_port;
>> +}
>> +
>> +
>>  static char *
>>  virStorageBackendSCSISerial(const char *dev)
>>  {
>> @@ -3813,6 +3856,8 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
>>      virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
>>      virStorageVolDefPtr vol = NULL;
>>      char *devpath = NULL;
>> +    char *key = NULL;
>> +    char *target_port = NULL;
>>      int retval = -1;
>>  
>>      /* Check if the pool is using a stable target path. The call to
>> @@ -3877,9 +3922,21 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
>>                                                   VIR_STORAGE_VOL_READ_NOERROR)) < 0)
>>          goto cleanup;
>>  
>> -    if (!(vol->key = virStorageBackendSCSISerial(vol->target.path)))
>> +    if (!(key = virStorageBackendSCSISerial(vol->target.path)))
>>          goto cleanup;
>>  
>> +    if (def->source.adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
>> +        STRNEQ(key, vol->target.path)) {
>> +        /* NPIV based LUNs use the same "serial" key. In order to distinguish
>> +         * we need to append a port value */
>> +        if (!(target_port = virStorageBackendSCSITargetPort(vol->target.path)))
>> +            goto cleanup;
>> +        if (virAsprintf(&vol->key, "%s_PORT%s", key, target_port) < 0)
>> +            goto cleanup;
>> +    } else {
>> +        VIR_STEAL_PTR(vol->key, key);
>> +    }
>> +
>>      def->capacity += vol->target.capacity;
>>      def->allocation += vol->target.allocation;
>>  
>> @@ -3892,6 +3949,8 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
>>   cleanup:
>>      virStorageVolDefFree(vol);
>>      VIR_FREE(devpath);
>> +    VIR_FREE(target_port);
>> +    VIR_FREE(key);
>>      return retval;
>>  }
>>  
>>
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
> 




More information about the libvir-list mailing list