libmultipath: retain_attached_hw_handler obsolete with 4.3+
authorMartin Wilck <mwilck@suse.com>
Thu, 22 Jun 2017 14:59:11 +0000 (16:59 +0200)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Thu, 3 Aug 2017 06:14:52 +0000 (08:14 +0200)
Kernels 4.3 and newer (commit 1bab0de0 "dm-mpath, scsi_dh: don't
let dm detach device handlers") imply "retain_attached_hw_handler yes".

Clarify this in the propsel code, log messages, and documentation.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
libmultipath/configure.c
libmultipath/dmparser.c
libmultipath/propsel.c
libmultipath/util.c
libmultipath/util.h
multipath/multipath.conf.5

index a7f2b44..74b6f52 100644 (file)
@@ -572,7 +572,8 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
        }
 
        if (mpp->retain_hwhandler != RETAIN_HWHANDLER_UNDEF &&
-           mpp->retain_hwhandler != cmpp->retain_hwhandler) {
+           mpp->retain_hwhandler != cmpp->retain_hwhandler &&
+           get_linux_version_code() < KERNEL_VERSION(4, 3, 0)) {
                mpp->action = ACT_RELOAD;
                condlog(3, "%s: set ACT_RELOAD (retain_hwhandler change)",
                        mpp->alias);
index 1121c71..b647c25 100644 (file)
@@ -97,7 +97,8 @@ assemble_map (struct multipath * mp, char * params, int len)
        } else if (mp->no_path_retry != NO_PATH_RETRY_UNDEF) {
                add_feature(&f, no_path_retry);
        }
-       if (mp->retain_hwhandler == RETAIN_HWHANDLER_ON)
+       if (mp->retain_hwhandler == RETAIN_HWHANDLER_ON &&
+           get_linux_version_code() < KERNEL_VERSION(4, 3, 0))
                add_feature(&f, retain_hwhandler);
 
        APPEND(p, end, "%s %s %i %i", f, mp->hwhandler, nr_priority_groups,
index e885a84..d609394 100644 (file)
@@ -628,7 +628,12 @@ int select_retain_hwhandler(struct config *conf, struct multipath *mp)
 
        if (!VERSION_GE(conf->version, minv_dm_retain)) {
                mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
-               origin = "(setting: WARNING, requires kernel version >= 1.5.0)";
+               origin = "(setting: WARNING, requires kernel dm-mpath version >= 1.5.0)";
+               goto out;
+       }
+       if (get_linux_version_code() >= KERNEL_VERSION(4, 3, 0)) {
+               mp->retain_hwhandler = RETAIN_HWHANDLER_ON;
+               origin = "(setting: implied in kernel >= 4.3.0)";
                goto out;
        }
        mp_set_ovr(retain_hwhandler);
index b90cd8b..dff2ed3 100644 (file)
@@ -6,6 +6,7 @@
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <dirent.h>
 #include <unistd.h>
 #include <errno.h>
@@ -380,3 +381,38 @@ int systemd_service_enabled(const char *dev)
                found = systemd_service_enabled_in(dev, "/run");
        return found;
 }
+
+static int _linux_version_code;
+static pthread_once_t _lvc_initialized = PTHREAD_ONCE_INIT;
+
+/* Returns current kernel version encoded as major*65536 + minor*256 + patch,
+ * so, for example,  to check if the kernel is greater than 2.2.11:
+ *
+ *     if (get_linux_version_code() > KERNEL_VERSION(2,2,11)) { <stuff> }
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ * Code copied from busybox (GPLv2 or later)
+ */
+static void
+_set_linux_version_code(void)
+{
+       struct utsname name;
+       char *t;
+       int i, r;
+
+       uname(&name); /* never fails */
+       t = name.release;
+       r = 0;
+       for (i = 0; i < 3; i++) {
+               t = strtok(t, ".");
+               r = r * 256 + (t ? atoi(t) : 0);
+               t = NULL;
+       }
+       _linux_version_code = r;
+}
+
+int get_linux_version_code(void)
+{
+       pthread_once(&_lvc_initialized, _set_linux_version_code);
+       return _linux_version_code;
+}
index b087e32..45291be 100644 (file)
@@ -15,6 +15,8 @@ char *convert_dev(char *dev, int is_path_device);
 char *parse_uid_attribute_by_attrs(char *uid_attrs, char *path_dev);
 void setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached);
 int systemd_service_enabled(const char *dev);
+int get_linux_version_code(void);
+#define KERNEL_VERSION(maj, min, ptc) ((((maj) * 256) + (min)) * 256 + (ptc))
 
 #define safe_sprintf(var, format, args...)     \
        snprintf(var, sizeof(var), format, ##args) >= sizeof(var)
index b32d038..3b4e518 100644 (file)
@@ -698,15 +698,16 @@ The default is: \fB<unset>\fR
 .
 .TP
 .B retain_attached_hw_handler
-If set to
+(Obsolete for kernels >= 4.3) If set to
 .I yes
 and the SCSI layer has already attached a hardware_handler to the device,
 multipath will not force the device to use the hardware_handler specified by
 mutipath.conf. If the SCSI layer has not attached a hardware handler,
 multipath will continue to use its configured hardware handler.
 .RS
-.TP
-The default is: \fByes\fR
+.PP
+The default is: \fByes\fR. Linux kernel 4.3 or newer always behaves as if
+\fB"retain_attached_hw_handler yes"\fR was set.
 .RE
 .
 .
@@ -1182,8 +1183,14 @@ Active/Standby mode exclusively.
 .I 1 alua
 (Hardware-dependent)
 Hardware handler for SCSI-3 ALUA compatible arrays.
-.TP
+.PP
 The default is: \fB<unset>\fR
+.PP
+\fBImportant Note:\fR Linux kernels 4.3 and newer automatically attach a device
+handler to known devices (which includes all devices supporting SCSI-3 ALUA)
+and disallow changing the handler
+afterwards. Setting \fBhardware_handler\fR for such devices on these kernels
+has no effect.
 .RE
 .
 .