On Sun, Sep 14, 2025 at 11:05:08AM +1000, NeilBrown wrote: > READDIR without establishing and "open" state. > > Why do you think nfs4_opendata_access() expects the possibilty of a > directory? static int nfs4_opendata_access(const struct cred *cred, struct nfs4_opendata *opendata, struct nfs4_state *state, fmode_t fmode) { struct nfs_access_entry cache; u32 mask, flags; /* access call failed or for some reason the server doesn't * support any access modes -- defer access call until later */ if (opendata->o_res.access_supported == 0) return 0; mask = 0; if (fmode & FMODE_EXEC) { /* ONLY check for exec rights */ if (S_ISDIR(state->inode->i_mode)) ^^^^^^^ How else would you describe this? mask = NFS4_ACCESS_LOOKUP; else mask = NFS4_ACCESS_EXECUTE; > > 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?) > > I don't know what is going on here. > Based on the commit that introduced this code > > Commit: c45ffdd26961 ("NFSv4: Close another NFSv4 recovery race") > > there is presumably some race that can cause the test to fail. > Maybe Trond (cc:ed) could help explain. AFAICS, it can happen if you are there from nfs4_file_open(), hit _nfs4_opendata_to_nfs4_state(opendata), find ->rpc_done to be true in there, hit nfs4_opendata_find_nfs4_state(), have it call nfs4_opendata_get_inode() and run into a server without NFS_CAP_ATOMIC_OPEN_V1. Then you get ->o_arg.claim set to NFS4_OPEN_CLAIM_NULL and hit this: inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr); finding not the same inode as your dentry has attached to it. So the test might end up not being true, at least from my reading of that code. What I don't understand is the reasons for not failing immediately with EOPENSTALE in that case. TBH, I would be a lot more comfortable if the "attach inode to dentry" logics in there had been taken several levels up the call chains - analysis would be much easier that way...