Add libmpathcmd library and use it internally
[multipath-tools/.git] / multipathd / main.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Kiyoshi Ueda, NEC
4  * Copyright (c) 2005 Benjamin Marzinski, Redhat
5  * Copyright (c) 2005 Edward Goggin, EMC
6  */
7 #include <unistd.h>
8 #include <sys/stat.h>
9 #include <libdevmapper.h>
10 #include <wait.h>
11 #include <sys/mman.h>
12 #include <sys/types.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 #include <sys/time.h>
16 #include <sys/resource.h>
17 #include <limits.h>
18 #include <linux/oom.h>
19 #include <libudev.h>
20 #ifdef USE_SYSTEMD
21 #include <systemd/sd-daemon.h>
22 #endif
23 #include <semaphore.h>
24 #include <mpath_cmd.h>
25 #include <mpath_persist.h>
26 #include <time.h>
27
28 /*
29  * libcheckers
30  */
31 #include <checkers.h>
32
33 #ifdef USE_SYSTEMD
34 static int use_watchdog;
35 #endif
36
37 /*
38  * libmultipath
39  */
40 #include <parser.h>
41 #include <vector.h>
42 #include <memory.h>
43 #include <config.h>
44 #include <util.h>
45 #include <hwtable.h>
46 #include <defaults.h>
47 #include <structs.h>
48 #include <blacklist.h>
49 #include <structs_vec.h>
50 #include <dmparser.h>
51 #include <devmapper.h>
52 #include <sysfs.h>
53 #include <dict.h>
54 #include <discovery.h>
55 #include <debug.h>
56 #include <propsel.h>
57 #include <uevent.h>
58 #include <switchgroup.h>
59 #include <print.h>
60 #include <configure.h>
61 #include <prio.h>
62 #include <wwids.h>
63 #include <pgpolicies.h>
64 #include <uevent.h>
65 #include <log.h>
66 #include "prioritizers/alua_rtpg.h"
67
68 #include "main.h"
69 #include "pidfile.h"
70 #include "uxlsnr.h"
71 #include "uxclnt.h"
72 #include "cli.h"
73 #include "cli_handlers.h"
74 #include "lock.h"
75 #include "waiter.h"
76 #include "wwids.h"
77
78 #define FILE_NAME_SIZE 256
79 #define CMDSIZE 160
80
81 #define LOG_MSG(a, b) \
82 do { \
83         if (pp->offline) \
84                 condlog(a, "%s: %s - path offline", pp->mpp->alias, pp->dev); \
85         else if (strlen(b)) \
86                 condlog(a, "%s: %s - %s", pp->mpp->alias, pp->dev, b); \
87 } while(0)
88
89 struct mpath_event_param
90 {
91         char * devname;
92         struct multipath *mpp;
93 };
94
95 unsigned int mpath_mx_alloc_len;
96
97 int logsink;
98 enum daemon_status running_state;
99 pid_t daemon_pid;
100
101 static sem_t exit_sem;
102 /*
103  * global copy of vecs for use in sig handlers
104  */
105 struct vectors * gvecs;
106
107 struct udev * udev;
108
109 static int
110 need_switch_pathgroup (struct multipath * mpp, int refresh)
111 {
112         struct pathgroup * pgp;
113         struct path * pp;
114         unsigned int i, j;
115
116         if (!mpp || mpp->pgfailback == -FAILBACK_MANUAL)
117                 return 0;
118
119         /*
120          * Refresh path priority values
121          */
122         if (refresh)
123                 vector_foreach_slot (mpp->pg, pgp, i)
124                         vector_foreach_slot (pgp->paths, pp, j)
125                                 pathinfo(pp, conf->hwtable, DI_PRIO);
126
127         mpp->bestpg = select_path_group(mpp);
128
129         if (mpp->bestpg != mpp->nextpg)
130                 return 1;
131
132         return 0;
133 }
134
135 static void
136 switch_pathgroup (struct multipath * mpp)
137 {
138         mpp->stat_switchgroup++;
139         dm_switchgroup(mpp->alias, mpp->bestpg);
140         condlog(2, "%s: switch to path group #%i",
141                  mpp->alias, mpp->bestpg);
142 }
143
144 static int
145 coalesce_maps(struct vectors *vecs, vector nmpv)
146 {
147         struct multipath * ompp;
148         vector ompv = vecs->mpvec;
149         unsigned int i;
150
151         vector_foreach_slot (ompv, ompp, i) {
152                 condlog(3, "%s: coalesce map", ompp->alias);
153                 if (!find_mp_by_wwid(nmpv, ompp->wwid)) {
154                         /*
155                          * remove all current maps not allowed by the
156                          * current configuration
157                          */
158                         if (dm_flush_map(ompp->alias)) {
159                                 condlog(0, "%s: unable to flush devmap",
160                                         ompp->alias);
161                                 /*
162                                  * may be just because the device is open
163                                  */
164                                 if (setup_multipath(vecs, ompp) != 0) {
165                                         i--;
166                                         continue;
167                                 }
168                                 if (!vector_alloc_slot(nmpv))
169                                         return 1;
170
171                                 vector_set_slot(nmpv, ompp);
172
173                                 vector_del_slot(ompv, i);
174                                 i--;
175                         }
176                         else {
177                                 dm_lib_release();
178                                 condlog(2, "%s devmap removed", ompp->alias);
179                         }
180                 } else if (conf->reassign_maps) {
181                         condlog(3, "%s: Reassign existing device-mapper"
182                                 " devices", ompp->alias);
183                         dm_reassign(ompp->alias);
184                 }
185         }
186         return 0;
187 }
188
189 void
190 sync_map_state(struct multipath *mpp)
191 {
192         struct pathgroup *pgp;
193         struct path *pp;
194         unsigned int i, j;
195
196         if (!mpp->pg)
197                 return;
198
199         vector_foreach_slot (mpp->pg, pgp, i){
200                 vector_foreach_slot (pgp->paths, pp, j){
201                         if (pp->state == PATH_UNCHECKED || 
202                             pp->state == PATH_WILD ||
203                             pp->state == PATH_DELAYED)
204                                 continue;
205                         if ((pp->dmstate == PSTATE_FAILED ||
206                              pp->dmstate == PSTATE_UNDEF) &&
207                             (pp->state == PATH_UP || pp->state == PATH_GHOST))
208                                 dm_reinstate_path(mpp->alias, pp->dev_t);
209                         else if ((pp->dmstate == PSTATE_ACTIVE ||
210                                   pp->dmstate == PSTATE_UNDEF) &&
211                                  (pp->state == PATH_DOWN ||
212                                   pp->state == PATH_SHAKY))
213                                 dm_fail_path(mpp->alias, pp->dev_t);
214                 }
215         }
216 }
217
218 static void
219 sync_maps_state(vector mpvec)
220 {
221         unsigned int i;
222         struct multipath *mpp;
223
224         vector_foreach_slot (mpvec, mpp, i)
225                 sync_map_state(mpp);
226 }
227
228 static int
229 flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
230 {
231         int r;
232
233         if (nopaths)
234                 r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove);
235         else
236                 r = dm_flush_map(mpp->alias);
237         /*
238          * clear references to this map before flushing so we can ignore
239          * the spurious uevent we may generate with the dm_flush_map call below
240          */
241         if (r) {
242                 /*
243                  * May not really be an error -- if the map was already flushed
244                  * from the device mapper by dmsetup(8) for instance.
245                  */
246                 if (r == 1)
247                         condlog(0, "%s: can't flush", mpp->alias);
248                 else {
249                         condlog(2, "%s: devmap deferred remove", mpp->alias);
250                         mpp->deferred_remove = DEFERRED_REMOVE_IN_PROGRESS;
251                 }
252                 return r;
253         }
254         else {
255                 dm_lib_release();
256                 condlog(2, "%s: map flushed", mpp->alias);
257         }
258
259         orphan_paths(vecs->pathvec, mpp);
260         remove_map_and_stop_waiter(mpp, vecs, 1);
261
262         return 0;
263 }
264
265 static int
266 uev_add_map (struct uevent * uev, struct vectors * vecs)
267 {
268         char *alias;
269         int major = -1, minor = -1, rc;
270
271         condlog(3, "%s: add map (uevent)", uev->kernel);
272         alias = uevent_get_dm_name(uev);
273         if (!alias) {
274                 condlog(3, "%s: No DM_NAME in uevent", uev->kernel);
275                 major = uevent_get_major(uev);
276                 minor = uevent_get_minor(uev);
277                 alias = dm_mapname(major, minor);
278                 if (!alias) {
279                         condlog(2, "%s: mapname not found for %d:%d",
280                                 uev->kernel, major, minor);
281                         return 1;
282                 }
283         }
284         rc = ev_add_map(uev->kernel, alias, vecs);
285         FREE(alias);
286         return rc;
287 }
288
289 int
290 ev_add_map (char * dev, char * alias, struct vectors * vecs)
291 {
292         char * refwwid;
293         struct multipath * mpp;
294         int map_present;
295         int r = 1;
296
297         map_present = dm_map_present(alias);
298
299         if (map_present && !dm_is_mpath(alias)) {
300                 condlog(4, "%s: not a multipath map", alias);
301                 return 0;
302         }
303
304         mpp = find_mp_by_alias(vecs->mpvec, alias);
305
306         if (mpp) {
307                 /*
308                  * Not really an error -- we generate our own uevent
309                  * if we create a multipath mapped device as a result
310                  * of uev_add_path
311                  */
312                 if (conf->reassign_maps) {
313                         condlog(3, "%s: Reassign existing device-mapper devices",
314                                 alias);
315                         dm_reassign(alias);
316                 }
317                 return 0;
318         }
319         condlog(2, "%s: adding map", alias);
320
321         /*
322          * now we can register the map
323          */
324         if (map_present) {
325                 if ((mpp = add_map_without_path(vecs, alias))) {
326                         sync_map_state(mpp);
327                         condlog(2, "%s: devmap %s registered", alias, dev);
328                         return 0;
329                 } else {
330                         condlog(2, "%s: uev_add_map failed", dev);
331                         return 1;
332                 }
333         }
334         r = get_refwwid(dev, DEV_DEVMAP, vecs->pathvec, &refwwid);
335
336         if (refwwid) {
337                 r = coalesce_paths(vecs, NULL, refwwid, 0);
338                 dm_lib_release();
339         }
340
341         if (!r)
342                 condlog(2, "%s: devmap %s added", alias, dev);
343         else if (r == 2)
344                 condlog(2, "%s: uev_add_map %s blacklisted", alias, dev);
345         else
346                 condlog(0, "%s: uev_add_map %s failed", alias, dev);
347
348         FREE(refwwid);
349         return r;
350 }
351
352 static int
353 uev_remove_map (struct uevent * uev, struct vectors * vecs)
354 {
355         char *alias;
356         int minor;
357         struct multipath *mpp;
358
359         condlog(2, "%s: remove map (uevent)", uev->kernel);
360         alias = uevent_get_dm_name(uev);
361         if (!alias) {
362                 condlog(3, "%s: No DM_NAME in uevent, ignoring", uev->kernel);
363                 return 0;
364         }
365         minor = uevent_get_minor(uev);
366         mpp = find_mp_by_minor(vecs->mpvec, minor);
367
368         if (!mpp) {
369                 condlog(2, "%s: devmap not registered, can't remove",
370                         uev->kernel);
371                 goto out;
372         }
373         if (strcmp(mpp->alias, alias)) {
374                 condlog(2, "%s: minor number mismatch (map %d, event %d)",
375                         mpp->alias, mpp->dmi->minor, minor);
376                 goto out;
377         }
378
379         orphan_paths(vecs->pathvec, mpp);
380         remove_map_and_stop_waiter(mpp, vecs, 1);
381 out:
382         FREE(alias);
383         return 0;
384 }
385
386 int
387 ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs)
388 {
389         struct multipath * mpp;
390
391         mpp = find_mp_by_minor(vecs->mpvec, minor);
392
393         if (!mpp) {
394                 condlog(2, "%s: devmap not registered, can't remove",
395                         devname);
396                 return 0;
397         }
398         if (strcmp(mpp->alias, alias)) {
399                 condlog(2, "%s: minor number mismatch (map %d, event %d)",
400                         mpp->alias, mpp->dmi->minor, minor);
401                 return 0;
402         }
403         return flush_map(mpp, vecs, 0);
404 }
405
406 static int
407 uev_add_path (struct uevent *uev, struct vectors * vecs)
408 {
409         struct path *pp;
410         int ret = 0, i;
411
412         condlog(2, "%s: add path (uevent)", uev->kernel);
413         if (strstr(uev->kernel, "..") != NULL) {
414                 /*
415                  * Don't allow relative device names in the pathvec
416                  */
417                 condlog(0, "%s: path name is invalid", uev->kernel);
418                 return 1;
419         }
420
421         pp = find_path_by_dev(vecs->pathvec, uev->kernel);
422         if (pp) {
423                 int r;
424
425                 condlog(0, "%s: spurious uevent, path already in pathvec",
426                         uev->kernel);
427                 if (!pp->mpp && !strlen(pp->wwid)) {
428                         condlog(3, "%s: reinitialize path", uev->kernel);
429                         udev_device_unref(pp->udev);
430                         pp->udev = udev_device_ref(uev->udev);
431                         r = pathinfo(pp, conf->hwtable,
432                                      DI_ALL | DI_BLACKLIST);
433                         if (r == PATHINFO_OK)
434                                 ret = ev_add_path(pp, vecs);
435                         else if (r == PATHINFO_SKIPPED) {
436                                 condlog(3, "%s: remove blacklisted path",
437                                         uev->kernel);
438                                 i = find_slot(vecs->pathvec, (void *)pp);
439                                 if (i != -1)
440                                         vector_del_slot(vecs->pathvec, i);
441                                 free_path(pp);
442                         } else {
443                                 condlog(0, "%s: failed to reinitialize path",
444                                         uev->kernel);
445                                 ret = 1;
446                         }
447                 }
448                 return ret;
449         }
450
451         /*
452          * get path vital state
453          */
454         ret = alloc_path_with_pathinfo(conf->hwtable, uev->udev,
455                                        DI_ALL, &pp);
456         if (!pp) {
457                 if (ret == PATHINFO_SKIPPED)
458                         return 0;
459                 condlog(3, "%s: failed to get path info", uev->kernel);
460                 return 1;
461         }
462         ret = store_path(vecs->pathvec, pp);
463         if (!ret) {
464                 pp->checkint = conf->checkint;
465                 ret = ev_add_path(pp, vecs);
466         } else {
467                 condlog(0, "%s: failed to store path info, "
468                         "dropping event",
469                         uev->kernel);
470                 free_path(pp);
471                 ret = 1;
472         }
473
474         return ret;
475 }
476
477 /*
478  * returns:
479  * 0: added
480  * 1: error
481  */
482 int
483 ev_add_path (struct path * pp, struct vectors * vecs)
484 {
485         struct multipath * mpp;
486         char params[PARAMS_SIZE] = {0};
487         int retries = 3;
488         int start_waiter = 0;
489         int ret;
490
491         /*
492          * need path UID to go any further
493          */
494         if (strlen(pp->wwid) == 0) {
495                 condlog(0, "%s: failed to get path uid", pp->dev);
496                 goto fail; /* leave path added to pathvec */
497         }
498         mpp = pp->mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid);
499 rescan:
500         if (mpp) {
501                 if (mpp->size != pp->size) {
502                         condlog(0, "%s: failed to add new path %s, "
503                                 "device size mismatch",
504                                 mpp->alias, pp->dev);
505                         int i = find_slot(vecs->pathvec, (void *)pp);
506                         if (i != -1)
507                                 vector_del_slot(vecs->pathvec, i);
508                         free_path(pp);
509                         return 1;
510                 }
511
512                 condlog(4,"%s: adopting all paths for path %s",
513                         mpp->alias, pp->dev);
514                 if (adopt_paths(vecs->pathvec, mpp, 1))
515                         goto fail; /* leave path added to pathvec */
516
517                 verify_paths(mpp, vecs);
518                 mpp->flush_on_last_del = FLUSH_UNDEF;
519                 mpp->action = ACT_RELOAD;
520         } else {
521                 if (conf->find_multipaths &&
522                     !should_multipath(pp, vecs->pathvec)) {
523                         orphan_path(pp, "only one path");
524                         return 0;
525                 }
526                 condlog(4,"%s: creating new map", pp->dev);
527                 if ((mpp = add_map_with_path(vecs, pp, 1))) {
528                         mpp->action = ACT_CREATE;
529                         /*
530                          * We don't depend on ACT_CREATE, as domap will
531                          * set it to ACT_NOTHING when complete.
532                          */
533                         start_waiter = 1;
534                 }
535                 else
536                         goto fail; /* leave path added to pathvec */
537         }
538
539         /* persistent reseravtion check*/
540         mpath_pr_event_handle(pp);      
541
542         /*
543          * push the map to the device-mapper
544          */
545         if (setup_map(mpp, params, PARAMS_SIZE)) {
546                 condlog(0, "%s: failed to setup map for addition of new "
547                         "path %s", mpp->alias, pp->dev);
548                 goto fail_map;
549         }
550         /*
551          * reload the map for the multipath mapped device
552          */
553 retry:
554         ret = domap(mpp, params);
555         if (ret <= 0) {
556                 if (ret < 0 && retries-- > 0) {
557                         condlog(0, "%s: retry domap for addition of new "
558                                 "path %s", mpp->alias, pp->dev);
559                         sleep(1);
560                         goto retry;
561                 }
562                 condlog(0, "%s: failed in domap for addition of new "
563                         "path %s", mpp->alias, pp->dev);
564                 /*
565                  * deal with asynchronous uevents :((
566                  */
567                 if (mpp->action == ACT_RELOAD && retries-- > 0) {
568                         condlog(0, "%s: uev_add_path sleep", mpp->alias);
569                         sleep(1);
570                         update_mpp_paths(mpp, vecs->pathvec);
571                         goto rescan;
572                 }
573                 else if (mpp->action == ACT_RELOAD)
574                         condlog(0, "%s: giving up reload", mpp->alias);
575                 else
576                         goto fail_map;
577         }
578         dm_lib_release();
579
580         /*
581          * update our state from kernel regardless of create or reload
582          */
583         if (setup_multipath(vecs, mpp))
584                 goto fail; /* if setup_multipath fails, it removes the map */
585
586         sync_map_state(mpp);
587
588         if ((mpp->action == ACT_CREATE ||
589              (mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) &&
590             start_waiter_thread(mpp, vecs))
591                         goto fail_map;
592
593         if (retries >= 0) {
594                 condlog(2, "%s [%s]: path added to devmap %s",
595                         pp->dev, pp->dev_t, mpp->alias);
596                 return 0;
597         }
598         else
599                 goto fail;
600
601 fail_map:
602         remove_map(mpp, vecs, 1);
603 fail:
604         orphan_path(pp, "failed to add path");
605         return 1;
606 }
607
608 static int
609 uev_remove_path (struct uevent *uev, struct vectors * vecs)
610 {
611         struct path *pp;
612
613         condlog(2, "%s: remove path (uevent)", uev->kernel);
614         pp = find_path_by_dev(vecs->pathvec, uev->kernel);
615
616         if (!pp) {
617                 /* Not an error; path might have been purged earlier */
618                 condlog(0, "%s: path already removed", uev->kernel);
619                 return 0;
620         }
621
622         return ev_remove_path(pp, vecs);
623 }
624
625 int
626 ev_remove_path (struct path *pp, struct vectors * vecs)
627 {
628         struct multipath * mpp;
629         int i, retval = 0;
630         char params[PARAMS_SIZE] = {0};
631
632         /*
633          * avoid referring to the map of an orphaned path
634          */
635         if ((mpp = pp->mpp)) {
636                 /*
637                  * transform the mp->pg vector of vectors of paths
638                  * into a mp->params string to feed the device-mapper
639                  */
640                 if (update_mpp_paths(mpp, vecs->pathvec)) {
641                         condlog(0, "%s: failed to update paths",
642                                 mpp->alias);
643                         goto fail;
644                 }
645                 if ((i = find_slot(mpp->paths, (void *)pp)) != -1)
646                         vector_del_slot(mpp->paths, i);
647
648                 /*
649                  * remove the map IFF removing the last path
650                  */
651                 if (VECTOR_SIZE(mpp->paths) == 0) {
652                         char alias[WWID_SIZE];
653
654                         /*
655                          * flush_map will fail if the device is open
656                          */
657                         strncpy(alias, mpp->alias, WWID_SIZE);
658                         if (mpp->flush_on_last_del == FLUSH_ENABLED) {
659                                 condlog(2, "%s Last path deleted, disabling queueing", mpp->alias);
660                                 mpp->retry_tick = 0;
661                                 mpp->no_path_retry = NO_PATH_RETRY_FAIL;
662                                 mpp->flush_on_last_del = FLUSH_IN_PROGRESS;
663                                 dm_queue_if_no_path(mpp->alias, 0);
664                         }
665                         if (!flush_map(mpp, vecs, 1)) {
666                                 condlog(2, "%s: removed map after"
667                                         " removing all paths",
668                                         alias);
669                                 retval = 0;
670                                 goto out;
671                         }
672                         /*
673                          * Not an error, continue
674                          */
675                 }
676
677                 if (setup_map(mpp, params, PARAMS_SIZE)) {
678                         condlog(0, "%s: failed to setup map for"
679                                 " removal of path %s", mpp->alias, pp->dev);
680                         goto fail;
681                 }
682                 /*
683                  * reload the map
684                  */
685                 mpp->action = ACT_RELOAD;
686                 if (domap(mpp, params) <= 0) {
687                         condlog(0, "%s: failed in domap for "
688                                 "removal of path %s",
689                                 mpp->alias, pp->dev);
690                         retval = 1;
691                 } else {
692                         /*
693                          * update our state from kernel
694                          */
695                         if (setup_multipath(vecs, mpp))
696                                 return 1;
697                         sync_map_state(mpp);
698
699                         condlog(2, "%s [%s]: path removed from map %s",
700                                 pp->dev, pp->dev_t, mpp->alias);
701                 }
702         }
703
704 out:
705         if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
706                 vector_del_slot(vecs->pathvec, i);
707
708         free_path(pp);
709
710         return retval;
711
712 fail:
713         remove_map_and_stop_waiter(mpp, vecs, 1);
714         return 1;
715 }
716
717 static int
718 uev_update_path (struct uevent *uev, struct vectors * vecs)
719 {
720         int ro, retval = 0;
721         struct path * pp;
722
723         pp = find_path_by_dev(vecs->pathvec, uev->kernel);
724         if (!pp) {
725                 condlog(0, "%s: spurious uevent, path not found",
726                         uev->kernel);
727                 return 1;
728         }
729
730         if (pp->initialized == INIT_REQUESTED_UDEV)
731                 return uev_add_path(uev, vecs);
732
733         ro = uevent_get_disk_ro(uev);
734
735         if (ro >= 0) {
736                 condlog(2, "%s: update path write_protect to '%d' (uevent)",
737                         uev->kernel, ro);
738                 if (pp->mpp) {
739                         retval = reload_map(vecs, pp->mpp, 0);
740
741                         condlog(2, "%s: map %s reloaded (retval %d)",
742                                 uev->kernel, pp->mpp->alias, retval);
743                 }
744
745         }
746
747         return retval;
748 }
749
750 static int
751 map_discovery (struct vectors * vecs)
752 {
753         struct multipath * mpp;
754         unsigned int i;
755
756         if (dm_get_maps(vecs->mpvec))
757                 return 1;
758
759         vector_foreach_slot (vecs->mpvec, mpp, i)
760                 if (setup_multipath(vecs, mpp))
761                         return 1;
762
763         return 0;
764 }
765
766 int
767 uxsock_trigger (char * str, char ** reply, int * len, void * trigger_data)
768 {
769         struct vectors * vecs;
770         int r;
771
772         *reply = NULL;
773         *len = 0;
774         vecs = (struct vectors *)trigger_data;
775
776         pthread_cleanup_push(cleanup_lock, &vecs->lock);
777         lock(vecs->lock);
778         pthread_testcancel();
779
780         r = parse_cmd(str, reply, len, vecs);
781
782         if (r > 0) {
783                 *reply = STRDUP("fail\n");
784                 *len = strlen(*reply) + 1;
785                 r = 1;
786         }
787         else if (!r && *len == 0) {
788                 *reply = STRDUP("ok\n");
789                 *len = strlen(*reply) + 1;
790                 r = 0;
791         }
792         /* else if (r < 0) leave *reply alone */
793
794         lock_cleanup_pop(vecs->lock);
795         return r;
796 }
797
798 static int
799 uev_discard(char * devpath)
800 {
801         char *tmp;
802         char a[11], b[11];
803
804         /*
805          * keep only block devices, discard partitions
806          */
807         tmp = strstr(devpath, "/block/");
808         if (tmp == NULL){
809                 condlog(4, "no /block/ in '%s'", devpath);
810                 return 1;
811         }
812         if (sscanf(tmp, "/block/%10s", a) != 1 ||
813             sscanf(tmp, "/block/%10[^/]/%10s", a, b) == 2) {
814                 condlog(4, "discard event on %s", devpath);
815                 return 1;
816         }
817         return 0;
818 }
819
820 int
821 uev_trigger (struct uevent * uev, void * trigger_data)
822 {
823         int r = 0;
824         struct vectors * vecs;
825
826         vecs = (struct vectors *)trigger_data;
827
828         if (uev_discard(uev->devpath))
829                 return 0;
830
831         pthread_cleanup_push(cleanup_lock, &vecs->lock);
832         lock(vecs->lock);
833         pthread_testcancel();
834
835         /*
836          * device map event
837          * Add events are ignored here as the tables
838          * are not fully initialised then.
839          */
840         if (!strncmp(uev->kernel, "dm-", 3)) {
841                 if (!strncmp(uev->action, "change", 6)) {
842                         r = uev_add_map(uev, vecs);
843                         goto out;
844                 }
845                 if (!strncmp(uev->action, "remove", 6)) {
846                         r = uev_remove_map(uev, vecs);
847                         goto out;
848                 }
849                 goto out;
850         }
851
852         /*
853          * path add/remove event
854          */
855         if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
856                            uev->kernel) > 0)
857                 goto out;
858
859         if (!strncmp(uev->action, "add", 3)) {
860                 r = uev_add_path(uev, vecs);
861                 goto out;
862         }
863         if (!strncmp(uev->action, "remove", 6)) {
864                 r = uev_remove_path(uev, vecs);
865                 goto out;
866         }
867         if (!strncmp(uev->action, "change", 6)) {
868                 r = uev_update_path(uev, vecs);
869                 goto out;
870         }
871
872 out:
873         lock_cleanup_pop(vecs->lock);
874         return r;
875 }
876
877 static void *
878 ueventloop (void * ap)
879 {
880         struct udev *udev = ap;
881
882         if (uevent_listen(udev))
883                 condlog(0, "error starting uevent listener");
884
885         return NULL;
886 }
887
888 static void *
889 uevqloop (void * ap)
890 {
891         if (uevent_dispatch(&uev_trigger, ap))
892                 condlog(0, "error starting uevent dispatcher");
893
894         return NULL;
895 }
896 static void *
897 uxlsnrloop (void * ap)
898 {
899         if (cli_init())
900                 return NULL;
901
902         set_handler_callback(LIST+PATHS, cli_list_paths);
903         set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt);
904         set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw);
905         set_handler_callback(LIST+PATH, cli_list_path);
906         set_handler_callback(LIST+MAPS, cli_list_maps);
907         set_handler_callback(LIST+STATUS, cli_list_status);
908         set_handler_callback(LIST+DAEMON, cli_list_daemon);
909         set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status);
910         set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats);
911         set_handler_callback(LIST+MAPS+FMT, cli_list_maps_fmt);
912         set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw);
913         set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology);
914         set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology);
915         set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology);
916         set_handler_callback(LIST+CONFIG, cli_list_config);
917         set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
918         set_handler_callback(LIST+DEVICES, cli_list_devices);
919         set_handler_callback(LIST+WILDCARDS, cli_list_wildcards);
920         set_handler_callback(ADD+PATH, cli_add_path);
921         set_handler_callback(DEL+PATH, cli_del_path);
922         set_handler_callback(ADD+MAP, cli_add_map);
923         set_handler_callback(DEL+MAP, cli_del_map);
924         set_handler_callback(SWITCH+MAP+GROUP, cli_switch_group);
925         set_handler_callback(RECONFIGURE, cli_reconfigure);
926         set_handler_callback(SUSPEND+MAP, cli_suspend);
927         set_handler_callback(RESUME+MAP, cli_resume);
928         set_handler_callback(RESIZE+MAP, cli_resize);
929         set_handler_callback(RELOAD+MAP, cli_reload);
930         set_handler_callback(RESET+MAP, cli_reassign);
931         set_handler_callback(REINSTATE+PATH, cli_reinstate);
932         set_handler_callback(FAIL+PATH, cli_fail);
933         set_handler_callback(DISABLEQ+MAP, cli_disable_queueing);
934         set_handler_callback(RESTOREQ+MAP, cli_restore_queueing);
935         set_handler_callback(DISABLEQ+MAPS, cli_disable_all_queueing);
936         set_handler_callback(RESTOREQ+MAPS, cli_restore_all_queueing);
937         set_handler_callback(QUIT, cli_quit);
938         set_handler_callback(SHUTDOWN, cli_shutdown);
939         set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus);
940         set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus);
941         set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus);
942         set_handler_callback(FORCEQ+DAEMON, cli_force_no_daemon_q);
943         set_handler_callback(RESTOREQ+DAEMON, cli_restore_no_daemon_q);
944
945         umask(077);
946         uxsock_listen(&uxsock_trigger, ap);
947
948         return NULL;
949 }
950
951 void
952 exit_daemon (void)
953 {
954         sem_post(&exit_sem);
955 }
956
957 const char *
958 daemon_status(void)
959 {
960         switch (running_state) {
961         case DAEMON_INIT:
962                 return "init";
963         case DAEMON_START:
964                 return "startup";
965         case DAEMON_CONFIGURE:
966                 return "configure";
967         case DAEMON_RUNNING:
968                 return "running";
969         case DAEMON_SHUTDOWN:
970                 return "shutdown";
971         }
972         return NULL;
973 }
974
975 static void
976 fail_path (struct path * pp, int del_active)
977 {
978         if (!pp->mpp)
979                 return;
980
981         condlog(2, "checker failed path %s in map %s",
982                  pp->dev_t, pp->mpp->alias);
983
984         dm_fail_path(pp->mpp->alias, pp->dev_t);
985         if (del_active)
986                 update_queue_mode_del_path(pp->mpp);
987 }
988
989 /*
990  * caller must have locked the path list before calling that function
991  */
992 static int
993 reinstate_path (struct path * pp, int add_active)
994 {
995         int ret = 0;
996
997         if (!pp->mpp)
998                 return 0;
999
1000         if (dm_reinstate_path(pp->mpp->alias, pp->dev_t)) {
1001                 condlog(0, "%s: reinstate failed", pp->dev_t);
1002                 ret = 1;
1003         } else {
1004                 condlog(2, "%s: reinstated", pp->dev_t);
1005                 if (add_active)
1006                         update_queue_mode_add_path(pp->mpp);
1007         }
1008         return ret;
1009 }
1010
1011 static void
1012 enable_group(struct path * pp)
1013 {
1014         struct pathgroup * pgp;
1015
1016         /*
1017          * if path is added through uev_add_path, pgindex can be unset.
1018          * next update_strings() will set it, upon map reload event.
1019          *
1020          * we can safely return here, because upon map reload, all
1021          * PG will be enabled.
1022          */
1023         if (!pp->mpp->pg || !pp->pgindex)
1024                 return;
1025
1026         pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1);
1027
1028         if (pgp->status == PGSTATE_DISABLED) {
1029                 condlog(2, "%s: enable group #%i", pp->mpp->alias, pp->pgindex);
1030                 dm_enablegroup(pp->mpp->alias, pp->pgindex);
1031         }
1032 }
1033
1034 static void
1035 mpvec_garbage_collector (struct vectors * vecs)
1036 {
1037         struct multipath * mpp;
1038         unsigned int i;
1039
1040         if (!vecs->mpvec)
1041                 return;
1042
1043         vector_foreach_slot (vecs->mpvec, mpp, i) {
1044                 if (mpp && mpp->alias && !dm_map_present(mpp->alias)) {
1045                         condlog(2, "%s: remove dead map", mpp->alias);
1046                         remove_map_and_stop_waiter(mpp, vecs, 1);
1047                         i--;
1048                 }
1049         }
1050 }
1051
1052 /* This is called after a path has started working again. It the multipath
1053  * device for this path uses the followover failback type, and this is the
1054  * best pathgroup, and this is the first path in the pathgroup to come back
1055  * up, then switch to this pathgroup */
1056 static int
1057 followover_should_failback(struct path * pp)
1058 {
1059         struct pathgroup * pgp;
1060         struct path *pp1;
1061         int i;
1062
1063         if (pp->mpp->pgfailback != -FAILBACK_FOLLOWOVER ||
1064             !pp->mpp->pg || !pp->pgindex ||
1065             pp->pgindex != pp->mpp->bestpg)
1066                 return 0;
1067
1068         pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1);
1069         vector_foreach_slot(pgp->paths, pp1, i) {
1070                 if (pp1 == pp)
1071                         continue;
1072                 if (pp1->chkrstate != PATH_DOWN && pp1->chkrstate != PATH_SHAKY)
1073                         return 0;
1074         }
1075         return 1;
1076 }
1077
1078 static void
1079 defered_failback_tick (vector mpvec)
1080 {
1081         struct multipath * mpp;
1082         unsigned int i;
1083
1084         vector_foreach_slot (mpvec, mpp, i) {
1085                 /*
1086                  * defered failback getting sooner
1087                  */
1088                 if (mpp->pgfailback > 0 && mpp->failback_tick > 0) {
1089                         mpp->failback_tick--;
1090
1091                         if (!mpp->failback_tick && need_switch_pathgroup(mpp, 1))
1092                                 switch_pathgroup(mpp);
1093                 }
1094         }
1095 }
1096
1097 static void
1098 retry_count_tick(vector mpvec)
1099 {
1100         struct multipath *mpp;
1101         unsigned int i;
1102
1103         vector_foreach_slot (mpvec, mpp, i) {
1104                 if (mpp->retry_tick) {
1105                         mpp->stat_total_queueing_time++;
1106                         condlog(4, "%s: Retrying.. No active path", mpp->alias);
1107                         if(--mpp->retry_tick == 0) {
1108                                 dm_queue_if_no_path(mpp->alias, 0);
1109                                 condlog(2, "%s: Disable queueing", mpp->alias);
1110                         }
1111                 }
1112         }
1113 }
1114
1115 int update_prio(struct path *pp, int refresh_all)
1116 {
1117         int oldpriority;
1118         struct path *pp1;
1119         struct pathgroup * pgp;
1120         int i, j, changed = 0;
1121
1122         if (refresh_all) {
1123                 vector_foreach_slot (pp->mpp->pg, pgp, i) {
1124                         vector_foreach_slot (pgp->paths, pp1, j) {
1125                                 oldpriority = pp1->priority;
1126                                 pathinfo(pp1, conf->hwtable, DI_PRIO);
1127                                 if (pp1->priority != oldpriority)
1128                                         changed = 1;
1129                         }
1130                 }
1131                 return changed;
1132         }
1133         oldpriority = pp->priority;
1134         pathinfo(pp, conf->hwtable, DI_PRIO);
1135
1136         if (pp->priority == oldpriority)
1137                 return 0;
1138         return 1;
1139 }
1140
1141 int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh)
1142 {
1143         if (reload_map(vecs, mpp, refresh))
1144                 return 1;
1145
1146         dm_lib_release();
1147         if (setup_multipath(vecs, mpp) != 0)
1148                 return 1;
1149         sync_map_state(mpp);
1150
1151         return 0;
1152 }
1153
1154 /*
1155  * Returns '1' if the path has been checked, '0' otherwise
1156  */
1157 int
1158 check_path (struct vectors * vecs, struct path * pp)
1159 {
1160         int newstate;
1161         int new_path_up = 0;
1162         int chkr_new_path_up = 0;
1163         int add_active;
1164         int disable_reinstate = 0;
1165         int oldchkrstate = pp->chkrstate;
1166
1167         if ((pp->initialized == INIT_OK ||
1168              pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp)
1169                 return 0;
1170
1171         if (pp->tick && --pp->tick)
1172                 return 0; /* don't check this path yet */
1173
1174         if (!pp->mpp && pp->initialized == INIT_MISSING_UDEV &&
1175             pp->retriggers < conf->retrigger_tries) {
1176                 condlog(2, "%s: triggering change event to reinitialize",
1177                         pp->dev);
1178                 pp->initialized = INIT_REQUESTED_UDEV;
1179                 pp->retriggers++;
1180                 sysfs_attr_set_value(pp->udev, "uevent", "change",
1181                                      strlen("change"));
1182                 return 0;
1183         } 
1184
1185         /*
1186          * provision a next check soonest,
1187          * in case we exit abnormaly from here
1188          */
1189         pp->tick = conf->checkint;
1190
1191         newstate = path_offline(pp);
1192         /*
1193          * Wait for uevent for removed paths;
1194          * some LLDDs like zfcp keep paths unavailable
1195          * without sending uevents.
1196          */
1197         if (newstate == PATH_REMOVED)
1198                 newstate = PATH_DOWN;
1199
1200         if (newstate == PATH_UP)
1201                 newstate = get_state(pp, 1);
1202         else
1203                 checker_clear_message(&pp->checker);
1204
1205         if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) {
1206                 condlog(2, "%s: unusable path", pp->dev);
1207                 pathinfo(pp, conf->hwtable, 0);
1208                 return 1;
1209         }
1210         if (!pp->mpp) {
1211                 if (!strlen(pp->wwid) && pp->initialized != INIT_MISSING_UDEV &&
1212                     (newstate == PATH_UP || newstate == PATH_GHOST)) {
1213                         condlog(2, "%s: add missing path", pp->dev);
1214                         if (pathinfo(pp, conf->hwtable, DI_ALL) == 0) {
1215                                 ev_add_path(pp, vecs);
1216                                 pp->tick = 1;
1217                         }
1218                 }
1219                 return 0;
1220         }
1221         /*
1222          * Async IO in flight. Keep the previous path state
1223          * and reschedule as soon as possible
1224          */
1225         if (newstate == PATH_PENDING) {
1226                 pp->tick = 1;
1227                 return 0;
1228         }
1229         /*
1230          * Synchronize with kernel state
1231          */
1232         if (update_multipath_strings(pp->mpp, vecs->pathvec)) {
1233                 condlog(1, "%s: Could not synchronize with kernel state",
1234                         pp->dev);
1235                 pp->dmstate = PSTATE_UNDEF;
1236         }
1237         /* if update_multipath_strings orphaned the path, quit early */
1238         if (!pp->mpp)
1239                 return 0;
1240
1241         if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
1242              pp->wait_checks > 0) {
1243                 if (pp->mpp && pp->mpp->nr_active > 0) {
1244                         pp->state = PATH_DELAYED;
1245                         pp->wait_checks--;
1246                         return 1;
1247                 } else
1248                         pp->wait_checks = 0;
1249         }
1250
1251         /*
1252          * don't reinstate failed path, if its in stand-by
1253          * and if target supports only implicit tpgs mode.
1254          * this will prevent unnecessary i/o by dm on stand-by
1255          * paths if there are no other active paths in map.
1256          */
1257         disable_reinstate = (newstate == PATH_GHOST &&
1258                             pp->mpp->nr_active == 0 &&
1259                             pp->tpgs == TPGS_IMPLICIT) ? 1 : 0;
1260
1261         pp->chkrstate = newstate;
1262         if (newstate != pp->state) {
1263                 int oldstate = pp->state;
1264                 pp->state = newstate;
1265
1266                 if (strlen(checker_message(&pp->checker)))
1267                         LOG_MSG(1, checker_message(&pp->checker));
1268
1269                 /*
1270                  * upon state change, reset the checkint
1271                  * to the shortest delay
1272                  */
1273                 pp->checkint = conf->checkint;
1274
1275                 if (newstate == PATH_DOWN || newstate == PATH_SHAKY) {
1276                         /*
1277                          * proactively fail path in the DM
1278                          */
1279                         if (oldstate == PATH_UP ||
1280                             oldstate == PATH_GHOST) {
1281                                 fail_path(pp, 1);
1282                                 if (pp->mpp->delay_wait_checks > 0 &&
1283                                     pp->watch_checks > 0) {
1284                                         pp->wait_checks = pp->mpp->delay_wait_checks;
1285                                         pp->watch_checks = 0;
1286                                 }
1287                         }else
1288                                 fail_path(pp, 0);
1289
1290                         /*
1291                          * cancel scheduled failback
1292                          */
1293                         pp->mpp->failback_tick = 0;
1294
1295                         pp->mpp->stat_path_failures++;
1296                         return 1;
1297                 }
1298
1299                 if(newstate == PATH_UP || newstate == PATH_GHOST){
1300                         if ( pp->mpp && pp->mpp->prflag ){
1301                                 /*
1302                                  * Check Persistent Reservation.
1303                                  */
1304                         condlog(2, "%s: checking persistent reservation "
1305                                 "registration", pp->dev);
1306                         mpath_pr_event_handle(pp);
1307                         }
1308                 }
1309
1310                 /*
1311                  * reinstate this path
1312                  */
1313                 if (oldstate != PATH_UP &&
1314                     oldstate != PATH_GHOST) {
1315                         if (pp->mpp->delay_watch_checks > 0)
1316                                 pp->watch_checks = pp->mpp->delay_watch_checks;
1317                         add_active = 1;
1318                 } else {
1319                         if (pp->watch_checks > 0)
1320                                 pp->watch_checks--;
1321                         add_active = 0;
1322                 }
1323                 if (!disable_reinstate && reinstate_path(pp, add_active)) {
1324                         condlog(3, "%s: reload map", pp->dev);
1325                         ev_add_path(pp, vecs);
1326                         pp->tick = 1;
1327                         return 0;
1328                 }
1329                 new_path_up = 1;
1330
1331                 if (oldchkrstate != PATH_UP && oldchkrstate != PATH_GHOST)
1332                         chkr_new_path_up = 1;
1333
1334                 /*
1335                  * if at least one path is up in a group, and
1336                  * the group is disabled, re-enable it
1337                  */
1338                 if (newstate == PATH_UP)
1339                         enable_group(pp);
1340         }
1341         else if (newstate == PATH_UP || newstate == PATH_GHOST) {
1342                 if ((pp->dmstate == PSTATE_FAILED ||
1343                     pp->dmstate == PSTATE_UNDEF) &&
1344                     !disable_reinstate) {
1345                         /* Clear IO errors */
1346                         if (reinstate_path(pp, 0)) {
1347                                 condlog(3, "%s: reload map", pp->dev);
1348                                 ev_add_path(pp, vecs);
1349                                 pp->tick = 1;
1350                                 return 0;
1351                         }
1352                 } else {
1353                         LOG_MSG(4, checker_message(&pp->checker));
1354                         if (pp->checkint != conf->max_checkint) {
1355                                 /*
1356                                  * double the next check delay.
1357                                  * max at conf->max_checkint
1358                                  */
1359                                 if (pp->checkint < (conf->max_checkint / 2))
1360                                         pp->checkint = 2 * pp->checkint;
1361                                 else
1362                                         pp->checkint = conf->max_checkint;
1363
1364                                 condlog(4, "%s: delay next check %is",
1365                                         pp->dev_t, pp->checkint);
1366                         }
1367                         if (pp->watch_checks > 0)
1368                                 pp->watch_checks--;
1369                         pp->tick = pp->checkint;
1370                 }
1371         }
1372         else if (newstate == PATH_DOWN &&
1373                  strlen(checker_message(&pp->checker))) {
1374                 if (conf->log_checker_err == LOG_CHKR_ERR_ONCE)
1375                         LOG_MSG(3, checker_message(&pp->checker));
1376                 else
1377                         LOG_MSG(2, checker_message(&pp->checker));
1378         }
1379
1380         pp->state = newstate;
1381
1382         /*
1383          * path prio refreshing
1384          */
1385         condlog(4, "path prio refresh");
1386
1387         if (update_prio(pp, new_path_up) &&
1388             (pp->mpp->pgpolicyfn == (pgpolicyfn *)group_by_prio) &&
1389              pp->mpp->pgfailback == -FAILBACK_IMMEDIATE)
1390                 update_path_groups(pp->mpp, vecs, !new_path_up);
1391         else if (need_switch_pathgroup(pp->mpp, 0)) {
1392                 if (pp->mpp->pgfailback > 0 &&
1393                     (new_path_up || pp->mpp->failback_tick <= 0))
1394                         pp->mpp->failback_tick =
1395                                 pp->mpp->pgfailback + 1;
1396                 else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE ||
1397                          (chkr_new_path_up && followover_should_failback(pp)))
1398                         switch_pathgroup(pp->mpp);
1399         }
1400         return 1;
1401 }
1402
1403 static void *
1404 checkerloop (void *ap)
1405 {
1406         struct vectors *vecs;
1407         struct path *pp;
1408         int count = 0;
1409         unsigned int i;
1410
1411         mlockall(MCL_CURRENT | MCL_FUTURE);
1412         vecs = (struct vectors *)ap;
1413         condlog(2, "path checkers start up");
1414
1415         /*
1416          * init the path check interval
1417          */
1418         vector_foreach_slot (vecs->pathvec, pp, i) {
1419                 pp->checkint = conf->checkint;
1420         }
1421
1422         while (1) {
1423                 struct timeval diff_time, start_time, end_time;
1424                 int num_paths = 0;
1425
1426                 if (gettimeofday(&start_time, NULL) != 0)
1427                         start_time.tv_sec = 0;
1428                 pthread_cleanup_push(cleanup_lock, &vecs->lock);
1429                 lock(vecs->lock);
1430                 pthread_testcancel();
1431                 condlog(4, "tick");
1432 #ifdef USE_SYSTEMD
1433                 if (use_watchdog)
1434                         sd_notify(0, "WATCHDOG=1");
1435 #endif
1436                 if (vecs->pathvec) {
1437                         vector_foreach_slot (vecs->pathvec, pp, i) {
1438                                 num_paths += check_path(vecs, pp);
1439                         }
1440                 }
1441                 if (vecs->mpvec) {
1442                         defered_failback_tick(vecs->mpvec);
1443                         retry_count_tick(vecs->mpvec);
1444                 }
1445                 if (count)
1446                         count--;
1447                 else {
1448                         condlog(4, "map garbage collection");
1449                         mpvec_garbage_collector(vecs);
1450                         count = MAPGCINT;
1451                 }
1452
1453                 lock_cleanup_pop(vecs->lock);
1454                 if (start_time.tv_sec &&
1455                     gettimeofday(&end_time, NULL) == 0 &&
1456                     num_paths) {
1457                         timersub(&end_time, &start_time, &diff_time);
1458                         condlog(3, "checked %d path%s in %lu.%06lu secs",
1459                                 num_paths, num_paths > 1 ? "s" : "",
1460                                 diff_time.tv_sec, diff_time.tv_usec);
1461                 }
1462                 sleep(1);
1463         }
1464         return NULL;
1465 }
1466
1467 int
1468 configure (struct vectors * vecs, int start_waiters)
1469 {
1470         struct multipath * mpp;
1471         struct path * pp;
1472         vector mpvec;
1473         int i, ret;
1474
1475         if (!vecs->pathvec && !(vecs->pathvec = vector_alloc()))
1476                 return 1;
1477
1478         if (!vecs->mpvec && !(vecs->mpvec = vector_alloc()))
1479                 return 1;
1480
1481         if (!(mpvec = vector_alloc()))
1482                 return 1;
1483
1484         /*
1485          * probe for current path (from sysfs) and map (from dm) sets
1486          */
1487         ret = path_discovery(vecs->pathvec, conf, DI_ALL);
1488         if (ret < 0)
1489                 return 1;
1490
1491         vector_foreach_slot (vecs->pathvec, pp, i){
1492                 if (filter_path(conf, pp) > 0){
1493                         vector_del_slot(vecs->pathvec, i);
1494                         free_path(pp);
1495                         i--;
1496                 }
1497                 else
1498                         pp->checkint = conf->checkint;
1499         }
1500         if (map_discovery(vecs))
1501                 return 1;
1502
1503         /*
1504          * create new set of maps & push changed ones into dm
1505          */
1506         if (coalesce_paths(vecs, mpvec, NULL, 1))
1507                 return 1;
1508
1509         /*
1510          * may need to remove some maps which are no longer relevant
1511          * e.g., due to blacklist changes in conf file
1512          */
1513         if (coalesce_maps(vecs, mpvec))
1514                 return 1;
1515
1516         dm_lib_release();
1517
1518         sync_maps_state(mpvec);
1519         vector_foreach_slot(mpvec, mpp, i){
1520                 remember_wwid(mpp->wwid);
1521                 update_map_pr(mpp);
1522         }
1523
1524         /*
1525          * purge dm of old maps
1526          */
1527         remove_maps(vecs);
1528
1529         /*
1530          * save new set of maps formed by considering current path state
1531          */
1532         vector_free(vecs->mpvec);
1533         vecs->mpvec = mpvec;
1534
1535         /*
1536          * start dm event waiter threads for these new maps
1537          */
1538         vector_foreach_slot(vecs->mpvec, mpp, i) {
1539                 if (setup_multipath(vecs, mpp))
1540                         return 1;
1541                 if (start_waiters)
1542                         if (start_waiter_thread(mpp, vecs))
1543                                 return 1;
1544         }
1545         return 0;
1546 }
1547
1548 int
1549 reconfigure (struct vectors * vecs)
1550 {
1551         struct config * old = conf;
1552         int retval = 1;
1553
1554         running_state = DAEMON_CONFIGURE;
1555
1556         /*
1557          * free old map and path vectors ... they use old conf state
1558          */
1559         if (VECTOR_SIZE(vecs->mpvec))
1560                 remove_maps_and_stop_waiters(vecs);
1561
1562         if (VECTOR_SIZE(vecs->pathvec))
1563                 free_pathvec(vecs->pathvec, FREE_PATHS);
1564
1565         vecs->pathvec = NULL;
1566         conf = NULL;
1567
1568         /* Re-read any timezone changes */
1569         tzset();
1570
1571         if (!load_config(DEFAULT_CONFIGFILE, udev)) {
1572                 dm_drv_version(conf->version, TGT_MPATH);
1573                 conf->verbosity = old->verbosity;
1574                 conf->bindings_read_only = old->bindings_read_only;
1575                 conf->daemon = 1;
1576                 configure(vecs, 1);
1577                 free_config(old);
1578                 retval = 0;
1579         }
1580
1581         running_state = DAEMON_RUNNING;
1582
1583         return retval;
1584 }
1585
1586 static struct vectors *
1587 init_vecs (void)
1588 {
1589         struct vectors * vecs;
1590
1591         vecs = (struct vectors *)MALLOC(sizeof(struct vectors));
1592
1593         if (!vecs)
1594                 return NULL;
1595
1596         vecs->lock.mutex =
1597                 (pthread_mutex_t *)MALLOC(sizeof(pthread_mutex_t));
1598
1599         if (!vecs->lock.mutex)
1600                 goto out;
1601
1602         pthread_mutex_init(vecs->lock.mutex, NULL);
1603         vecs->lock.depth = 0;
1604
1605         return vecs;
1606
1607 out:
1608         FREE(vecs);
1609         condlog(0, "failed to init paths");
1610         return NULL;
1611 }
1612
1613 static void *
1614 signal_set(int signo, void (*func) (int))
1615 {
1616         int r;
1617         struct sigaction sig;
1618         struct sigaction osig;
1619
1620         sig.sa_handler = func;
1621         sigemptyset(&sig.sa_mask);
1622         sig.sa_flags = 0;
1623
1624         r = sigaction(signo, &sig, &osig);
1625
1626         if (r < 0)
1627                 return (SIG_ERR);
1628         else
1629                 return (osig.sa_handler);
1630 }
1631
1632 void
1633 handle_signals(void)
1634 {
1635         if (reconfig_sig && running_state == DAEMON_RUNNING) {
1636                 condlog(2, "reconfigure (signal)");
1637                 pthread_cleanup_push(cleanup_lock,
1638                                 &gvecs->lock);
1639                 lock(gvecs->lock);
1640                 pthread_testcancel();
1641                 reconfigure(gvecs);
1642                 lock_cleanup_pop(gvecs->lock);
1643         }
1644         if (log_reset_sig) {
1645                 condlog(2, "reset log (signal)");
1646                 pthread_mutex_lock(&logq_lock);
1647                 log_reset("multipathd");
1648                 pthread_mutex_unlock(&logq_lock);
1649         }
1650         reconfig_sig = 0;
1651         log_reset_sig = 0;
1652 }
1653
1654 static void
1655 sighup (int sig)
1656 {
1657         reconfig_sig = 1;
1658 }
1659
1660 static void
1661 sigend (int sig)
1662 {
1663         exit_daemon();
1664 }
1665
1666 static void
1667 sigusr1 (int sig)
1668 {
1669         log_reset_sig = 1;
1670 }
1671
1672 static void
1673 sigusr2 (int sig)
1674 {
1675         condlog(3, "SIGUSR2 received");
1676 }
1677
1678 static void
1679 signal_init(void)
1680 {
1681         sigset_t set;
1682
1683         sigemptyset(&set);
1684         sigaddset(&set, SIGHUP);
1685         sigaddset(&set, SIGUSR1);
1686         sigaddset(&set, SIGUSR2);
1687         pthread_sigmask(SIG_BLOCK, &set, NULL);
1688
1689         signal_set(SIGHUP, sighup);
1690         signal_set(SIGUSR1, sigusr1);
1691         signal_set(SIGUSR2, sigusr2);
1692         signal_set(SIGINT, sigend);
1693         signal_set(SIGTERM, sigend);
1694         signal(SIGPIPE, SIG_IGN);
1695 }
1696
1697 static void
1698 setscheduler (void)
1699 {
1700         int res;
1701         static struct sched_param sched_param = {
1702                 .sched_priority = 99
1703         };
1704
1705         res = sched_setscheduler (0, SCHED_RR, &sched_param);
1706
1707         if (res == -1)
1708                 condlog(LOG_WARNING, "Could not set SCHED_RR at priority 99");
1709         return;
1710 }
1711
1712 static void
1713 set_oom_adj (void)
1714 {
1715 #ifdef OOM_SCORE_ADJ_MIN
1716         int retry = 1;
1717         char *file = "/proc/self/oom_score_adj";
1718         int score = OOM_SCORE_ADJ_MIN;
1719 #else
1720         int retry = 0;
1721         char *file = "/proc/self/oom_adj";
1722         int score = OOM_ADJUST_MIN;
1723 #endif
1724         FILE *fp;
1725         struct stat st;
1726         char *envp;
1727
1728         envp = getenv("OOMScoreAdjust");
1729         if (envp) {
1730                 condlog(3, "Using systemd provided OOMScoreAdjust");
1731                 return;
1732         }
1733         do {
1734                 if (stat(file, &st) == 0){
1735                         fp = fopen(file, "w");
1736                         if (!fp) {
1737                                 condlog(0, "couldn't fopen %s : %s", file,
1738                                         strerror(errno));
1739                                 return;
1740                         }
1741                         fprintf(fp, "%i", score);
1742                         fclose(fp);
1743                         return;
1744                 }
1745                 if (errno != ENOENT) {
1746                         condlog(0, "couldn't stat %s : %s", file,
1747                                 strerror(errno));
1748                         return;
1749                 }
1750 #ifdef OOM_ADJUST_MIN
1751                 file = "/proc/self/oom_adj";
1752                 score = OOM_ADJUST_MIN;
1753 #else
1754                 retry = 0;
1755 #endif
1756         } while (retry--);
1757         condlog(0, "couldn't adjust oom score");
1758 }
1759
1760 static int
1761 child (void * param)
1762 {
1763         pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr;
1764         pthread_attr_t log_attr, misc_attr, uevent_attr;
1765         struct vectors * vecs;
1766         struct multipath * mpp;
1767         int i;
1768 #ifdef USE_SYSTEMD
1769         unsigned long checkint;
1770 #endif
1771         int rc, pid_rc;
1772         char *envp;
1773
1774         mlockall(MCL_CURRENT | MCL_FUTURE);
1775         sem_init(&exit_sem, 0, 0);
1776         signal_init();
1777
1778         udev = udev_new();
1779
1780         setup_thread_attr(&misc_attr, 64 * 1024, 1);
1781         setup_thread_attr(&uevent_attr, DEFAULT_UEVENT_STACKSIZE * 1024, 1);
1782         setup_thread_attr(&waiter_attr, 32 * 1024, 1);
1783
1784         if (logsink == 1) {
1785                 setup_thread_attr(&log_attr, 64 * 1024, 0);
1786                 log_thread_start(&log_attr);
1787                 pthread_attr_destroy(&log_attr);
1788         }
1789
1790         running_state = DAEMON_START;
1791
1792 #ifdef USE_SYSTEMD
1793         sd_notify(0, "STATUS=startup");
1794 #endif
1795         condlog(2, "--------start up--------");
1796         condlog(2, "read " DEFAULT_CONFIGFILE);
1797
1798         if (load_config(DEFAULT_CONFIGFILE, udev))
1799                 goto failed;
1800
1801         dm_drv_version(conf->version, TGT_MPATH);
1802         if (init_checkers()) {
1803                 condlog(0, "failed to initialize checkers");
1804                 goto failed;
1805         }
1806         if (init_prio()) {
1807                 condlog(0, "failed to initialize prioritizers");
1808                 goto failed;
1809         }
1810
1811         setlogmask(LOG_UPTO(conf->verbosity + 3));
1812
1813         envp = getenv("LimitNOFILE");
1814
1815         if (envp) {
1816                 condlog(2,"Using systemd provided open fds limit of %s", envp);
1817         } else if (conf->max_fds) {
1818                 struct rlimit fd_limit;
1819
1820                 if (getrlimit(RLIMIT_NOFILE, &fd_limit) < 0) {
1821                         condlog(0, "can't get open fds limit: %s",
1822                                 strerror(errno));
1823                         fd_limit.rlim_cur = 0;
1824                         fd_limit.rlim_max = 0;
1825                 }
1826                 if (fd_limit.rlim_cur < conf->max_fds) {
1827                         fd_limit.rlim_cur = conf->max_fds;
1828                         if (fd_limit.rlim_max < conf->max_fds)
1829                                 fd_limit.rlim_max = conf->max_fds;
1830                         if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0) {
1831                                 condlog(0, "can't set open fds limit to "
1832                                         "%lu/%lu : %s",
1833                                         fd_limit.rlim_cur, fd_limit.rlim_max,
1834                                         strerror(errno));
1835                         } else {
1836                                 condlog(3, "set open fds limit to %lu/%lu",
1837                                         fd_limit.rlim_cur, fd_limit.rlim_max);
1838                         }
1839                 }
1840
1841         }
1842
1843         vecs = gvecs = init_vecs();
1844         if (!vecs)
1845                 goto failed;
1846
1847         setscheduler();
1848         set_oom_adj();
1849
1850         conf->daemon = 1;
1851         dm_udev_set_sync_support(0);
1852 #ifdef USE_SYSTEMD
1853         envp = getenv("WATCHDOG_USEC");
1854         if (envp && sscanf(envp, "%lu", &checkint) == 1) {
1855                 /* Value is in microseconds */
1856                 conf->max_checkint = checkint / 1000000;
1857                 /* Rescale checkint */
1858                 if (conf->checkint > conf->max_checkint)
1859                         conf->checkint = conf->max_checkint;
1860                 else
1861                         conf->checkint = conf->max_checkint / 4;
1862                 condlog(3, "enabling watchdog, interval %d max %d",
1863                         conf->checkint, conf->max_checkint);
1864                 use_watchdog = conf->checkint;
1865         }
1866 #endif
1867         /*
1868          * Start uevent listener early to catch events
1869          */
1870         if ((rc = pthread_create(&uevent_thr, &uevent_attr, ueventloop, udev))) {
1871                 condlog(0, "failed to create uevent thread: %d", rc);
1872                 goto failed;
1873         }
1874         pthread_attr_destroy(&uevent_attr);
1875         if ((rc = pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs))) {
1876                 condlog(0, "failed to create cli listener: %d", rc);
1877                 goto failed;
1878         }
1879         /*
1880          * fetch and configure both paths and multipaths
1881          */
1882 #ifdef USE_SYSTEMD
1883         sd_notify(0, "STATUS=configure");
1884 #endif
1885         running_state = DAEMON_CONFIGURE;
1886
1887         lock(vecs->lock);
1888         if (configure(vecs, 1)) {
1889                 unlock(vecs->lock);
1890                 condlog(0, "failure during configuration");
1891                 goto failed;
1892         }
1893         unlock(vecs->lock);
1894
1895         /*
1896          * start threads
1897          */
1898         if ((rc = pthread_create(&check_thr, &misc_attr, checkerloop, vecs))) {
1899                 condlog(0,"failed to create checker loop thread: %d", rc);
1900                 goto failed;
1901         }
1902         if ((rc = pthread_create(&uevq_thr, &misc_attr, uevqloop, vecs))) {
1903                 condlog(0, "failed to create uevent dispatcher: %d", rc);
1904                 goto failed;
1905         }
1906         pthread_attr_destroy(&misc_attr);
1907
1908         /* Startup complete, create logfile */
1909         pid_rc = pidfile_create(DEFAULT_PIDFILE, daemon_pid);
1910         /* Ignore errors, we can live without */
1911
1912         running_state = DAEMON_RUNNING;
1913 #ifdef USE_SYSTEMD
1914         sd_notify(0, "READY=1\nSTATUS=running");
1915 #endif
1916
1917         /*
1918          * exit path
1919          */
1920         while(sem_wait(&exit_sem) != 0); /* Do nothing */
1921
1922 #ifdef USE_SYSTEMD
1923         sd_notify(0, "STATUS=shutdown");
1924 #endif
1925         running_state = DAEMON_SHUTDOWN;
1926         lock(vecs->lock);
1927         if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF)
1928                 vector_foreach_slot(vecs->mpvec, mpp, i)
1929                         dm_queue_if_no_path(mpp->alias, 0);
1930         remove_maps_and_stop_waiters(vecs);
1931         unlock(vecs->lock);
1932
1933         pthread_cancel(check_thr);
1934         pthread_cancel(uevent_thr);
1935         pthread_cancel(uxlsnr_thr);
1936         pthread_cancel(uevq_thr);
1937
1938         lock(vecs->lock);
1939         free_pathvec(vecs->pathvec, FREE_PATHS);
1940         vecs->pathvec = NULL;
1941         unlock(vecs->lock);
1942         /* Now all the waitevent threads will start rushing in. */
1943         while (vecs->lock.depth > 0) {
1944                 sleep (1); /* This is weak. */
1945                 condlog(3, "Have %d wait event checkers threads to de-alloc,"
1946                         " waiting...", vecs->lock.depth);
1947         }
1948         pthread_mutex_destroy(vecs->lock.mutex);
1949         FREE(vecs->lock.mutex);
1950         vecs->lock.depth = 0;
1951         vecs->lock.mutex = NULL;
1952         FREE(vecs);
1953         vecs = NULL;
1954
1955         cleanup_checkers();
1956         cleanup_prio();
1957
1958         dm_lib_release();
1959         dm_lib_exit();
1960
1961         /* We're done here */
1962         if (!pid_rc) {
1963                 condlog(3, "unlink pidfile");
1964                 unlink(DEFAULT_PIDFILE);
1965         }
1966
1967         condlog(2, "--------shut down-------");
1968
1969         if (logsink == 1)
1970                 log_thread_stop();
1971
1972         /*
1973          * Freeing config must be done after condlog() and dm_lib_exit(),
1974          * because logging functions like dlog() and dm_write_log()
1975          * reference the config.
1976          */
1977         free_config(conf);
1978         conf = NULL;
1979         udev_unref(udev);
1980         udev = NULL;
1981 #ifdef _DEBUG_
1982         dbg_free_final(NULL);
1983 #endif
1984
1985 #ifdef USE_SYSTEMD
1986         sd_notify(0, "ERRNO=0");
1987 #endif
1988         exit(0);
1989
1990 failed:
1991 #ifdef USE_SYSTEMD
1992         sd_notify(0, "ERRNO=1");
1993 #endif
1994         exit(1);
1995 }
1996
1997 static int
1998 daemonize(void)
1999 {
2000         int pid;
2001         int dev_null_fd;
2002
2003         if( (pid = fork()) < 0){
2004                 fprintf(stderr, "Failed first fork : %s\n", strerror(errno));
2005                 return -1;
2006         }
2007         else if (pid != 0)
2008                 return pid;
2009
2010         setsid();
2011
2012         if ( (pid = fork()) < 0)
2013                 fprintf(stderr, "Failed second fork : %s\n", strerror(errno));
2014         else if (pid != 0)
2015                 _exit(0);
2016
2017         if (chdir("/") < 0)
2018                 fprintf(stderr, "cannot chdir to '/', continuing\n");
2019
2020         dev_null_fd = open("/dev/null", O_RDWR);
2021         if (dev_null_fd < 0){
2022                 fprintf(stderr, "cannot open /dev/null for input & output : %s\n",
2023                         strerror(errno));
2024                 _exit(0);
2025         }
2026
2027         close(STDIN_FILENO);
2028         if (dup(dev_null_fd) < 0) {
2029                 fprintf(stderr, "cannot dup /dev/null to stdin : %s\n",
2030                         strerror(errno));
2031                 _exit(0);
2032         }
2033         close(STDOUT_FILENO);
2034         if (dup(dev_null_fd) < 0) {
2035                 fprintf(stderr, "cannot dup /dev/null to stdout : %s\n",
2036                         strerror(errno));
2037                 _exit(0);
2038         }
2039         close(STDERR_FILENO);
2040         if (dup(dev_null_fd) < 0) {
2041                 fprintf(stderr, "cannot dup /dev/null to stderr : %s\n",
2042                         strerror(errno));
2043                 _exit(0);
2044         }
2045         close(dev_null_fd);
2046         daemon_pid = getpid();
2047         return 0;
2048 }
2049
2050 int
2051 main (int argc, char *argv[])
2052 {
2053         extern char *optarg;
2054         extern int optind;
2055         int arg;
2056         int err;
2057         int foreground = 0;
2058
2059         logsink = 1;
2060         running_state = DAEMON_INIT;
2061         dm_init();
2062
2063         if (getuid() != 0) {
2064                 fprintf(stderr, "need to be root\n");
2065                 exit(1);
2066         }
2067
2068         /* make sure we don't lock any path */
2069         if (chdir("/") < 0)
2070                 fprintf(stderr, "can't chdir to root directory : %s\n",
2071                         strerror(errno));
2072         umask(umask(077) | 022);
2073
2074         conf = alloc_config();
2075
2076         if (!conf)
2077                 exit(1);
2078
2079         while ((arg = getopt(argc, argv, ":dsv:k::B")) != EOF ) {
2080         switch(arg) {
2081                 case 'd':
2082                         foreground = 1;
2083                         if (logsink > 0)
2084                                 logsink = 0;
2085                         //debug=1; /* ### comment me out ### */
2086                         break;
2087                 case 'v':
2088                         if (sizeof(optarg) > sizeof(char *) ||
2089                             !isdigit(optarg[0]))
2090                                 exit(1);
2091
2092                         conf->verbosity = atoi(optarg);
2093                         break;
2094                 case 's':
2095                         logsink = -1;
2096                         break;
2097                 case 'k':
2098                         if (load_config(DEFAULT_CONFIGFILE, udev_new()))
2099                                 exit(1);
2100                         uxclnt(optarg, conf->uxsock_timeout);
2101                         exit(0);
2102                 case 'B':
2103                         conf->bindings_read_only = 1;
2104                         break;
2105                 default:
2106                         ;
2107                 }
2108         }
2109         if (optind < argc) {
2110                 char cmd[CMDSIZE];
2111                 char * s = cmd;
2112                 char * c = s;
2113
2114                 if (load_config(DEFAULT_CONFIGFILE, udev_new()))
2115                         exit(1);
2116                 while (optind < argc) {
2117                         if (strchr(argv[optind], ' '))
2118                                 c += snprintf(c, s + CMDSIZE - c, "\"%s\" ", argv[optind]);
2119                         else
2120                                 c += snprintf(c, s + CMDSIZE - c, "%s ", argv[optind]);
2121                         optind++;
2122                 }
2123                 c += snprintf(c, s + CMDSIZE - c, "\n");
2124                 uxclnt(s, conf->uxsock_timeout);
2125                 exit(0);
2126         }
2127
2128         if (foreground) {
2129                 if (!isatty(fileno(stdout)))
2130                         setbuf(stdout, NULL);
2131                 err = 0;
2132                 daemon_pid = getpid();
2133         } else
2134                 err = daemonize();
2135
2136         if (err < 0)
2137                 /* error */
2138                 exit(1);
2139         else if (err > 0)
2140                 /* parent dies */
2141                 exit(0);
2142         else
2143                 /* child lives */
2144                 return (child(NULL));
2145 }
2146
2147 void *  mpath_pr_event_handler_fn (void * pathp )
2148 {
2149         struct multipath * mpp;
2150         int i,j, ret, isFound;
2151         struct path * pp = (struct path *)pathp;
2152         unsigned char *keyp;
2153         uint64_t prkey;
2154         struct prout_param_descriptor *param;
2155         struct prin_resp *resp;
2156
2157         mpp = pp->mpp;
2158
2159         resp = mpath_alloc_prin_response(MPATH_PRIN_RKEY_SA);
2160         if (!resp){
2161                 condlog(0,"%s Alloc failed for prin response", pp->dev);
2162                 return NULL;
2163         }
2164
2165         ret = prin_do_scsi_ioctl(pp->dev, MPATH_PRIN_RKEY_SA, resp, 0);
2166         if (ret != MPATH_PR_SUCCESS )
2167         {
2168                 condlog(0,"%s : pr in read keys service action failed. Error=%d", pp->dev, ret);
2169                 goto out;
2170         }
2171
2172         condlog(3, " event pr=%d addlen=%d",resp->prin_descriptor.prin_readkeys.prgeneration,
2173                         resp->prin_descriptor.prin_readkeys.additional_length );
2174
2175         if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
2176         {
2177                 condlog(1, "%s: No key found. Device may not be registered.", pp->dev);
2178                 ret = MPATH_PR_SUCCESS;
2179                 goto out;
2180         }
2181         prkey = 0;
2182         keyp = (unsigned char *)mpp->reservation_key;
2183         for (j = 0; j < 8; ++j) {
2184                 if (j > 0)
2185                         prkey <<= 8;
2186                 prkey |= *keyp;
2187                 ++keyp;
2188         }
2189         condlog(2, "Multipath  reservation_key: 0x%" PRIx64 " ", prkey);
2190
2191         isFound =0;
2192         for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ )
2193         {
2194                 condlog(2, "PR IN READKEYS[%d]  reservation key:",i);
2195                 dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , -1);
2196                 if (!memcmp(mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
2197                 {
2198                         condlog(2, "%s: pr key found in prin readkeys response", mpp->alias);
2199                         isFound =1;
2200                         break;
2201                 }
2202         }
2203         if (!isFound)
2204         {
2205                 condlog(0, "%s: Either device not registered or ", pp->dev);
2206                 condlog(0, "host is not authorised for registration. Skip path");
2207                 ret = MPATH_PR_OTHER;
2208                 goto out;
2209         }
2210
2211         param= malloc(sizeof(struct prout_param_descriptor));
2212         memset(param, 0 , sizeof(struct prout_param_descriptor));
2213
2214         for (j = 7; j >= 0; --j) {
2215                 param->sa_key[j] = (prkey & 0xff);
2216                 prkey >>= 8;
2217         }
2218         param->num_transportid = 0;
2219
2220         condlog(3, "device %s:%s", pp->dev, pp->mpp->wwid);
2221
2222         ret = prout_do_scsi_ioctl(pp->dev, MPATH_PROUT_REG_IGN_SA, 0, 0, param, 0);
2223         if (ret != MPATH_PR_SUCCESS )
2224         {
2225                 condlog(0,"%s: Reservation registration failed. Error: %d", pp->dev, ret);
2226         }
2227         mpp->prflag = 1;
2228
2229         free(param);
2230 out:
2231         free(resp);
2232         return NULL;
2233 }
2234
2235 int mpath_pr_event_handle(struct path *pp)
2236 {
2237         pthread_t thread;
2238         int rc;
2239         pthread_attr_t attr;
2240         struct multipath * mpp;
2241
2242         mpp = pp->mpp;
2243
2244         if (!mpp->reservation_key)
2245                 return -1;
2246
2247         pthread_attr_init(&attr);
2248         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
2249
2250         rc = pthread_create(&thread, NULL , mpath_pr_event_handler_fn, pp);
2251         if (rc) {
2252                 condlog(0, "%s: ERROR; return code from pthread_create() is %d", pp->dev, rc);
2253                 return -1;
2254         }
2255         pthread_attr_destroy(&attr);
2256         rc = pthread_join(thread, NULL);
2257         return 0;
2258 }
2259