> Date: Wed, 4 May 2022 17:58:14 +0200
> From: Martin Pieuchot <[email protected]>
>
> On 04/05/22(Wed) 09:16, Sebastien Marie wrote:
> > [...]
> > we don't have any vclean label ("vclean (inactive)" or "vclean (active)"),
> > so
> > vclean() was not called in this timeframe.
>
> So we are narrowing down the issue:
>
> 1. A file is opened
> 2. Then mmaped
> 3. Some of its pages are swapped to disk
Hmm, why does this happen? Is this because the mmap(2) was done using
MAP_PRIVATE? But then what's the point of setting
UVM_VNODE_CANPERSIST?
> 4. The process die, closing the file
> 5. The reaper calls uvn_detach() on the vnode which has UVM_VNODE_CANPERSIST
> . This release the last reference of the vnode without sync' the pages
> -> the vnode ends up on the free list
> 6. The page daemon tries to sync the pages, grab a reference on the vnode
> which has already been recycled.
>
> I don't understand the mechanism around UVM_VNODE_CANPERSIST. I looked
> for missing uvm_vnp_uncache() and found the following two. I doubt
> those are the one triggering the bug because they are in NFS & softdep.
>
> So my question is should UVM_VNODE_CANPERSIST be cleared at some point
> in this scenario? If so, when?
>
> What is the interaction between this flag and mmap pages which are on
> swap? In other words, is it safe to call vrele(9) in uvn_detach() if
> uvn_flush() hasn't been called with PGO_FREE|PGO_ALLPAGES? If yes, why?
>
> What it this flag suppose to say? Why is it always cleared before
> VOP_REMOVE() & VOP_RENAME()?
>
> Index: nfs/nfs_serv.c
> ===================================================================
> RCS file: /cvs/src/sys/nfs/nfs_serv.c,v
> retrieving revision 1.120
> diff -u -p -r1.120 nfs_serv.c
> --- nfs/nfs_serv.c 11 Mar 2021 13:31:35 -0000 1.120
> +++ nfs/nfs_serv.c 4 May 2022 15:29:06 -0000
> @@ -1488,6 +1488,9 @@ nfsrv_rename(struct nfsrv_descript *nfsd
> error = -1;
> out:
> if (!error) {
> + if (tvp) {
> + (void)uvm_vnp_uncache(tvp);
> + }
> error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
> tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
> } else {
> Index: ufs/ffs/ffs_inode.c
> ===================================================================
> RCS file: /cvs/src/sys/ufs/ffs/ffs_inode.c,v
> retrieving revision 1.81
> diff -u -p -r1.81 ffs_inode.c
> --- ufs/ffs/ffs_inode.c 12 Dec 2021 09:14:59 -0000 1.81
> +++ ufs/ffs/ffs_inode.c 4 May 2022 15:32:15 -0000
> @@ -172,11 +172,12 @@ ffs_truncate(struct inode *oip, off_t le
> if (length > fs->fs_maxfilesize)
> return (EFBIG);
>
> - uvm_vnp_setsize(ovp, length);
> oip->i_ci.ci_lasta = oip->i_ci.ci_clen
> = oip->i_ci.ci_cstart = oip->i_ci.ci_lastw = 0;
>
> if (DOINGSOFTDEP(ovp)) {
> + uvm_vnp_setsize(ovp, length);
> + (void) uvm_vnp_uncache(ovp);
> if (length > 0 || softdep_slowdown(ovp)) {
> /*
> * If a file is only partially truncated, then
>
>