e47d0cae0ab7192a9ed72b956c496b2b00a4198b
[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 = dm_get_name(mp->wwid);
267                 if (mp->alias == NULL)
268                         mp->alias = STRDUP(mp->wwid);
269         }
270
271         return mp->alias ? 0 : 1;
272 }
273
274 extern int
275 select_features (struct multipath * mp)
276 {
277         struct mpentry * mpe;
278         char *origin;
279
280         if ((mpe = find_mpe(mp->wwid)) && mpe->features) {
281                 mp->features = STRDUP(mpe->features);
282                 origin = "LUN setting";
283         } else if (mp->hwe && mp->hwe->features) {
284                 mp->features = STRDUP(mp->hwe->features);
285                 origin = "controller setting";
286         } else if (conf->features) {
287                 mp->features = STRDUP(conf->features);
288                 origin = "config file default";
289         } else {
290                 mp->features = set_default(DEFAULT_FEATURES);
291                 origin = "internal default";
292         }
293         condlog(3, "%s: features = %s (%s)",
294                 mp->alias, mp->features, origin);
295         if (strstr(mp->features, "queue_if_no_path")) {
296                 if (mp->no_path_retry == NO_PATH_RETRY_UNDEF)
297                         mp->no_path_retry = NO_PATH_RETRY_QUEUE;
298                 else if (mp->no_path_retry == NO_PATH_RETRY_FAIL) {
299                         condlog(1, "%s: config error, overriding 'no_path_retry' value",
300                                 mp->alias);
301                         mp->no_path_retry = NO_PATH_RETRY_QUEUE;
302                 }
303         }
304         return 0;
305 }
306
307 extern int
308 select_hwhandler (struct multipath * mp)
309 {
310         if (mp->hwe && mp->hwe->hwhandler) {
311                 mp->hwhandler = mp->hwe->hwhandler;
312                 condlog(3, "%s: hwhandler = %s (controller setting)",
313                         mp->alias, mp->hwhandler);
314                 return 0;
315         }
316         if (conf->hwhandler) {
317                 mp->hwhandler = conf->hwhandler;
318                 condlog(3, "%s: hwhandler = %s (config file default)",
319                         mp->alias, mp->hwhandler);
320                 return 0;
321         }
322         mp->hwhandler = set_default(DEFAULT_HWHANDLER);
323         condlog(3, "%s: hwhandler = %s (internal default)",
324                 mp->alias, mp->hwhandler);
325         return 0;
326 }
327
328 extern int
329 select_checker(struct path *pp)
330 {
331         struct checker * c = &pp->checker;
332
333         if (pp->hwe && pp->hwe->checker_name) {
334                 checker_get(c, pp->hwe->checker_name);
335                 condlog(3, "%s: path checker = %s (controller setting)",
336                         pp->dev, checker_name(c));
337                 goto out;
338         }
339         if (conf->checker_name) {
340                 checker_get(c, conf->checker_name);
341                 condlog(3, "%s: path checker = %s (config file default)",
342                         pp->dev, checker_name(c));
343                 goto out;
344         }
345         checker_get(c, DEFAULT_CHECKER);
346         condlog(3, "%s: path checker = %s (internal default)",
347                 pp->dev, checker_name(c));
348 out:
349         if (conf->checker_timeout) {
350                 c->timeout = conf->checker_timeout;
351                 condlog(3, "%s: checker timeout = %u s (config file default)",
352                                 pp->dev, c->timeout);
353         }
354         else if (pp->udev && sysfs_get_timeout(pp, &c->timeout) == 0)
355                 condlog(3, "%s: checker timeout = %u ms (sysfs setting)",
356                                 pp->dev, c->timeout);
357         else {
358                 c->timeout = DEF_TIMEOUT;
359                 condlog(3, "%s: checker timeout = %u ms (internal default)",
360                                 pp->dev, c->timeout);
361         }
362         return 0;
363 }
364
365 extern int
366 select_getuid (struct path * pp)
367 {
368         if (pp->hwe && pp->hwe->uid_attribute) {
369                 pp->uid_attribute = pp->hwe->uid_attribute;
370                 condlog(3, "%s: uid_attribute = %s (controller setting)",
371                         pp->dev, pp->uid_attribute);
372                 return 0;
373         }
374         if (pp->hwe && pp->hwe->getuid) {
375                 pp->getuid = pp->hwe->getuid;
376                 condlog(3, "%s: getuid = %s (deprecated) (controller setting)",
377                         pp->dev, pp->getuid);
378                 return 0;
379         }
380         if (conf->uid_attribute) {
381                 pp->uid_attribute = conf->uid_attribute;
382                 condlog(3, "%s: uid_attribute = %s (config file default)",
383                         pp->dev, pp->uid_attribute);
384                 return 0;
385         }
386         if (conf->getuid) {
387                 pp->getuid = conf->getuid;
388                 condlog(3, "%s: getuid = %s (deprecated) (config file default)",
389                         pp->dev, pp->getuid);
390                 return 0;
391         }
392         pp->uid_attribute = STRDUP(DEFAULT_UID_ATTRIBUTE);
393         condlog(3, "%s: uid_attribute = %s (internal default)",
394                 pp->dev, pp->uid_attribute);
395         return 0;
396 }
397
398 void
399 detect_prio(struct path * pp)
400 {
401         struct prio *p = &pp->prio;
402
403         if (get_target_port_group_support(pp->fd) > 0)
404                 prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS);
405 }
406
407 extern int
408 select_prio (struct path * pp)
409 {
410         struct mpentry * mpe;
411         struct prio * p = &pp->prio;
412
413         if (pp->detect_prio == DETECT_PRIO_ON) {
414                 detect_prio(pp);
415                 if (prio_selected(p)) {
416                         condlog(3, "%s: prio = %s (detected setting)",
417                                 pp->dev, prio_name(p));
418                         return 0;
419                 }
420         }
421
422         if ((mpe = find_mpe(pp->wwid))) {
423                 if (mpe->prio_name) {
424                         prio_get(p, mpe->prio_name, mpe->prio_args);
425                         condlog(3, "%s: prio = %s (LUN setting)",
426                                 pp->dev, prio_name(p));
427                         return 0;
428                 }
429         }
430
431         if (pp->hwe && pp->hwe->prio_name) {
432                 prio_get(p, pp->hwe->prio_name, pp->hwe->prio_args);
433                 condlog(3, "%s: prio = %s (controller setting)",
434                         pp->dev, pp->hwe->prio_name);
435                 condlog(3, "%s: prio args = %s (controller setting)",
436                         pp->dev, pp->hwe->prio_args);
437                 return 0;
438         }
439         if (conf->prio_name) {
440                 prio_get(p, conf->prio_name, conf->prio_args);
441                 condlog(3, "%s: prio = %s (config file default)",
442                         pp->dev, conf->prio_name);
443                 condlog(3, "%s: prio args = %s (config file default)",
444                         pp->dev, conf->prio_args);
445                 return 0;
446         }
447         prio_get(p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS);
448         condlog(3, "%s: prio = %s (internal default)",
449                 pp->dev, DEFAULT_PRIO);
450         condlog(3, "%s: prio args = %s (internal default)",
451                 pp->dev, DEFAULT_PRIO_ARGS);
452         return 0;
453 }
454
455 extern int
456 select_no_path_retry(struct multipath *mp)
457 {
458         if (mp->flush_on_last_del == FLUSH_IN_PROGRESS) {
459                 condlog(0, "flush_on_last_del in progress");
460                 mp->no_path_retry = NO_PATH_RETRY_FAIL;
461                 return 0;
462         }
463         if (mp->mpe && mp->mpe->no_path_retry != NO_PATH_RETRY_UNDEF) {
464                 mp->no_path_retry = mp->mpe->no_path_retry;
465                 condlog(3, "%s: no_path_retry = %i (multipath setting)",
466                         mp->alias, mp->no_path_retry);
467                 return 0;
468         }
469         if (mp->hwe && mp->hwe->no_path_retry != NO_PATH_RETRY_UNDEF) {
470                 mp->no_path_retry = mp->hwe->no_path_retry;
471                 condlog(3, "%s: no_path_retry = %i (controller setting)",
472                         mp->alias, mp->no_path_retry);
473                 return 0;
474         }
475         if (conf->no_path_retry != NO_PATH_RETRY_UNDEF) {
476                 mp->no_path_retry = conf->no_path_retry;
477                 condlog(3, "%s: no_path_retry = %i (config file default)",
478                         mp->alias, mp->no_path_retry);
479                 return 0;
480         }
481         if (mp->no_path_retry != NO_PATH_RETRY_UNDEF)
482                 condlog(3, "%s: no_path_retry = %i (inherited setting)",
483                         mp->alias, mp->no_path_retry);
484         else
485                 condlog(3, "%s: no_path_retry = %i (internal default)",
486                         mp->alias, mp->no_path_retry);
487         return 0;
488 }
489
490 int
491 select_minio_rq (struct multipath * mp)
492 {
493         if (mp->mpe && mp->mpe->minio_rq) {
494                 mp->minio = mp->mpe->minio_rq;
495                 condlog(3, "%s: minio = %i rq (LUN setting)",
496                         mp->alias, mp->minio);
497                 return 0;
498         }
499         if (mp->hwe && mp->hwe->minio_rq) {
500                 mp->minio = mp->hwe->minio_rq;
501                 condlog(3, "%s: minio = %i rq (controller setting)",
502                         mp->alias, mp->minio);
503                 return 0;
504         }
505         if (conf->minio) {
506                 mp->minio = conf->minio_rq;
507                 condlog(3, "%s: minio = %i rq (config file default)",
508                         mp->alias, mp->minio);
509                 return 0;
510         }
511         mp->minio = DEFAULT_MINIO_RQ;
512         condlog(3, "%s: minio = %i rq (internal default)",
513                 mp->alias, mp->minio);
514         return 0;
515 }
516
517 int
518 select_minio_bio (struct multipath * mp)
519 {
520         if (mp->mpe && mp->mpe->minio) {
521                 mp->minio = mp->mpe->minio;
522                 condlog(3, "%s: minio = %i (LUN setting)",
523                         mp->alias, mp->minio);
524                 return 0;
525         }
526         if (mp->hwe && mp->hwe->minio) {
527                 mp->minio = mp->hwe->minio;
528                 condlog(3, "%s: minio = %i (controller setting)",
529                         mp->alias, mp->minio);
530                 return 0;
531         }
532         if (conf->minio) {
533                 mp->minio = conf->minio;
534                 condlog(3, "%s: minio = %i (config file default)",
535                         mp->alias, mp->minio);
536                 return 0;
537         }
538         mp->minio = DEFAULT_MINIO;
539         condlog(3, "%s: minio = %i (internal default)",
540                 mp->alias, mp->minio);
541         return 0;
542 }
543
544 extern int
545 select_minio (struct multipath * mp)
546 {
547         unsigned int minv_dmrq[3] = {1, 1, 0};
548
549         if (VERSION_GE(conf->version, minv_dmrq))
550                 return select_minio_rq(mp);
551         else
552                 return select_minio_bio(mp);
553 }
554
555 extern int
556 select_fast_io_fail(struct multipath *mp)
557 {
558         if (mp->hwe && mp->hwe->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
559                 mp->fast_io_fail = mp->hwe->fast_io_fail;
560                 if (mp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
561                         condlog(3, "%s: fast_io_fail_tmo = off "
562                                 "(controller setting)", mp->alias);
563                 else
564                         condlog(3, "%s: fast_io_fail_tmo = %d "
565                                 "(controller setting)", mp->alias,
566                                 mp->fast_io_fail == MP_FAST_IO_FAIL_ZERO ? 0 : mp->fast_io_fail);
567                 return 0;
568         }
569         if (conf->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
570                 mp->fast_io_fail = conf->fast_io_fail;
571                 if (mp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
572                         condlog(3, "%s: fast_io_fail_tmo = off "
573                                 "(config file default)", mp->alias);
574                 else
575                         condlog(3, "%s: fast_io_fail_tmo = %d "
576                                 "(config file default)", mp->alias,
577                                 mp->fast_io_fail == MP_FAST_IO_FAIL_ZERO ? 0 : mp->fast_io_fail);
578                 return 0;
579         }
580         mp->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
581         return 0;
582 }
583
584 extern int
585 select_dev_loss(struct multipath *mp)
586 {
587         if (mp->hwe && mp->hwe->dev_loss) {
588                 mp->dev_loss = mp->hwe->dev_loss;
589                 condlog(3, "%s: dev_loss_tmo = %u (controller default)",
590                         mp->alias, mp->dev_loss);
591                 return 0;
592         }
593         if (conf->dev_loss) {
594                 mp->dev_loss = conf->dev_loss;
595                 condlog(3, "%s: dev_loss_tmo = %u (config file default)",
596                         mp->alias, mp->dev_loss);
597                 return 0;
598         }
599         mp->dev_loss = 0;
600         return 0;
601 }
602
603 extern int
604 select_flush_on_last_del(struct multipath *mp)
605 {
606         if (mp->flush_on_last_del == FLUSH_IN_PROGRESS)
607                 return 0;
608         if (mp->mpe && mp->mpe->flush_on_last_del != FLUSH_UNDEF) {
609                 mp->flush_on_last_del = mp->mpe->flush_on_last_del;
610                 condlog(3, "%s: flush_on_last_del = %i (multipath setting)",
611                         mp->alias, mp->flush_on_last_del);
612                 return 0;
613         }
614         if (mp->hwe && mp->hwe->flush_on_last_del != FLUSH_UNDEF) {
615                 mp->flush_on_last_del = mp->hwe->flush_on_last_del;
616                 condlog(3, "%s: flush_on_last_del = %i (controler setting)",
617                         mp->alias, mp->flush_on_last_del);
618                 return 0;
619         }
620         if (conf->flush_on_last_del != FLUSH_UNDEF) {
621                 mp->flush_on_last_del = conf->flush_on_last_del;
622                 condlog(3, "%s: flush_on_last_del = %i (config file default)",
623                         mp->alias, mp->flush_on_last_del);
624                 return 0;
625         }
626         mp->flush_on_last_del = FLUSH_UNDEF;
627         condlog(3, "%s: flush_on_last_del = DISABLED (internal default)",
628                 mp->alias);
629         return 0;
630 }
631
632 extern int
633 select_reservation_key (struct multipath * mp)
634 {
635         int j;
636         unsigned char *keyp;
637         uint64_t prkey = 0;
638
639         mp->reservation_key = NULL;
640
641         if (mp->mpe && mp->mpe->reservation_key) {
642                 keyp =  mp->mpe->reservation_key;
643                 for (j = 0; j < 8; ++j) {
644                         if (j > 0)
645                                 prkey <<= 8;
646                         prkey |= *keyp;
647                         ++keyp;
648                 }
649
650                 condlog(3, "%s: reservation_key = 0x%" PRIx64 " "
651                                 "(multipath setting)",  mp->alias, prkey);
652
653                 mp->reservation_key = mp->mpe->reservation_key;
654                 return 0;
655         }
656
657         if (conf->reservation_key) {
658                 keyp = conf->reservation_key;
659                 for (j = 0; j < 8; ++j) {
660                         if (j > 0)
661                                 prkey <<= 8;
662                         prkey |= *keyp;
663                         ++keyp;
664                 }
665
666                 condlog(3, "%s: reservation_key  = 0x%" PRIx64
667                                 " (config file default)", mp->alias, prkey);
668
669                 mp->reservation_key = conf->reservation_key;
670                 return 0;
671         }
672
673         return 0;
674 }
675
676 extern int
677 select_retain_hwhandler (struct multipath * mp)
678 {
679         unsigned int minv_dm_retain[3] = {1, 5, 0};
680
681         if (!VERSION_GE(conf->version, minv_dm_retain)) {
682                 mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
683                 condlog(3, "%s: retain_attached_hw_hander disabled (requires kernel version >= 1.5.0)", mp->alias);
684                 return 0;
685         }
686
687         if (mp->hwe && mp->hwe->retain_hwhandler) {
688                 mp->retain_hwhandler = mp->hwe->retain_hwhandler;
689                 condlog(3, "%s: retain_attached_hw_handler = %d (controller default)", mp->alias, mp->retain_hwhandler);
690                 return 0;
691         }
692         if (conf->retain_hwhandler) {
693                 mp->retain_hwhandler = conf->retain_hwhandler;
694                 condlog(3, "%s: retain_attached_hw_handler = %d (config file default)", mp->alias, mp->retain_hwhandler);
695                 return 0;
696         }
697         mp->retain_hwhandler = 0;
698         condlog(3, "%s: retain_attached_hw_handler = %d (compiled in default)", mp->alias, mp->retain_hwhandler);
699         return 0;
700 }
701
702 extern int
703 select_detect_prio (struct path * pp)
704 {
705         if (pp->hwe && pp->hwe->detect_prio) {
706                 pp->detect_prio = pp->hwe->detect_prio;
707                 condlog(3, "%s: detect_prio = %d (controller default)", pp->dev, pp->detect_prio);
708                 return 0;
709         }
710         if (conf->detect_prio) {
711                 pp->detect_prio = conf->detect_prio;
712                 condlog(3, "%s: detect_prio = %d (config file default)", pp->dev, pp->detect_prio);
713                 return 0;
714         }
715         pp->detect_prio = 0;
716         condlog(3, "%s: detect_prio = %d (compiled in default)", pp->dev, pp->detect_prio);
717         return 0;
718 }