On Mon, Sep 08, 2025 at 10:05:57AM +0100, Al Viro wrote: > > Fudging some type-state with C may well be useful but I suspect it is at > > most part of a solution. Simplification, documentation, run-time checks > > might also be important parts. As the type-state flag-day is a big > > thing, maybe it shouldn't be first. > > All of that requires being able to answer questions about what's there in > the existing filesystems. Which is pretty much the same problem as > those audits, obviously. And static annotations are way easier to > reason about. Speaking of annoyances, d_exact_alias() is gone, and good riddance, but there's another fun issue in the same area - environment for d_splice_alias() call *and* for one of those d_drop()-just-in-case. The call tree is still the same: _nfs4_open_and_get_state() <- _nfs4_do_open() <- nfs4_do_open() <- nfs4_atomic_open() == nfs_rpc_ops:open_context <- nfs_atomic_open() == ->atomic_open <- nfs4_file_open() == ->open <- nfs4_proc_create() == nfs_rpc_ops:create <- nfs_do_create() <- nfs_create() == ->create <- nfs_atomic_open_v23(), with O_CREAT == ->atomic_open # won't reach nfs4 stuff? ->create() and ->atomic_open() have the parent held at least shared; ->open() does not, but the chunk in question is hit only if dentry is negative, which won't happen in case of ->open(). Additional complication comes from the possibility for _nfs4_open_and_get_state() to fail after that d_splice_alias(). In that case we have _nfs4_do_open() return an error; its caller is inside a do-while loop in nfs4_do_open() and I think we can't end up going around the loop after such late failure (the only error possible after that is -EACCES/-NFS4ERR_ACCESS and that's not one of those that can lead to more iterations. However, looking at that late failure, that's the only call of nfs4_opendata_access(), and that function seems to expect the possibility of state->inode being a directory; can that really happen? Because if it can, we have a problem: alias = d_splice_alias(igrab(state->inode), dentry); /* d_splice_alias() can't fail here - it's a non-directory */ if (alias) { dput(ctx->dentry); ctx->dentry = dentry = alias; } very much *can* fail if it's reached with state->inode being a directory - we can get ERR_PTR() out of that d_splice_alias() and that will oops at if (d_inode(dentry) == state->inode) nfs_inode_attach_open_context(ctx); shortly afterwards (incidentally, what is that check about? It can only fail in case of nfs4_file_open(); should we have open(2) succeed in such situation?) Sigh...