2 Copyright (c) 2018 Martin Wilck, SUSE Linux GmbH
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.
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.
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/>.
19 #include <sys/types.h>
20 #include <sys/sysmacros.h>
42 static const char nvme_vendor[] = "NVMe";
43 static const char N_A[] = "n/a";
47 struct nvme_pathgroup {
48 struct gen_pathgroup gen;
49 struct _vector pathvec;
54 struct udev_device *udev;
55 struct udev_device *ctl;
59 * The kernel works in failover mode.
60 * Each path has a separate path group.
62 struct nvme_pathgroup pg;
66 struct gen_multipath gen;
67 struct udev_device *udev;
68 struct udev_device *subsys;
75 #define NAME_LEN 64 /* buffer length for temp attributes */
76 #define const_gen_mp_to_nvme(g) ((const struct nvme_map*)(g))
77 #define gen_mp_to_nvme(g) ((struct nvme_map*)(g))
78 #define nvme_mp_to_gen(n) &((n)->gen)
79 #define const_gen_pg_to_nvme(g) ((const struct nvme_pathgroup*)(g))
80 #define gen_pg_to_nvme(g) ((struct nvme_pathgroup*)(g))
81 #define nvme_pg_to_gen(n) &((n)->gen)
82 #define const_gen_path_to_nvme(g) ((const struct nvme_path*)(g))
83 #define gen_path_to_nvme(g) ((struct nvme_path*)(g))
84 #define nvme_path_to_gen(n) &((n)->gen)
85 #define nvme_pg_to_path(x) (VECTOR_SLOT(&((x)->pathvec), 0))
86 #define nvme_path_to_pg(x) &((x)->pg)
88 static void cleanup_nvme_path(struct nvme_path *path)
90 condlog(5, "%s: %p %p", __func__, path, path->udev);
92 udev_device_unref(path->udev);
93 vector_reset(&path->pg.pathvec);
95 /* ctl is implicitly referenced by udev, no need to unref */
99 static void cleanup_nvme_map(struct nvme_map *map)
101 struct nvme_pathgroup *pg;
102 struct nvme_path *path;
105 vector_foreach_slot_backwards(&map->pgvec, pg, i) {
106 path = nvme_pg_to_path(pg);
107 condlog(5, "%s: %d %p", __func__, i, path);
108 cleanup_nvme_path(path);
109 vector_del_slot(&map->pgvec, i);
111 vector_reset(&map->pgvec);
113 udev_device_unref(map->udev);
114 /* subsys is implicitly referenced by udev, no need to unref */
118 static const struct _vector*
119 nvme_mp_get_pgs(const struct gen_multipath *gmp) {
120 const struct nvme_map *nvme = const_gen_mp_to_nvme(gmp);
122 /* This is all used under the lock, no need to copy */
127 nvme_mp_rel_pgs(__attribute__((unused)) const struct gen_multipath *gmp,
128 __attribute__((unused)) const struct _vector *v)
133 static void rstrip(char *str)
137 for (n = strlen(str) - 1; n >= 0 && str[n] == ' '; n--);
141 static int snprint_nvme_map(const struct gen_multipath *gmp,
142 struct strbuf *buff, char wildcard)
144 const struct nvme_map *nvm = const_gen_mp_to_nvme(gmp);
150 return append_strbuf_str(buff,
151 udev_device_get_sysname(nvm->udev));
153 return print_strbuf(buff, "%s:nsid.%s",
154 udev_device_get_sysattr_value(nvm->subsys,
156 udev_device_get_sysattr_value(nvm->udev,
159 return append_strbuf_str(buff,
160 udev_device_get_sysattr_value(nvm->udev,
163 return print_strbuf(buff, "%u", nvm->nr_live);
165 return append_strbuf_str(buff,
166 udev_device_get_sysattr_value(nvm->udev,
169 return append_strbuf_str(buff, nvme_vendor);
172 snprintf(fld, sizeof(fld), "%s",
173 udev_device_get_sysattr_value(nvm->subsys,
177 return append_strbuf_str(buff, fld);
178 return print_strbuf(buff, "%s,%s,%s", nvme_vendor, fld,
179 udev_device_get_sysattr_value(nvm->subsys,
182 return append_strbuf_str(buff,
183 udev_device_get_sysattr_value(nvm->subsys,
186 val = udev_device_get_sysattr_value(nvm->udev, "ro");
188 return append_strbuf_str(buff, "ro");
190 return append_strbuf_str(buff, "rw");
192 return append_strbuf_str(buff, THIS);
194 if (nvm->ana_supported == YNU_YES)
195 return append_strbuf_str(buff, "ANA");
200 return append_strbuf_str(buff, N_A);
203 static const struct _vector*
204 nvme_pg_get_paths(const struct gen_pathgroup *gpg) {
205 const struct nvme_pathgroup *gp = const_gen_pg_to_nvme(gpg);
207 /* This is all used under the lock, no need to copy */
212 nvme_pg_rel_paths(__attribute__((unused)) const struct gen_pathgroup *gpg,
213 __attribute__((unused)) const struct _vector *v)
218 static int snprint_hcil(const struct nvme_path *np, struct strbuf *buf)
220 unsigned int nvmeid, ctlid, nsid;
222 const char *sysname = udev_device_get_sysname(np->udev);
224 rc = sscanf(sysname, "nvme%uc%un%u", &nvmeid, &ctlid, &nsid);
226 condlog(1, "%s: failed to scan %s", __func__, sysname);
227 return print_strbuf(buf, "(ERR:%s)", sysname);
229 return print_strbuf(buf, "%u:%u:%u", nvmeid, ctlid, nsid);
232 static int snprint_nvme_path(const struct gen_path *gp,
233 struct strbuf *buff, char wildcard)
235 const struct nvme_path *np = const_gen_path_to_nvme(gp);
238 struct udev_device *pci;
242 return print_strbuf(buff, "%s",
243 udev_device_get_sysattr_value(np->udev,
246 return print_strbuf(buff, "%s",
247 udev_device_get_sysname(np->udev));
249 return snprint_hcil(np, buff);
251 devt = udev_device_get_devnum(np->udev);
252 return print_strbuf(buff, "%u:%u", major(devt), minor(devt));
254 if (sysfs_attr_get_value(np->ctl, "state",
255 fld, sizeof(fld)) > 0)
256 return append_strbuf_str(buff, fld);
259 if (sysfs_attr_get_value(np->udev, "ana_state", fld,
261 return append_strbuf_str(buff, fld);
264 if (sysfs_attr_get_value(np->udev, "ana_state", fld,
267 if (!strcmp(fld, "optimized"))
268 return print_strbuf(buff, "%d", 50);
269 else if (!strcmp(fld, "non-optimized"))
270 return print_strbuf(buff, "%d", 10);
272 return print_strbuf(buff, "%d", 0);
276 snprintf(fld, sizeof(fld), "%s",
277 udev_device_get_sysattr_value(np->ctl,
280 return print_strbuf(buff, "%s,%s,%s", nvme_vendor, fld,
281 udev_device_get_sysattr_value(np->ctl,
284 return append_strbuf_str(buff,
285 udev_device_get_sysattr_value(np->udev,
288 return append_strbuf_str(buff,
289 udev_device_get_sysattr_value(np->ctl,
292 return append_strbuf_str(buff,
293 udev_device_get_sysname(np->map->udev));
296 return print_strbuf(buff, "%s:%s",
297 udev_device_get_sysattr_value(np->ctl,
299 udev_device_get_sysattr_value(np->ctl,
302 return print_strbuf(buff, "[%s]", THIS);
304 pci = udev_device_get_parent_with_subsystem_devtype(np->ctl,
308 return print_strbuf(buff, "PCI:%s",
309 udev_device_get_sysname(pci));
314 return append_strbuf_str(buff, N_A);
317 static int snprint_nvme_pg(const struct gen_pathgroup *gmp,
318 struct strbuf *buff, char wildcard)
320 const struct nvme_pathgroup *pg = const_gen_pg_to_nvme(gmp);
321 const struct nvme_path *path = nvme_pg_to_path(pg);
325 return snprint_nvme_path(nvme_path_to_gen(path),
328 return snprint_nvme_path(nvme_path_to_gen(path),
331 return append_strbuf_str(buff, N_A);
335 static int nvme_style(__attribute__((unused)) const struct gen_multipath* gm,
336 struct strbuf *buf, __attribute__((unused)) int verbosity)
338 return append_strbuf_str(buf, "%%w [%%G]:%%d %%s");
341 static const struct gen_multipath_ops nvme_map_ops = {
342 .get_pathgroups = nvme_mp_get_pgs,
343 .rel_pathgroups = nvme_mp_rel_pgs,
345 .snprint = snprint_nvme_map,
348 static const struct gen_pathgroup_ops nvme_pg_ops __attribute__((unused)) = {
349 .get_paths = nvme_pg_get_paths,
350 .rel_paths = nvme_pg_rel_paths,
351 .snprint = snprint_nvme_pg,
354 static const struct gen_path_ops nvme_path_ops __attribute__((unused)) = {
355 .snprint = snprint_nvme_path,
359 pthread_mutex_t mutex;
364 void lock(struct context *ctx)
366 pthread_mutex_lock(&ctx->mutex);
369 void unlock(void *arg)
371 struct context *ctx = arg;
373 pthread_mutex_unlock(&ctx->mutex);
376 static int _delete_all(struct context *ctx)
379 int n = VECTOR_SIZE(ctx->mpvec), i;
382 return FOREIGN_IGNORED;
384 vector_foreach_slot_backwards(ctx->mpvec, nm, i) {
385 vector_del_slot(ctx->mpvec, i);
386 cleanup_nvme_map(nm);
391 int delete_all(struct context *ctx)
395 condlog(5, "%s called for \"%s\"", __func__, THIS);
398 pthread_cleanup_push(unlock, ctx);
399 rc = _delete_all(ctx);
400 pthread_cleanup_pop(1);
405 void cleanup(struct context *ctx)
407 (void)delete_all(ctx);
411 * Locking is not strictly necessary here, locking in foreign.c
412 * makes sure that no other code is called with this ctx any more.
413 * But this should make static checkers feel better.
415 pthread_cleanup_push(unlock, ctx);
417 udev_unref(ctx->udev);
419 vector_free(ctx->mpvec);
422 pthread_cleanup_pop(1);
423 pthread_mutex_destroy(&ctx->mutex);
428 struct context *init(unsigned int api, const char *name)
432 if (api > LIBMP_FOREIGN_API) {
433 condlog(0, "%s: api version mismatch: %08x > %08x\n",
434 __func__, api, LIBMP_FOREIGN_API);
438 if ((ctx = calloc(1, sizeof(*ctx)))== NULL)
441 pthread_mutex_init(&ctx->mutex, NULL);
443 ctx->udev = udev_new();
444 if (ctx->udev == NULL)
447 ctx->mpvec = vector_alloc();
448 if (ctx->mpvec == NULL)
458 static struct nvme_map *_find_nvme_map_by_devt(const struct context *ctx,
464 if (ctx->mpvec == NULL)
467 vector_foreach_slot(ctx->mpvec, nm, i) {
468 if (nm->devt == devt)
475 static struct nvme_path *
476 _find_path_by_syspath(struct nvme_map *map, const char *syspath)
478 struct nvme_pathgroup *pg;
481 const char *psyspath;
484 ppath = realpath(syspath, real);
486 condlog(1, "%s: %s: error in realpath", __func__, THIS);
490 vector_foreach_slot(&map->pgvec, pg, i) {
491 struct nvme_path *path = nvme_pg_to_path(pg);
493 psyspath = udev_device_get_syspath(path->udev);
494 if (psyspath && !strcmp(ppath, psyspath))
497 condlog(4, "%s: %s: %s not found", __func__, THIS, ppath);
501 static void _udev_device_unref(void *p)
503 udev_device_unref(p);
506 static void _udev_enumerate_unref(void *p)
508 udev_enumerate_unref(p);
511 static int _dirent_controller(const struct dirent *di)
513 static const char nvme_prefix[] = "nvme";
516 #ifdef _DIRENT_HAVE_D_TYPE
517 if (di->d_type != DT_LNK)
520 if (strncmp(di->d_name, nvme_prefix, sizeof(nvme_prefix) - 1))
522 p = di->d_name + sizeof(nvme_prefix) - 1;
523 if (*p == '\0' || !isdigit(*p))
525 for (++p; *p != '\0'; ++p)
531 /* Find the block device for a given nvme controller */
532 struct udev_device *get_ctrl_blkdev(const struct context *ctx,
533 struct udev_device *ctrl)
535 struct udev_list_entry *item;
536 struct udev_device *blkdev = NULL;
537 struct udev_enumerate *enm = udev_enumerate_new(ctx->udev);
543 pthread_cleanup_push(_udev_enumerate_unref, enm);
544 if (udev_enumerate_add_match_parent(enm, ctrl) < 0)
546 if (udev_enumerate_add_match_subsystem(enm, "block"))
549 if (udev_enumerate_scan_devices(enm) < 0) {
550 condlog(1, "%s: %s: error enumerating devices", __func__, THIS);
554 for (item = udev_enumerate_get_list_entry(enm);
556 item = udev_list_entry_get_next(item)) {
557 struct udev_device *tmp;
559 tmp = udev_device_new_from_syspath(ctx->udev,
560 udev_list_entry_get_name(item));
564 devtype = udev_device_get_devtype(tmp);
565 if (devtype && !strcmp(devtype, "disk")) {
569 udev_device_unref(tmp);
573 condlog(1, "%s: %s: failed to get blockdev for %s",
574 __func__, THIS, udev_device_get_sysname(ctrl));
576 condlog(5, "%s: %s: got %s", __func__, THIS,
577 udev_device_get_sysname(blkdev));
579 pthread_cleanup_pop(1);
583 static void test_ana_support(struct nvme_map *map, struct udev_device *ctl)
590 if (map->ana_supported != YNU_UNDEF)
593 dev_t = udev_device_get_sysattr_value(ctl, "dev");
594 if (safe_sprintf(sys_path, "/dev/char/%s", dev_t))
597 fd = open(sys_path, O_RDONLY);
599 condlog(2, "%s: error opening %s", __func__, sys_path);
603 pthread_cleanup_push(close_fd, (void *)fd);
604 rc = nvme_id_ctrl_ana(fd, NULL);
606 condlog(2, "%s: error in nvme_id_ctrl: %s", __func__,
609 map->ana_supported = (rc == 1 ? YNU_YES : YNU_NO);
610 condlog(3, "%s: NVMe ctrl %s: ANA %s supported", __func__, dev_t,
611 rc == 1 ? "is" : "is not");
613 pthread_cleanup_pop(1);
616 static void _find_controllers(struct context *ctx, struct nvme_map *map)
618 char pathbuf[PATH_MAX], realbuf[PATH_MAX];
619 struct dirent **di = NULL;
620 struct scandir_result sr;
621 struct udev_device *subsys;
622 struct nvme_pathgroup *pg;
623 struct nvme_path *path;
626 if (map == NULL || map->udev == NULL)
629 vector_foreach_slot(&map->pgvec, pg, i) {
630 path = nvme_pg_to_path(pg);
634 subsys = udev_device_get_parent_with_subsystem_devtype(map->udev,
637 if (subsys == NULL) {
638 condlog(1, "%s: %s: BUG: no NVME subsys for %s", __func__, THIS,
639 udev_device_get_sysname(map->udev));
643 n = snprintf(pathbuf, sizeof(pathbuf), "%s",
644 udev_device_get_syspath(subsys));
645 r = scandir(pathbuf, &di, _dirent_controller, alphasort);
648 condlog(3, "%s: %s: no controllers for %s", __func__, THIS,
649 udev_device_get_sysname(map->udev));
652 condlog(1, "%s: %s: error %d scanning controllers of %s",
653 __func__, THIS, errno,
654 udev_device_get_sysname(map->udev));
660 pthread_cleanup_push_cast(free_scandir_result, &sr);
661 for (i = 0; i < r; i++) {
662 char *fn = di[i]->d_name;
663 struct udev_device *ctrl, *udev;
665 if (safe_snprintf(pathbuf + n, sizeof(pathbuf) - n, "/%s", fn))
667 if (realpath(pathbuf, realbuf) == NULL) {
668 condlog(3, "%s: %s: realpath: %s", __func__, THIS,
672 condlog(4, "%s: %s: found %s", __func__, THIS, realbuf);
674 ctrl = udev_device_new_from_syspath(ctx->udev, realbuf);
676 condlog(1, "%s: %s: failed to get udev device for %s",
677 __func__, THIS, realbuf);
681 pthread_cleanup_push(_udev_device_unref, ctrl);
682 udev = get_ctrl_blkdev(ctx, ctrl);
684 * We give up the reference to the nvme device here and get
685 * it back from the child below.
686 * This way we don't need to worry about unreffing it.
688 pthread_cleanup_pop(1);
693 path = _find_path_by_syspath(map,
694 udev_device_get_syspath(udev));
697 condlog(4, "%s: %s already known",
702 path = calloc(1, sizeof(*path));
706 path->gen.ops = &nvme_path_ops;
710 path->ctl = udev_device_get_parent_with_subsystem_devtype
711 (udev, "nvme", NULL);
712 if (path->ctl == NULL) {
713 condlog(1, "%s: %s: failed to get controller for %s",
715 cleanup_nvme_path(path);
718 test_ana_support(map, path->ctl);
720 path->pg.gen.ops = &nvme_pg_ops;
721 if (!vector_alloc_slot(&path->pg.pathvec)) {
722 cleanup_nvme_path(path);
725 vector_set_slot(&path->pg.pathvec, path);
726 if (!vector_alloc_slot(&map->pgvec)) {
727 cleanup_nvme_path(path);
730 vector_set_slot(&map->pgvec, &path->pg);
731 condlog(3, "%s: %s: new path %s added to %s",
732 __func__, THIS, udev_device_get_sysname(udev),
733 udev_device_get_sysname(map->udev));
735 pthread_cleanup_pop(1);
738 vector_foreach_slot_backwards(&map->pgvec, pg, i) {
739 path = nvme_pg_to_path(pg);
741 condlog(1, "path %d not found in %s any more",
742 i, udev_device_get_sysname(map->udev));
743 vector_del_slot(&map->pgvec, i);
744 cleanup_nvme_path(path);
746 static const char live_state[] = "live";
749 if ((sysfs_attr_get_value(path->ctl, "state", state,
750 sizeof(state)) > 0) &&
751 !strncmp(state, live_state, sizeof(live_state) - 1))
755 condlog(3, "%s: %s: map %s has %d/%d live paths", __func__, THIS,
756 udev_device_get_sysname(map->udev), map->nr_live,
757 VECTOR_SIZE(&map->pgvec));
760 static int _add_map(struct context *ctx, struct udev_device *ud,
761 struct udev_device *subsys)
763 dev_t devt = udev_device_get_devnum(ud);
764 struct nvme_map *map;
766 if (_find_nvme_map_by_devt(ctx, devt) != NULL)
769 map = calloc(1, sizeof(*map));
774 map->udev = udev_device_ref(ud);
776 * subsys is implicitly referenced by map->udev,
777 * no need to take a reference here.
779 map->subsys = subsys;
780 map->gen.ops = &nvme_map_ops;
782 if (!vector_alloc_slot(ctx->mpvec)) {
783 cleanup_nvme_map(map);
786 vector_set_slot(ctx->mpvec, map);
787 _find_controllers(ctx, map);
789 return FOREIGN_CLAIMED;
792 int add(struct context *ctx, struct udev_device *ud)
794 struct udev_device *subsys;
798 condlog(5, "%s called for \"%s\"", __func__, THIS);
802 if ((devtype = udev_device_get_devtype(ud)) == NULL ||
803 strcmp("disk", devtype))
804 return FOREIGN_IGNORED;
806 subsys = udev_device_get_parent_with_subsystem_devtype(ud,
810 return FOREIGN_IGNORED;
813 pthread_cleanup_push(unlock, ctx);
814 rc = _add_map(ctx, ud, subsys);
815 pthread_cleanup_pop(1);
817 if (rc == FOREIGN_CLAIMED)
818 condlog(3, "%s: %s: added map %s", __func__, THIS,
819 udev_device_get_sysname(ud));
820 else if (rc != FOREIGN_OK)
821 condlog(1, "%s: %s: retcode %d adding %s",
822 __func__, THIS, rc, udev_device_get_sysname(ud));
827 int change(__attribute__((unused)) struct context *ctx,
828 __attribute__((unused)) struct udev_device *ud)
830 condlog(5, "%s called for \"%s\"", __func__, THIS);
831 return FOREIGN_IGNORED;
834 static int _delete_map(struct context *ctx, struct udev_device *ud)
837 struct nvme_map *map;
838 dev_t devt = udev_device_get_devnum(ud);
840 map = _find_nvme_map_by_devt(ctx, devt);
842 return FOREIGN_IGNORED;
844 k = find_slot(ctx->mpvec, map);
848 vector_del_slot(ctx->mpvec, k);
850 cleanup_nvme_map(map);
855 int delete(struct context *ctx, struct udev_device *ud)
859 condlog(5, "%s called for \"%s\"", __func__, THIS);
865 pthread_cleanup_push(unlock, ctx);
866 rc = _delete_map(ctx, ud);
867 pthread_cleanup_pop(1);
869 if (rc == FOREIGN_OK)
870 condlog(3, "%s: %s: map %s deleted", __func__, THIS,
871 udev_device_get_sysname(ud));
872 else if (rc != FOREIGN_IGNORED)
873 condlog(1, "%s: %s: retcode %d deleting map %s", __func__,
874 THIS, rc, udev_device_get_sysname(ud));
879 void _check(struct context *ctx)
881 struct gen_multipath *gm;
884 vector_foreach_slot(ctx->mpvec, gm, i) {
885 struct nvme_map *map = gen_mp_to_nvme(gm);
887 _find_controllers(ctx, map);
891 void check(struct context *ctx)
893 condlog(4, "%s called for \"%s\"", __func__, THIS);
895 pthread_cleanup_push(unlock, ctx);
897 pthread_cleanup_pop(1);
902 * It's safe to pass our internal pointer, this is only used under the lock.
904 const struct _vector *get_multipaths(const struct context *ctx)
906 condlog(5, "%s called for \"%s\"", __func__, THIS);
910 void release_multipaths(__attribute__((unused)) const struct context *ctx,
911 __attribute__((unused)) const struct _vector *mpvec)
913 condlog(5, "%s called for \"%s\"", __func__, THIS);
918 * It's safe to pass our internal pointer, this is only used under the lock.
920 const struct _vector * get_paths(const struct context *ctx)
923 const struct gen_multipath *gm;
926 condlog(5, "%s called for \"%s\"", __func__, THIS);
927 vector_foreach_slot(ctx->mpvec, gm, i) {
928 const struct nvme_map *nm = const_gen_mp_to_nvme(gm);
929 paths = vector_convert(paths, &nm->pgvec,
930 struct nvme_pathgroup, nvme_pg_to_path);
935 void release_paths(__attribute__((unused)) const struct context *ctx,
936 const struct _vector *mpvec)
938 condlog(5, "%s called for \"%s\"", __func__, THIS);
939 vector_free_const(mpvec);
942 /* compile-time check whether all methods are present and correctly typed */
943 #define _METHOD_INIT(x) .x = x
944 static struct foreign __methods __attribute__((unused)) = {
946 _METHOD_INIT(cleanup),
947 _METHOD_INIT(change),
948 _METHOD_INIT(delete),
949 _METHOD_INIT(delete_all),
952 _METHOD_INIT(unlock),
953 _METHOD_INIT(get_multipaths),
954 _METHOD_INIT(release_multipaths),
955 _METHOD_INIT(get_paths),
956 _METHOD_INIT(release_paths),