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
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

Reply via email to