Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multipath-tools 0.9.9 #85

Merged
merged 54 commits into from
Jun 13, 2024
Merged

multipath-tools 0.9.9 #85

merged 54 commits into from
Jun 13, 2024

Conversation

mwilck
Copy link
Collaborator

@mwilck mwilck commented May 3, 2024

Important note

It is not recommended to use lvm2 2.03.24 and newer with multipath-tools
versions earlier than 0.9.9. See "Other major changes" below.

User-Visible Changes

  • Changed realtime scheduling: multipathd used to run at the highest possible
    realtime priority, 99. This has always been excessive, and on some
    distributions (e.g. RHEL 8), it hasn't worked at all. It is now possible to
    set multipathd's real time scheduling by setting the hard limit for
    RLIMIT_RTPRIO (see getrlimit(2)), which corresponds to the rtprio
    setting in limits.conf and to LimitRTPRIO= in the systemd unit file. The
    default in the systemd unit file has been set to 10. If the limit is set to
    0, multipathd doesn't attempt to enable real-time scheduling.
    Otherwise, it will try to set the scheduling priority to the given value.
    Fixes #82.
  • Changed normal scheduling: In order to make sure that multipathd has
    sufficient priority even if real time scheduling is switched off, the
    CPUWeight= setting in the unit file is set to 1000. This is necessary
    because regular nice(2) values have no effect in systems with cgroups enabled.
  • Changed handling of max_sectors_kb configuration: multipathd applies
    the max_sectors_kb setting only during map creation, or when a new path is
    added to an existing map. The kernel makes sure that the multipath device
    never has a larger max_sectors_kb value than any of its configured path
    devices. The reason for this change is that applying max_sectors_kb on
    live maps can cause IO errors and data loss in rare situations.
    It can now happen that some path devices have a higher max_sectors_kb
    value than the map; this is not an error. It is not possible any more to
    decrease max_sectors_kb in multipath.conf and run multipathd reconfigure to "apply" this setting to the map and its paths. If decreasing
    the IO size is necessary, either destroy and recreate the map, or remove one
    path with multipathd del path $PATH, run multipathd reconfigure, and
    re-add the path with multipathd add path $PATH.
  • New wildcard %k: The wildcard %k for max_sectors_kb has been added to
    the multipathd show paths format and multipathd show maps format
    commands.
  • Changed semantics of flush_on_last_del: The flush_on_last_del option
    now takes the values always , unused, or never. yes and no
    are still accepted as aliases for always and unused, respectively.
    always means that when all paths for a multipath map have been removed,
    outstanding IO will be failed and the map will be deleted. unused means
    that this will only happen when the map is not mounted or otherwise opened.
    never means the map will only be removed if the queue_if_no_path
    feature is off.
    This fixes a problem where multipathd could hang when the last path of
    a queueing map was deleted.
  • Better parsing of $map arguments in multipathd interactive shell: The
    $map argument in commands like resize map $map now accepts a WWID,
    and poorly chosen map aliases that could be mistaken for device names.
  • Added documentation for CLI wildcards. The wildcards used in the show maps format and show paths format commands are documented in the
    multipathd(8) man page now.
  • %s wildcard for paths: this wildcard in show paths format now prints
    the product revision, too.

Other major changes

  • Adapted the dm-mpath udev rules such that they will work with the modified
    device mapper udev rules (DM_UDEV_RULES_VSN==3, lvm2 >= 2.03.24). They are
    still compatible with older versions of the device-mapper udev
    rules (lvm2 < 2.03.24). If lvm2 2.03.24 or newer is installed, it is
    recommended to update multipath-tools to 0.9.9 or newer.
    See also LVM2 2.03.24 release notes.

Bug fixes

  • Fixed misspelled DM_UDEV_DISABLE_OTHER_RULES_FLAG in 11-dm-mpath.rules
  • Always use glibc_basename() to avoid some issues with MUSL libc.
    Fixes #84.
  • Fixed map failure counting for no_path_retry > 0.
  • The wildcards for path groups are not available for actual
    commands and have thus been removed from the show wildcards command
    output.

Other

  • Build: added TGTDIR option to simplify building for a different target
    host (see README.md).

Shortlog

