From: Dominique Martinet <asmadeus@codewreck.org>
To: Yuanfu Xie <yuanfuxie@stu.pku.edu.cn>
Cc: Eric Van Hensbergen <ericvh@kernel.org>,
Latchesar Ionkov <lucho@ionkov.net>,
Christian Schoenebeck <linux_oss@crudebyte.com>,
v9fs@lists.linux.dev, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: Re: [PATCH] 9p: don't decrement a server-owned zero nlink
Date: Thu, 29 Oct 2026 10:52:34 +0900 [thread overview]
Message-ID: <auKm4tewzgNX6VLh@codewreck.org> (raw)
In-Reply-To: <8B490036-EBB0-4A36-AE39-F294F7C79649@stu.pku.edu.cn>
Yuanfu Xie wrote on Mon, Sep 28, 2026 at 03:25:48PM +0800:
> A 9P2000.L server can report nlink=0 for a regular file that still
> exists. On a cache=loose or cache=fscache mount, lookup stores that
> value with set_nlink(). A later successful unlink calls
> v9fs_dec_count(), which still calls drop_nlink() for a non-directory.
> drop_nlink() warns, and the unsigned link count wraps to 4294967295.
> fstat() on a descriptor opened before the unlink shows 0 before and
> 4294967295 after.
>
> The warning on the unpatched kernel, trimmed:
>
> WARNING: fs/inode.c:408 at drop_nlink+0xac/0xd0, CPU#1: trigger/188
> CPU: 1 UID: 0 PID: 188 Comm: trigger Tainted: G N 7.3.0-rc4-00537-ga3ff15db6820 #1 PREEMPT(lazy)
> RIP: 0010:drop_nlink+0xac/0xd0
> Call Trace:
> <TASK>
> v9fs_remove+0x529/0x750
> vfs_unlink+0x2f0/0xbd0
> filename_unlinkat+0x340/0x6c0
> __x64_sys_unlink+0x46/0x70
> do_syscall_64+0xe8/0x4f0
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
> </TASK>
> ---[ end trace 0000000000000000 ]---
>
> Directories whose cached nlink is at most 2 already skip this
> decrement, because the exported filesystem may not maintain nlink
> (commit ac89b2ef9b559). cache=none skips it as well (commit
> 574aa0b479947). cache=mmap does not take this path: it sets neither
> CACHE_META nor CACHE_LOOSE. A regular file on cache=loose or
> cache=fscache still does. Its count came from GETATTR and may
> already be zero, so skip the decrement when i_nlink is already 0.
>
> Verified on 7.3-rc4-00537-ga3ff15db6820 with only this change. A
> server that advertises nlink=0 and accepts the unlink no longer
> warns, and the open descriptor stays at nlink 0. An honest server
> on the same mount still goes from 1 to 0. A rejected unlink leaves
> the count unchanged. cache=none is unchanged. With panic_on_warn
> the unpatched kernel panics on the warning; the patched kernel does
> not.
>
> Fixes: ac89b2ef9b559 ("9p: don't maintain dir i_nlink if the exported fs doesn't either")
> Cc: stable@vger.kernel.org
> Signed-off-by: Yuanfu Xie <yuanfuxie@stu.pku.edu.cn>
This is the same as part of what was sent in [1], but they never
bothered resending split commits, so picking this up instead
[1] https://lore.kernel.org/r/20260919221734.3708000-1-benquike@gmail.com
> ---
> fs/9p/vfs_inode.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index d7e678de0a036..347739b81513f 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -495,6 +495,12 @@ static int v9fs_at_to_dotl_flags(int flags)
> * nothing and races with concurrent metadata fetches that may already
> * have observed the post-unlink value (nlink == 0).
> *
> + * The same applies to a regular file whose cached nlink has already been
> + * driven to zero by the server: in the cached modes the attributes come
> + * from GETATTR and are applied verbatim, so decrementing a link count the
> + * server does not maintain only trips the drop_nlink() WARN_ON and
> + * underflows i_nlink.
> + *
> * @inode: inode whose nlink is being dropped
> */
> static void v9fs_dec_count(struct inode *inode)
> @@ -503,6 +509,8 @@ static void v9fs_dec_count(struct inode *inode)
>
> if (!(v9ses->cache & (CACHE_META | CACHE_LOOSE)))
> return;
> + if (inode->i_nlink == 0)
> + return;
> if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
> drop_nlink(inode);
> }
>
>
--
Dominique Martinet | Asmadeus
prev parent reply other threads:[~2026-10-29 1:52 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 7:25 [PATCH] 9p: don't decrement a server-owned zero nlink Yuanfu Xie
2026-10-29 1:52 ` Dominique Martinet [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=auKm4tewzgNX6VLh@codewreck.org \
--to=asmadeus@codewreck.org \
--cc=ericvh@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux_oss@crudebyte.com \
--cc=lucho@ionkov.net \
--cc=stable@vger.kernel.org \
--cc=v9fs@lists.linux.dev \
--cc=yuanfuxie@stu.pku.edu.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.