Package: nfs-common
Version: 2.6.2-4
Severity: important
Tags: patch upstream

On some of our bookworm systems I've seen what looked like a file descriptor 
leak. Sample lsof output:

[...]
rpc.idmap 675 root  126r      DIR               0,40        0      10813 
/run/rpc_pipefs/nfs/clnt11e6 (deleted)
rpc.idmap 675 root  127u     FIFO               0,40      0t0      10817 
/run/rpc_pipefs/nfs/clnt11e6/idmap (deleted)
rpc.idmap 675 root  128r      DIR               0,40        0      10834 
/run/rpc_pipefs/nfs/clnt11ef (deleted)
rpc.idmap 675 root  129u     FIFO               0,40      0t0      10838 
/run/rpc_pipefs/nfs/clnt11ef/idmap (deleted)
rpc.idmap 675 root  130r      DIR               0,40        0      10855 
/run/rpc_pipefs/nfs/clnt11f8 (deleted)
rpc.idmap 675 root  131u     FIFO               0,40      0t0      10859 
/run/rpc_pipefs/nfs/clnt11f8/idmap (deleted)

Cranking up the verbosity level to 3 showed that dirscancb never reaps stale 
entries in its queue (no "Stale client" lines). The reason turns out to be that 
the scan terminates on the first directory entry that doesn't contain an 
"idmap" file. Applying the attached patch seems to have solved the problem for 
me.

As far as I can tell the bug is still present upstream, and has been for many 
years (that "goto out" is from 2007 and replaced a "return" so the bug is even 
older than that).

Marking "important" since this has actually caused observable problems in our 
environment.
From: Sergio Gelato <sergio.gel...@astro.su.se>
Date: Tue, 4 Jun 2024 16:02:59 +0200
Subject: rpc.idmapd: nfsopen() failures should not be fatal

dirscancb() loops over all clnt* subdirectories of /run/rpc_pipefs/nfs/.
Some of these directories contain /idmap files, others don't. nfsopen()
returns -1 for the latter; we then want to skip the directory, not abort
the entire scan.
---
 utils/idmapd/idmapd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
index e79c124..f3c540d 100644
--- a/utils/idmapd/idmapd.c
+++ b/utils/idmapd/idmapd.c
@@ -556,7 +556,7 @@ dirscancb(int fd, short UNUSED(which), void *data)
 			if (nfsopen(ic) == -1) {
 				close(ic->ic_dirfd);
 				free(ic);
-				goto out;
+				continue;
 			}
 
 			if (verbose > 2)

Reply via email to