[libvirt] [PATCH v2 1/2] nodedev: Fabric name must not be required for fc_host capability

John Ferlan jferlan at redhat.com
Fri Jan 13 14:47:20 UTC 2017



On 01/13/2017 06:56 AM, Boris Fiuczynski wrote:
> fabric_name is one of many fc_host attributes in Linux that is optional
> and left to the low-level driver to decide if it is implemented.
> The zfcp device driver does not provide a fabric name for an fcp host.
> 
> This patch removes the requirement for a fabric name by making it optional.
> 
> Signed-off-by: Boris Fiuczynski <fiuczy at linux.vnet.ibm.com>
> ---
>  docs/formatnode.html.in                   |  2 +-
>  docs/news.xml                             | 12 +++++++++
>  docs/schemas/nodedev.rng                  |  8 +++---
>  src/libvirt_private.syms                  |  1 +
>  src/node_device/node_device_linux_sysfs.c |  6 ++---
>  src/util/virutil.c                        | 23 ++++++++++++++++
>  src/util/virutil.h                        |  5 ++++
>  tests/fchostdata/fc_host/host6/node_name  |  1 +
>  tests/fchostdata/fc_host/host6/port_name  |  1 +
>  tests/fchostdata/fc_host/host6/port_state |  1 +
>  tests/fchosttest.c                        | 44 ++++++++++++++++++++++++++++---
>  11 files changed, 94 insertions(+), 10 deletions(-)
>  create mode 100644 tests/fchostdata/fc_host/host6/node_name
>  create mode 100644 tests/fchostdata/fc_host/host6/port_name
>  create mode 100644 tests/fchostdata/fc_host/host6/port_state
> 
> diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in
> index e7b1140..f8d0e12 100644
> --- a/docs/formatnode.html.in
> +++ b/docs/formatnode.html.in
> @@ -254,7 +254,7 @@
>                  number of vport in use. <code>max_vports</code> shows the
>                  maximum vports the HBA supports. "fc_host" implies following
>                  sub-elements: <code>wwnn</code>, <code>wwpn</code>, and
> -                <code>fabric_wwn</code>.
> +                optionally <code>fabric_wwn</code>.
>                </dd>
>              </dl>
>            </dd>
> diff --git a/docs/news.xml b/docs/news.xml
> index 50c3b3e..a645953 100644
> --- a/docs/news.xml
> +++ b/docs/news.xml
> @@ -144,6 +144,18 @@
>      <section title="Bug fixes">
>        <change>
>          <summary>
> +          nodedev: Fabric name must not be required for fc_host capability
> +        </summary>
> +        <description>
> +          fabric_name is one of many fc_host attributes in Linux that is
> +          optional and left to the low-level driver to decide if it is
> +          implemented. For example the zfcp device driver does not provide a
> +          fabric name for an fcp host. The requirement for the existence of
> +          a fabric name has been removed by making it optional.
> +        </description>
> +      </change>
> +      <change>
> +        <summary>
>            qemu: Correct GetBlockInfo values
>          </summary>
>          <description>
> diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
> index 9c98402..b100a6e 100644
> --- a/docs/schemas/nodedev.rng
> +++ b/docs/schemas/nodedev.rng
> @@ -367,9 +367,11 @@
>        <ref name='wwn'/>
>      </element>
>  
> -    <element name='fabric_wwn'>
> -      <ref name='wwn'/>
> -    </element>
> +    <optional>
> +      <element name='fabric_wwn'>
> +        <ref name='wwn'/>
> +      </element>
> +    </optional>
>    </define>
>  
>    <define name='capsvports'>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 70ed87b..43f460f 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -2717,6 +2717,7 @@ virParseOwnershipIds;
>  virParseVersionString;
>  virPipeReadUntilEOF;
>  virReadFCHost;
> +virReadFCHostOption;

I don't think the Option; API is necessary

