Andrew,
Here a new diff which will record a bit more information.
It keep track of the last 10 v_usecount changes with:
- pid and ps_comm
- usecount value (before and after)
- stacktrace
We will need:
- the vnode_history (without offsets)
- the panic and the backtrace of it
but keep also photos.
On Wed, Apr 13, 2022 at 11:42:22AM +0200, Martin Pieuchot wrote:
> On 12/04/22(Tue) 14:58, Sebastien Marie wrote:
> > [...]
> > uvn_io: start: 0x8000ffab9688, type VREG, use 0, write 0, hold 0, flags
> > (VBIOONFREELIST)
> > tag VT_UFS, ino 14802284, on dev 4, 30 flags 0x100, effnlink 1, nlink 1
> > mode 0100644, owner 858, group 1000, size 345603015
> > => vnode_history_print 0x8000ffab9688, next=1
>
> So we see the same crash in the pdaemon when trying to sync, at least,
> an inactive page to disk...
>
> [...]
> The vnode is mmaped here.
>
> [...]
> The process exit here, it seems single-threaded.
>
> [...]
> The reaper unmap all the memory and release the referenced grabbed
> during mmap.
>
> [...]
> Who is doing this? Could you print the pid of the process? It seems
> the vnode has been recycled at this point.
>
> [...]
> Same for this, has the vnode been recycled?
>
>
> > panic: vn_lock: v_usecount == 0
> > Stopped at db_enter+0x10: popq %rbp
> > TIDPID UID PRFLAGS PFLAGS CPU COMMAND
> > 448838 87877 858 0 0x400 3 qbittorrent-nox
> > *281933 50305 0 0x14000 0x200 1K pagedaemon
> > db_enter() at ...
> > panic(...)
> > vn_lock(800ffab9688,81)
> > uvn_io(fd837a66bee8,...,1,90,1)
> > uvm_pager_put(fd837a66bee8, )
> > uvmpd_scan_inactive(...)
> > uvmpd_scan()
> > uvm_pageout(80005270)
>
> This indicates a page hasn't been freed during uvn_detach() which is
> called as part of uvm_unmap_detach() by the reaper... Weird.
>
--
Sebastien Marie
diff 153abd98269720429ee0b19133ca24d5c39a7f36 /home/semarie/repos/openbsd/src
blob - 13c70890ccc11f131013d14b853f4f06941924cc
file + sys/kern/vfs_subr.c
--- sys/kern/vfs_subr.c
+++ sys/kern/vfs_subr.c
@@ -66,6 +66,7 @@
#include
#include
#include
+#include
#include
@@ -126,8 +127,27 @@ void vfs_unmountall(void);
void printlockedvnodes(void);
#endif
+#define VH_MAXST 10 /* ring size */
+#define VH_INCR0
+#define VH_DECR1
+struct vhistory {
+ pid_t vhh_pid;
+ charvhh_comm[_MAXCOMLEN]; /* incl NUL */
+ u_int vhh_old_usecount;
+ u_int vhh_new_usecount;
+ struct stacktrace vhh_st;
+};
+struct vnode_history {
+ u_int vh_next;/* [K] next free slot in vh_ring */
+ struct vhistory vh_ring[VH_MAXST]; /* [K] ring for holding the vnode
history */
+};
+void vnode_history_init(struct vnode *);
+void vnode_history_record(struct vnode *, int);
+void vnode_history_print(struct vnode *, int (*pr)(const char *, ...)
__attribute__((__format__(__kprintf__,1,2;
+
struct pool vnode_pool;
struct pool uvm_vnode_pool;
+struct pool vnode_history_pool;
static inline int rb_buf_compare(const struct buf *b1, const struct buf *b2);
RBT_GENERATE(buf_rb_bufs, buf, b_rbbufs, rb_buf_compare);
@@ -154,6 +174,8 @@ vntblinit(void)
PR_WAITOK, "vnodes", NULL);
pool_init(_vnode_pool, sizeof(struct uvm_vnode), 0, IPL_NONE,
PR_WAITOK, "uvmvnodes", NULL);
+ pool_init(_history_pool, sizeof(struct vnode_history), 0,
+ IPL_NONE, PR_WAITOK, "vnodehis", NULL);
TAILQ_INIT(_hold_list);
TAILQ_INIT(_free_list);
TAILQ_INIT();
@@ -410,6 +432,7 @@ getnewvnode(enum vtagtype tag, struct mount *mp, const
splx(s);
vp = pool_get(_pool, PR_WAITOK | PR_ZERO);
vp->v_uvm = pool_get(_vnode_pool, PR_WAITOK | PR_ZERO);
+ vp->v_history = pool_get(_history_pool, PR_WAITOK);
vp->v_uvm->u_vnode = vp;
uvm_obj_init(>v_uvm->u_obj, _vnodeops, 0);
RBT_INIT(buf_rb_bufs, >v_bufs_tree);
@@ -460,6 +483,7 @@ getnewvnode(enum vtagtype tag, struct mount *mp, const
vp->v_socket = NULL;
}
cache_purge(vp);
+ vnode_history_init(vp);
vp->v_type = VNON;
vp->v_tag = tag;
vp->v_op = vops;
@@ -674,9 +698,13 @@ vget(struct vnode *vp, int flags)
}
vp->v_usecount++;
+ vnode_history_record(vp, VH_INCR);
+
if (flags & LK_TYPE_MASK) {
if ((error = vn_lock(vp, flags)) != 0) {
vp->v_usecount--;
+ vnode_history_record(vp, VH_DECR);
+
if (vp->v_usecount == 0 && onfreelist)
vputonfreelist(vp);
}
@@ -700,6 +728,7 @@ vref(struct vnode *vp)
panic("vref on a VNON vnode");
#endif
vp->v_usecount++;
+ vnode_history_record(vp, VH_INCR);
}
void
@@ -762,6 +791,7 @@ vput(struct vnode *vp)
}
#endif