On Mon, May 23, 2016 at 12:20:28PM +0200, Hannes Reinecke wrote:
> Recent kernels have an 'access_state' attribute which allows
> us to read the asymmetric access state directly from sysfs.

Neat. Just some thoughts. I'm not sure if you want to add a prioritizer
option to be able to change what the pref bit does (perhaps
"no_exclusive_pref_bit"). Also, we should probably make the alua
prioritizer default to the same pref bit behavior as the sysfs
prioritizer.

ACK

-Ben

> 
> Signed-off-by: Hannes Reinecke <[email protected]>
> ---
>  libmultipath/discovery.c           | 33 +++++++++++++++++++++++++++++
>  libmultipath/discovery.h           |  2 ++
>  libmultipath/prio.h                |  1 +
>  libmultipath/prioritizers/Makefile |  3 ++-
>  libmultipath/prioritizers/sysfs.c  | 43 
> ++++++++++++++++++++++++++++++++++++++
>  libmultipath/propsel.c             |  6 +++++-
>  multipath/multipath.conf.5         | 14 ++++++++++++-
>  7 files changed, 99 insertions(+), 3 deletions(-)
>  create mode 100644 libmultipath/prioritizers/sysfs.c
> 
> diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
> index a364056..4a4b828 100644
> --- a/libmultipath/discovery.c
> +++ b/libmultipath/discovery.c
> @@ -208,6 +208,8 @@ declare_sysfs_get_str(devtype);
>  declare_sysfs_get_str(vendor);
>  declare_sysfs_get_str(model);
>  declare_sysfs_get_str(rev);
> +declare_sysfs_get_str(access_state);
> +declare_sysfs_get_str(preferred_path);
>  
>  ssize_t
>  sysfs_get_vpd (struct udev_device * udev, int pg,
> @@ -483,6 +485,37 @@ int sysfs_get_iscsi_ip_address(struct path *pp, char 
> *ip_address)
>       return 1;
>  }
>  
> +int
> +sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen)
> +{
> +     struct udev_device *parent = pp->udev;
> +     char value[16], *eptr;
> +     unsigned int preferred;
> +
> +     while (parent) {
> +             const char *subsys = udev_device_get_subsystem(parent);
> +             if (subsys && !strncmp(subsys, "scsi", 4))
> +                     break;
> +             parent = udev_device_get_parent(parent);
> +     }
> +
> +     if (!parent)
> +             return -1;
> +
> +     if (sysfs_get_access_state(parent, buff, buflen) <= 0)
> +             return -1;
> +
> +     if (sysfs_get_preferred_path(parent, value, 16) <= 0)
> +             return 0;
> +
> +     preferred = strtoul(value, &eptr, 0);
> +     if (value == eptr || preferred == ULONG_MAX) {
> +             /* Parse error, ignore */
> +             return 0;
> +     }
> +     return  preferred;
> +}
> +
>  static void
>  sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
>  {
> diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
> index 5931bc6..b45c802 100644
> --- a/libmultipath/discovery.h
> +++ b/libmultipath/discovery.h
> @@ -47,6 +47,8 @@ int sysfs_get_host_pci_name(struct path *pp, char 
> *pci_name);
>  int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address);
>  ssize_t sysfs_get_vpd (struct udev_device * udev, int pg, unsigned char * 
> buff,
>                      size_t len);
> +int sysfs_get_asymmetric_access_state(struct path *pp,
> +                                   char *buff, int buflen);
>  
>  /*
>   * discovery bitmask
> diff --git a/libmultipath/prio.h b/libmultipath/prio.h
> index 495688f..65abf54 100644
> --- a/libmultipath/prio.h
> +++ b/libmultipath/prio.h
> @@ -29,6 +29,7 @@ struct path;
>  #define PRIO_RDAC "rdac"
>  #define PRIO_DATACORE "datacore"
>  #define PRIO_WEIGHTED_PATH "weightedpath"
> +#define PRIO_SYSFS "sysfs"
>  
>  /*
>   * Value used to mark the fact prio was not defined
> diff --git a/libmultipath/prioritizers/Makefile 
> b/libmultipath/prioritizers/Makefile
> index 6cfac88..0d1857f 100644
> --- a/libmultipath/prioritizers/Makefile
> +++ b/libmultipath/prioritizers/Makefile
> @@ -15,7 +15,8 @@ LIBS = \
>       libpriodatacore.so \
>       libpriohds.so \
>       libprioweightedpath.so \
> -     libprioiet.so
> +     libprioiet.so \
> +     libpriosysfs.so
>  
>  CFLAGS += -I..
>  
> diff --git a/libmultipath/prioritizers/sysfs.c 
> b/libmultipath/prioritizers/sysfs.c
> new file mode 100644
> index 0000000..35a5c83
> --- /dev/null
> +++ b/libmultipath/prioritizers/sysfs.c
> @@ -0,0 +1,43 @@
> +/*
> + * sysfs.c
> + *
> + * Copyright(c) 2016 Hannes Reinecke, SUSE Linux GmbH
> + */
> +
> +#include <stdio.h>
> +
> +#include "structs.h"
> +#include "discovery.h"
> +#include "prio.h"
> +
> +static const struct {
> +     unsigned char value;
> +     char *name;
> +} sysfs_access_state_map[] = {
> +     { 50, "active/optimized" },
> +     { 10, "active/non-optimized" },
> +     {  5, "lba-dependent" },
> +     {  1, "standby" },
> +};
> +
> +int getprio (struct path * pp, char * args)
> +{
> +     int prio = 0, rc, i;
> +     char buff[512];
> +
> +     rc = sysfs_get_asymmetric_access_state(pp, buff, 512);
> +     if (rc < 0)
> +             return PRIO_UNDEF;
> +     prio = 0;
> +     for (i = 0; i < 4; i++) {
> +             if (!strncmp(buff, sysfs_access_state_map[i].name,
> +                          strlen(sysfs_access_state_map[i].name))) {
> +                     prio = sysfs_access_state_map[i].value;
> +                     break;
> +             }
> +     }
> +     if (rc > 0)
> +             prio += 80;
> +
> +     return prio;
> +}
> diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
> index 8abe360..b0182de 100644
> --- a/libmultipath/propsel.c
> +++ b/libmultipath/propsel.c
> @@ -374,6 +374,7 @@ detect_prio(struct path * pp)
>       int ret;
>       struct prio *p = &pp->prio;
>       int tpgs = 0;
> +     char buff[512];
>  
>       if ((tpgs = get_target_port_group_support(pp->fd)) <= 0)
>               return;
> @@ -383,7 +384,10 @@ detect_prio(struct path * pp)
>               return;
>       if (get_asymmetric_access_state(pp->fd, ret) < 0)
>               return;
> -     prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS);
> +     if (sysfs_get_asymmetric_access_state(pp, buff, 512) < 0)
> +             prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS);
> +     else
> +             prio_get(p, PRIO_SYSFS, DEFAULT_PRIO_ARGS);
>  }
>  
>  #define set_prio(src, msg)                                           \
> diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
> index 2ff88c4..aaaa01b 100644
> --- a/multipath/multipath.conf.5
> +++ b/multipath/multipath.conf.5
> @@ -203,6 +203,10 @@ Generate the path priority for NetApp arrays.
>  .B rdac
>  Generate the path priority for LSI/Engenio/NetApp E-Series RDAC controller.
>  .TP
> +.B sysfs
> +Use the sysfs attributes access_state and preferred_path to generate the
> +path priority.
> +.TP
>  .B hp_sw
>  Generate the path priority for Compaq/HP controller in
>  active/standby mode.
> @@ -449,8 +453,16 @@ If set to
>  .I yes
>  , multipath will try to detect if the device supports ALUA. If so, the device
>  will automatically use the
> +.I sysfs
> +prioritizer if the required sysfs attributes
> +.I access_state
> +and
> +.I preferred_path
> +are supported, or the
>  .I alua
> -prioritizer. If not, the prioritizer will be selected as usual. Default is
> +prioritizer if not. If set to
> +.I no
> +, the prioritizer will be selected as usual. Default is
>  .I no
>  .TP
>  .B force_sync
> -- 
> 2.6.6

--
dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel

Reply via email to