@bmarzins (17):
multipathd: use condlog level for setscheduler error message
multipathd: make multipathd scheduling configurable
multipathd: make multipathd set priority to RLIMIT_RTPRIO
multipathd: Set CPUWeight to 1000 and LimitRTPRIO to 10
libmultipath: export partmap_in_use
libmultipath: change flush_on_last_del to fix a multipathd hang
libmultipath: remove redundant config option from InfiniBox config
libmultipath: pad dev_loss_tmo to avoid race with no_path_retry
libmultipath: fix deferred_remove function arguments
libmultipath: remove redundant config option from InfiniBox config
libmultipath: pad dev_loss_tmo to avoid race with no_path_retry
libmultipath: fix deferred_remove function arguments
libmultipath: accept poorly chosen aliases in find_mp_by_str
libmultipath: accept wwids in find_mp_by_str
multipath-tools man pages: don't assume multipath.socket is enabled
libmultipath: print all values in snprint_failback
multipathd: Stop double counting map failures for no_path_retry > 0
multipath-tools man pages: add missing multipathd commands
libmultipath: change the vend/prod/rev printing
multipath-tools man pages: Add format wildcard descriptions

@mwilck (33):
11-dm-mpath.rules: fix misspelled DM_UDEV_DISABLE_OTHER_RULES_FLAG
libmpathutil: really always use glibc basename()
11-dm-mpath.rules: explain logic for device becoming ready while suspended
11-dm-mpath.rules: don't import DM_NOSCAN from udev db
11-dm-mpath.rules: don't import ID_FS_VERSION from udev db
11-dm-mpath.rules: adapt MPATH_DEVICE_READY=0 logic to 10-dm.rules update
11-dm-mpath.rules: adapt coldplug event handling ro 10-dm.rules update
11-dm-mpath.rules: don't import properties with new 13-dm-disk.rules
11-dm-mpath.rules: replace DM_SUSPENDED by .DM_SUSPENDED
11-dm-mpath.rules: replace DM_NOSCAN by .DM_NOSCAN
11-dm-mpath.rules: simplify PATH_FAILED case
11-dm-mpath.rules: make label names more intuitive
kpartx.rules: ignore DM_SUSPENDED
multipath-tools tests: fix CI failures on arm/v7 with glibc 2.37
multipath-tools tests: fix CI failures with clang on Fedora Rawhide
GitHub actions: fixes for spelling CI
GitHub workflows: run workflows if workflow file has changed
multipath-tools: add TGTDIR option
libmultipath: move get_udev_for_mpp to sysfs.c
libmultipath: add mp_find_path_by_devt()
Revert "libmultipath: fix max_sectors_kb on adding path"
libmultipath: Only set max_sectors_kb on map creation
libmultipath: set max_sectors_kb in adopt_paths()
libmultipath: add wildcard %k for printing max_sectors_kb
multipath.conf(5): update documentation for max_sectors_kb
libmultipath: use bitwise flags for map flushing API
libmultipath: use bitwise flags for dm_simplecmd API
libmultipath: add argument names to some prototypes
libmultipath: bump version to 0.9.9
GitHub Workflows: native.yaml: run for Fedora 40
update NEWS.md
multipath.conf.5.in: fix man page date
More updates to NEWS.md

@NitinYewale (1):
libmultipath: remove pathgroup wildcard options

@xosevp (3):
multipath-tools: simplify comment in hwtable
multipath-tools: unify text in multipath.conf.5
multipath-tools: update man pages dates

As usual, all patches have a Reviewed-by: trailer, except those that just concern NEWS.md, the workflows, and the version bump, and the trivial commit 9fa3770.

Update 2024-06-04

Added some more patches from @bmarzins and @NitinYewale. Mostly man pages and wildcard treatment.

mwilck and others added 30 commits March 1, 2024 21:08
Fixes: b3582da ("11-dm-mpath.rules: use import logic like 13-dm-disk.rules")
Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
condlog uses its own log levels, so LOG_WARNING makes no sense. It
actually translates to a message sent at the LOG_DEBUG level.

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
Currently multipathd always tries to run as a realtime process with a
priority of 99. This is excessive. As a first step towards fixing this,
make it possible at compile time to lower the priority or keep
multipathd from making itself a realtime process.

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
Despite 03a5456 ("libmultipath: always use glibc basename()"), we
still call the system library's basename() from libmultipath.
musl libc until 1.24 provided a prototype for basename() in string.h,
which was not correct and was resolved to the destructive POSIX
basename(). musl libc 1.25 removed this prototype.

