df096031c411156cf37c4e2624228e2245bdf2de
[multipath-tools/.git] / libmultipath / propsel.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Benjamin Marzinski, Redhat
4  * Copyright (c) 2005 Kiyoshi Ueda, NEC
5  */
6 #include <stdio.h>
7
8 #include "checkers.h"
9 #include "memory.h"
10 #include "vector.h"
11 #include "structs.h"
12 #include "config.h"
13 #include "debug.h"
14 #include "pgpolicies.h"
15 #include "alias.h"
16 #include "defaults.h"
17 #include "devmapper.h"
18 #include "prio.h"
19 #include "discovery.h"
20 #include "prioritizers/alua_rtpg.h"
21 #include <inttypes.h>
22
23 pgpolicyfn *pgpolicies[] = {
24         NULL,
25         one_path_per_group,
26         one_group,
27         group_by_serial,
28         group_by_prio,
29         group_by_node_name
30 };
31
32 extern int
33 select_mode (struct multipath *mp)
34 {
35         if (mp->mpe && (mp->mpe->attribute_flags & (1 << ATTR_MODE))) {
36                 mp->attribute_flags |= (1 << ATTR_MODE);
37                 mp->mode = mp->mpe->mode;
38                 condlog(3, "mode = 0%o (LUN setting)", mp->mode);
39         }
40         else if (conf->attribute_flags & (1 << ATTR_MODE)) {
41                 mp->attribute_flags |= (1 << ATTR_MODE);
42                 mp->mode = conf->mode;
43                 condlog(3, "mode = 0%o (config file default)", mp->mode);
44         }
45         else
46                 mp->attribute_flags &= ~(1 << ATTR_MODE);
47         return 0;
48 }
49
50 extern int
51 select_uid (struct multipath *mp)
52 {
53         if (mp->mpe && (mp->mpe->attribute_flags & (1 << ATTR_UID))) {
54                 mp->attribute_flags |= (1 << ATTR_UID);
55                 mp->uid = mp->mpe->uid;
56                 condlog(3, "uid = %u (LUN setting)", mp->uid);
57         }
58         else if (conf->attribute_flags & (1 << ATTR_UID)) {
59                 mp->attribute_flags |= (1 << ATTR_UID);
60                 mp->uid = conf->uid;
61                 condlog(3, "uid = %u (config file default)", mp->uid);
62         }
63         else
64                 mp->attribute_flags &= ~(1 << ATTR_UID);
65         return 0;
66 }
67
68 extern int
69 select_gid (struct multipath *mp)
70 {
71         if (mp->mpe && (mp->mpe->attribute_flags & (1 << ATTR_GID))) {
72                 mp->attribute_flags |= (1 << ATTR_GID);
73                 mp->gid = mp->mpe->gid;
74                 condlog(3, "gid = %u (LUN setting)", mp->gid);
75         }
76         else if (conf->attribute_flags & (1 << ATTR_GID)) {
77                 mp->attribute_flags |= (1 << ATTR_GID);
78                 mp->gid = conf->gid;
79                 condlog(3, "gid = %u (config file default)", mp->gid);
80         }
81         else
82                 mp->attribute_flags &= ~(1 << ATTR_GID);
83         return 0;
84 }
85
86 /*
87  * selectors :
88  * traverse the configuration layers from most specific to most generic
89  * stop at first explicit setting found
90  */
91 extern int
92 select_rr_weight (struct multipath * mp)
93 {
94         if (mp->mpe && mp->mpe->rr_weight) {
95                 mp->rr_weight = mp->mpe->rr_weight;
96                 condlog(3, "%s: rr_weight = %i (LUN setting)",
97                         mp->alias, mp->rr_weight);
98                 return 0;
99         }
100         if (mp->hwe && mp->hwe->rr_weight) {
101                 mp->rr_weight = mp->hwe->rr_weight;
102                 condlog(3, "%s: rr_weight = %i (controller setting)",
103                         mp->alias, mp->rr_weight);
104                 return 0;
105         }
106         if (conf->rr_weight) {
107                 mp->rr_weight = conf->rr_weight;
108                 condlog(3, "%s: rr_weight = %i (config file default)",
109                         mp->alias, mp->rr_weight);
110                 return 0;
111         }
112         mp->rr_weight = RR_WEIGHT_NONE;
113         condlog(3, "%s: rr_weight = %i (internal default)",
114                 mp->alias, mp->rr_weight);
115         return 0;
116 }
117
118 extern int
119 select_pgfailback (struct multipath * mp)
120 {
121         if (mp->mpe && mp->mpe->pgfailback != FAILBACK_UNDEF) {
122                 mp->pgfailback = mp->mpe->pgfailback;
123                 condlog(3, "%s: pgfailback = %i (LUN setting)",
124                         mp->alias, mp->pgfailback);
125                 return 0;
126         }
127         if (mp->hwe && mp->hwe->pgfailback != FAILBACK_UNDEF) {
128                 mp->pgfailback = mp->hwe->pgfailback;
129                 condlog(3, "%s: pgfailback = %i (controller setting)",
130                         mp->alias, mp->pgfailback);
131                 return 0;
132         }
133         if (conf->pgfailback != FAILBACK_UNDEF) {
134                 mp->pgfailback = conf->pgfailback;
135                 condlog(3, "%s: pgfailback = %i (config file default)",
136                         mp->alias, mp->pgfailback);
137                 return 0;
138         }
139         mp->pgfailback = DEFAULT_FAILBACK;
140         condlog(3, "%s: pgfailover = %i (internal default)",
141                 mp->alias, mp->pgfailback);
142         return 0;
143 }
144
145 extern int
146 select_pgpolicy (struct multipath * mp)
147 {
148         char pgpolicy_name[POLICY_NAME_SIZE];
149
150         if (conf->pgpolicy_flag > 0) {
151                 mp->pgpolicy = conf->pgpolicy_flag;
152                 mp->pgpolicyfn = pgpolicies[mp->pgpolicy];
153                 get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE,
154                                   mp->pgpolicy);
155                 condlog(3, "%s: pgpolicy = %s (cmd line flag)",
156                         mp->alias, pgpolicy_name);
157                 return 0;
158         }
159         if (mp->mpe && mp->mpe->pgpolicy > 0) {
160                 mp->pgpolicy = mp->mpe->pgpolicy;
161                 mp->pgpolicyfn = pgpolicies[mp->pgpolicy];
162                 get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE,
163                                   mp->pgpolicy);
164                 condlog(3, "%s: pgpolicy = %s (LUN setting)",
165                         mp->alias, pgpolicy_name);
166                 return 0;
167         }
168         if (mp->hwe && mp->hwe->pgpolicy > 0) {
169                 mp->pgpolicy = mp->hwe->pgpolicy;
170                 mp->pgpolicyfn = pgpolicies[mp->pgpolicy];
171                 get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE,
172                                   mp->pgpolicy);
173                 condlog(3, "%s: pgpolicy = %s (controller setting)",
174                         mp->alias, pgpolicy_name);
175                 return 0;
176         }
177         if (conf->pgpolicy > 0) {
178                 mp->pgpolicy = conf->pgpolicy;
179                 mp->pgpolicyfn = pgpolicies[mp->pgpolicy];
180                 get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE,
181                                   mp->pgpolicy);
182                 condlog(3, "%s: pgpolicy = %s (config file default)",
183                         mp->alias, pgpolicy_name);
184                 return 0;
185         }
186         mp->pgpolicy = DEFAULT_PGPOLICY;
187         mp->pgpolicyfn = pgpolicies[mp->pgpolicy];
188         get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE, mp->pgpolicy);
189         condlog(3, "%s: pgpolicy = %s (internal default)",
190                 mp->alias, pgpolicy_name);
191         return 0;
192 }
193
194 extern int
195 select_selector (struct multipath * mp)
196 {
197         if (mp->mpe && mp->mpe->selector) {
198                 mp->selector = mp->mpe->selector;
199                 condlog(3, "%s: selector = %s (LUN setting)",
200                         mp->alias, mp->selector);
201                 return 0;
202         }
203         if (mp->hwe && mp->hwe->selector) {
204                 mp->selector = mp->hwe->selector;
205                 condlog(3, "%s: selector = %s (controller setting)",
206                         mp->alias, mp->selector);
207                 return 0;
208         }
209         if (conf->selector) {
210                 mp->selector = conf->selector;
211                 condlog(3, "%s: selector = %s (config file default)",
212                         mp->alias, mp->selector);
213                 return 0;
214         }
215         mp->selector = set_default(DEFAULT_SELECTOR);
216         condlog(3, "%s: selector = %s (internal default)",
217                 mp->alias, mp->selector);
218         return 0;
219 }
220
221 static void
222 select_alias_prefix (struct multipath * mp)
223 {
224         if (mp->hwe && mp->hwe->alias_prefix) {
225                 mp->alias_prefix = mp->hwe->alias_prefix;
226                 condlog(3, "%s: alias_prefix = %s (controller setting)",
227                         mp->wwid, mp->alias_prefix);
228                 return;
229         }
230         if (conf->alias_prefix) {
231                 mp->alias_prefix = conf->alias_prefix;
232                 condlog(3, "%s: alias_prefix = %s (config file default)",
233                         mp->wwid, mp->alias_prefix);
234                 return;
235         }
236         mp->alias_prefix = set_default(DEFAULT_ALIAS_PREFIX);
237         condlog(3, "%s: alias_prefix = %s (internal default)",
238                 mp->wwid, mp->alias_prefix);
239 }
240
241 static int
242 want_user_friendly_names(struct multipath * mp)
243 {
244         if (mp->mpe &&
245             mp->mpe->user_friendly_names != USER_FRIENDLY_NAMES_UNDEF)
246                 return (mp->mpe->user_friendly_names == USER_FRIENDLY_NAMES_ON);
247         if (mp->hwe &&
248             mp->hwe->user_friendly_names != USER_FRIENDLY_NAMES_UNDEF)
249                 return (mp->hwe->user_friendly_names == USER_FRIENDLY_NAMES_ON);
250         return (conf->user_friendly_names  == USER_FRIENDLY_NAMES_ON);
251 }
252
253 extern int
254 select_alias (struct multipath * mp)
255 {
256         if (mp->mpe && mp->mpe->alias)
257                 mp->alias = STRDUP(mp->mpe->alias);
258         else {
259                 mp->alias = NULL;
260                 if (want_user_friendly_names(mp)) {
261                         select_alias_prefix(mp);
262                         mp->alias = get_user_friendly_alias(mp->wwid,
263                                         conf->bindings_file, mp->alias_prefix, conf->bindings_read_only);
264                 }
265                 if (mp->alias == NULL)
266                         mp->alias = STRDUP(mp->wwid);
267         }
268
269         return mp->alias ? 0 : 1;
270 }
271
272 extern int
273 select_features (struct multipath * mp)
274 {
275         struct mpentry * mpe;
276         char *origin;
277
278         if ((mpe = find_mpe(mp->wwid)) && mpe->features) {
279                 mp->features = STRDUP(mpe->features);
280                 origin = "LUN setting";
281         } else if (mp->hwe && mp->hwe->features) {
282                 mp->features = STRDUP(mp->hwe->features);
283                 origin = "controller setting";
284         } else if (conf->features) {
285                 mp->features = STRDUP(conf->features);
286                 origin = "config file default";
287         } else {
288                 mp->features = set_default(DEFAULT_FEATURES);
289                 origin = "internal default";
290         }
291         condlog(3, "%s: features = %s (%s)",
292                 mp->alias, mp->features, origin);
293         if (strstr(mp->features, "queue_if_no_path")) {
294                 if (mp->no_path_retry == NO_PATH_RETRY_UNDEF)
295                         mp->no_path_retry = NO_PATH_RETRY_QUEUE;
296                 else if (mp->no_path_retry == NO_PATH_RETRY_FAIL) {
297                         condlog(1, "%s: config error, overriding 'no_path_retry' value",
298                                 mp->alias);
299                         mp->no_path_retry = NO_PATH_RETRY_QUEUE;
300                 }
301         }
302         return 0;
303 }
304
305 extern int
306 select_hwhandler (struct multipath * mp)
307 {
308         if (mp->hwe && mp->hwe->hwhandler) {
309                 mp->hwhandler = mp->hwe->hwhandler;
310                 condlog(3, "%s: hwhandler = %s (controller setting)",
311                         mp->alias, mp->hwhandler);
312                 return 0;
313         }
314         if (conf->hwhandler) {
315                 mp->hwhandler = conf->hwhandler;
316                 condlog(3, "%s: hwhandler = %s (config file default)",
317                         mp->alias, mp->hwhandler);
318                 return 0;
319         }
320         mp->hwhandler = set_default(DEFAULT_HWHANDLER);
321         condlog(3, "%s: hwhandler = %s (internal default)",
322                 mp->alias, mp->hwhandler);
323         return 0;
324 }
325
326 extern int
327 select_checker(struct path *pp)
328 {
329         struct checker * c = &pp->checker;
330
331         if (pp->hwe && pp->hwe->checker_name) {
332                 checker_get(c, pp->hwe->checker_name);
333                 condlog(3, "%s: path checker = %s (controller setting)",
334                         pp->dev, checker_name(c));
335                 goto out;
336         }
337         if (conf->checker_name) {
338                 checker_get(c, conf->checker_name);
339                 condlog(3, "%s: path checker = %s (config file default)",
340                         pp->dev, checker_name(c));
341                 goto out;
342         }
343         checker_get(c, DEFAULT_CHECKER);
344         condlog(3, "%s: path checker = %s (internal default)",
345                 pp->dev, checker_name(c));
346 out:
347         if (conf->checker_timeout) {
348                 c->timeout = conf->checker_timeout;
349                 condlog(3, "%s: checker timeout = %u s (config file default)",
350                                 pp->dev, c->timeout);
351         }
352         else if (sysfs_get_timeout(pp, &c->timeout) > 0)
353                 condlog(3, "%s: checker timeout = %u ms (sysfs setting)",
354                                 pp->dev, c->timeout);
355         else {
356                 c->timeout = DEF_TIMEOUT;
357                 condlog(3, "%s: checker timeout = %u ms (internal default)",
358                                 pp->dev, c->timeout);
359         }
360         return 0;
361 }
362
363 extern int
364 select_getuid (struct path * pp)
365 {
366         if (pp->hwe && pp->hwe->uid_attribute) {
367                 pp->uid_attribute = pp->hwe->uid_attribute;
368                 condlog(3, "%s: uid_attribute = %s (controller setting)",
369                         pp->dev, pp->uid_attribute);
370                 return 0;
371         }
372         if (pp->hwe && pp->hwe->getuid) {
373                 pp->getuid = pp->hwe->getuid;
374                 condlog(3, "%s: getuid = %s (deprecated) (controller setting)",
375                         pp->dev, pp->getuid);
376                 return 0;
377         }
378         if (conf->uid_attribute) {
379                 pp->uid_attribute = conf->uid_attribute;
380                 condlog(3, "%s: uid_attribute = %s (config file default)",
381                         pp->dev, pp->uid_attribute);
382                 return 0;
383         }
384         if (conf->getuid) {
385                 pp->getuid = conf->getuid;
386                 condlog(3, "%s: getuid = %s (deprecated) (config file default)",
387                         pp->dev, pp->getuid);
388                 return 0;
389         }
390         pp->uid_attribute = STRDUP(DEFAULT_UID_ATTRIBUTE);
391         condlog(3, "%s: uid_attribute = %s (internal default)",
392                 pp->dev, pp->uid_attribute);
393         return 0;
394 }
395
396 void
397 detect_prio(struct path * pp)
398 {
399         int ret;
400         struct prio *p = &pp->prio;
401
402         if (get_target_port_group_support(pp->fd) <= 0)
403                 return;
404         ret = get_target_port_group(pp->fd);
405         if (ret < 0)
406                 return;
407         if (get_asymmetric_access_state(pp->fd, ret) < 0)
408                 return;
409         prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS);
410 }
411
412 extern int
413 select_prio (struct path * pp)
414 {
415         struct mpentry * mpe;
416         struct prio * p = &pp->prio;
417
418         if (pp->detect_prio == DETECT_PRIO_ON) {
419                 detect_prio(pp);
420                 if (prio_selected(p)) {
421                         condlog(3, "%s: prio = %s (detected setting)",
422                                 pp->dev, prio_name(p));
423                         return 0;
424                 }
425         }
426
427         if ((mpe = find_mpe(pp->wwid))) {
428                 if (mpe->prio_name) {
429                         prio_get(p, mpe->prio_name, mpe->prio_args);
430                         condlog(3, "%s: prio = %s (LUN setting)",
431                                 pp->dev, prio_name(p));
432                         return 0;
433                 }
434         }
435
436         if (pp->hwe && pp->hwe->prio_name) {
437                 prio_get(p, pp->hwe->prio_name, pp->hwe->prio_args);
438                 condlog(3, "%s: prio = %s (controller setting)",
439                         pp->dev, pp->hwe->prio_name);
440                 condlog(3, "%s: prio args = %s (controller setting)",
441                         pp->dev, pp->hwe->prio_args);
442                 return 0;
443         }
444         if (conf->prio_name) {
445                 prio_get(p, conf->prio_name, conf->prio_args);
446                 condlog(3, "%s: prio = %s (config file default)",
447                         pp->dev, conf->prio_name);
448                 condlog(3, "%s: prio args = %s (config file default)",
449                         pp->dev, conf->prio_args);
450                 return 0;
451         }
452         prio_get(p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS);
453         condlog(3, "%s: prio = %s (internal default)",
454                 pp->dev, DEFAULT_PRIO);
455         condlog(3, "%s: prio args = %s (internal default)",
456                 pp->dev, DEFAULT_PRIO_ARGS);
457         return 0;
458 }
459
460 extern int
461 select_no_path_retry(struct multipath *mp)
462 {
463         if (mp->flush_on_last_del == FLUSH_IN_PROGRESS) {
464                 condlog(0, "flush_on_last_del in progress");
465                 mp->no_path_retry = NO_PATH_RETRY_FAIL;
466                 return 0;
467         }
468         if (mp->mpe && mp->mpe->no_path_retry != NO_PATH_RETRY_UNDEF) {
469                 mp->no_path_retry = mp->mpe->no_path_retry;
470                 condlog(3, "%s: no_path_retry = %i (multipath setting)",
471                         mp->alias, mp->no_path_retry);
472                 return 0;
473         }
474         if (mp->hwe && mp->hwe->no_path_retry != NO_PATH_RETRY_UNDEF) {
475                 mp->no_path_retry = mp->hwe->no_path_retry;
476                 condlog(3, "%s: no_path_retry = %i (controller setting)",
477                         mp->alias, mp->no_path_retry);
478                 return 0;
479         }
480         if (conf->no_path_retry != NO_PATH_RETRY_UNDEF) {
481                 mp->no_path_retry = conf->no_path_retry;
482                 condlog(3, "%s: no_path_retry = %i (config file default)",
483                         mp->alias, mp->no_path_retry);
484                 return 0;
485         }
486         if (mp->no_path_retry != NO_PATH_RETRY_UNDEF)
487                 condlog(3, "%s: no_path_retry = %i (inherited setting)",
488                         mp->alias, mp->no_path_retry);
489         else
490                 condlog(3, "%s: no_path_retry = %i (internal default)",
491                         mp->alias, mp->no_path_retry);
492         return 0;
493 }
494
495 int
496 select_minio_rq (struct multipath * mp)
497 {
498         if (mp->mpe && mp->mpe->minio_rq) {
499                 mp->minio = mp->mpe->minio_rq;
500                 condlog(3, "%s: minio = %i rq (LUN setting)",
501                         mp->alias, mp->minio);
502                 return 0;
503         }
504         if (mp->hwe && mp->hwe->minio_rq) {
505                 mp->minio = mp->hwe->minio_rq;
506                 condlog(3, "%s: minio = %i rq (controller setting)",
507                         mp->alias, mp->minio);
508                 return 0;
509         }
510         if (conf->minio) {
511                 mp->minio = conf->minio_rq;
512                 condlog(3, "%s: minio = %i rq (config file default)",
513                         mp->alias, mp->minio);
514                 return 0;
515         }
516         mp->minio = DEFAULT_MINIO_RQ;
517         condlog(3, "%s: minio = %i rq (internal default)",
518                 mp->alias, mp->minio);
519         return 0;
520 }
521
522 int
523 select_minio_bio (struct multipath * mp)
524 {
525         if (mp->mpe && mp->mpe->minio) {
526                 mp->minio = mp->mpe->minio;
527                 condlog(3, "%s: minio = %i (LUN setting)",
528                         mp->alias, mp->minio);
529                 return 0;
530         }
531         if (mp->hwe && mp->hwe->minio) {
532                 mp->minio = mp->hwe->minio;
533                 condlog(3, "%s: minio = %i (controller setting)",
534                         mp->alias, mp->minio);
535                 return 0;
536         }
537         if (conf->minio) {
538                 mp->minio = conf->minio;
539                 condlog(3, "%s: minio = %i (config file default)",
540                         mp->alias, mp->minio);
541                 return 0;
542         }
543         mp->minio = DEFAULT_MINIO;
544         condlog(3, "%s: minio = %i (internal default)",
545                 mp->alias, mp->minio);
546         return 0;
547 }
548
549 extern int
550 select_minio (struct multipath * mp)
551 {
552         unsigned int minv_dmrq[3] = {1, 1, 0};
553
554         if (VERSION_GE(conf->version, minv_dmrq))
555                 return select_minio_rq(mp);
556         else
557                 return select_minio_bio(mp);
558 }
559
560 extern int
561 select_fast_io_fail(struct multipath *mp)
562 {
563         if (mp->hwe && mp->hwe->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
564                 mp->fast_io_fail = mp->hwe->fast_io_fail;
565                 if (mp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
566                         condlog(3, "%s: fast_io_fail_tmo = off "
567                                 "(controller setting)", mp->alias);
568                 else
569                         condlog(3, "%s: fast_io_fail_tmo = %d "
570                                 "(controller setting)", mp->alias,
571                                 mp->fast_io_fail == MP_FAST_IO_FAIL_ZERO ? 0 : mp->fast_io_fail);
572                 return 0;
573         }
574         if (conf->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
575                 mp->fast_io_fail = conf->fast_io_fail;
576                 if (mp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
577                         condlog(3, "%s: fast_io_fail_tmo = off "
578                                 "(config file default)", mp->alias);
579                 else
580                         condlog(3, "%s: fast_io_fail_tmo = %d "
581                                 "(config file default)", mp->alias,
582                                 mp->fast_io_fail == MP_FAST_IO_FAIL_ZERO ? 0 : mp->fast_io_fail);
583                 return 0;
584         }
585         mp->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
586         return 0;
587 }
588
589 extern int
590 select_dev_loss(struct multipath *mp)
591 {
592         if (mp->hwe && mp->hwe->dev_loss) {
593                 mp->dev_loss = mp->hwe->dev_loss;
594                 condlog(3, "%s: dev_loss_tmo = %u (controller default)",
595                         mp->alias, mp->dev_loss);
596                 return 0;
597         }
598         if (conf->dev_loss) {
599                 mp->dev_loss = conf->dev_loss;
600                 condlog(3, "%s: dev_loss_tmo = %u (config file default)",
601                         mp->alias, mp->dev_loss);
602                 return 0;
603         }
604         mp->dev_loss = 0;
605         return 0;
606 }
607
608 extern int
609 select_flush_on_last_del(struct multipath *mp)
610 {
611         if (mp->flush_on_last_del == FLUSH_IN_PROGRESS)
612                 return 0;
613         if (mp->mpe && mp->mpe->flush_on_last_del != FLUSH_UNDEF) {
614                 mp->flush_on_last_del = mp->mpe->flush_on_last_del;
615                 condlog(3, "%s: flush_on_last_del = %i (multipath setting)",
616                         mp->alias, mp->flush_on_last_del);
617                 return 0;
618         }
619         if (mp->hwe && mp->hwe->flush_on_last_del != FLUSH_UNDEF) {
620                 mp->flush_on_last_del = mp->hwe->flush_on_last_del;
621                 condlog(3, "%s: flush_on_last_del = %i (controler setting)",
622                         mp->alias, mp->flush_on_last_del);
623                 return 0;
624         }
625         if (conf->flush_on_last_del != FLUSH_UNDEF) {
626                 mp->flush_on_last_del = conf->flush_on_last_del;
627                 condlog(3, "%s: flush_on_last_del = %i (config file default)",
628                         mp->alias, mp->flush_on_last_del);
629                 return 0;
630         }
631         mp->flush_on_last_del = FLUSH_UNDEF;
632         condlog(3, "%s: flush_on_last_del = DISABLED (internal default)",
633                 mp->alias);
634         return 0;
635 }
636
637 extern int
638 select_reservation_key (struct multipath * mp)
639 {
640         int j;
641         unsigned char *keyp;
642         uint64_t prkey = 0;
643
644         mp->reservation_key = NULL;
645
646         if (mp->mpe && mp->mpe->reservation_key) {
647                 keyp =  mp->mpe->reservation_key;
648                 for (j = 0; j < 8; ++j) {
649                         if (j > 0)
650                                 prkey <<= 8;
651                         prkey |= *keyp;
652                         ++keyp;
653                 }
654
655                 condlog(3, "%s: reservation_key = 0x%" PRIx64 " "
656                                 "(multipath setting)",  mp->alias, prkey);
657
658                 mp->reservation_key = mp->mpe->reservation_key;
659                 return 0;
660         }
661
662         if (conf->reservation_key) {
663                 keyp = conf->reservation_key;
664                 for (j = 0; j < 8; ++j) {
665                         if (j > 0)
666                                 prkey <<= 8;
667                         prkey |= *keyp;
668                         ++keyp;
669                 }
670
671                 condlog(3, "%s: reservation_key  = 0x%" PRIx64
672                                 " (config file default)", mp->alias, prkey);
673
674                 mp->reservation_key = conf->reservation_key;
675                 return 0;
676         }
677
678         return 0;
679 }
680
681 extern int
682 select_retain_hwhandler (struct multipath * mp)
683 {
684         unsigned int minv_dm_retain[3] = {1, 5, 0};
685
686         if (!VERSION_GE(conf->version, minv_dm_retain)) {
687                 mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
688                 condlog(3, "%s: retain_attached_hw_hander disabled (requires kernel version >= 1.5.0)", mp->alias);
689                 return 0;
690         }
691
692         if (mp->hwe && mp->hwe->retain_hwhandler) {
693                 mp->retain_hwhandler = mp->hwe->retain_hwhandler;
694                 condlog(3, "%s: retain_attached_hw_handler = %d (controller default)", mp->alias, mp->retain_hwhandler);
695                 return 0;
696         }
697         if (conf->retain_hwhandler) {
698                 mp->retain_hwhandler = conf->retain_hwhandler;
699                 condlog(3, "%s: retain_attached_hw_handler = %d (config file default)", mp->alias, mp->retain_hwhandler);
700                 return 0;
701         }
702         mp->retain_hwhandler = 0;
703         condlog(3, "%s: retain_attached_hw_handler = %d (compiled in default)", mp->alias, mp->retain_hwhandler);
704         return 0;
705 }
706
707 extern int
708 select_detect_prio (struct path * pp)
709 {
710         if (pp->hwe && pp->hwe->detect_prio) {
711                 pp->detect_prio = pp->hwe->detect_prio;
712                 condlog(3, "%s: detect_prio = %d (controller default)", pp->dev, pp->detect_prio);
713                 return 0;
714         }
715         if (conf->detect_prio) {
716                 pp->detect_prio = conf->detect_prio;
717                 condlog(3, "%s: detect_prio = %d (config file default)", pp->dev, pp->detect_prio);
718                 return 0;
719         }
720         pp->detect_prio = 0;
721         condlog(3, "%s: detect_prio = %d (compiled in default)", pp->dev, pp->detect_prio);
722         return 0;
723 }