multipath-tools: replace <> with "" for local headers
[multipath-tools/.git] / libmultipath / configure.c
1 /*
2  * Copyright (c) 2003, 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Benjamin Marzinski, Redhat
4  * Copyright (c) 2005 Kiyoshi Ueda, NEC
5  * Copyright (c) 2005 Patrick Caulfield, Redhat
6  * Copyright (c) 2005 Edward Goggin, EMC
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <sys/file.h>
14 #include <errno.h>
15 #include <libdevmapper.h>
16 #include <libudev.h>
17 #include "mpath_cmd.h"
18
19 #include "checkers.h"
20 #include "vector.h"
21 #include "memory.h"
22 #include "devmapper.h"
23 #include "defaults.h"
24 #include "structs.h"
25 #include "structs_vec.h"
26 #include "dmparser.h"
27 #include "config.h"
28 #include "blacklist.h"
29 #include "propsel.h"
30 #include "discovery.h"
31 #include "debug.h"
32 #include "switchgroup.h"
33 #include "print.h"
34 #include "configure.h"
35 #include "pgpolicies.h"
36 #include "dict.h"
37 #include "alias.h"
38 #include "prio.h"
39 #include "util.h"
40 #include "uxsock.h"
41 #include "wwids.h"
42
43 /* group paths in pg by host adapter
44  */
45 int group_by_host_adapter(struct pathgroup *pgp, vector adapters)
46 {
47         struct adapter_group *agp;
48         struct host_group *hgp;
49         struct path *pp, *pp1;
50         char adapter_name1[SLOT_NAME_SIZE];
51         char adapter_name2[SLOT_NAME_SIZE];
52         int i, j;
53         int found_hostgroup = 0;
54
55         while (VECTOR_SIZE(pgp->paths) > 0) {
56
57                 pp = VECTOR_SLOT(pgp->paths, 0);
58
59                 if (sysfs_get_host_adapter_name(pp, adapter_name1))
60                         goto out;
61                 /* create a new host adapter group
62                  */
63                 agp = alloc_adaptergroup();
64                 if (!agp)
65                         goto out;
66                 agp->pgp = pgp;
67
68                 strncpy(agp->adapter_name, adapter_name1, SLOT_NAME_SIZE - 1);
69                 store_adaptergroup(adapters, agp);
70
71                 /* create a new host port group
72                  */
73                 hgp = alloc_hostgroup();
74                 if (!hgp)
75                         goto out;
76                 if (store_hostgroup(agp->host_groups, hgp))
77                         goto out;
78
79                 hgp->host_no = pp->sg_id.host_no;
80                 agp->num_hosts++;
81                 if (store_path(hgp->paths, pp))
82                         goto out;
83
84                 hgp->num_paths++;
85                 /* delete path from path group
86                  */
87                 vector_del_slot(pgp->paths, 0);
88
89                 /* add all paths belonging to same host adapter
90                  */
91                 vector_foreach_slot(pgp->paths, pp1, i) {
92                         if (sysfs_get_host_adapter_name(pp1, adapter_name2))
93                                 goto out;
94                         if (strcmp(adapter_name1, adapter_name2) == 0) {
95                                 found_hostgroup = 0;
96                                 vector_foreach_slot(agp->host_groups, hgp, j) {
97                                         if (hgp->host_no == pp1->sg_id.host_no) {
98                                                 if (store_path(hgp->paths, pp1))
99                                                         goto out;
100                                                 hgp->num_paths++;
101                                                 found_hostgroup = 1;
102                                                 break;
103                                         }
104                                 }
105                                 if (!found_hostgroup) {
106                                         /* this path belongs to new host port
107                                          * within this adapter
108                                          */
109                                         hgp = alloc_hostgroup();
110                                         if (!hgp)
111                                                 goto out;
112
113                                         if (store_hostgroup(agp->host_groups, hgp))
114                                                 goto out;
115
116                                         agp->num_hosts++;
117                                         if (store_path(hgp->paths, pp1))
118                                                 goto out;
119
120                                         hgp->host_no = pp1->sg_id.host_no;
121                                         hgp->num_paths++;
122                                 }
123                                 /* delete paths from original path_group
124                                  * as they are added into adapter group now
125                                  */
126                                 vector_del_slot(pgp->paths, i);
127                                 i--;
128                         }
129                 }
130         }
131         return 0;
132
133 out:    /* add back paths into pg as re-ordering failed
134          */
135         vector_foreach_slot(adapters, agp, i) {
136                         vector_foreach_slot(agp->host_groups, hgp, j) {
137                                 while (VECTOR_SIZE(hgp->paths) > 0) {
138                                         pp = VECTOR_SLOT(hgp->paths, 0);
139                                         if (store_path(pgp->paths, pp))
140                                                 condlog(3, "failed to restore "
141                                                 "path %s into path group",
142                                                  pp->dev);
143                                         vector_del_slot(hgp->paths, 0);
144                                 }
145                         }
146                 }
147         free_adaptergroup(adapters);
148         return 1;
149 }
150
151 /* re-order paths in pg by alternating adapters and host ports
152  * for optimized selection
153  */
154 int order_paths_in_pg_by_alt_adapters(struct pathgroup *pgp, vector adapters,
155                  int total_paths)
156 {
157         int next_adapter_index = 0;
158         struct adapter_group *agp;
159         struct host_group *hgp;
160         struct path *pp;
161
162         while (total_paths > 0) {
163                 agp = VECTOR_SLOT(adapters, next_adapter_index);
164                 if (!agp) {
165                         condlog(0, "can't get adapter group %d", next_adapter_index);
166                         return 1;
167                 }
168
169                 hgp = VECTOR_SLOT(agp->host_groups, agp->next_host_index);
170                 if (!hgp) {
171                         condlog(0, "can't get host group %d of adapter group %d", next_adapter_index, agp->next_host_index);
172                         return 1;
173                 }
174
175                 if (!hgp->num_paths) {
176                         agp->next_host_index++;
177                         agp->next_host_index %= agp->num_hosts;
178                         next_adapter_index++;
179                         next_adapter_index %= VECTOR_SIZE(adapters);
180                         continue;
181                 }
182
183                 pp  = VECTOR_SLOT(hgp->paths, 0);
184
185                 if (store_path(pgp->paths, pp))
186                         return 1;
187
188                 total_paths--;
189
190                 vector_del_slot(hgp->paths, 0);
191
192                 hgp->num_paths--;
193
194                 agp->next_host_index++;
195                 agp->next_host_index %= agp->num_hosts;
196                 next_adapter_index++;
197                 next_adapter_index %= VECTOR_SIZE(adapters);
198         }
199
200         /* all paths are added into path_group
201          * in crafted child order
202          */
203         return 0;
204 }
205
206 /* round-robin: order paths in path group to alternate
207  * between all host adapters
208  */
209 int rr_optimize_path_order(struct pathgroup *pgp)
210 {
211         vector adapters;
212         struct path *pp;
213         int total_paths;
214         int i;
215
216         total_paths = VECTOR_SIZE(pgp->paths);
217         vector_foreach_slot(pgp->paths, pp, i) {
218                 if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP &&
219                         pp->sg_id.proto_id != SCSI_PROTOCOL_SAS &&
220                         pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI &&
221                         pp->sg_id.proto_id != SCSI_PROTOCOL_SRP) {
222                         /* return success as default path order
223                          * is maintained in path group
224                          */
225                         return 0;
226                 }
227         }
228         adapters = vector_alloc();
229         if (!adapters)
230                 return 0;
231
232         /* group paths in path group by host adapters
233          */
234         if (group_by_host_adapter(pgp, adapters)) {
235                 /* already freed adapters */
236                 condlog(3, "Failed to group paths by adapters");
237                 return 0;
238         }
239
240         /* re-order paths in pg to alternate between adapters and host ports
241          */
242         if (order_paths_in_pg_by_alt_adapters(pgp, adapters, total_paths)) {
243                 condlog(3, "Failed to re-order paths in pg by adapters "
244                         "and host ports");
245                 free_adaptergroup(adapters);
246                 /* return failure as original paths are
247                  * removed form pgp
248                  */
249                 return 1;
250         }
251
252         free_adaptergroup(adapters);
253         return 0;
254 }
255
256 extern int
257 setup_map (struct multipath * mpp, char * params, int params_size)
258 {
259         struct pathgroup * pgp;
260         struct config *conf;
261         int i;
262
263         /*
264          * don't bother if devmap size is unknown
265          */
266         if (mpp->size <= 0) {
267                 condlog(3, "%s: devmap size is unknown", mpp->alias);
268                 return 1;
269         }
270
271         /*
272          * free features, selector, and hwhandler properties if they are being reused
273          */
274         free_multipath_attributes(mpp);
275
276         /*
277          * properties selectors
278          */
279         conf = get_multipath_config();
280         select_pgfailback(conf, mpp);
281         select_pgpolicy(conf, mpp);
282         select_selector(conf, mpp);
283         select_features(conf, mpp);
284         select_hwhandler(conf, mpp);
285         select_rr_weight(conf, mpp);
286         select_minio(conf, mpp);
287         select_no_path_retry(conf, mpp);
288         select_mode(conf, mpp);
289         select_uid(conf, mpp);
290         select_gid(conf, mpp);
291         select_fast_io_fail(conf, mpp);
292         select_dev_loss(conf, mpp);
293         select_reservation_key(conf, mpp);
294         select_retain_hwhandler(conf, mpp);
295         select_deferred_remove(conf, mpp);
296         select_delay_watch_checks(conf, mpp);
297         select_delay_wait_checks(conf, mpp);
298
299         sysfs_set_scsi_tmo(mpp, conf->checkint);
300         put_multipath_config(conf);
301         /*
302          * assign paths to path groups -- start with no groups and all paths
303          * in mpp->paths
304          */
305         if (mpp->pg) {
306                 vector_foreach_slot (mpp->pg, pgp, i)
307                         free_pathgroup(pgp, KEEP_PATHS);
308
309                 vector_free(mpp->pg);
310                 mpp->pg = NULL;
311         }
312         if (mpp->pgpolicyfn && mpp->pgpolicyfn(mpp))
313                 return 1;
314
315         mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
316
317         /*
318          * ponders each path group and determine highest prio pg
319          * to switch over (default to first)
320          */
321         mpp->bestpg = select_path_group(mpp);
322
323         /* re-order paths in all path groups in an optimized way
324          * for round-robin path selectors to get maximum throughput.
325          */
326         if (!strncmp(mpp->selector, "round-robin", 11)) {
327                 vector_foreach_slot(mpp->pg, pgp, i) {
328                         if (VECTOR_SIZE(pgp->paths) <= 2)
329                                 continue;
330                         if (rr_optimize_path_order(pgp)) {
331                                 condlog(2, "cannot re-order paths for "
332                                         "optimization: %s",
333                                         mpp->alias);
334                                 return 1;
335                         }
336                 }
337         }
338
339         /*
340          * transform the mp->pg vector of vectors of paths
341          * into a mp->params strings to feed the device-mapper
342          */
343         if (assemble_map(mpp, params, params_size)) {
344                 condlog(0, "%s: problem assembing map", mpp->alias);
345                 return 1;
346         }
347         return 0;
348 }
349
350 static void
351 compute_pgid(struct pathgroup * pgp)
352 {
353         struct path * pp;
354         int i;
355
356         vector_foreach_slot (pgp->paths, pp, i)
357                 pgp->id ^= (long)pp;
358 }
359
360 static int
361 pgcmp (struct multipath * mpp, struct multipath * cmpp)
362 {
363         int i, j;
364         struct pathgroup * pgp;
365         struct pathgroup * cpgp;
366         int r = 0;
367
368         if (!mpp)
369                 return 0;
370
371         vector_foreach_slot (mpp->pg, pgp, i) {
372                 compute_pgid(pgp);
373
374                 vector_foreach_slot (cmpp->pg, cpgp, j) {
375                         if (pgp->id == cpgp->id &&
376                             !pathcmp(pgp, cpgp)) {
377                                 r = 0;
378                                 break;
379                         }
380                         r++;
381                 }
382                 if (r)
383                         return r;
384         }
385         return r;
386 }
387
388 static void
389 select_action (struct multipath * mpp, vector curmp, int force_reload)
390 {
391         struct multipath * cmpp;
392         struct multipath * cmpp_by_name;
393
394         cmpp = find_mp_by_wwid(curmp, mpp->wwid);
395         cmpp_by_name = find_mp_by_alias(curmp, mpp->alias);
396
397         if (!cmpp_by_name) {
398                 if (cmpp) {
399                         condlog(2, "%s: rename %s to %s", mpp->wwid,
400                                 cmpp->alias, mpp->alias);
401                         strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE - 1);
402                         mpp->action = ACT_RENAME;
403                         if (force_reload)
404                                 mpp->action = ACT_FORCERENAME;
405                         return;
406                 }
407                 mpp->action = ACT_CREATE;
408                 condlog(3, "%s: set ACT_CREATE (map does not exist)",
409                         mpp->alias);
410                 return;
411         }
412
413         if (!cmpp) {
414                 condlog(2, "%s: remove (wwid changed)", mpp->alias);
415                 dm_flush_map(mpp->alias);
416                 strncpy(cmpp_by_name->wwid, mpp->wwid, WWID_SIZE - 1);
417                 drop_multipath(curmp, cmpp_by_name->wwid, KEEP_PATHS);
418                 mpp->action = ACT_CREATE;
419                 condlog(3, "%s: set ACT_CREATE (map wwid change)",
420                         mpp->alias);
421                 return;
422         }
423
424         if (cmpp != cmpp_by_name) {
425                 condlog(2, "%s: unable to rename %s to %s (%s is used by %s)",
426                         mpp->wwid, cmpp->alias, mpp->alias,
427                         mpp->alias, cmpp_by_name->wwid);
428                 /* reset alias to existing alias */
429                 FREE(mpp->alias);
430                 mpp->alias = STRDUP(cmpp->alias);
431                 mpp->action = ACT_NOTHING;
432                 return;
433         }
434
435         if (pathcount(mpp, PATH_UP) == 0) {
436                 mpp->action = ACT_NOTHING;
437                 condlog(3, "%s: set ACT_NOTHING (no usable path)",
438                         mpp->alias);
439                 return;
440         }
441         if (force_reload) {
442                 mpp->action = ACT_RELOAD;
443                 condlog(3, "%s: set ACT_RELOAD (forced by user)",
444                         mpp->alias);
445                 return;
446         }
447         if (cmpp->size != mpp->size) {
448                 mpp->action = ACT_RESIZE;
449                 condlog(3, "%s: set ACT_RESIZE (size change)",
450                         mpp->alias);
451                 return;
452         }
453         if (!mpp->no_path_retry &&
454             (strlen(cmpp->features) != strlen(mpp->features) ||
455              strcmp(cmpp->features, mpp->features))) {
456                 mpp->action =  ACT_RELOAD;
457                 condlog(3, "%s: set ACT_RELOAD (features change)",
458                         mpp->alias);
459                 return;
460         }
461         if (mpp->retain_hwhandler != RETAIN_HWHANDLER_ON &&
462             (strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) ||
463              strncmp(cmpp->hwhandler, mpp->hwhandler,
464                     strlen(mpp->hwhandler)))) {
465                 mpp->action = ACT_RELOAD;
466                 condlog(3, "%s: set ACT_RELOAD (hwhandler change)",
467                         mpp->alias);
468                 return;
469         }
470         if (!cmpp->selector || strncmp(cmpp->selector, mpp->selector,
471                     strlen(mpp->selector))) {
472                 mpp->action = ACT_RELOAD;
473                 condlog(3, "%s: set ACT_RELOAD (selector change)",
474                         mpp->alias);
475                 return;
476         }
477         if (cmpp->minio != mpp->minio) {
478                 mpp->action = ACT_RELOAD;
479                 condlog(3, "%s: set ACT_RELOAD (minio change, %u->%u)",
480                         mpp->alias, cmpp->minio, mpp->minio);
481                 return;
482         }
483         if (!cmpp->pg || VECTOR_SIZE(cmpp->pg) != VECTOR_SIZE(mpp->pg)) {
484                 mpp->action = ACT_RELOAD;
485                 condlog(3, "%s: set ACT_RELOAD (path group number change)",
486                         mpp->alias);
487                 return;
488         }
489         if (pgcmp(mpp, cmpp)) {
490                 mpp->action = ACT_RELOAD;
491                 condlog(3, "%s: set ACT_RELOAD (path group topology change)",
492                         mpp->alias);
493                 return;
494         }
495         if (cmpp->nextpg != mpp->bestpg) {
496                 mpp->action = ACT_SWITCHPG;
497                 condlog(3, "%s: set ACT_SWITCHPG (next path group change)",
498                         mpp->alias);
499                 return;
500         }
501         mpp->action = ACT_NOTHING;
502         condlog(3, "%s: set ACT_NOTHING (map unchanged)",
503                 mpp->alias);
504         return;
505 }
506
507 extern int
508 reinstate_paths (struct multipath * mpp)
509 {
510         int i, j;
511         struct pathgroup * pgp;
512         struct path * pp;
513
514         if (!mpp->pg)
515                 return 0;
516
517         vector_foreach_slot (mpp->pg, pgp, i) {
518                 if (!pgp->paths)
519                         continue;
520
521                 vector_foreach_slot (pgp->paths, pp, j) {
522                         if (pp->state != PATH_UP &&
523                             (pgp->status == PGSTATE_DISABLED ||
524                              pgp->status == PGSTATE_ACTIVE))
525                                 continue;
526
527                         if (pp->dmstate == PSTATE_FAILED) {
528                                 if (dm_reinstate_path(mpp->alias, pp->dev_t))
529                                         condlog(0, "%s: error reinstating",
530                                                 pp->dev);
531                         }
532                 }
533         }
534         return 0;
535 }
536
537 static int
538 lock_multipath (struct multipath * mpp, int lock)
539 {
540         struct pathgroup * pgp;
541         struct path * pp;
542         int i, j;
543         int x, y;
544
545         if (!mpp || !mpp->pg)
546                 return 0;
547
548         vector_foreach_slot (mpp->pg, pgp, i) {
549                 if (!pgp->paths)
550                         continue;
551                 vector_foreach_slot(pgp->paths, pp, j) {
552                         if (lock && flock(pp->fd, LOCK_SH | LOCK_NB) &&
553                             errno == EWOULDBLOCK)
554                                 goto fail;
555                         else if (!lock)
556                                 flock(pp->fd, LOCK_UN);
557                 }
558         }
559         return 0;
560 fail:
561         vector_foreach_slot (mpp->pg, pgp, x) {
562                 if (x > i)
563                         return 1;
564                 if (!pgp->paths)
565                         continue;
566                 vector_foreach_slot(pgp->paths, pp, y) {
567                         if (x == i && y >= j)
568                                 return 1;
569                         flock(pp->fd, LOCK_UN);
570                 }
571         }
572         return 1;
573 }
574
575 /*
576  * Return value:
577  */
578 #define DOMAP_RETRY     -1
579 #define DOMAP_FAIL      0
580 #define DOMAP_OK        1
581 #define DOMAP_EXIST     2
582 #define DOMAP_DRY       3
583
584 extern int
585 domap (struct multipath * mpp, char * params, int is_daemon)
586 {
587         int r = DOMAP_FAIL;
588         struct config *conf;
589
590         /*
591          * last chance to quit before touching the devmaps
592          */
593         if (mpp->action == ACT_DRY_RUN) {
594                 conf = get_multipath_config();
595                 print_multipath_topology(mpp, conf->verbosity);
596                 put_multipath_config(conf);
597                 return DOMAP_DRY;
598         }
599
600         if (mpp->action == ACT_CREATE &&
601             dm_map_present(mpp->alias)) {
602                 condlog(3, "%s: map already present", mpp->alias);
603                 mpp->action = ACT_RELOAD;
604         }
605
606         switch (mpp->action) {
607         case ACT_REJECT:
608         case ACT_NOTHING:
609                 return DOMAP_EXIST;
610
611         case ACT_SWITCHPG:
612                 dm_switchgroup(mpp->alias, mpp->bestpg);
613                 /*
614                  * we may have avoided reinstating paths because there where in
615                  * active or disabled PG. Now that the topology has changed,
616                  * retry.
617                  */
618                 reinstate_paths(mpp);
619                 return DOMAP_EXIST;
620
621         case ACT_CREATE:
622                 if (lock_multipath(mpp, 1)) {
623                         condlog(3, "%s: failed to create map (in use)",
624                                 mpp->alias);
625                         return DOMAP_RETRY;
626                 }
627
628                 r = dm_addmap_create(mpp, params);
629
630                 lock_multipath(mpp, 0);
631                 break;
632
633         case ACT_RELOAD:
634                 r = dm_addmap_reload(mpp, params, 0);
635                 break;
636
637         case ACT_RESIZE:
638                 r = dm_addmap_reload(mpp, params, 1);
639                 break;
640
641         case ACT_RENAME:
642                 conf = get_multipath_config();
643                 r = dm_rename(mpp->alias_old, mpp->alias,
644                               conf->partition_delim);
645                 put_multipath_config(conf);
646                 break;
647
648         case ACT_FORCERENAME:
649                 conf = get_multipath_config();
650                 r = dm_rename(mpp->alias_old, mpp->alias,
651                               conf->partition_delim);
652                 put_multipath_config(conf);
653                 if (r)
654                         r = dm_addmap_reload(mpp, params, 0);
655                 break;
656
657         default:
658                 break;
659         }
660
661         if (r == DOMAP_OK) {
662                 /*
663                  * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
664                  * succeeded
665                  */
666                 if (mpp->action == ACT_CREATE)
667                         remember_wwid(mpp->wwid);
668                 if (!is_daemon) {
669                         /* multipath client mode */
670                         dm_switchgroup(mpp->alias, mpp->bestpg);
671                 } else  {
672                         /* multipath daemon mode */
673                         mpp->stat_map_loads++;
674                         condlog(2, "%s: load table [0 %llu %s %s]", mpp->alias,
675                                 mpp->size, TGT_MPATH, params);
676                         /*
677                          * Required action is over, reset for the stateful daemon.
678                          * But don't do it for creation as we use in the caller the
679                          * mpp->action to figure out whether to start the watievent checker.
680                          */
681                         if (mpp->action != ACT_CREATE)
682                                 mpp->action = ACT_NOTHING;
683                         else {
684                                 conf = get_multipath_config();
685                                 mpp->wait_for_udev = 1;
686                                 mpp->uev_wait_tick = conf->uev_wait_timeout;
687                                 put_multipath_config(conf);
688                         }
689                 }
690                 dm_setgeometry(mpp);
691                 return DOMAP_OK;
692         }
693         return DOMAP_FAIL;
694 }
695
696 static int
697 deadmap (struct multipath * mpp)
698 {
699         int i, j;
700         struct pathgroup * pgp;
701         struct path * pp;
702
703         if (!mpp->pg)
704                 return 1;
705
706         vector_foreach_slot (mpp->pg, pgp, i) {
707                 if (!pgp->paths)
708                         continue;
709
710                 vector_foreach_slot (pgp->paths, pp, j)
711                         if (strlen(pp->dev))
712                                 return 0; /* alive */
713         }
714
715         return 1; /* dead */
716 }
717
718 int check_daemon(void)
719 {
720         int fd;
721         char *reply;
722         int ret = 0;
723         unsigned int timeout;
724         struct config *conf;
725
726         fd = mpath_connect();
727         if (fd == -1)
728                 return 0;
729
730         if (send_packet(fd, "show daemon") != 0)
731                 goto out;
732         conf = get_multipath_config();
733         timeout = conf->uxsock_timeout;
734         put_multipath_config(conf);
735         if (recv_packet(fd, &reply, timeout) != 0)
736                 goto out;
737
738         if (strstr(reply, "shutdown"))
739                 goto out_free;
740
741         ret = 1;
742
743 out_free:
744         FREE(reply);
745 out:
746         mpath_disconnect(fd);
747         return ret;
748 }
749
750 extern int
751 coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_reload, enum mpath_cmds cmd)
752 {
753         int r = 1;
754         int k, i;
755         int is_daemon = (cmd == CMD_NONE) ? 1 : 0;
756         char params[PARAMS_SIZE];
757         struct multipath * mpp;
758         struct path * pp1;
759         struct path * pp2;
760         vector curmp = vecs->mpvec;
761         vector pathvec = vecs->pathvec;
762         struct config *conf;
763         int allow_queueing;
764
765         /* ignore refwwid if it's empty */
766         if (refwwid && !strlen(refwwid))
767                 refwwid = NULL;
768
769         if (force_reload) {
770                 vector_foreach_slot (pathvec, pp1, k) {
771                         pp1->mpp = NULL;
772                 }
773         }
774         vector_foreach_slot (pathvec, pp1, k) {
775                 /* skip this path for some reason */
776
777                 /* 1. if path has no unique id or wwid blacklisted */
778                 conf = get_multipath_config();
779                 if (strlen(pp1->wwid) == 0 ||
780                     filter_path(conf, pp1) > 0) {
781                         put_multipath_config(conf);
782                         orphan_path(pp1, "wwid blacklisted");
783                         continue;
784                 }
785                 put_multipath_config(conf);
786
787                 /* 2. if path already coalesced */
788                 if (pp1->mpp)
789                         continue;
790
791                 /* 3. if path has disappeared */
792                 if (pp1->state == PATH_REMOVED) {
793                         orphan_path(pp1, "path removed");
794                         continue;
795                 }
796
797                 /* 4. path is out of scope */
798                 if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE - 1))
799                         continue;
800
801                 /* If find_multipaths was selected check if the path is valid */
802                 if (!refwwid && !should_multipath(pp1, pathvec)) {
803                         orphan_path(pp1, "only one path");
804                         continue;
805                 }
806
807                 /*
808                  * at this point, we know we really got a new mp
809                  */
810                 mpp = add_map_with_path(vecs, pp1, 0);
811                 if (!mpp)
812                         return 1;
813
814                 if (pp1->priority == PRIO_UNDEF)
815                         mpp->action = ACT_REJECT;
816
817                 if (!mpp->paths) {
818                         condlog(0, "%s: skip coalesce (no paths)", mpp->alias);
819                         remove_map(mpp, vecs, 0);
820                         continue;
821                 }
822
823                 for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
824                         pp2 = VECTOR_SLOT(pathvec, i);
825
826                         if (strcmp(pp1->wwid, pp2->wwid))
827                                 continue;
828
829                         if (!mpp->size && pp2->size)
830                                 mpp->size = pp2->size;
831
832                         if (mpp->size && pp2->size &&
833                             pp2->size != mpp->size) {
834                                 /*
835                                  * ouch, avoid feeding that to the DM
836                                  */
837                                 condlog(0, "%s: size %llu, expected %llu. "
838                                         "Discard", pp2->dev_t, pp2->size,
839                                         mpp->size);
840                                 mpp->action = ACT_REJECT;
841                         }
842                         if (pp2->priority == PRIO_UNDEF)
843                                 mpp->action = ACT_REJECT;
844                 }
845                 verify_paths(mpp, vecs);
846
847                 params[0] = '\0';
848                 if (setup_map(mpp, params, PARAMS_SIZE)) {
849                         remove_map(mpp, vecs, 0);
850                         continue;
851                 }
852
853                 if (cmd == CMD_DRY_RUN)
854                         mpp->action = ACT_DRY_RUN;
855                 if (mpp->action == ACT_UNDEF)
856                         select_action(mpp, curmp, force_reload);
857
858                 r = domap(mpp, params, is_daemon);
859
860                 if (r == DOMAP_FAIL || r == DOMAP_RETRY) {
861                         condlog(3, "%s: domap (%u) failure "
862                                    "for create/reload map",
863                                 mpp->alias, r);
864                         if (r == DOMAP_FAIL) {
865                                 condlog(2, "%s: %s map",
866                                         mpp->alias, (mpp->action == ACT_CREATE)?
867                                         "ignoring" : "removing");
868                                 remove_map(mpp, vecs, 0);
869                                 continue;
870                         } else /* if (r == DOMAP_RETRY) */
871                                 return r;
872                 }
873                 if (r == DOMAP_DRY)
874                         continue;
875
876                 conf = get_multipath_config();
877                 allow_queueing = conf->allow_queueing;
878                 put_multipath_config(conf);
879                 if (!is_daemon && !allow_queueing && !check_daemon()) {
880                         if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
881                             mpp->no_path_retry != NO_PATH_RETRY_FAIL)
882                                 condlog(3, "%s: multipathd not running, unset "
883                                         "queue_if_no_path feature", mpp->alias);
884                         if (!dm_queue_if_no_path(mpp->alias, 0))
885                                 remove_feature(&mpp->features,
886                                                "queue_if_no_path");
887                 }
888                 else if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
889                         if (mpp->no_path_retry == NO_PATH_RETRY_FAIL) {
890                                 condlog(3, "%s: unset queue_if_no_path feature",
891                                         mpp->alias);
892                                 if (!dm_queue_if_no_path(mpp->alias, 0))
893                                         remove_feature(&mpp->features,
894                                                        "queue_if_no_path");
895                         } else {
896                                 condlog(3, "%s: set queue_if_no_path feature",
897                                         mpp->alias);
898                                 if (!dm_queue_if_no_path(mpp->alias, 1))
899                                         add_feature(&mpp->features,
900                                                     "queue_if_no_path");
901                         }
902                 }
903
904                 if (!is_daemon && mpp->action != ACT_NOTHING) {
905                         conf = get_multipath_config();
906                         print_multipath_topology(mpp, conf->verbosity);
907                         put_multipath_config(conf);
908                 }
909
910                 if (newmp) {
911                         if (mpp->action != ACT_REJECT) {
912                                 if (!vector_alloc_slot(newmp))
913                                         return 1;
914                                 vector_set_slot(newmp, mpp);
915                         }
916                         else
917                                 remove_map(mpp, vecs, 0);
918                 }
919         }
920         /*
921          * Flush maps with only dead paths (ie not in sysfs)
922          * Keep maps with only failed paths
923          */
924         if (newmp) {
925                 vector_foreach_slot (newmp, mpp, i) {
926                         char alias[WWID_SIZE];
927
928                         if (!deadmap(mpp))
929                                 continue;
930
931                         strncpy(alias, mpp->alias, WWID_SIZE - 1);
932
933                         vector_del_slot(newmp, i);
934                         i--;
935                         remove_map(mpp, vecs, 0);
936
937                         if (dm_flush_map(alias))
938                                 condlog(2, "%s: remove failed (dead)",
939                                         alias);
940                         else
941                                 condlog(2, "%s: remove (dead)", alias);
942                 }
943         }
944         return 0;
945 }
946
947 /*
948  * returns:
949  * 0 - success
950  * 1 - failure
951  * 2 - blacklist
952  */
953 extern int
954 get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type,
955              vector pathvec, char **wwid)
956 {
957         int ret = 1;
958         struct path * pp;
959         char buff[FILE_NAME_SIZE];
960         char * refwwid = NULL, tmpwwid[WWID_SIZE];
961         int flags = DI_SYSFS | DI_WWID;
962         struct config *conf;
963
964         if (!wwid)
965                 return 1;
966         *wwid = NULL;
967
968         if (dev_type == DEV_NONE)
969                 return 1;
970
971         if (cmd != CMD_REMOVE_WWID)
972                 flags |= DI_BLACKLIST;
973
974         if (dev_type == DEV_DEVNODE) {
975                 if (basenamecpy(dev, buff, FILE_NAME_SIZE) == 0) {
976                         condlog(1, "basename failed for '%s' (%s)",
977                                 dev, buff);
978                         return 1;
979                 }
980
981                 pp = find_path_by_dev(pathvec, buff);
982                 if (!pp) {
983                         struct udev_device *udevice = udev_device_new_from_subsystem_sysname(udev, "block", buff);
984
985                         if (!udevice) {
986                                 condlog(2, "%s: can't get udev device", buff);
987                                 return 1;
988                         }
989                         conf = get_multipath_config();
990                         ret = store_pathinfo(pathvec, conf, udevice,
991                                              flags, &pp);
992                         put_multipath_config(conf);
993                         udev_device_unref(udevice);
994                         if (!pp) {
995                                 if (ret == 1)
996                                         condlog(0, "%s: can't store path info",
997                                                 dev);
998                                 return ret;
999                         }
1000                 }
1001                 conf = get_multipath_config();
1002                 if (pp->udev && pp->uid_attribute &&
1003                     filter_property(conf, pp->udev) > 0) {
1004                         put_multipath_config(conf);
1005                         return 2;
1006                 }
1007                 put_multipath_config(conf);
1008
1009                 refwwid = pp->wwid;
1010                 goto out;
1011         }
1012
1013         if (dev_type == DEV_DEVT) {
1014                 strchop(dev);
1015                 if (devt2devname(buff, FILE_NAME_SIZE, dev)) {
1016                         condlog(0, "%s: cannot find block device\n", dev);
1017                         return 1;
1018                 }
1019                 pp = find_path_by_dev(pathvec, buff);
1020                 if (!pp) {
1021                         struct udev_device *udevice = udev_device_new_from_devnum(udev, 'b', parse_devt(dev));
1022
1023                         if (!udevice) {
1024                                 condlog(2, "%s: can't get udev device", dev);
1025                                 return 1;
1026                         }
1027                         conf = get_multipath_config();
1028                         ret = store_pathinfo(pathvec, conf, udevice,
1029                                              flags, &pp);
1030                         put_multipath_config(conf);
1031                         udev_device_unref(udevice);
1032                         if (!pp) {
1033                                 if (ret == 1)
1034                                         condlog(0, "%s can't store path info",
1035                                                 buff);
1036                                 return ret;
1037                         }
1038                 }
1039                 conf = get_multipath_config();
1040                 if (pp->udev && pp->uid_attribute &&
1041                     filter_property(conf, pp->udev) > 0) {
1042                         put_multipath_config(conf);
1043                         return 2;
1044                 }
1045                 put_multipath_config(conf);
1046                 refwwid = pp->wwid;
1047                 goto out;
1048         }
1049
1050         if (dev_type == DEV_UEVENT) {
1051                 struct udev_device *udevice = udev_device_new_from_environment(udev);
1052
1053                 if (!udevice) {
1054                         condlog(2, "%s: can't get udev device", dev);
1055                         return 1;
1056                 }
1057                 conf = get_multipath_config();
1058                 ret = store_pathinfo(pathvec, conf, udevice,
1059                                      flags, &pp);
1060                 udev_device_unref(udevice);
1061                 if (!pp) {
1062                         if (ret == 1)
1063                                 condlog(0, "%s: can't store path info",
1064                                         dev);
1065                         put_multipath_config(conf);
1066                         return ret;
1067                 }
1068                 if (pp->udev && pp->uid_attribute &&
1069                     filter_property(conf, pp->udev) > 0) {
1070                         put_multipath_config(conf);
1071                         return 2;
1072                 }
1073                 put_multipath_config(conf);
1074                 refwwid = pp->wwid;
1075                 goto out;
1076         }
1077
1078         if (dev_type == DEV_DEVMAP) {
1079
1080                 conf = get_multipath_config();
1081                 if (((dm_get_uuid(dev, tmpwwid)) == 0) && (strlen(tmpwwid))) {
1082                         refwwid = tmpwwid;
1083                         goto check;
1084                 }
1085
1086                 /*
1087                  * may be a binding
1088                  */
1089                 if (get_user_friendly_wwid(dev, tmpwwid,
1090                                            conf->bindings_file) == 0) {
1091                         refwwid = tmpwwid;
1092                         put_multipath_config(conf);
1093                         goto check;
1094                 }
1095
1096                 /*
1097                  * or may be an alias
1098                  */
1099                 refwwid = get_mpe_wwid(conf->mptable, dev);
1100
1101                 /*
1102                  * or directly a wwid
1103                  */
1104                 if (!refwwid)
1105                         refwwid = dev;
1106
1107 check:
1108                 if (refwwid && strlen(refwwid)) {
1109                         if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
1110                                         refwwid, NULL) > 0) {
1111                                 put_multipath_config(conf);
1112                                 return 2;
1113                         }
1114                 }
1115                 put_multipath_config(conf);
1116         }
1117 out:
1118         if (refwwid && strlen(refwwid)) {
1119                 *wwid = STRDUP(refwwid);
1120                 return 0;
1121         }
1122
1123         return 1;
1124 }
1125
1126 extern int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon)
1127 {
1128         char params[PARAMS_SIZE] = {0};
1129         struct path *pp;
1130         int i, r;
1131
1132         update_mpp_paths(mpp, vecs->pathvec);
1133         if (refresh) {
1134                 vector_foreach_slot (mpp->paths, pp, i) {
1135                         struct config *conf = get_multipath_config();
1136                         r = pathinfo(pp, conf, DI_PRIO);
1137                         put_multipath_config(conf);
1138                         if (r) {
1139                                 condlog(2, "%s: failed to refresh pathinfo",
1140                                         mpp->alias);
1141                                 return 1;
1142                         }
1143                 }
1144         }
1145         if (setup_map(mpp, params, PARAMS_SIZE)) {
1146                 condlog(0, "%s: failed to setup map", mpp->alias);
1147                 return 1;
1148         }
1149         select_action(mpp, vecs->mpvec, 1);
1150
1151         r = domap(mpp, params, is_daemon);
1152         if (r == DOMAP_FAIL || r == DOMAP_RETRY) {
1153                 condlog(3, "%s: domap (%u) failure "
1154                         "for reload map", mpp->alias, r);
1155                 return 1;
1156         }
1157         if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
1158                 if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
1159                         dm_queue_if_no_path(mpp->alias, 0);
1160                 else
1161                         dm_queue_if_no_path(mpp->alias, 1);
1162         }
1163
1164         return 0;
1165 }