>  virReadSCSIUniqueId;
>  virScaleInteger;
>  virSetBlocking;
> diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c
> index be99c41..1bb5b74 100644
> --- a/src/node_device/node_device_linux_sysfs.c
> +++ b/src/node_device/node_device_linux_sysfs.c
> @@ -72,10 +72,10 @@ nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapDataPtr d)
>          VIR_FREE(d->scsi_host.wwnn);
>          VIR_STEAL_PTR(d->scsi_host.wwnn, tmp);
>  
> -        if (!(tmp = virReadFCHost(NULL, d->scsi_host.host, "fabric_name"))) {
> -            VIR_WARN("Failed to read fabric WWN for host%d",
> +        if (!(tmp = virReadFCHostOption(NULL, d->scsi_host.host,
> +                                        "fabric_name", false))) {
> +            VIR_INFO("Optional fabric WWN for host%d not available",
>                       d->scsi_host.host);
> -            goto cleanup;
>          }

Just make this:

    if ((tmp = virReadFCHost(NULL, d->scsi_host.host, "fabric_name"))) {
        VIR_FREE(d->scsi_host.fabric_wwn);
        VIR_STEAL_PTR(d->scsi_host.fabric_wwn, tmp);
    }

and remove the "need" for a virReadFCHostOption function...

>          VIR_FREE(d->scsi_host.fabric_wwn);
>          VIR_STEAL_PTR(d->scsi_host.fabric_wwn, tmp);
> diff --git a/src/util/virutil.c b/src/util/virutil.c
> index aeaa7f9..5bfbf37 100644
> --- a/src/util/virutil.c
> +++ b/src/util/virutil.c
> @@ -2019,6 +2019,26 @@ virReadFCHost(const char *sysfs_prefix,
>                int host,
>                const char *entry)
>  {
> +   return virReadFCHostOption(sysfs_prefix, host, entry, true);
> +}
> +
> +/* virReadFCHostOption:
> + * @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH
> + * @host: Host number, E.g. 5 of "fc_host/host5"
> + * @entry: Name of the sysfs entry to read
> + * @required: If true reports error when entry not found else no error
> + *
> + * Read the value of sysfs "fc_host" entry.
> + *
> + * Returns result as a string on success, caller must free @result after
> + * Otherwise returns NULL.
> + */
> +char *
> +virReadFCHostOption(const char *sysfs_prefix,
> +                    int host,
> +                    const char *entry,
> +                    bool required)
> +{
>      char *sysfs_path = NULL;
>      char *p = NULL;
>      char *buf = NULL;
> @@ -2029,6 +2049,9 @@ virReadFCHost(const char *sysfs_prefix,
>                      host, entry) < 0)
>          goto cleanup;
>  
> +    if (!required && !virFileExists(sysfs_path))
> +        goto cleanup;
> +

As a "first"/separate patch, modify virReadFCHost to perform the "if
!virFileExists(sysfs_path)" anyway since that's a good check and will
avoid the error message when/if the open fails in virFileReadAll. In
that same patch - feel free to modify the comment....

Since the callers of virReadFCHost "handle" the NULL return not having
an extraneous message when the file doesn't exist wouldn't be a bad
thing. There are VIR_WARN/DEBUG messages from callers anyway.

You'll also note most callers of nodeDeviceSysfsGetSCSIHostCaps ignore
the return status anyway (the old hal code being the only one that cares)...


>      if (virFileReadAll(sysfs_path, 1024, &buf) < 0)
>          goto cleanup;
>  
> diff --git a/src/util/virutil.h b/src/util/virutil.h
> index 3fbd7b0..db86052 100644
> --- a/src/util/virutil.h
> +++ b/src/util/virutil.h
> @@ -186,6 +186,11 @@ char *virReadFCHost(const char *sysfs_prefix,
>                      int host,
>                      const char *entry)
>      ATTRIBUTE_NONNULL(3);
> +char *virReadFCHostOption(const char *sysfs_prefix,
> +                          int host,
> +                          const char *entry,
> +                          bool required)
> +    ATTRIBUTE_NONNULL(3);
>  
>  bool virIsCapableFCHost(const char *sysfs_prefix, int host);
>  bool virIsCapableVport(const char *sysfs_prefix, int host);
> diff --git a/tests/fchostdata/fc_host/host6/node_name b/tests/fchostdata/fc_host/host6/node_name
> new file mode 100644
> index 0000000..73a91bd
> --- /dev/null
> +++ b/tests/fchostdata/fc_host/host6/node_name
> @@ -0,0 +1 @@
> +0x2002001b32a9da4e
> diff --git a/tests/fchostdata/fc_host/host6/port_name b/tests/fchostdata/fc_host/host6/port_name
> new file mode 100644
> index 0000000..f25abeb
> --- /dev/null
> +++ b/tests/fchostdata/fc_host/host6/port_name
> @@ -0,0 +1 @@
> +0x2102001b32a9da4e
> diff --git a/tests/fchostdata/fc_host/host6/port_state b/tests/fchostdata/fc_host/host6/port_state
> new file mode 100644
> index 0000000..b73dd46
> --- /dev/null
> +++ b/tests/fchostdata/fc_host/host6/port_state
> @@ -0,0 +1 @@
> +Online
> diff --git a/tests/fchosttest.c b/tests/fchosttest.c
> index a08a2e8..01c20df 100644
> --- a/tests/fchosttest.c
> +++ b/tests/fchosttest.c
> @@ -29,13 +29,16 @@ static char *fchost_prefix;
>  
>  #define TEST_FC_HOST_PREFIX fchost_prefix
>  #define TEST_FC_HOST_NUM 5
> +#define TEST_FC_HOST_NUM_NO_FAB 6
>  
>  /* Test virIsCapableFCHost */
>  static int
>  test1(const void *data ATTRIBUTE_UNUSED)
>  {
>      if (virIsCapableFCHost(TEST_FC_HOST_PREFIX,
> -                           TEST_FC_HOST_NUM))
> +                           TEST_FC_HOST_NUM) &&
> +        virIsCapableFCHost(TEST_FC_HOST_PREFIX,
> +                           TEST_FC_HOST_NUM_NO_FAB))
>          return 0;
>  
>      return -1;
> @@ -76,8 +79,8 @@ test3(const void *data ATTRIBUTE_UNUSED)
>                                 "port_name")))
>          goto cleanup;
>  
> -    if (!(fabric_wwn = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
> -                                     "fabric_name")))
> +    if (!(fabric_wwn = virReadFCHostOption(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
> +                                           "fabric_name", false)))