While the remaining code path doesn't strictly depend on the non-destructive
behavior of glibc's basename(), it's cleaner and safer to use the same
implementation everywhere.

Fixes: 03a5456 ("libmultipath: always use glibc basename()")
Fixes: opensvc#84

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Khem Raj <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
With this change, if the SCHED_RT_PRIO compiler flag has been removed.
Instead multipathd will call getrlimit(RLIMIT_RTPRIO, ...) and look at
the hard limit. It it's 0, multipath will do nothing. Otherwise it will
change its scheduling policy to SCHED_RR and its priority to the hard
limit.

This allows users to change the priority of that multipathd runs with by
adding

LimitRTPRIO=<prio>

to the [Service] section of the multipathd.service unit file. Setting
LimitRTPRIO=0 will make multipathd run as a normal process, while
setting LimitRTPRIO=infinity will make it use the maximum SCHED_RR prio,
which is 99.

To keep the existing behavior, multipathd.service now sets
LimitRTPRIO=infinity

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
If multipathd doesn't become a real time process, it was scheduled as a
normal process, without any priority increase. Bump up the CPUWeight so
that even as a normal process, it will still run with increased
priority.

If multipathd did become a real time process, it set itself to the
highest priority, which is excessive. A priority of 10 is plenty.

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
…ended

Add a comment to explain why we must set MPATH_DEVICE_READY=0 when
we see a device becoming ready (number of active paths 0 -> 1) while
the device is suspended.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
DM_NOSCAN is our "output" flag for 13-dm-disk.rules, and it should
be treated the same way as DM_UDEV_DISABLE_OTHER_RULES_FLAG, which
isn't imported from the udev database. The state that we need to
remember is MPATH_DEVICE_READY, which we've already imported above,
and we will set the "output" flags accordingly in the "force_activation"
code path further down.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
Use the same set of properties to import as 13-dm-disk.rules.
ID_FS_VERSION isn't used in any udev rule I am aware of.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
…date

With the late patches for 10-dm.rules, DM_UDEV_DISABLE_OTHER_RULES_FLAG isn't
restored from the udev database any more, so we don't need to restore
the flag to its original state before it is saved to the db.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
With late late patches for 10-dm.rules, DM_UDEV_DISABLE_OTHER_RULES_FLAG is
never restored from the udev db. Thus we don't need to clear it here
any more for coldplug events. Also, we must use .DM_SUSPENDED instead of
DM_SUSPENDED as input flag with the v3 rule set (other occurences of
DM_SUSPENDED will be replaced in a follow-up patch).

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
With the late changes to 13-dm-disk.rules, we don't need to import any
blkid-generated properties from the udev database, because they will
be imported later.

