return r;
}
+static int
+has_partmap(const char *name, void *data)
+{
+ return 1;
+}
+
static int
partmap_in_use(const char *name, void *data)
{
{
int r;
int queue_if_no_path = 0;
+ int udev_flags = 0;
unsigned long long mapsize;
char params[PARAMS_SIZE] = {0};
if (!dm_is_mpath(mapname))
return 0; /* nothing to do */
+ /* if the device currently has no partitions, do not
+ run kpartx on it if you fail to delete it */
+ if (do_foreach_partmaps(mapname, has_partmap, NULL) == 0)
+ udev_flags |= MPATH_UDEV_NO_KPARTX_FLAG;
+
/* If you aren't doing a deferred remove, make sure that no
* devices are in use */
if (!do_deferred(deferred_remove) && partmap_in_use(mapname, NULL))
mapname);
if (need_suspend && queue_if_no_path != -1) {
dm_simplecmd_noflush(DM_DEVICE_RESUME,
- mapname, 0);
+ mapname, udev_flags);
}
}
if (retries)
int do_tur (char *);
int path_offline (struct path *);
int get_state (struct path * pp, struct config * conf, int daemon);
+int get_vpd_sgio (int fd, int pg, char * str, int maxlen);
int pathinfo (struct path * pp, struct config * conf, int mask);
int alloc_path_with_pathinfo (struct config *conf, struct udev_device *udevice,
char *wwid, int flag, struct path **pp_ptr);
if (conf->pgpolicy_flag > 0) {
mp->pgpolicy = conf->pgpolicy_flag;
- origin = "(cmd line flag)";
+ origin = "(setting: multipath command line [-p] flag)";
goto out;
}
mp_set_mpe(pgpolicy);
mp->alias_old, mp->alias_prefix,
conf->bindings_read_only);
memset (mp->alias_old, 0, WWID_SIZE);
- origin = "(using existing alias)";
+ origin = "(setting: using existing alias)";
}
if (mp->alias == NULL) {
mp->alias = get_user_friendly_alias(mp->wwid,
conf->bindings_file, mp->alias_prefix, conf->bindings_read_only);
- origin = "(user_friendly_name)";
+ origin = "(setting: user_friendly_name)";
}
out:
if (mp->alias == NULL) {
mp->alias = STRDUP(mp->wwid);
- origin = "(default to wwid)";
+ origin = "(setting: default to WWID)";
}
if (mp->alias)
condlog(3, "%s: alias = %s %s", mp->wwid, mp->alias, origin);
return 0;
}
+/*
+ * Current RDAC (NetApp E-Series) firmware relies
+ * on periodic REPORT TARGET PORT GROUPS for
+ * internal load balancing.
+ * Using the sysfs priority checker defeats this purpose.
+ */
+static int
+check_rdac(struct path * pp)
+{
+ int len;
+ char buff[44];
+
+ len = get_vpd_sgio(pp->fd, 0xC9, buff, 44);
+ if (len <= 0)
+ return 0;
+ return !(memcmp(buff + 4, "vac1", 4));
+}
+
void
detect_prio(struct config *conf, struct path * pp)
{
if (pp->tpgs <= 0)
return;
- if (sysfs_get_asymmetric_access_state(pp, buff, 512) >= 0)
- default_prio = PRIO_SYSFS;
+ if (pp->tpgs == 2 && !check_rdac(pp)) {
+ if (sysfs_get_asymmetric_access_state(pp, buff, 512) >= 0)
+ default_prio = PRIO_SYSFS;
+ }
prio_get(conf->multipath_dir, p, default_prio, DEFAULT_PRIO_ARGS);
}
if (!VERSION_GE(conf->version, minv_dm_retain)) {
mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
- origin = "(requires kernel version >= 1.5.0)";
+ origin = "(setting: WARNING, requires kernel version >= 1.5.0)";
goto out;
}
mp_set_ovr(retain_hwhandler);
#ifndef LIBDM_API_DEFERRED
mp->deferred_remove = DEFERRED_REMOVE_OFF;
- origin = "(not compiled with support)";
+ origin = "(setting: WARNING, not compiled with support)";
goto out;
#endif
if (mp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) {