[dm-devel] [PATCH v2 17/20] libmultipath/foreign/nvme: use failover topology
Martin Wilck
mwilck at suse.com
Sun Dec 23 22:21:23 UTC 2018
The native multipath driver does not use a multibus policy
as the current topology output of the NVMe foreign code
indicates. Rather, it uses failover policy, queueing all
IO to the current path until a failure occurs.
Change the data structures of the nvme foreign library
accordingly.
Signed-off-by: Martin Wilck <mwilck at suse.com>
---
libmultipath/foreign/nvme.c | 92 +++++++++++++++++++------------------
1 file changed, 48 insertions(+), 44 deletions(-)
diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c
index c753a747..11849889 100644
--- a/libmultipath/foreign/nvme.c
+++ b/libmultipath/foreign/nvme.c
@@ -40,17 +40,22 @@ static const char N_A[] = "n/a";
const char *THIS;
struct nvme_map;
+struct nvme_pathgroup {
+ struct gen_pathgroup gen;
+ struct _vector pathvec;
+};
+
struct nvme_path {
struct gen_path gen;
struct udev_device *udev;
struct udev_device *ctl;
struct nvme_map *map;
bool seen;
-};
-
-struct nvme_pathgroup {
- struct gen_pathgroup gen;
- vector pathvec;
+ /*
+ * The kernel works in failover mode.
+ * Each path has a separate path group.
+ */
+ struct nvme_pathgroup pg;
};
struct nvme_map {
@@ -58,11 +63,7 @@ struct nvme_map {
struct udev_device *udev;
struct udev_device *subsys;
dev_t devt;
- /* Just one static pathgroup for NVMe for now */
- struct nvme_pathgroup pg;
- struct gen_pathgroup *gpg;
struct _vector pgvec;
- vector pathvec;
int nr_live;
};
@@ -76,29 +77,33 @@ struct nvme_map {
#define const_gen_path_to_nvme(g) ((const struct nvme_path*)(g))
#define gen_path_to_nvme(g) ((struct nvme_path*)(g))
#define nvme_path_to_gen(n) &((n)->gen)
+#define nvme_pg_to_path(x) (VECTOR_SLOT(&((x)->pathvec), 0))
+#define nvme_path_to_pg(x) &((x)->pg)
static void cleanup_nvme_path(struct nvme_path *path)
{
condlog(5, "%s: %p %p", __func__, path, path->udev);
if (path->udev)
udev_device_unref(path->udev);
+ vector_reset(&path->pg.pathvec);
+
/* ctl is implicitly referenced by udev, no need to unref */
free(path);
}
static void cleanup_nvme_map(struct nvme_map *map)
{
- if (map->pathvec) {
- struct nvme_path *path;
- int i;
+ struct nvme_pathgroup *pg;
+ struct nvme_path *path;
+ int i;
- vector_foreach_slot_backwards(map->pathvec, path, i) {
- condlog(5, "%s: %d %p", __func__, i, path);
- cleanup_nvme_path(path);
- vector_del_slot(map->pathvec, i);
- }
+ vector_foreach_slot_backwards(&map->pgvec, pg, i) {
+ path = nvme_pg_to_path(pg);
+ condlog(5, "%s: %d %p", __func__, i, path);
+ cleanup_nvme_path(path);
+ vector_del_slot(&map->pgvec, i);
}
- vector_free(map->pathvec);
+ vector_reset(&map->pgvec);
if (map->udev)
udev_device_unref(map->udev);
/* subsys is implicitly referenced by udev, no need to unref */
@@ -190,7 +195,7 @@ nvme_pg_get_paths(const struct gen_pathgroup *gpg) {
const struct nvme_pathgroup *gp = const_gen_pg_to_nvme(gpg);
/* This is all used under the lock, no need to copy */
- return gp->pathvec;
+ return &gp->pathvec;
}
static void
@@ -432,7 +437,7 @@ static struct nvme_map *_find_nvme_map_by_devt(const struct context *ctx,
static struct nvme_path *
_find_path_by_syspath(struct nvme_map *map, const char *syspath)
{
- struct nvme_path *path;
+ struct nvme_pathgroup *pg;
char real[PATH_MAX];
const char *ppath;
int i;
@@ -443,7 +448,9 @@ _find_path_by_syspath(struct nvme_map *map, const char *syspath)
ppath = syspath;
}
- vector_foreach_slot(map->pathvec, path, i) {
+ vector_foreach_slot(&map->pgvec, pg, i) {
+ struct nvme_path *path = nvme_pg_to_path(pg);
+
if (!strcmp(ppath,
udev_device_get_syspath(path->udev)))
return path;
@@ -537,14 +544,17 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map)
struct dirent **di = NULL;
struct scandir_result sr;
struct udev_device *subsys;
+ struct nvme_pathgroup *pg;
struct nvme_path *path;
int r, i, n;
if (map == NULL || map->udev == NULL)
return;
- vector_foreach_slot(map->pathvec, path, i)
+ vector_foreach_slot(&map->pgvec, pg, i) {
+ path = nvme_pg_to_path(pg);
path->seen = false;
+ }
subsys = udev_device_get_parent_with_subsystem_devtype(map->udev,
"nvme-subsystem",
@@ -606,7 +616,8 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map)
if (udev == NULL)
continue;
- path = _find_path_by_syspath(map, udev_device_get_syspath(udev));
+ path = _find_path_by_syspath(map,
+ udev_device_get_syspath(udev));
if (path != NULL) {
path->seen = true;
condlog(4, "%s: %s already known",
@@ -630,24 +641,30 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map)
cleanup_nvme_path(path);
continue;
}
-
- if (vector_alloc_slot(map->pathvec) == NULL) {
+ path->pg.gen.ops = &nvme_pg_ops;
+ if (vector_alloc_slot(&path->pg.pathvec) == NULL) {
cleanup_nvme_path(path);
continue;
}
+ vector_set_slot(&path->pg.pathvec, path);
+ if (vector_alloc_slot(&map->pgvec) == NULL) {
+ cleanup_nvme_path(path);
+ continue;
+ }
+ vector_set_slot(&map->pgvec, &path->pg);
condlog(3, "%s: %s: new path %s added to %s",
__func__, THIS, udev_device_get_sysname(udev),
udev_device_get_sysname(map->udev));
- vector_set_slot(map->pathvec, path);
}
pthread_cleanup_pop(1);
map->nr_live = 0;
- vector_foreach_slot_backwards(map->pathvec, path, i) {
+ vector_foreach_slot_backwards(&map->pgvec, pg, i) {
+ path = nvme_pg_to_path(pg);
if (!path->seen) {
condlog(1, "path %d not found in %s any more",
i, udev_device_get_sysname(map->udev));
- vector_del_slot(map->pathvec, i);
+ vector_del_slot(&map->pgvec, i);
cleanup_nvme_path(path);
} else {
static const char live_state[] = "live";
@@ -661,7 +678,7 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map)
}
condlog(3, "%s: %s: map %s has %d/%d live paths", __func__, THIS,
udev_device_get_sysname(map->udev), map->nr_live,
- VECTOR_SIZE(map->pathvec));
+ VECTOR_SIZE(&map->pgvec));
}
static int _add_map(struct context *ctx, struct udev_device *ud,
@@ -686,19 +703,6 @@ static int _add_map(struct context *ctx, struct udev_device *ud,
map->subsys = subsys;
map->gen.ops = &nvme_map_ops;
- map->pathvec = vector_alloc();
- if (map->pathvec == NULL) {
- cleanup_nvme_map(map);
- return FOREIGN_ERR;
- }
-
- map->pg.gen.ops = &nvme_pg_ops;
- map->pg.pathvec = map->pathvec;
- map->gpg = nvme_pg_to_gen(&map->pg);
-
- map->pgvec.allocated = 1;
- map->pgvec.slot = (void**)&map->gpg;
-
if (vector_alloc_slot(ctx->mpvec) == NULL) {
cleanup_nvme_map(map);
return FOREIGN_ERR;
@@ -842,8 +846,8 @@ const struct _vector * get_paths(const struct context *ctx)
condlog(5, "%s called for \"%s\"", __func__, THIS);
vector_foreach_slot(ctx->mpvec, gm, i) {
const struct nvme_map *nm = const_gen_mp_to_nvme(gm);
- paths = vector_convert(paths, nm->pathvec,
- struct gen_path, identity);
+ paths = vector_convert(paths, &nm->pgvec,
+ struct nvme_pathgroup, nvme_pg_to_path);
}
return paths;
}
--
2.19.2
More information about the dm-devel
mailing list