Except for ID_FS_TYPE, this actually holds since lvm2 commit 94f77a4 ("udev:
import previous results of blkid when in suspended state"), included in lvm2
2.03.19, but we have no simple way to detect the version of the lvm2 rules.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
With the late changes to the device mapper rules, DM_SUSPENDED
is not exported any more. Use .DM_SUSPENDED instead.

Note that although 11-dm-mpath.rules is not a part of lvm2, it
can be considered as part of the device-mapper layer (everything
before 13-dm-disk.rules can), and is thus allowed to use
.DM_SUSPENDED. In practice .DM_SUSPENDED is equivalent to
DM_UDEV_DISABLE_OTHER_RULES_FLAG for multipath devices, but
using .DM_SUSPENDED here makes the intention more obvious.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
We don't need to restore DM_NOSCAN from the db anymore, so we can rename
it to .DM_NOSCAN, making it a temporary property.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
This combination of a GOTO and a simple rule can be combined
into a single rule.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
The labels "dont_activate" and "scan_import" denote the same code line.
Remove "dont_activate". Improve two misleading label names.

Substitutions:
   dont_activate -> scan_import
   force_activation -> check_mpath_ready
   mpath_action -> check_mpath_unchanged

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
DM_SUSPENDED=1 implies DM_UDEV_DISABLE_OTHER_RULES_FLAG=1, no
need to check it again. The DM_NOSCAN check needs to remain in
order to keep compatibility with dm rules v2.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
glibc 2.37 has added several new wrappers around the ioctl and
io_getevents system calls on 32 bit systems, to deal with 64bit
time_t. These aren't resolved with cmocka's wrapping technique.

Fix this with C preprocessor trickery, similar to
7b217f8 ("multipath-tools: Makefile.inc: set _FILE_OFFSET_BITS=64").

Note: the directio test with DIO_TEST_DEV for fails under qemu-linux-user
with foreign-arch binfmt, because aio-related system calls are unsupported
by qemu-linux-user. See https://gitlab.com/qemu-project/qemu/-/issues/210.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
Fedora's glibc 2.39 includes the following patch:

https://patches.linaro.org/project/libc-alpha/patch/[email protected]/

It causes open("file", O_RDONLY) to resolve to __open64_2(),
whereas it resolves to open64() with gcc, causing CI failures because of
wrong wrapper substitutions.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
We want to run workflows if the workflow file itself has changed.

Fixes: 2cbe81a ("GitHub Workflows: run expensive workflows only on relevant changes")
Signed-off-by: Martin Wilck <[email protected]>
TGTDIR is a convenience option for developers for building multipath-tools such
that compiled-in paths of the plugins, config files, etc. match an
installation under some optional path. See README.md for instructions and
examples.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
No functional changes, just code movement.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
A helper function that searches a struct multipath by dev_t, and
works whether or not mpp->paths is currently available.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
This reverts commit bbb77f3.
Reviewed-by: Benjamin Marzinski <[email protected]>
Changing max_sectors_kb on a live map is dangerous. When I/O occurs while the
max_sectors_kb value of a map is larger than that of any of its paths, I/O
errors like this may result:

  blk_insert_cloned_request: over max size limit. (127 > 126)

This situation must be strictly avoided. The kernel makes sure that the
map's limits match those of the paths when the map is created. But setting
max_sectors_kb on path devices before reloading is dangerous, even if we
read the value from the map's max_sectors_kb beforehand. The reason for
this is that the sysfs value max_sectors_kb is the kernel's max_sectors
divided by 2, and user space has no way to figure out if the kernel-internal
value is odd or even. Thus by writing back the value just read to
max_sectors_kb, one might actually decrease the kernel value by one.

The only safe way to set max_sectors_kb on a live map would be to suspend
it, flushing all outstanding IO, then the path max_sectors_kb, reload,
and resume.

Since commit 8fd4868 ("libmultipath: don't set max_sectors_kb on reloads"),
we don't set the configured max_sectors_kb any more. But as shown above,
this is not safe. So really only set max_sectors_kb when creating a map.

Users who have stacked block devices on top of multipath, as described in the
commit message of 8fd4868 must make sure that the max_sectors_kb setting is
correct when the multipath map is first created. Decreasing the map's
max_sectors_kb value (without touching the paths) should actually be possible
in this situation, because stacked block devices are usually bio-based, and
bio-based IO (in contrast to request-based) can be split if the lower-level
device has can't handle the size of the I/O.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
As explained in the previous commit, setting max_sectors_kb for
paths that are members of a live map is dangerous. But as long as
a path is not a member of a map, setting max_sectors_kb poses no risk.
Set the parameter in adopt_paths(), for paths that aren't members
of the map yet. In order to determine whether or not a path is currently
member of the map, adopt_paths() needs to passed the current member list. If
(and only if) it's called from coalesce_paths(), the passed struct multipath
doesn not represent the current state of the map; adopt_paths() must therefore
get a new argument current_mpp that represents the kernel state.

We must still call sysfs_set_max_sectors_kb() from domap() in the ACT_CREATE
case, because when adopt_paths is called from coalesce_paths() for a map that
doesn't exist yet, mpp->max_sectors_kb is not set.

Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
Signed-off-by: Martin Wilck <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
Instead of adding the new 5300 model, replace them with wildcards.

Cc: Martin Wilck <[email protected]>
Cc: Benjamin Marzinski <[email protected]>
Cc: Christophe Varoqui <[email protected]>
Cc: DM-DEVEL ML <[email protected]>
Signed-off-by: Xose Vazquez Perez <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
bmarzins added 6 commits June 4, 2024 18:33
Add "If enabled, " to the sentence about multipathd.socket, since it is
no longer enabled by default.

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
Add the missing output for manual failback and print the defferral time
for deferred failbacks, if one isn't currently in progress.

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
If no_path_retry was greater than 0, multipathd was counting a map
failure when recovery mode was entered, and again when queueing was
disabled. The first one is incorrect, since the map is still queueing.

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
Also, the description for "del map $map" was incorrect.

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
The %s multipath and path wildcards both say they print the device
vend/prod/rev string, but neither of them do. The multipath wildcards
already provide a way to print the revision string and the %s wildcard
is used in the multipath -l output, so leave the wildcard output alone,
and change the description to only mention the vendor and product. There
is no other way to print the revision by path, and the path %s wildcard
is only used in the verbose multipath output, so make it actually print
the revision. Also check for unset strings, and print "##" instead of
nothing.

Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
(mwilck: minor spelling fixes applied).

Suggested-by: Nitin Yewale <[email protected]>
Signed-off-by: Benjamin Marzinski <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>

This comment has been minimized.

mwilck added 2 commits June 4, 2024 18:40
@mwilck
Copy link
Collaborator Author

mwilck commented Jun 4, 2024

@check-spelling-bot Report

has been resolved with latest push

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 4, 2024

@yu-re-ka, forgive my ignorance, I have zero knowledge about NixOS.

Can you provide a quick recipe for me to reproduce your issue, preferably in a container?

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 4, 2024

@yu-re-ka

It's strange because your environment uses the same base versions that I have in mine (openSUSE Tumbleweed).

The NixOS issue seems to be here:

building util.o because of util.c
util.c: In function 'test_basename_01':
util.c:174:16:error: implicit declaration of function 'basename'; did you mean 'dm_basename'? https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wimplicit-function-declaration-Werror=implicit-function-declaration
  174 |         base = basename(path);

But if you look at the file tests/util.c, it has:

#define _GNU_SOURCE
#include <string.h>
#include "util.h"

and util.h includes

const char *libmp_basename(const char *filename);
#ifndef __GLIBC__
#define basename(x) libmp_basename(x)
#endif

So if you are actually compiling against glibc1, you should be fine because of the string.h include, and if you are compiling against musl libc, the code from util.h should resolve basename() to libmp_basename(). This works for me for Tumbleweed and Fedora (recent glibc and gcc) and in Alpine (recent gcc and musl).

If this doesn't work, I fear I have to ask you to do some debugging on your own behalf and see what's going wrong in your environment.

Footnotes

  1. You say you're using glibc but AFAICS NixOS is carrying MUSL related patches, so maybe it isn't using glibc after all?

@mitchty
Copy link

mitchty commented Jun 6, 2024

So running with these changes to the nixos-24.05 branch I get this, looks like util.h isn't getting included by my eyes.

Diff to the derivation:

diff --git a/pkgs/os-specific/linux/multipath-tools/default.nix b/pkgs/os-specific/linux/multipath-tools/default.nix
index 5ec8197451cf..39fa47418c34 100644
--- a/pkgs/os-specific/linux/multipath-tools/default.nix
+++ b/pkgs/os-specific/linux/multipath-tools/default.nix
@@ -21,20 +21,20 @@
 
 stdenv.mkDerivation rec {
   pname = "multipath-tools";
-  version = "0.9.6";
+  version = "0.9.9";
 
   src = fetchFromGitHub {
-    owner = "opensvc";
+    owner = "openSUSE";
     repo = "multipath-tools";
-    rev = "refs/tags/${version}";
-    sha256 = "sha256-X4sAMGn4oBMY3cQkVj1dMcrDF7FgMl8SbZeUnCCOY6Q=";
+    rev = "queue";
+    sha256 = "sha256-D2t1XsDa82m9JliL/i+68TZ/PKanXrtkN3w4gYrb/dM=";
   };
 
   postPatch = ''
     substituteInPlace create-config.mk \
       --replace /bin/echo ${coreutils}/bin/echo
 
-    substituteInPlace multipathd/multipathd.service \
+    substituteInPlace multipathd/multipathd.service.in \
       --replace /sbin/multipathd "$out/bin/multipathd"
 
     sed -i -re '
@@ -64,6 +64,7 @@ stdenv.mkDerivation rec {
   ];
 
   makeFlags = [
+    "V=1"
     "LIB=lib"
     "prefix=$(out)"
     "systemd_prefix=$(out)"

Built locally via nix build .#legacyPackages.x86_64-linux.multipath-tools -L

multipath-tools> == running parser-test ==
multipath-tools> building util.o because of util.c
multipath-tools> gcc -D_FORTIFY_SOURCE=3  -DURCU_VERSION=0x000e00 -D_FILE_OFFSET_BITS=64 -DBIN_DIR=\"/nix/store/dc3z48ls70h8sr9dkir71ybrvqy50rb8-multipath-tools-0.9.9/sbin\" -DMULTIPATH_DIR=\"/nix/store/dc3z48ls70h8sr9dkir71ybrvqy50rb8-multipath-tools-0.9.9/lib/multipath\" -DRUNTIME_DIR=\"/run\" -DCONFIG_DIR=\"/nix/store/dc3z48ls70h8sr9dkir71ybrvqy50rb8-multipath-tools-0.9.9/etc/multipath/conf.d\" -DDEFAULT_CONFIGFILE=\"/nix/store/dc3z48ls70h8sr9dkir71ybrvqy50rb8-multipath-tools-0.9.9/etc/multipath.conf\" -DSTATE_DIR=\"/nix/store/dc3z48ls70h8sr9dkir71ybrvqy50rb8-multipath-tools-0.9.9/etc/multipath\" -DEXTRAVERSION=\"\" -MMD -MP -I../libmultipath -I../libmpathutil -I../libmpathcmd -I../multipathd -DTESTCONFDIR=\"/build/source/tests/conf.d\" -std=gnu99  -O2 -g -fstack-protector-strong --param=ssp-buffer-size=4 -Werror -Wall -Wextra -Wformat=2 -Wformat-overflow=2 -Werror=implicit-int -Werror=implicit-function-declaration -Werror=format-security -Wno-clobbered -Wno-error=clobbered -Werror=cast-qual -Werror=discarded-qualifiers  -pipe -fPIE -DPIE -Wno-unused-parameter   -c -o util.o util.c
multipath-tools> util.c: In function 'test_basename_01':
multipath-tools> util.c:174:16: error: implicit declaration of function 'basename'; did you mean 'dm_basename'? [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wimplicit-function-declaration-Werror=implicit-function-declaration8;;]
multipath-tools>   174 |         base = basename(path);
multipath-tools>       |                ^~~~~~~~
multipath-tools>       |                dm_basename
multipath-tools> util.c:174:14: error: assignment to 'const char *' from 'int' makes pointer from integer without a cast [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wint-conversion-Werror=int-conversion8;;]
multipath-tools>   174 |         base = basename(path);
multipath-tools>       |              ^
multipath-tools> util.c: In function 'test_basename_02':
multipath-tools> util.c:184:14: error: assignment to 'const char *' from 'int' makes pointer from integer without a cast [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wint-conversion-Werror=int-conversion8;;]
multipath-tools>   184 |         base = basename(path);
multipath-tools>       |              ^
multipath-tools> cc1: all warnings being treated as errors
multipath-tools> make[1]: *** [Makefile:74: util.o] Error 1
multipath-tools> rm parser.o.wrap uevent.o.wrap
multipath-tools> make[1]: Leaving directory '/build/source/tests'
multipath-tools> make: *** [Makefile:121: test] Error 2

Not entirely sure whats going on the makefiles are a bit confusing but it looks more to me like the makefiles aren't including what is expected.

@mitchty
Copy link

mitchty commented Jun 6, 2024

Noting from glibc, the import we want is <libgen.h> according to:
https://sourceware.org/git/?p=glibc.git;a=blob;f=misc/libgen.h;hb=HEAD#l26

And rerunning with these changes to those test files like so (and killing the const warning as a const char seems to be being passed into basename):

diff --git a/pkgs/os-specific/linux/multipath-tools/default.nix b/pkgs/os-specific/linux/multipath-tools/default.nix
index 5ec8197451cf..50e6307b3a03 100644
--- a/pkgs/os-specific/linux/multipath-tools/default.nix
+++ b/pkgs/os-specific/linux/multipath-tools/default.nix
@@ -21,20 +21,20 @@
 
 stdenv.mkDerivation rec {
   pname = "multipath-tools";
-  version = "0.9.6";
+  version = "0.9.9";
 
   src = fetchFromGitHub {
-    owner = "opensvc";
+    owner = "openSUSE";
     repo = "multipath-tools";
-    rev = "refs/tags/${version}";
-    sha256 = "sha256-X4sAMGn4oBMY3cQkVj1dMcrDF7FgMl8SbZeUnCCOY6Q=";
+    rev = "queue";
+    sha256 = "sha256-D2t1XsDa82m9JliL/i+68TZ/PKanXrtkN3w4gYrb/dM=";
   };
 
   postPatch = ''
     substituteInPlace create-config.mk \
       --replace /bin/echo ${coreutils}/bin/echo
 
-    substituteInPlace multipathd/multipathd.service \
+    substituteInPlace multipathd/multipathd.service.in \
       --replace /sbin/multipathd "$out/bin/multipathd"
 
     sed -i -re '
@@ -46,6 +46,7 @@ stdenv.mkDerivation rec {
       $(find * -name Makefile\*)
 
     sed '1i#include <assert.h>' -i tests/{util,vpd}.c
+    sed '1i#include <libgen.h>' -i tests/{util,vpd}.c
   '';
 
   nativeBuildInputs = [
@@ -64,6 +65,8 @@ stdenv.mkDerivation rec {
   ];
 
   makeFlags = [
+    "V=1"
+    "CFLAGS=-Wno-discarded-qualifiers"
     "LIB=lib"
     "prefix=$(out)"
     "systemd_prefix=$(out)"

I get to here where util.h is definitely not getting sent to CFLAGS as an include dir:

multipath-tools> gcc  -Wl,-z,relro -Wl,-z,now -Wl,-z,defs -shared -Wl,-soname=libmultipath.so.0 \
multipath-tools>        -Wl,--version-script=libmultipath.version -o libmultipath.so.0 devmapper.o hwtable.o blacklist.o dmparser.o structs.o discovery.o propsel.o dict.o pgpolicies.o defaults.o uevent.o switchgroup.o print.o alias.o configure.o structs_vec.o sysfs.o lock.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o io_err_stat.o dm-generic.o generic.o nvme-lib.o libsg.o valid.o prio.o checkers.o foreign.o config.o -lpthread -ldl -ldevmapper -ludev -L../libmpathutil -lmpathutil -L../libmpathcmd -lmpathcmd -lmount -lurcu -laio -lsystemd
multipath-tools> ln -sf libmultipath.so.0 libmultipath.so
multipath-tools> make[1]: Leaving directory '/build/source/libmultipath'
multipath-tools> make[1]: Entering directory '/build/source/libmpathpersist'
multipath-tools> building mpath_persist.o because of mpath_persist.c
multipath-tools> gcc -D_FORTIFY_SOURCE=3  -DURCU_VERSION=0x000e00 -D_FILE_OFFSET_BITS=64 -DBIN_DIR=\"/nix/store/x5gck165q7r1h0dhqrfpvv1vfk9h8hw0-multipath-tools-0.9.9/sbin\" -DMULTIPATH_DIR=\"/nix/store/x5gck165q7r1h0dhqrfpvv1vfk9h8hw0-multipath-tools-0.9.9/lib/multipath\" -DRUNTIME_DIR=\"/run\" -DCONFIG_DIR=\"/nix/store/x5gck165q7r1h0dhqrfpvv1vfk9h8hw0-multipath-tools-0.9.9/etc/multipath/conf.d\" -DDEFAULT_CONFIGFILE=\"/nix/store/x5gck165q7r1h0dhqrfpvv1vfk9h8hw0-multipath-tools-0.9.9/etc/multipath.conf\" -DSTATE_DIR=\"/nix/store/x5gck165q7r1h0dhqrfpvv1vfk9h8hw0-multipath-tools-0.9.9/etc/multipath\" -DEXTRAVERSION=\"\" -MMD -MP -Wno-discarded-qualifiers -c -o mpath_persist.o mpath_persist.c
multipath-tools> mpath_persist.c:3:10: fatal error: util.h: No such file or directory
multipath-tools>     3 | #include "util.h"
multipath-tools>       |          ^~~~~~~~
multipath-tools> compilation terminated.
multipath-tools> make[1]: *** [../Makefile.inc:136: mpath_persist.o] Error 1
multipath-tools> make[1]: Leaving directory '/build/source/libmpathpersist'
multipath-tools> make: *** [Makefile:45: libmpathpersist] Error 2

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 6, 2024

@yu-re-ka

The problem is in the nix derivation itself, not in the multipath-tools code. Because of the insertion of #include <assert.h> in line 1 in the source file, the #define _GNU_SOURCE later in the file has no effect.1

The insertion of #include <assert.h> is obsoleted by 5e95a28 (0.9.5) and can be removed. The same holds for this downstream patch (obsoleted by e5004de, this PR).

Next time, instead of creating downstream changes or string substitution hacks, please send patches upstream that make the NixOS build succeed without such customizations. We won't reject such patches unless they break something in other distros.

Footnotes

  1. "These directives must come before any #include of a system header file".

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 6, 2024

This code block in multipath-tools default.nix also seems superfluous:

    sed -i -re '
      s,^( *#define +DEFAULT_MULTIPATHDIR\>).*,\1 "'"$out/lib/multipath"'",
    ' libmultipath/defaults.h
    sed -i -e 's,\$(DESTDIR)/\(usr/\)\?,$(prefix)/,g' \
      kpartx/Makefile libmpathpersist/Makefile
    sed -i -e "s,GZIP,GZ," \
      $(find * -name Makefile\*)

The first two sed commands replace patterns which we don't use any more, and the 3rd one appears totally pointless to me.

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 7, 2024

the 3rd one appears totally pointless to me.

Historically, it was necessary. It has been obsoleted by 02bc889.

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 7, 2024

The first two sed commands replace patterns which we don't use any more

DEFAULT_MULTIPATHDIR has been removed in af15832 (0.9.0). $(DESTDIR)/usr hasn't been referenced since 66bea11 (0.6.2).

@yu-re-ka
Copy link

Thank you so much for figuring this out! I have not been involved with the multipath-tools package before except updating it to this new version / backporting the fix for the new musl basename compatibility things.

These lines are quite old (up to 8 years!). I would like to believe we are a lot more strict in how we patch around code nowadays. Anyways, it's cleaned up now.

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 10, 2024

@yu-re-ka

while we're discussing this, what's the right way to insert absolute paths to executables e.g. in systemd unit files or udev rules in NixoS?

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 11, 2024

@cvaroqui, as the NixOS issue is resolved, can we go forward with this PR?

yu-re-ka pushed a commit to NixOS/nixpkgs that referenced this pull request Jun 12, 2024
The upstream devs have pointed out[^1] that these sed commands are obsolete
and are responsible for issues with building the 0.9.9 release (not tagged yet)

[^1]: opensvc/multipath-tools#85 (comment)
@cvaroqui cvaroqui merged commit efa6a26 into opensvc:master Jun 13, 2024
63 of 64 checks passed
@yu-re-ka
Copy link

while we're discussing this, what's the right way to insert absolute paths to executables e.g. in systemd unit > files or udev rules in NixoS?

this depends: is it a executable from your own application, or from another
my expectation would be:

  • from your own application: template the path according to the DESTDIR / PREFIX parameters which are given to the makefile
  • from another application: search the application in the PATH at build-time and insert the absolute path into the service/...

@mwilck
Copy link
Collaborator Author

mwilck commented Jun 13, 2024

I think we can do the former (I'm currently working on a patch series for it) but not the latter, which is just too NixOS-specific and up to the Nix developers to care about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multipathd should not try to acquire realtime scheduling, just run with high priority.
7 participants