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