From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id 128301FF0ED for ; Fri, 31 Jul 2026 12:22:15 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 4B14B21561; Fri, 31 Jul 2026 12:22:03 +0200 (CEST) From: Dietmar Maurer To: pve-devel@lists.proxmox.com Subject: [RFC pve-storage 06/27] diskmanage: link multipath member disks to their map device Date: Fri, 31 Jul 2026 12:21:35 +0200 Message-ID: <20260731102156.3947857-7-dietmar@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260731102156.3947857-1-dietmar@proxmox.com> References: <20260731102156.3947857-1-dietmar@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 AWL -0.510 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods RDNS_NONE 1.274 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Message-ID-Hash: XMJ2XU6R2IPNRSEDJO2NVZH33DQO3IJJ X-Message-ID-Hash: XMJ2XU6R2IPNRSEDJO2NVZH33DQO3IJJ X-MailFrom: dietmar@zilli.proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Multipath member disks only reported the generic 'Device Mapper' usage, with no way to tell which map a member belongs to, or that the device mapper holder is a multipath map at all. Report the mapped device path in the new multipath property, so clients can group paths by map or hide members in favor of the mapped device. Signed-off-by: Dietmar Maurer --- src/PVE/API2/Disks.pm | 6 ++++ src/PVE/Diskmanage.pm | 33 +++++++++++++++++++ .../multipath/disklist_expected.json | 12 ++++--- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/PVE/API2/Disks.pm b/src/PVE/API2/Disks.pm index ee287f7..2417340 100644 --- a/src/PVE/API2/Disks.pm +++ b/src/PVE/API2/Disks.pm @@ -149,6 +149,12 @@ __PACKAGE__->register_method({ . 'example sata, sas, usb, fc, iscsi, nvme, nvme-fc, nvme-tcp).', optional => 1, }, + multipath => { + type => 'string', + description => 'For multipath member devices only. The mapped ' + . 'device path of the multipath map the device belongs to.', + optional => 1, + }, parent => { type => 'string', description => 'For partitions only. The device path of ' diff --git a/src/PVE/Diskmanage.pm b/src/PVE/Diskmanage.pm index ed270e9..5ac04dd 100644 --- a/src/PVE/Diskmanage.pm +++ b/src/PVE/Diskmanage.pm @@ -535,12 +535,42 @@ sub mounted_paths { return $mounted; } +# Maps multipath member devices (e.g. 'sda') to the mapped device path of +# their multipath map (e.g. '/dev/mapper/mpatha'). +my sub get_multipath_slave_map { + my $slave_map = {}; + + dir_glob_foreach( + '/sys/block', + 'dm-\d+', + sub { + my ($dev) = @_; + my $sysdir = "/sys/block/$dev"; + + my $uuid = file_read_firstline("$sysdir/dm/uuid") // return; + return if $uuid !~ m/^mpath-/; + + my $name = file_read_firstline("$sysdir/dm/name") // return; + + dir_glob_foreach( + "$sysdir/slaves", + '[^.].*', + sub { $slave_map->{ $_[0] } = "/dev/mapper/$name"; }, + ); + }, + ); + + return $slave_map; +} + sub get_disks { my ($disks, $nosmart, $include_partitions) = @_; my $disklist = {}; my $mounted = mounted_blockdevs(); + my $mpath_slave_map = get_multipath_slave_map(); + my $lsblk_info = get_lsblk_info(); my $journalhash = get_ceph_journals($lsblk_info); @@ -655,6 +685,9 @@ sub get_disks { $disklist->{$dev}->{transport} = $transport if defined($transport); $disklist->{$dev}->{mounted} = 1 if exists $mounted->{$devpath}; + my $mpath = $mpath_slave_map->{$dev}; + $disklist->{$dev}->{multipath} = $mpath if defined($mpath); + my $by_id_link = $data->{by_id_link}; $disklist->{$dev}->{by_id_link} = $by_id_link if defined($by_id_link); diff --git a/src/test/disk_tests/multipath/disklist_expected.json b/src/test/disk_tests/multipath/disklist_expected.json index ec44296..001193d 100644 --- a/src/test/disk_tests/multipath/disklist_expected.json +++ b/src/test/disk_tests/multipath/disklist_expected.json @@ -15,7 +15,8 @@ "osdid-list": null, "by_id_link": "/dev/disk/by-id/scsi-36001405000000000000000000000000a", "transport": "fc", - "used": "Device Mapper" + "used": "Device Mapper", + "multipath": "/dev/mapper/mpatha" }, "sdb": { "devpath": "/dev/sdb", @@ -33,7 +34,8 @@ "osdid-list": null, "by_id_link": "/dev/disk/by-id/scsi-36001405000000000000000000000000b", "transport": "fc", - "used": "Device Mapper" + "used": "Device Mapper", + "multipath": "/dev/mapper/mpatha" }, "sdc": { "devpath": "/dev/sdc", @@ -51,7 +53,8 @@ "osdid-list": null, "by_id_link": "/dev/disk/by-id/scsi-36001405000000000000000000000000c", "transport": "fc", - "used": "Device Mapper" + "used": "Device Mapper", + "multipath": "/dev/mapper/mpathb" }, "sdd": { "devpath": "/dev/sdd", @@ -69,7 +72,8 @@ "osdid-list": null, "by_id_link": "/dev/disk/by-id/scsi-36001405000000000000000000000000d", "transport": "fc", - "used": "Device Mapper" + "used": "Device Mapper", + "multipath": "/dev/mapper/mpathb" }, "nvme8n1": { "devpath": "/dev/nvme8n1", -- 2.47.3