From f844b13273e8b72d1e3205a3d548e61f905d56d9 Mon Sep 17 00:00:00 2001 From: Jeff Xie Date: Thu, 29 Jan 2026 17:37:01 +0800 Subject: [PATCH] Treat NFS ESTALE fds as unlinked for +L selection On NFS clients, a file can be deleted on the server while still referenced by an open fd on the client. In such cases, stat(2)/lstat(2) on /proc//fd/ may fail with ESTALE ("Stale file handle"). lsof's +L selection is commonly used to find open-but-unlinked files, but ESTALE fds were not selectable. Record per-fd errno from statsafely() / lstatsafely() and, when +L selection is enabled (SELNLINK), mark the file as matching and annotate NAME with " (STALE)". This helps identify NFS open-but-deleted/stale file handles using existing +L workflows without introducing new command-line options. Signed-off-by: Jeff Xie --- lib/dialects/linux/dproc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/dialects/linux/dproc.c b/lib/dialects/linux/dproc.c index 8dc7c27a..5d62724c 100644 --- a/lib/dialects/linux/dproc.c +++ b/lib/dialects/linux/dproc.c @@ -917,6 +917,8 @@ static int process_id(struct lsof_context *ctx, /* context */ static int pathil = 0; char *rest; int txts = 0; + int enss_fd = 0; + int enls_fd = 0; #if defined(HASSELINUX) cntxlist_t *cntxp; @@ -1206,6 +1208,7 @@ static int process_id(struct lsof_context *ctx, /* context */ } else { if (HasNFS) { if (lstatsafely(ctx, path, &lsb)) { + enls_fd = errno; (void)statEx(ctx, pbuf, &lsb, &ls); enls = errno; } else { @@ -1213,6 +1216,7 @@ static int process_id(struct lsof_context *ctx, /* context */ ls = SB_ALL; } if (statsafely(ctx, path, &sb)) { + enss_fd = errno; (void)statEx(ctx, pbuf, &sb, &ss); enss = errno; } else { @@ -1353,6 +1357,12 @@ static int process_id(struct lsof_context *ctx, /* context */ enter_nm(ctx, rest); } + if ((Selflags & SELNLINK) && + (enss_fd == ESTALE || enls_fd == ESTALE)) { + Lf->sf |= SELNLINK; + (void)add_nma(ctx, " (STALE)", 8); + } + if (Lf->sf) link_lfile(ctx); }