This hunk is thus unnecessary..

>          goto cleanup;
>  
>      if (!(max_vports = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
> @@ -148,6 +151,39 @@ test5(const void *data ATTRIBUTE_UNUSED)
>      return ret;
>  }
>  
> +/* Test virReadFCHost fabric name optional */
> +static int
> +test6(const void *data ATTRIBUTE_UNUSED)
> +{
> +    const char *expect_wwnn = "2002001b32a9da4e";
> +    const char *expect_wwpn = "2102001b32a9da4e";
> +    char *wwnn = NULL;
> +    char *wwpn = NULL;
> +    int ret = -1;
> +
> +    if (!(wwnn = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM_NO_FAB,
> +                               "node_name")))
> +        return -1;
> +
> +    if (!(wwpn = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM_NO_FAB,
> +                               "port_name")))
> +        goto cleanup;
> +
> +    if (virReadFCHostOption(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM_NO_FAB,

and this just changes to virReadFCHost w/o the false parameter

> +                            "fabric_name", false))
> +        goto cleanup;
> +
> +    if (STRNEQ(expect_wwnn, wwnn) ||
> +        STRNEQ(expect_wwpn, wwpn))
> +        goto cleanup;
> +
> +    ret = 0;
> + cleanup:
> +    VIR_FREE(wwnn);
> +    VIR_FREE(wwpn);
> +    return ret;
> +}
> +
>  static int
>  mymain(void)
>  {
> @@ -169,6 +205,8 @@ mymain(void)
>          ret = -1;
>      if (virTestRun("test5", test5, NULL) < 0)
>          ret = -1;
> +    if (virTestRun("test6", test6, NULL) < 0)
> +        ret = -1;
>  
>   cleanup:
>      VIR_FREE(fchost_prefix);
> 




More information about the libvir-list mailing list