a7e1fc2717ee694c9530bc3ba392990a579ec0f9
[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 * 1000;
351                 condlog(3, "%s: checker timeout = %u ms (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 (conf->uid_attribute) {
375                 pp->uid_attribute = conf->uid_attribute;
376                 condlog(3, "%s: uid_attribute = %s (config file default)",
377                         pp->dev, pp->uid_attribute);
378                 return 0;
379         }
380         pp->uid_attribute = STRDUP(DEFAULT_UID_ATTRIBUTE);
381         condlog(3, "%s: uid_attribute = %s (internal default)",
382                 pp->dev, pp->uid_attribute);
383         return 0;
384 }
385
386 void
387 detect_prio(struct path * pp)
388 {
389         struct prio *p = &pp->prio;
390
391         if (get_target_port_group_support(pp->fd) > 0)
392                 prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS);
393 }
394
395 extern int
396 select_prio (struct path * pp)
397 {
398         struct mpentry * mpe;
399         struct prio * p = &pp->prio;
400
401         if (pp->detect_prio == DETECT_PRIO_ON) {
402                 detect_prio(pp);
403                 if (prio_selected(p)) {
404                         condlog(3, "%s: prio = %s (detected setting)",
405                                 pp->dev, prio_name(p));
406                         return 0;
407                 }
408         }
409
410         if ((mpe = find_mpe(pp->wwid))) {
411                 if (mpe->prio_name) {
412                         prio_get(p, mpe->prio_name, mpe->prio_args);
413                         condlog(3, "%s: prio = %s (LUN setting)",
414                                 pp->dev, prio_name(p));
415                         return 0;
416                 }
417         }
418
419         if (pp->hwe && pp->hwe->prio_name) {
420                 prio_get(p, pp->hwe->prio_name, pp->hwe->prio_args);
421                 condlog(3, "%s: prio = %s (controller setting)",
422                         pp->dev, pp->hwe->prio_name);
423                 condlog(3, "%s: prio args = %s (controller setting)",
424                         pp->dev, pp->hwe->prio_args);
425                 return 0;
426         }
427         if (conf->prio_name) {
428                 prio_get(p, conf->prio_name, conf->prio_args);
429                 condlog(3, "%s: prio = %s (config file default)",
430                         pp->dev, conf->prio_name);
431                 condlog(3, "%s: prio args = %s (config file default)",
432                         pp->dev, conf->prio_args);
433                 return 0;
434         }
435         prio_get(p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS);
436         condlog(3, "%s: prio = %s (internal default)",
437                 pp->dev, DEFAULT_PRIO);
438         condlog(3, "%s: prio = %s (internal default)",
439                 pp->dev, DEFAULT_PRIO_ARGS);
440         return 0;
441 }
442
443 extern int
444 select_no_path_retry(struct multipath *mp)
445 {
446         if (mp->flush_on_last_del == FLUSH_IN_PROGRESS) {
447                 condlog(0, "flush_on_last_del in progress");
448                 mp->no_path_retry = NO_PATH_RETRY_FAIL;
449                 return 0;
450         }
451         if (mp->mpe && mp->mpe->no_path_retry != NO_PATH_RETRY_UNDEF) {
452                 mp->no_path_retry = mp->mpe->no_path_retry;
453                 condlog(3, "%s: no_path_retry = %i (multipath setting)",
454                         mp->alias, mp->no_path_retry);
455                 return 0;
456         }
457         if (mp->hwe && mp->hwe->no_path_retry != NO_PATH_RETRY_UNDEF) {
458                 mp->no_path_retry = mp->hwe->no_path_retry;
459                 condlog(3, "%s: no_path_retry = %i (controller setting)",
460                         mp->alias, mp->no_path_retry);
461                 return 0;
462         }
463         if (conf->no_path_retry != NO_PATH_RETRY_UNDEF) {
464                 mp->no_path_retry = conf->no_path_retry;
465                 condlog(3, "%s: no_path_retry = %i (config file default)",
466                         mp->alias, mp->no_path_retry);
467                 return 0;
468         }
469         if (mp->no_path_retry != NO_PATH_RETRY_UNDEF)
470                 condlog(3, "%s: no_path_retry = %i (inherited setting)",
471                         mp->alias, mp->no_path_retry);
472         else
473                 condlog(3, "%s: no_path_retry = %i (internal default)",
474                         mp->alias, mp->no_path_retry);
475         return 0;
476 }
477
478 int
479 select_minio_rq (struct multipath * mp)
480 {
481         if (mp->mpe && mp->mpe->minio_rq) {
482                 mp->minio = mp->mpe->minio_rq;
483                 condlog(3, "%s: minio = %i rq (LUN setting)",
484                         mp->alias, mp->minio);
485                 return 0;
486         }
487         if (mp->hwe && mp->hwe->minio_rq) {
488                 mp->minio = mp->hwe->minio_rq;
489                 condlog(3, "%s: minio = %i rq (controller setting)",
490                         mp->alias, mp->minio);
491                 return 0;
492         }
493         if (conf->minio) {
494                 mp->minio = conf->minio_rq;
495                 condlog(3, "%s: minio = %i rq (config file default)",
496                         mp->alias, mp->minio);
497                 return 0;
498         }
499         mp->minio = DEFAULT_MINIO_RQ;
500         condlog(3, "%s: minio = %i rq (internal default)",
501                 mp->alias, mp->minio);
502         return 0;
503 }
504
505 int
506 select_minio_bio (struct multipath * mp)
507 {
508         if (mp->mpe && mp->mpe->minio) {
509                 mp->minio = mp->mpe->minio;
510                 condlog(3, "%s: minio = %i (LUN setting)",
511                         mp->alias, mp->minio);
512                 return 0;
513         }
514         if (mp->hwe && mp->hwe->minio) {
515                 mp->minio = mp->hwe->minio;
516                 condlog(3, "%s: minio = %i (controller setting)",
517                         mp->alias, mp->minio);
518                 return 0;
519         }
520         if (conf->minio) {
521                 mp->minio = conf->minio;
522                 condlog(3, "%s: minio = %i (config file default)",
523                         mp->alias, mp->minio);
524                 return 0;
525         }
526         mp->minio = DEFAULT_MINIO;
527         condlog(3, "%s: minio = %i (internal default)",
528                 mp->alias, mp->minio);
529         return 0;
530 }
531
532 extern int
533 select_minio (struct multipath * mp)
534 {
535         unsigned int minv_dmrq[3] = {1, 1, 0};
536
537         if (VERSION_GE(conf->version, minv_dmrq))
538                 return select_minio_rq(mp);
539         else
540                 return select_minio_bio(mp);
541 }
542
543 extern int
544 select_pg_timeout(struct multipath *mp)
545 {
546         if (mp->mpe && mp->mpe->pg_timeout != PGTIMEOUT_UNDEF) {
547                 mp->pg_timeout = mp->mpe->pg_timeout;
548                 if (mp->pg_timeout > 0)
549                         condlog(3, "%s: pg_timeout = %d (multipath setting)",
550                                 mp->alias, mp->pg_timeout);
551                 else
552                         condlog(3, "%s: pg_timeout = NONE (multipath setting)",
553                                 mp->alias);
554                 return 0;
555         }
556         if (mp->hwe && mp->hwe->pg_timeout != PGTIMEOUT_UNDEF) {
557                 mp->pg_timeout = mp->hwe->pg_timeout;
558                 if (mp->pg_timeout > 0)
559                         condlog(3, "%s: pg_timeout = %d (controller setting)",
560                                 mp->alias, mp->pg_timeout);
561                 else
562                         condlog(3, "%s: pg_timeout = NONE (controller setting)",
563                                 mp->alias);
564                 return 0;
565         }
566         if (conf->pg_timeout != PGTIMEOUT_UNDEF) {
567                 mp->pg_timeout = conf->pg_timeout;
568                 if (mp->pg_timeout > 0)
569                         condlog(3, "%s: pg_timeout = %d (config file default)",
570                                 mp->alias, mp->pg_timeout);
571                 else
572                         condlog(3,
573                                 "%s: pg_timeout = NONE (config file default)",
574                                 mp->alias);
575                 return 0;
576         }
577         mp->pg_timeout = PGTIMEOUT_UNDEF;
578         condlog(3, "%s: pg_timeout = NONE (internal default)", mp->alias);
579         return 0;
580 }
581
582 extern int
583 select_fast_io_fail(struct multipath *mp)
584 {
585         if (mp->hwe && mp->hwe->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
586                 mp->fast_io_fail = mp->hwe->fast_io_fail;
587                 if (mp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
588                         condlog(3, "%s: fast_io_fail_tmo = off "
589                                 "(controller setting)", mp->alias);
590                 else
591                         condlog(3, "%s: fast_io_fail_tmo = %d "
592                                 "(controller setting)", mp->alias,
593                                 mp->fast_io_fail == MP_FAST_IO_FAIL_ZERO ? 0 : mp->fast_io_fail);
594                 return 0;
595         }
596         if (conf->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
597                 mp->fast_io_fail = conf->fast_io_fail;
598                 if (mp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
599                         condlog(3, "%s: fast_io_fail_tmo = off "
600                                 "(config file default)", mp->alias);
601                 else
602                         condlog(3, "%s: fast_io_fail_tmo = %d "
603                                 "(config file default)", mp->alias,
604                                 mp->fast_io_fail == MP_FAST_IO_FAIL_ZERO ? 0 : mp->fast_io_fail);
605                 return 0;
606         }
607         mp->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
608         return 0;
609 }
610
611 extern int
612 select_dev_loss(struct multipath *mp)
613 {
614         if (mp->hwe && mp->hwe->dev_loss) {
615                 mp->dev_loss = mp->hwe->dev_loss;
616                 condlog(3, "%s: dev_loss_tmo = %u (controller default)",
617                         mp->alias, mp->dev_loss);
618                 return 0;
619         }
620         if (conf->dev_loss) {
621                 mp->dev_loss = conf->dev_loss;
622                 condlog(3, "%s: dev_loss_tmo = %u (config file default)",
623                         mp->alias, mp->dev_loss);
624                 return 0;
625         }
626         mp->dev_loss = 0;
627         return 0;
628 }
629
630 extern int
631 select_flush_on_last_del(struct multipath *mp)
632 {
633         if (mp->flush_on_last_del == FLUSH_IN_PROGRESS)
634                 return 0;
635         if (mp->mpe && mp->mpe->flush_on_last_del != FLUSH_UNDEF) {
636                 mp->flush_on_last_del = mp->mpe->flush_on_last_del;
637                 condlog(3, "%s: flush_on_last_del = %i (multipath setting)",
638                         mp->alias, mp->flush_on_last_del);
639                 return 0;
640         }
641         if (mp->hwe && mp->hwe->flush_on_last_del != FLUSH_UNDEF) {
642                 mp->flush_on_last_del = mp->hwe->flush_on_last_del;
643                 condlog(3, "%s: flush_on_last_del = %i (controler setting)",
644                         mp->alias, mp->flush_on_last_del);
645                 return 0;
646         }
647         if (conf->flush_on_last_del != FLUSH_UNDEF) {
648                 mp->flush_on_last_del = conf->flush_on_last_del;
649                 condlog(3, "%s: flush_on_last_del = %i (config file default)",
650                         mp->alias, mp->flush_on_last_del);
651                 return 0;
652         }
653         mp->flush_on_last_del = FLUSH_UNDEF;
654         condlog(3, "%s: flush_on_last_del = DISABLED (internal default)",
655                 mp->alias);
656         return 0;
657 }
658
659 extern int
660 select_reservation_key (struct multipath * mp)
661 {
662         int j;
663         unsigned char *keyp;
664         uint64_t prkey = 0;
665
666         mp->reservation_key = NULL;
667
668         if (mp->mpe && mp->mpe->reservation_key) {
669                 keyp =  mp->mpe->reservation_key;
670                 for (j = 0; j < 8; ++j) {
671                         if (j > 0)
672                                 prkey <<= 8;
673                         prkey |= *keyp;
674                         ++keyp;
675                 }
676
677                 condlog(3, "%s: reservation_key = 0x%" PRIx64 " "
678                                 "(multipath setting)",  mp->alias, prkey);
679
680                 mp->reservation_key = mp->mpe->reservation_key;
681                 return 0;
682         }
683
684         if (conf->reservation_key) {
685                 keyp = conf->reservation_key;
686                 for (j = 0; j < 8; ++j) {
687                         if (j > 0)
688                                 prkey <<= 8;
689                         prkey |= *keyp;
690                         ++keyp;
691                 }
692
693                 condlog(3, "%s: reservation_key  = 0x%" PRIx64
694                                 " (config file default)", mp->alias, prkey);
695
696                 mp->reservation_key = conf->reservation_key;
697                 return 0;
698         }
699
700         return 0;
701 }
702
703 extern int
704 select_retain_hwhandler (struct multipath * mp)
705 {
706         unsigned int minv_dm_retain[3] = {1, 5, 0};
707
708         if (!VERSION_GE(conf->version, minv_dm_retain)) {
709                 mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
710                 condlog(3, "%s: retain_attached_hw_hander disabled (requires kernel version >= 1.5.0)", mp->alias);
711                 return 0;
712         }
713
714         if (mp->hwe && mp->hwe->retain_hwhandler) {
715                 mp->retain_hwhandler = mp->hwe->retain_hwhandler;
716                 condlog(3, "%s: retain_attached_hw_handler = %d (controller default)", mp->alias, mp->retain_hwhandler);
717                 return 0;
718         }
719         if (conf->retain_hwhandler) {
720                 mp->retain_hwhandler = conf->retain_hwhandler;
721                 condlog(3, "%s: retain_attached_hw_handler = %d (config file default)", mp->alias, mp->retain_hwhandler);
722                 return 0;
723         }
724         mp->retain_hwhandler = 0;
725         condlog(3, "%s: retain_attached_hw_handler = %d (compiled in default)", mp->alias, mp->retain_hwhandler);
726         return 0;
727 }
728
729 extern int
730 select_detect_prio (struct path * pp)
731 {
732         if (pp->hwe && pp->hwe->detect_prio) {
733                 pp->detect_prio = pp->hwe->detect_prio;
734                 condlog(3, "%s: detect_prio = %d (controller default)", pp->dev, pp->detect_prio);
735                 return 0;
736         }
737         if (conf->detect_prio) {
738                 pp->detect_prio = conf->detect_prio;
739                 condlog(3, "%s: detect_prio = %d (config file default)", pp->dev, pp->detect_prio);
740                 return 0;
741         }
742         pp->detect_prio = 0;
743         condlog(3, "%s: detect_prio = %d (compiled in default)", pp->dev, pp->detect_prio);
744         return 0;
745 }