From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: chengjike Date: Fri, 8 Oct 2021 20:24:49 +0800 Subject: [PATCH] multipath-tools: fix "multipath -ll" bug for Native NVME Multipath devices After "Native NVME Multipath" is configured, the content displayed is incorrect when you run "multipath -ll" command. Each NVME devices have the same path name. For example: [root@localhost home]# multipath -ll eui.710032e8fb22a86c24a52c1000000db8 [nvme]:nvme1n1 NVMe,Huawei-XSG1,1000001 size=10485760 features='n/a' hwhandler='ANA' wp=rw |-+- policy='n/a' prio=50 status=optimized | `- 1:4:1 nvme1c4n1 0:0 n/a optimized live `-+- policy='n/a' prio=50 status=optimized `- 1:9:1 nvme1c9n1 0:0 n/a optimized live eui.710032e8fb22a86b24a52c7c00000db7 [nvme]:nvme1n2 NVMe,Huawei-XSG1,1000001 size=10485760 features='n/a' hwhandler='ANA' wp=rw |-+- policy='n/a' prio=50 status=optimized | `- 1:4:1 nvme1c4n1 0:0 n/a optimized live `-+- policy='n/a' prio=50 status=optimized `- 1:9:1 nvme1c9n1 0:0 n/a optimized live [root@localhost home]# The logical paths of "nvme1n1" and "nvme1n2" are both "nvme1c4n1" and "nvme1c9n1". So when multipath-tools aggregates disks, use "nvme_ns_head->instance" for matching. such as ,Use "b" in "nvmeanb" string to match "z" in "nvmexcynz"(a,b,x,y,z can be any number), and if "b" and "z" are the same, they are related. Signed-off-by: chengjike Reviewed-by: Martin Wilck Signed-off-by: Benjamin Marzinski --- libmultipath/foreign/nvme.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c index 23355ca5..76b57283 100644 --- a/libmultipath/foreign/nvme.c +++ b/libmultipath/foreign/nvme.c @@ -530,14 +530,18 @@ static int _dirent_controller(const struct dirent *di) /* Find the block device for a given nvme controller */ struct udev_device *get_ctrl_blkdev(const struct context *ctx, - struct udev_device *ctrl) + struct udev_device *ctrl, const char *ctrl_name) { + int ctrl_num, ns_num; struct udev_list_entry *item; struct udev_device *blkdev = NULL; struct udev_enumerate *enm = udev_enumerate_new(ctx->udev); const char *devtype; - if (enm == NULL) + if (enm == NULL || ctrl_name == NULL) + return NULL; + + if (sscanf(ctrl_name, "nvme%dn%d", &ctrl_num, &ns_num) != 2) return NULL; pthread_cleanup_push(_udev_enumerate_unref, enm); @@ -555,6 +559,8 @@ struct udev_device *get_ctrl_blkdev(const struct context *ctx, item != NULL; item = udev_list_entry_get_next(item)) { struct udev_device *tmp; + const char *name = NULL ; + int m, n, l; tmp = udev_device_new_from_syspath(ctx->udev, udev_list_entry_get_name(item)); @@ -562,11 +568,19 @@ struct udev_device *get_ctrl_blkdev(const struct context *ctx, continue; devtype = udev_device_get_devtype(tmp); - if (devtype && !strcmp(devtype, "disk")) { + if (devtype == NULL || strcmp(devtype, "disk")) { + udev_device_unref(tmp); + continue; + } + + name = udev_device_get_sysname(tmp); + if (name != NULL && + sscanf(name, "nvme%dc%dn%d", &m, &n, &l) == 3 && + l == ns_num) { blkdev = tmp; break; - } else - udev_device_unref(tmp); + } + udev_device_unref(tmp); } if (blkdev == NULL) @@ -679,7 +693,7 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map) } pthread_cleanup_push(_udev_device_unref, ctrl); - udev = get_ctrl_blkdev(ctx, ctrl); + udev = get_ctrl_blkdev(ctx, ctrl, udev_device_get_sysname(map->udev)); /* * We give up the reference to the nvme device here and get * it back from the child below.