libmultipath/foreign/nvme: fix ouput for "%n" wildcard
[multipath-tools/.git] / libmultipath / foreign / nvme.c
1 /*
2   Copyright (c) 2018 Martin Wilck, SUSE Linux GmbH
3
4   This program is free software; you can redistribute it and/or
5   modify it under the terms of the GNU General Public License
6   as published by the Free Software Foundation; either version 2
7   of the License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "nvme-lib.h"
19 #include <sys/types.h>
20 #include <sys/sysmacros.h>
21 #include <libudev.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdbool.h>
26 #include <libudev.h>
27 #include <pthread.h>
28 #include <limits.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include "util.h"
34 #include "vector.h"
35 #include "generic.h"
36 #include "foreign.h"
37 #include "debug.h"
38 #include "structs.h"
39 #include "sysfs.h"
40
41 static const char nvme_vendor[] = "NVMe";
42 static const char N_A[] = "n/a";
43 const char *THIS;
44
45 struct nvme_map;
46 struct nvme_pathgroup {
47         struct gen_pathgroup gen;
48         struct _vector pathvec;
49 };
50
51 struct nvme_path {
52         struct gen_path gen;
53         struct udev_device *udev;
54         struct udev_device *ctl;
55         struct nvme_map *map;
56         bool seen;
57         /*
58          * The kernel works in failover mode.
59          * Each path has a separate path group.
60          */
61         struct nvme_pathgroup pg;
62 };
63
64 struct nvme_map {
65         struct gen_multipath gen;
66         struct udev_device *udev;
67         struct udev_device *subsys;
68         dev_t devt;
69         struct _vector pgvec;
70         int nr_live;
71         int ana_supported;
72 };
73
74 #define NAME_LEN 64 /* buffer length for temp attributes */
75 #define const_gen_mp_to_nvme(g) ((const struct nvme_map*)(g))
76 #define gen_mp_to_nvme(g) ((struct nvme_map*)(g))
77 #define nvme_mp_to_gen(n) &((n)->gen)
78 #define const_gen_pg_to_nvme(g) ((const struct nvme_pathgroup*)(g))
79 #define gen_pg_to_nvme(g) ((struct nvme_pathgroup*)(g))
80 #define nvme_pg_to_gen(n) &((n)->gen)
81 #define const_gen_path_to_nvme(g) ((const struct nvme_path*)(g))
82 #define gen_path_to_nvme(g) ((struct nvme_path*)(g))
83 #define nvme_path_to_gen(n) &((n)->gen)
84 #define nvme_pg_to_path(x) (VECTOR_SLOT(&((x)->pathvec), 0))
85 #define nvme_path_to_pg(x) &((x)->pg)
86
87 static void cleanup_nvme_path(struct nvme_path *path)
88 {
89         condlog(5, "%s: %p %p", __func__, path, path->udev);
90         if (path->udev)
91                 udev_device_unref(path->udev);
92         vector_reset(&path->pg.pathvec);
93
94         /* ctl is implicitly referenced by udev, no need to unref */
95         free(path);
96 }
97
98 static void cleanup_nvme_map(struct nvme_map *map)
99 {
100         struct nvme_pathgroup *pg;
101         struct nvme_path *path;
102         int i;
103
104         vector_foreach_slot_backwards(&map->pgvec, pg, i) {
105                 path = nvme_pg_to_path(pg);
106                 condlog(5, "%s: %d %p", __func__, i, path);
107                 cleanup_nvme_path(path);
108                 vector_del_slot(&map->pgvec, i);
109         }
110         vector_reset(&map->pgvec);
111         if (map->udev)
112                 udev_device_unref(map->udev);
113         /* subsys is implicitly referenced by udev, no need to unref */
114         free(map);
115 }
116
117 static const struct _vector*
118 nvme_mp_get_pgs(const struct gen_multipath *gmp) {
119         const struct nvme_map *nvme = const_gen_mp_to_nvme(gmp);
120
121         /* This is all used under the lock, no need to copy */
122         return &nvme->pgvec;
123 }
124
125 static void
126 nvme_mp_rel_pgs(const struct gen_multipath *gmp, const struct _vector *v)
127 {
128         /* empty */
129 }
130
131 static void rstrip(char *str)
132 {
133         int n;
134
135         for (n = strlen(str) - 1; n >= 0 && str[n] == ' '; n--);
136         str[n+1] = '\0';
137 }
138
139 static int snprint_nvme_map(const struct gen_multipath *gmp,
140                             char *buff, int len, char wildcard)
141 {
142         const struct nvme_map *nvm = const_gen_mp_to_nvme(gmp);
143         char fld[NAME_LEN];
144         const char *val;
145
146         switch (wildcard) {
147         case 'd':
148                 return snprintf(buff, len, "%s",
149                                 udev_device_get_sysname(nvm->udev));
150         case 'n':
151                 return snprintf(buff, len, "%s:nsid.%s",
152                                 udev_device_get_sysattr_value(nvm->subsys,
153                                                               "subsysnqn"),
154                                 udev_device_get_sysattr_value(nvm->udev,
155                                                               "nsid"));
156         case 'w':
157                 return snprintf(buff, len, "%s",
158                                 udev_device_get_sysattr_value(nvm->udev,
159                                                               "wwid"));
160         case 'N':
161                 return snprintf(buff, len, "%u", nvm->nr_live);
162         case 'S':
163                 return snprintf(buff, len, "%s",
164                                 udev_device_get_sysattr_value(nvm->udev,
165                                                               "size"));
166         case 'v':
167                 return snprintf(buff, len, "%s", nvme_vendor);
168         case 's':
169         case 'p':
170                 snprintf(fld, sizeof(fld), "%s",
171                          udev_device_get_sysattr_value(nvm->subsys,
172                                                       "model"));
173                 rstrip(fld);
174                 if (wildcard == 'p')
175                         return snprintf(buff, len, "%s", fld);
176                 return snprintf(buff, len, "%s,%s,%s", nvme_vendor, fld,
177                                 udev_device_get_sysattr_value(nvm->subsys,
178                                                               "firmware_rev"));
179         case 'e':
180                 return snprintf(buff, len, "%s",
181                                 udev_device_get_sysattr_value(nvm->subsys,
182                                                               "firmware_rev"));
183         case 'r':
184                 val = udev_device_get_sysattr_value(nvm->udev, "ro");
185                 if (val[0] == 1)
186                         return snprintf(buff, len, "%s", "ro");
187                 else
188                         return snprintf(buff, len, "%s", "rw");
189         case 'G':
190                 return snprintf(buff, len, "%s", THIS);
191         case 'h':
192                 if (nvm->ana_supported == YNU_YES)
193                         return snprintf(buff, len, "ANA");
194         default:
195                 break;
196         }
197
198         return snprintf(buff, len, N_A);
199 }
200
201 static const struct _vector*
202 nvme_pg_get_paths(const struct gen_pathgroup *gpg) {
203         const struct nvme_pathgroup *gp = const_gen_pg_to_nvme(gpg);
204
205         /* This is all used under the lock, no need to copy */
206         return &gp->pathvec;
207 }
208
209 static void
210 nvme_pg_rel_paths(const struct gen_pathgroup *gpg, const struct _vector *v)
211 {
212         /* empty */
213 }
214
215 static int snprint_hcil(const struct nvme_path *np, char *buf, int len)
216 {
217         unsigned int nvmeid, ctlid, nsid;
218         int rc;
219         const char *sysname = udev_device_get_sysname(np->udev);
220
221         rc = sscanf(sysname, "nvme%uc%un%u", &nvmeid, &ctlid, &nsid);
222         if (rc != 3) {
223                 condlog(1, "%s: failed to scan %s", __func__, sysname);
224                 rc = snprintf(buf, len, "(ERR:%s)", sysname);
225         } else
226                 rc = snprintf(buf, len, "%u:%u:%u", nvmeid, ctlid, nsid);
227         return (rc < len ? rc : len);
228 }
229
230 static int snprint_nvme_path(const struct gen_path *gp,
231                              char *buff, int len, char wildcard)
232 {
233         const struct nvme_path *np = const_gen_path_to_nvme(gp);
234         dev_t devt;
235         char fld[NAME_LEN];
236         struct udev_device *pci;
237
238         switch (wildcard) {
239         case 'w':
240                 return snprintf(buff, len, "%s",
241                                 udev_device_get_sysattr_value(np->udev,
242                                                               "wwid"));
243         case 'd':
244                 return snprintf(buff, len, "%s",
245                                 udev_device_get_sysname(np->udev));
246         case 'i':
247                 return snprint_hcil(np, buff, len);
248         case 'D':
249                 devt = udev_device_get_devnum(np->udev);
250                 return snprintf(buff, len, "%u:%u", major(devt), minor(devt));
251         case 'o':
252                 sysfs_attr_get_value(np->ctl, "state", fld, sizeof(fld));
253                 return snprintf(buff, len, "%s", fld);
254         case 'T':
255                 if (sysfs_attr_get_value(np->udev, "ana_state", fld,
256                                          sizeof(fld)) > 0)
257                         return snprintf(buff, len, "%s", fld);
258                 break;
259         case 'p':
260                 if (sysfs_attr_get_value(np->udev, "ana_state", fld,
261                                          sizeof(fld)) > 0) {
262                         rstrip(fld);
263                         if (!strcmp(fld, "optimized"))
264                                 return snprintf(buff, len, "%d", 50);
265                         else if (!strcmp(fld, "non-optimized"))
266                                 return snprintf(buff, len, "%d", 10);
267                         else
268                                 return snprintf(buff, len, "%d", 0);
269                 }
270                 break;
271         case 's':
272                 snprintf(fld, sizeof(fld), "%s",
273                          udev_device_get_sysattr_value(np->ctl,
274                                                       "model"));
275                 rstrip(fld);
276                 return snprintf(buff, len, "%s,%s,%s", nvme_vendor, fld,
277                                 udev_device_get_sysattr_value(np->ctl,
278                                                               "firmware_rev"));
279         case 'S':
280                 return snprintf(buff, len, "%s",
281                         udev_device_get_sysattr_value(np->udev,
282                                                       "size"));
283         case 'z':
284                 return snprintf(buff, len, "%s",
285                                 udev_device_get_sysattr_value(np->ctl,
286                                                               "serial"));
287         case 'm':
288                 return snprintf(buff, len, "%s",
289                                 udev_device_get_sysname(np->map->udev));
290         case 'N':
291         case 'R':
292                 return snprintf(buff, len, "%s:%s",
293                         udev_device_get_sysattr_value(np->ctl,
294                                                       "transport"),
295                         udev_device_get_sysattr_value(np->ctl,
296                                                       "address"));
297         case 'G':
298                 return snprintf(buff, len, "[%s]", THIS);
299         case 'a':
300                 pci = udev_device_get_parent_with_subsystem_devtype(np->ctl,
301                                                                     "pci",
302                                                                     NULL);
303                 if (pci != NULL)
304                         return snprintf(buff, len, "PCI:%s",
305                                         udev_device_get_sysname(pci));
306                 /* fall through */
307         default:
308                 break;
309         }
310         return snprintf(buff, len, "%s", N_A);
311         return 0;
312 }
313
314 static int snprint_nvme_pg(const struct gen_pathgroup *gmp,
315                            char *buff, int len, char wildcard)
316 {
317         const struct nvme_pathgroup *pg = const_gen_pg_to_nvme(gmp);
318         const struct nvme_path *path = nvme_pg_to_path(pg);
319
320         switch (wildcard) {
321         case 't':
322                 return snprint_nvme_path(nvme_path_to_gen(path),
323                                          buff, len, 'T');
324         case 'p':
325                 return snprint_nvme_path(nvme_path_to_gen(path),
326                                          buff, len, 'p');
327         default:
328                 return snprintf(buff, len, N_A);
329         }
330 }
331
332 static int nvme_style(const struct gen_multipath* gm,
333                       char *buf, int len, int verbosity)
334 {
335         int n = snprintf(buf, len, "%%w [%%G]:%%d %%s");
336
337         return (n < len ? n : len - 1);
338 }
339
340 static const struct gen_multipath_ops nvme_map_ops = {
341         .get_pathgroups = nvme_mp_get_pgs,
342         .rel_pathgroups = nvme_mp_rel_pgs,
343         .style = nvme_style,
344         .snprint = snprint_nvme_map,
345 };
346
347 static const struct gen_pathgroup_ops nvme_pg_ops __attribute__((unused)) = {
348         .get_paths = nvme_pg_get_paths,
349         .rel_paths = nvme_pg_rel_paths,
350         .snprint = snprint_nvme_pg,
351 };
352
353 static const struct gen_path_ops nvme_path_ops __attribute__((unused)) = {
354         .snprint = snprint_nvme_path,
355 };
356
357 struct context {
358         pthread_mutex_t mutex;
359         vector mpvec;
360         struct udev *udev;
361 };
362
363 void lock(struct context *ctx)
364 {
365         pthread_mutex_lock(&ctx->mutex);
366 }
367
368 void unlock(void *arg)
369 {
370         struct context *ctx = arg;
371
372         pthread_mutex_unlock(&ctx->mutex);
373 }
374
375 static int _delete_all(struct context *ctx)
376 {
377         struct nvme_map *nm;
378         int n = VECTOR_SIZE(ctx->mpvec), i;
379
380         if (n == 0)
381                 return FOREIGN_IGNORED;
382
383         vector_foreach_slot_backwards(ctx->mpvec, nm, i) {
384                 vector_del_slot(ctx->mpvec, i);
385                 cleanup_nvme_map(nm);
386         }
387         return FOREIGN_OK;
388 }
389
390 int delete_all(struct context *ctx)
391 {
392         int rc;
393
394         condlog(5, "%s called for \"%s\"", __func__, THIS);
395
396         lock(ctx);
397         pthread_cleanup_push(unlock, ctx);
398         rc = _delete_all(ctx);
399         pthread_cleanup_pop(1);
400
401         return rc;
402 }
403
404 void cleanup(struct context *ctx)
405 {
406         (void)delete_all(ctx);
407
408         lock(ctx);
409         /*
410          * Locking is not strictly necessary here, locking in foreign.c
411          * makes sure that no other code is called with this ctx any more.
412          * But this should make static checkers feel better.
413          */
414         pthread_cleanup_push(unlock, ctx);
415         if (ctx->udev)
416                 udev_unref(ctx->udev);
417         if (ctx->mpvec)
418                 vector_free(ctx->mpvec);
419         ctx->mpvec = NULL;
420         ctx->udev = NULL;
421         pthread_cleanup_pop(1);
422         pthread_mutex_destroy(&ctx->mutex);
423
424         free(ctx);
425 }
426
427 struct context *init(unsigned int api, const char *name)
428 {
429         struct context *ctx;
430
431         if (api > LIBMP_FOREIGN_API) {
432                 condlog(0, "%s: api version mismatch: %08x > %08x\n",
433                         __func__, api, LIBMP_FOREIGN_API);
434                 return NULL;
435         }
436
437         if ((ctx = calloc(1, sizeof(*ctx)))== NULL)
438                 return NULL;
439
440         pthread_mutex_init(&ctx->mutex, NULL);
441
442         ctx->udev = udev_new();
443         if (ctx->udev == NULL)
444                 goto err;
445
446         ctx->mpvec = vector_alloc();
447         if (ctx->mpvec == NULL)
448                 goto err;
449
450         THIS = name;
451         return ctx;
452 err:
453         cleanup(ctx);
454         return NULL;
455 }
456
457 static struct nvme_map *_find_nvme_map_by_devt(const struct context *ctx,
458                                               dev_t devt)
459 {
460         struct nvme_map *nm;
461         int i;
462
463         if (ctx->mpvec == NULL)
464                 return NULL;
465
466         vector_foreach_slot(ctx->mpvec, nm, i) {
467                 if (nm->devt == devt)
468                         return nm;
469         }
470
471         return NULL;
472 }
473
474 static struct nvme_path *
475 _find_path_by_syspath(struct nvme_map *map, const char *syspath)
476 {
477         struct nvme_pathgroup *pg;
478         char real[PATH_MAX];
479         const char *ppath;
480         int i;
481
482         ppath = realpath(syspath, real);
483         if (ppath == NULL) {
484                 condlog(1, "%s: %s: error in realpath", __func__, THIS);
485                 ppath = syspath;
486         }
487
488         vector_foreach_slot(&map->pgvec, pg, i) {
489                 struct nvme_path *path = nvme_pg_to_path(pg);
490
491                 if (!strcmp(ppath,
492                             udev_device_get_syspath(path->udev)))
493                         return path;
494         }
495         condlog(4, "%s: %s: %s not found", __func__, THIS, ppath);
496         return NULL;
497 }
498
499 static void _udev_device_unref(void *p)
500 {
501         udev_device_unref(p);
502 }
503
504 static void _udev_enumerate_unref(void *p)
505 {
506         udev_enumerate_unref(p);
507 }
508
509 static int _dirent_controller(const struct dirent *di)
510 {
511         static const char nvme_prefix[] = "nvme";
512         const char *p;
513
514 #ifdef _DIRENT_HAVE_D_TYPE
515         if (di->d_type != DT_LNK)
516                 return 0;
517 #endif
518         if (strncmp(di->d_name, nvme_prefix, sizeof(nvme_prefix) - 1))
519                 return 0;
520         p = di->d_name + sizeof(nvme_prefix) - 1;
521         if (*p == '\0' || !isdigit(*p))
522                 return 0;
523         for (++p; *p != '\0'; ++p)
524                 if (!isdigit(*p))
525                         return 0;
526         return 1;
527 }
528
529 /* Find the block device for a given nvme controller */
530 struct udev_device *get_ctrl_blkdev(const struct context *ctx,
531                                     struct udev_device *ctrl)
532 {
533         struct udev_list_entry *item;
534         struct udev_device *blkdev = NULL;
535         struct udev_enumerate *enm = udev_enumerate_new(ctx->udev);
536
537         if (enm == NULL)
538                 return NULL;
539
540         pthread_cleanup_push(_udev_enumerate_unref, enm);
541         if (udev_enumerate_add_match_parent(enm, ctrl) < 0)
542                 goto out;
543         if (udev_enumerate_add_match_subsystem(enm, "block"))
544                 goto out;
545
546         if (udev_enumerate_scan_devices(enm) < 0) {
547                 condlog(1, "%s: %s: error enumerating devices", __func__, THIS);
548                 goto out;
549         }
550
551         for (item = udev_enumerate_get_list_entry(enm);
552              item != NULL;
553              item = udev_list_entry_get_next(item)) {
554                 struct udev_device *tmp;
555
556                 tmp = udev_device_new_from_syspath(ctx->udev,
557                                            udev_list_entry_get_name(item));
558                 if (tmp == NULL)
559                         continue;
560                 if (!strcmp(udev_device_get_devtype(tmp), "disk")) {
561                         blkdev = tmp;
562                         break;
563                 } else
564                         udev_device_unref(tmp);
565         }
566
567         if (blkdev == NULL)
568                 condlog(1, "%s: %s: failed to get blockdev for %s",
569                         __func__, THIS, udev_device_get_sysname(ctrl));
570         else
571                 condlog(5, "%s: %s: got %s", __func__, THIS,
572                         udev_device_get_sysname(blkdev));
573 out:
574         pthread_cleanup_pop(1);
575         return blkdev;
576 }
577
578 static void test_ana_support(struct nvme_map *map, struct udev_device *ctl)
579 {
580         const char *dev_t;
581         char sys_path[64];
582         long fd;
583         int rc;
584
585         if (map->ana_supported != YNU_UNDEF)
586                 return;
587
588         dev_t = udev_device_get_sysattr_value(ctl, "dev");
589         if (snprintf(sys_path, sizeof(sys_path), "/dev/char/%s", dev_t)
590             >= sizeof(sys_path))
591                 return;
592
593         fd = open(sys_path, O_RDONLY);
594         if (fd == -1) {
595                 condlog(2, "%s: error opening %s", __func__, sys_path);
596                 return;
597         }
598
599         pthread_cleanup_push(close_fd, (void *)fd);
600         rc = nvme_id_ctrl_ana(fd, NULL);
601         if (rc < 0)
602                 condlog(2, "%s: error in nvme_id_ctrl: %s", __func__,
603                         strerror(errno));
604         else {
605                 map->ana_supported = (rc == 1 ? YNU_YES : YNU_NO);
606                 condlog(3, "%s: NVMe ctrl %s: ANA %s supported", __func__, dev_t,
607                         rc == 1 ? "is" : "is not");
608         }
609         pthread_cleanup_pop(1);
610 }
611
612 static void _find_controllers(struct context *ctx, struct nvme_map *map)
613 {
614         char pathbuf[PATH_MAX], realbuf[PATH_MAX];
615         struct dirent **di = NULL;
616         struct scandir_result sr;
617         struct udev_device *subsys;
618         struct nvme_pathgroup *pg;
619         struct nvme_path *path;
620         int r, i, n;
621
622         if (map == NULL || map->udev == NULL)
623                 return;
624
625         vector_foreach_slot(&map->pgvec, pg, i) {
626                 path = nvme_pg_to_path(pg);
627                 path->seen = false;
628         }
629
630         subsys = udev_device_get_parent_with_subsystem_devtype(map->udev,
631                                                                "nvme-subsystem",
632                                                                NULL);
633         if (subsys == NULL) {
634                 condlog(1, "%s: %s: BUG: no NVME subsys for %s", __func__, THIS,
635                         udev_device_get_sysname(map->udev));
636                 return;
637         }
638
639         n = snprintf(pathbuf, sizeof(pathbuf), "%s",
640                      udev_device_get_syspath(subsys));
641         r = scandir(pathbuf, &di, _dirent_controller, alphasort);
642
643         if (r == 0) {
644                 condlog(3, "%s: %s: no controllers for %s", __func__, THIS,
645                         udev_device_get_sysname(map->udev));
646                 return;
647         } else if (r < 0) {
648                 condlog(1, "%s: %s: error %d scanning controllers of %s",
649                         __func__, THIS, errno,
650                         udev_device_get_sysname(map->udev));
651                 return;
652         }
653
654         sr.di = di;
655         sr.n = r;
656         pthread_cleanup_push_cast(free_scandir_result, &sr);
657         for (i = 0; i < r; i++) {
658                 char *fn = di[i]->d_name;
659                 struct udev_device *ctrl, *udev;
660
661                 if (snprintf(pathbuf + n, sizeof(pathbuf) - n, "/%s", fn)
662                     >= sizeof(pathbuf) - n)
663                         continue;
664                 if (realpath(pathbuf, realbuf) == NULL) {
665                         condlog(3, "%s: %s: realpath: %s", __func__, THIS,
666                                 strerror(errno));
667                         continue;
668                 }
669                 condlog(4, "%s: %s: found %s", __func__, THIS, realbuf);
670
671                 ctrl = udev_device_new_from_syspath(ctx->udev, realbuf);
672                 if (ctrl == NULL) {
673                         condlog(1, "%s: %s: failed to get udev device for %s",
674                                 __func__, THIS, realbuf);
675                         continue;
676                 }
677
678                 pthread_cleanup_push(_udev_device_unref, ctrl);
679                 udev = get_ctrl_blkdev(ctx, ctrl);
680                 /*
681                  * We give up the reference to the nvme device here and get
682                  * it back from the child below.
683                  * This way we don't need to worry about unreffing it.
684                  */
685                 pthread_cleanup_pop(1);
686
687                 if (udev == NULL)
688                         continue;
689
690                 path = _find_path_by_syspath(map,
691                                              udev_device_get_syspath(udev));
692                 if (path != NULL) {
693                         path->seen = true;
694                         condlog(4, "%s: %s already known",
695                                 __func__, fn);
696                         continue;
697                 }
698
699                 path = calloc(1, sizeof(*path));
700                 if (path == NULL)
701                         continue;
702
703                 path->gen.ops = &nvme_path_ops;
704                 path->udev = udev;
705                 path->seen = true;
706                 path->map = map;
707                 path->ctl = udev_device_get_parent_with_subsystem_devtype
708                         (udev, "nvme", NULL);
709                 if (path->ctl == NULL) {
710                         condlog(1, "%s: %s: failed to get controller for %s",
711                                 __func__, THIS, fn);
712                         cleanup_nvme_path(path);
713                         continue;
714                 }
715                 test_ana_support(map, path->ctl);
716
717                 path->pg.gen.ops = &nvme_pg_ops;
718                 if (vector_alloc_slot(&path->pg.pathvec) == NULL) {
719                         cleanup_nvme_path(path);
720                         continue;
721                 }
722                 vector_set_slot(&path->pg.pathvec, path);
723                 if (vector_alloc_slot(&map->pgvec) == NULL) {
724                         cleanup_nvme_path(path);
725                         continue;
726                 }
727                 vector_set_slot(&map->pgvec, &path->pg);
728                 condlog(3, "%s: %s: new path %s added to %s",
729                         __func__, THIS, udev_device_get_sysname(udev),
730                         udev_device_get_sysname(map->udev));
731         }
732         pthread_cleanup_pop(1);
733
734         map->nr_live = 0;
735         vector_foreach_slot_backwards(&map->pgvec, pg, i) {
736                 path = nvme_pg_to_path(pg);
737                 if (!path->seen) {
738                         condlog(1, "path %d not found in %s any more",
739                                 i, udev_device_get_sysname(map->udev));
740                         vector_del_slot(&map->pgvec, i);
741                         cleanup_nvme_path(path);
742                 } else {
743                         static const char live_state[] = "live";
744                         char state[16];
745
746                         if ((sysfs_attr_get_value(path->ctl, "state", state,
747                                                   sizeof(state)) > 0) &&
748                             !strncmp(state, live_state, sizeof(live_state) - 1))
749                                 map->nr_live++;
750                 }
751         }
752         condlog(3, "%s: %s: map %s has %d/%d live paths", __func__, THIS,
753                 udev_device_get_sysname(map->udev), map->nr_live,
754                 VECTOR_SIZE(&map->pgvec));
755 }
756
757 static int _add_map(struct context *ctx, struct udev_device *ud,
758                     struct udev_device *subsys)
759 {
760         dev_t devt = udev_device_get_devnum(ud);
761         struct nvme_map *map;
762
763         if (_find_nvme_map_by_devt(ctx, devt) != NULL)
764                 return FOREIGN_OK;
765
766         map = calloc(1, sizeof(*map));
767         if (map == NULL)
768                 return FOREIGN_ERR;
769
770         map->devt = devt;
771         map->udev = udev_device_ref(ud);
772         /*
773          * subsys is implicitly referenced by map->udev,
774          * no need to take a reference here.
775          */
776         map->subsys = subsys;
777         map->gen.ops = &nvme_map_ops;
778
779         if (vector_alloc_slot(ctx->mpvec) == NULL) {
780                 cleanup_nvme_map(map);
781                 return FOREIGN_ERR;
782         }
783         vector_set_slot(ctx->mpvec, map);
784         _find_controllers(ctx, map);
785
786         return FOREIGN_CLAIMED;
787 }
788
789 int add(struct context *ctx, struct udev_device *ud)
790 {
791         struct udev_device *subsys;
792         int rc;
793
794         condlog(5, "%s called for \"%s\"", __func__, THIS);
795
796         if (ud == NULL)
797                 return FOREIGN_ERR;
798         if (strcmp("disk", udev_device_get_devtype(ud)))
799                 return FOREIGN_IGNORED;
800
801         subsys = udev_device_get_parent_with_subsystem_devtype(ud,
802                                                                "nvme-subsystem",
803                                                                NULL);
804         if (subsys == NULL)
805                 return FOREIGN_IGNORED;
806
807         lock(ctx);
808         pthread_cleanup_push(unlock, ctx);
809         rc = _add_map(ctx, ud, subsys);
810         pthread_cleanup_pop(1);
811
812         if (rc == FOREIGN_CLAIMED)
813                 condlog(3, "%s: %s: added map %s", __func__, THIS,
814                         udev_device_get_sysname(ud));
815         else if (rc != FOREIGN_OK)
816                 condlog(1, "%s: %s: retcode %d adding %s",
817                         __func__, THIS, rc, udev_device_get_sysname(ud));
818
819         return rc;
820 }
821
822 int change(struct context *ctx, struct udev_device *ud)
823 {
824         condlog(5, "%s called for \"%s\"", __func__, THIS);
825         return FOREIGN_IGNORED;
826 }
827
828 static int _delete_map(struct context *ctx, struct udev_device *ud)
829 {
830         int k;
831         struct nvme_map *map;
832         dev_t devt = udev_device_get_devnum(ud);
833
834         map = _find_nvme_map_by_devt(ctx, devt);
835         if (map ==NULL)
836                 return FOREIGN_IGNORED;
837
838         k = find_slot(ctx->mpvec, map);
839         if (k == -1)
840                 return FOREIGN_ERR;
841         else
842                 vector_del_slot(ctx->mpvec, k);
843
844         cleanup_nvme_map(map);
845
846         return FOREIGN_OK;
847 }
848
849 int delete(struct context *ctx, struct udev_device *ud)
850 {
851         int rc;
852
853         condlog(5, "%s called for \"%s\"", __func__, THIS);
854
855         if (ud == NULL)
856                 return FOREIGN_ERR;
857
858         lock(ctx);
859         pthread_cleanup_push(unlock, ctx);
860         rc = _delete_map(ctx, ud);
861         pthread_cleanup_pop(1);
862
863         if (rc == FOREIGN_OK)
864                 condlog(3, "%s: %s: map %s deleted", __func__, THIS,
865                         udev_device_get_sysname(ud));
866         else if (rc != FOREIGN_IGNORED)
867                 condlog(1, "%s: %s: retcode %d deleting map %s", __func__,
868                         THIS, rc, udev_device_get_sysname(ud));
869
870         return rc;
871 }
872
873 void _check(struct context *ctx)
874 {
875         struct gen_multipath *gm;
876         int i;
877
878         vector_foreach_slot(ctx->mpvec, gm, i) {
879                 struct nvme_map *map = gen_mp_to_nvme(gm);
880
881                 _find_controllers(ctx, map);
882         }
883 }
884
885 void check(struct context *ctx)
886 {
887         condlog(4, "%s called for \"%s\"", __func__, THIS);
888         lock(ctx);
889         pthread_cleanup_push(unlock, ctx);
890         _check(ctx);
891         pthread_cleanup_pop(1);
892         return;
893 }
894
895 /*
896  * It's safe to pass our internal pointer, this is only used under the lock.
897  */
898 const struct _vector *get_multipaths(const struct context *ctx)
899 {
900         condlog(5, "%s called for \"%s\"", __func__, THIS);
901         return ctx->mpvec;
902 }
903
904 void release_multipaths(const struct context *ctx, const struct _vector *mpvec)
905 {
906         condlog(5, "%s called for \"%s\"", __func__, THIS);
907         /* NOP */
908 }
909
910 /*
911  * It's safe to pass our internal pointer, this is only used under the lock.
912  */
913 const struct _vector * get_paths(const struct context *ctx)
914 {
915         vector paths = NULL;
916         const struct gen_multipath *gm;
917         int i;
918
919         condlog(5, "%s called for \"%s\"", __func__, THIS);
920         vector_foreach_slot(ctx->mpvec, gm, i) {
921                 const struct nvme_map *nm = const_gen_mp_to_nvme(gm);
922                 paths = vector_convert(paths, &nm->pgvec,
923                                        struct nvme_pathgroup, nvme_pg_to_path);
924         }
925         return paths;
926 }
927
928 void release_paths(const struct context *ctx, const struct _vector *mpvec)
929 {
930         condlog(5, "%s called for \"%s\"", __func__, THIS);
931         vector_free_const(mpvec);
932 }
933
934 /* compile-time check whether all methods are present and correctly typed */
935 #define _METHOD_INIT(x) .x = x
936 static struct foreign __methods __attribute__((unused)) = {
937         _METHOD_INIT(init),
938         _METHOD_INIT(cleanup),
939         _METHOD_INIT(change),
940         _METHOD_INIT(delete),
941         _METHOD_INIT(delete_all),
942         _METHOD_INIT(check),
943         _METHOD_INIT(lock),
944         _METHOD_INIT(unlock),
945         _METHOD_INIT(get_multipaths),
946         _METHOD_INIT(release_multipaths),
947         _METHOD_INIT(get_paths),
948         _METHOD_INIT(release_paths),
949 };