diff --git a/SOURCES/nfs-utils-2.3.3-nfsrahead-enable-event-driven-mountinfo-monitoring-a.patch b/SOURCES/nfs-utils-2.3.3-nfsrahead-enable-event-driven-mountinfo-monitoring-a.patch new file mode 100644 index 0000000..ae7e2cc --- /dev/null +++ b/SOURCES/nfs-utils-2.3.3-nfsrahead-enable-event-driven-mountinfo-monitoring-a.patch @@ -0,0 +1,133 @@ +From 0f5fe65d83f7455112aea82bf96f99523cb03ca7 Mon Sep 17 00:00:00 2001 +From: Aaron Tomlin +Date: Fri, 6 Mar 2026 17:01:44 -0500 +Subject: [PATCH] nfsrahead: enable event-driven mountinfo monitoring and skip + non-NFS devices + +The nfsrahead utility relies on parsing "/proc/self/mountinfo" to +correlate a device number with a specific NFS mount point. However, due +to the asynchronous nature of system initialisation, the relevant entry +in mountinfo may not be immediately available when the tool is executed. + +Currently, the utility employs a naive polling mechanism, retrying the +search five times with a fixed 50ms delay (totalling 250ms). This +approach proves brittle on systems under heavy load or during +distinctively slow boot sequences. + +To mitigate this race condition and improve robustness, update +get_device_info() to utilise the libmount monitoring API. + +The new implementation introduces the following logic: + + 1. Initialises a monitor on /proc/self/mountinfo using + mnt_new_monitor(). + + 2. Replaces the fixed polling loop with mnt_monitor_wait(). + + 3. Increases the maximum wait time to 10 seconds (MNT_NM_TIMEOUT). + + 4. Introduces a fast-path rejection mechanism. NFS backing devices are + allocated from the kernel's unnamed block device pool (major number + 0). While some local multi-device filesystems (such as Btrfs) also + utilise anonymous device numbers, physical hardware block devices + (e.g., sda, nvme) always possess specific, non-zero major numbers. + By instantly exiting with -ENODEV for any device string not + beginning with "0:", we safely bypass the monitor for physical + drives, preventing the exhaustion of udev worker threads. + See set_anon_super() and get_anon_bdev(). + + 5. Implements strict monotonic deadline tracking within the monitor + loop to prevent indefinite blocking. + +Fixes: 2b62ac4c ("nfsrahead: enable event-driven mountinfo monitoring") +Reported-by: Yi Zhang +Link: https://lore.kernel.org/linux-block/CAHj4cs8URj2fJ7KyP9ViAm6npVOaMiAErnw2uFyPYEU2wb7G_w@mail.gmail.com/T/#t +Signed-off-by: Aaron Tomlin +Signed-off-by: Steve Dickson +--- + tools/nfsrahead/main.c | 55 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 54 insertions(+), 1 deletion(-) + +diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c +index b7b889ff..78cd2581 100644 +--- a/tools/nfsrahead/main.c ++++ b/tools/nfsrahead/main.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -17,6 +18,8 @@ + #define CONF_NAME "nfsrahead" + #define NFS_DEFAULT_READAHEAD 128 + ++#define MNT_NM_TIMEOUT 10000 ++ + /* Device information from the system */ + struct device_info { + char *device_number; +@@ -117,7 +120,57 @@ out_free_device_info: + + static int get_device_info(const char *device_number, struct device_info *device_info) + { +- int ret = get_mountinfo(device_number, device_info, MOUNTINFO_PATH); ++ int ret; ++ struct libmnt_monitor *mn = NULL; ++ struct timespec start, now; ++ int remaining_ms = MNT_NM_TIMEOUT; ++ ++ /* ++ * Fast-path rejection: ++ * NFS backing devices always use the anonymous block device major number (0). ++ * If the device number does not start with "0:", it is a physical block device ++ * and will never be an NFS mount. Exit immediately to prevent blocking udev. ++ */ ++ if (strncmp(device_number, "0:", 2) != 0) ++ return -ENODEV; ++ ++ ret = get_mountinfo(device_number, device_info, MOUNTINFO_PATH); ++ if (ret == 0) ++ return 0; ++ ++ mn = mnt_new_monitor(); ++ if (!mn) ++ goto fallback; ++ ++ if (mnt_monitor_enable_kernel(mn, 1) < 0) { ++ mnt_unref_monitor(mn); ++ goto fallback; ++ } ++ ++ clock_gettime(CLOCK_MONOTONIC, &start); ++ ++ while (remaining_ms > 0) { ++ int rc = mnt_monitor_wait(mn, remaining_ms); ++ if (rc > 0) { ++ ret = get_mountinfo(device_number, device_info, MOUNTINFO_PATH); ++ if (ret == 0) { ++ mnt_unref_monitor(mn); ++ return 0; ++ } ++ } else { ++ break; ++ } ++ ++ clock_gettime(CLOCK_MONOTONIC, &now); ++ long elapsed_ms = (now.tv_sec - start.tv_sec) * 1000 + ++ (now.tv_nsec - start.tv_nsec) / 1000000; ++ remaining_ms = MNT_NM_TIMEOUT - elapsed_ms; ++ } ++ ++ mnt_unref_monitor(mn); ++ return ret; ++ ++fallback: + for (int retry_count = 0; retry_count < 5 && ret != 0; retry_count++) { + usleep(50000); + ret = get_mountinfo(device_number, device_info, MOUNTINFO_PATH); +-- +2.43.7 + diff --git a/SOURCES/nfs-utils-2.3.3-nfsrahead-quieten-misleading-error-for-non-NFS-block.patch b/SOURCES/nfs-utils-2.3.3-nfsrahead-quieten-misleading-error-for-non-NFS-block.patch new file mode 100644 index 0000000..91151f8 --- /dev/null +++ b/SOURCES/nfs-utils-2.3.3-nfsrahead-quieten-misleading-error-for-non-NFS-block.patch @@ -0,0 +1,48 @@ +From 3395a0aa79286ce9c3df283fd9fb6db14dbbc333 Mon Sep 17 00:00:00 2001 +From: Aaron Tomlin +Date: Wed, 11 Mar 2026 15:14:16 -0400 +Subject: [PATCH 2/2] nfsrahead: quieten misleading error for non-NFS block + devices + +When get_device_info() evaluates a physical block device via the +fast-path rejection logic, it deliberately returns -ENODEV. + +Previously, main() handled this by logging a D_GENERAL error ("unable to +find device"). Because udev invokes nfsrahead for all block devices +across the system, this results in misleading journal spam for devices +that were intentionally skipped, rather than genuinely missing. + +Update the error handling logic in main() to explicitly catch the +-ENODEV return code. When encountered, log a more accurate "skipping +non-NFS device" message at the D_ALL debugging level. This prevents +unnecessary journal noise whilst maintaining the existing behaviour of +returning the errno exit status. + +Reported-by: Yi Zhang +Tested-by: Yi Zhang +Signed-off-by: Aaron Tomlin +Signed-off-by: Steve Dickson +--- + tools/nfsrahead/main.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c +index 33487f37..86c7fcc6 100644 +--- a/tools/nfsrahead/main.c ++++ b/tools/nfsrahead/main.c +@@ -218,7 +218,11 @@ int main(int argc, char **argv) + if ((argc - optind) != 1) + xlog_err("expected the device number of a BDI; is udev ok?"); + +- if ((ret = get_device_info(argv[optind], &device)) != 0 || device.fstype == NULL) { ++ ret = get_device_info(argv[optind], &device); ++ if (ret == -ENODEV) { ++ xlog(D_ALL, "skipping non-NFS device %s\n", argv[optind]); ++ goto out; ++ } else if (ret != 0 || device.fstype == NULL) { + xlog(D_GENERAL, "unable to find device %s\n", argv[optind]); + goto out; + } +-- +2.43.7 + diff --git a/SOURCES/nfs-utils-2.3.3-nfsrahead-zero-initialise-device_info-struct.patch b/SOURCES/nfs-utils-2.3.3-nfsrahead-zero-initialise-device_info-struct.patch new file mode 100644 index 0000000..2161721 --- /dev/null +++ b/SOURCES/nfs-utils-2.3.3-nfsrahead-zero-initialise-device_info-struct.patch @@ -0,0 +1,48 @@ +From 20fa4785ce5235c41fd27044d7fdef377dd0e088 Mon Sep 17 00:00:00 2001 +From: Aaron Tomlin +Date: Wed, 11 Mar 2026 12:41:28 -0400 +Subject: [PATCH 1/2] nfsrahead: zero-initialise device_info struct + +A recent commit introduced a fast-path rejection mechanism to prevent +udev worker thread exhaustion. However, this optimisation exposed a bug +in the initialisation of the device_info struct in main(). + +When the fast-path is triggered (e.g., for a physical block device like +8:16), get_device_info() instantly returns -ENODEV. Because this early +exit occurs before get_mountinfo() is invoked, init_device_info() is +never called. + +Consequently, the device_info struct remains populated with +uninitialised stack memory. When main() catches the error and jumps to +the cleanup path, free_device_info() attempts to call free() on garbage +pointers, resulting in a glibc abort(3). + +Fix this by explicitly zero-initialising the device_info struct at +declaration, preventing the cleanup path from freeing uninitialised +memory during an early exit. + +Fixes: 0f5fe65d ("nfsrahead: fix udev worker exhaustion by skipping non-NFS devices") +Reported-by: Yi Zhang +Tested-by: Yi Zhang +Signed-off-by: Aaron Tomlin +Signed-off-by: Steve Dickson +--- + tools/nfsrahead/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c +index 78cd2581..33487f37 100644 +--- a/tools/nfsrahead/main.c ++++ b/tools/nfsrahead/main.c +@@ -191,7 +191,7 @@ static int conf_get_readahead(const char *kind) { + int main(int argc, char **argv) + { + int ret = 0, opt; +- struct device_info device; ++ struct device_info device = { 0 }; + unsigned int readahead = 128, log_level, log_stderr = 0; + + +-- +2.43.7 + diff --git a/SPECS/nfs-utils.spec b/SPECS/nfs-utils.spec index e35bf40..f25d46e 100644 --- a/SPECS/nfs-utils.spec +++ b/SPECS/nfs-utils.spec @@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser Name: nfs-utils URL: http://linux-nfs.org/ Version: 2.3.3 -Release: 68%{?dist} +Release: 69%{?dist} Epoch: 1 # group all 32bit related archs @@ -124,6 +124,9 @@ Patch066: nfs-utils-2.3.3-mountd-Minor-refactor-of-get_rootfh.patch Patch067: nfs-utils-2.3.3-mountd-Separate-lookup-of-the-exported-directory-and.patch Patch068: nfs-utils-2.3.3-support-Add-a-mini-library-to-extract-and-apply-RPC-.patch Patch069: nfs-utils-2.3.3-Fix-access-checks-when-mounting-subdirectories-in-NF.patch +Patch070: nfs-utils-2.3.3-nfsrahead-enable-event-driven-mountinfo-monitoring-a.patch +Patch071: nfs-utils-2.3.3-nfsrahead-zero-initialise-device_info-struct.patch +Patch072: nfs-utils-2.3.3-nfsrahead-quieten-misleading-error-for-non-NFS-block.patch Patch100: nfs-utils-1.2.1-statdpath-man.patch Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch @@ -403,6 +406,11 @@ fi %{_libdir}/libnfsidmap.so %changelog +* Thu Mar 19 2026 Scott Mayhew 2.3.3-69 +- nfsrahead: enable event-driven mountinfo monitoring and skip non-NFS devices (RHEL-150760) +- nfsrahead: zero-initialise device_info struct (RHEL-150760) +- nfsrahead: quieten misleading error for non-NFS block devices (RHEL-150760) + * Fri Feb 27 2026 Scott Mayhew 2.3.3-68 - Add requires for selinux-policy (RHEL-127095)