NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/60504: lfs_cleanerd can kernel crash on load in lfs_fcntl; lfs_sp == NULL



> Date: Sat, 08 Aug 2026 19:47:30 +0900
> From: Shinichi Doyashiki <clare%csel.org@localhost>
> 
> I experienced kernel crash while running cvs update on the LFS with
> the WIP patch.
> 
> [ 2136.0027704] panic: cpu0: softints stuck for 16 seconds
> [ 2136.0027704] cpu0: Begin traceback...
> [ 2136.0027704] vpanic() at netbsd:vpanic+0x171
> [ 2136.0027704] panic() at netbsd:panic+0x3c
> [ 2136.0027704] heartbeat() at netbsd:heartbeat+0x310
> [ 2136.0027704] hardclock() at netbsd:hardclock+0x89
> [ 2136.0027704] Xresume_lapic_ltimer() at netbsd:Xresume_lapic_ltimer+0x1e
> [ 2136.0027704] --- interrupt ---
> [ 2136.0027704] _kernel_lock() at netbsd:_kernel_lock+0x13e
> [ 2136.0027704] lfs_cluster_work() at netbsd:lfs_cluster_work+0x22
> [ 2136.0027704] workqueue_worker() at netbsd:workqueue_worker+0xf3
> [ 2136.0027704] cpu0: End traceback...

I bet this is just a matter of doing too much work in lfs with the
kernel lock held.  I think this is going to require ripping the
band-aid that is the kernel lock off lfs, which we need to do anyway
sooner or later.  Most of it is serialized by lfs_lock anyway.  Try
the attached patch?
# HG changeset patch
# User Taylor R Campbell <riastradh%NetBSD.org@localhost>
# Date 1787517532 0
#      Sun Aug 23 20:38:52 2026 +0000
# Branch trunk
# Node ID ab8e67a9238a093c16504fef6720a224a9f31a9e
# Parent  4fbd288ac1da9e7d9592ddecf04f7513e244152f
# EXP-Topic riastradh-20260823-lfshacks
WIP: lfs: Run this without the kernel lock.

diff -r 4fbd288ac1da -r ab8e67a9238a sys/ufs/lfs/lfs_syscalls.c
--- a/sys/ufs/lfs/lfs_syscalls.c	Mon Aug 10 13:36:10 2026 +0000
+++ b/sys/ufs/lfs/lfs_syscalls.c	Sun Aug 23 20:38:52 2026 +0000
@@ -130,7 +130,6 @@ sys_lfs_markv(struct lwp *l, const struc
 	if ((u_int) blkcnt > LFS_MARKV_MAXBLKCNT)
 		return (EINVAL);
 
-	KERNEL_LOCK(1, NULL);
 	blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
 	if ((error = copyin(SCARG(uap, blkiov), blkiov,
 			    blkcnt * sizeof(BLOCK_INFO))) != 0)
@@ -141,7 +140,6 @@ sys_lfs_markv(struct lwp *l, const struc
 			blkcnt * sizeof(BLOCK_INFO));
     out:
 	lfs_free(fs, blkiov, LFS_NB_BLKIOV);
-	KERNEL_UNLOCK_ONE(NULL);
 	return error;
 }
 #else
@@ -171,7 +169,6 @@ sys_lfs_markv(struct lwp *l, const struc
 	if ((u_int) blkcnt > LFS_MARKV_MAXBLKCNT)
 		return (EINVAL);
 
-	KERNEL_LOCK(1, NULL);
 	blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
 	blkiov15 = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO_15), LFS_NB_BLKIOV);
 	if ((error = copyin(SCARG(uap, blkiov), blkiov15,
@@ -204,7 +201,6 @@ sys_lfs_markv(struct lwp *l, const struc
     out:
 	lfs_free(fs, blkiov, LFS_NB_BLKIOV);
 	lfs_free(fs, blkiov15, LFS_NB_BLKIOV);
-	KERNEL_UNLOCK_ONE(NULL);
 	return error;
 }
 #endif
@@ -575,7 +571,6 @@ sys_lfs_bmapv(struct lwp *l, const struc
 	if ((u_int) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO))
 		return (EINVAL);
 #endif
-	KERNEL_LOCK(1, NULL);
 	blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
 	if ((error = copyin(SCARG(uap, blkiov), blkiov,
 			    blkcnt * sizeof(BLOCK_INFO))) != 0)
@@ -586,7 +581,6 @@ sys_lfs_bmapv(struct lwp *l, const struc
 			blkcnt * sizeof(BLOCK_INFO));
     out:
 	lfs_free(fs, blkiov, LFS_NB_BLKIOV);
-	KERNEL_UNLOCK_ONE(NULL);
 	return error;
 }
 #else
@@ -615,7 +609,6 @@ sys_lfs_bmapv(struct lwp *l, const struc
 	blkcnt = SCARG(uap, blkcnt);
 	if ((size_t) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO))
 		return (EINVAL);
-	KERNEL_LOCK(1, NULL);
 	blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
 	blkiov15 = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO_15), LFS_NB_BLKIOV);
 	if ((error = copyin(SCARG(uap, blkiov), blkiov15,
@@ -648,7 +641,6 @@ sys_lfs_bmapv(struct lwp *l, const struc
     out:
 	lfs_free(fs, blkiov, LFS_NB_BLKIOV);
 	lfs_free(fs, blkiov15, LFS_NB_BLKIOV);
-	KERNEL_UNLOCK_ONE(NULL);
 	return error;
 }
 #endif
@@ -683,9 +675,17 @@ lfs_bmapv(struct lwp *l, fsid_t *fsidp, 
 	ump = VFSTOULFS(mntp);
 	fs = ump->um_lfs;
 
-	if (fs->lfs_cleaner_thread == NULL)
+	mutex_enter(&lfs_lock);
+	if (fs->lfs_cleaner_thread == NULL) {
 		fs->lfs_cleaner_thread = curlwp;
+	} else if (fs->lfs_cleaner_thread != curlwp) {
+		error = EBUSY;
+		mutex_exit(&lfs_lock);
+		goto out;
+	}
+	panic("cleaning");
 	KASSERT(fs->lfs_cleaner_thread == curlwp);
+	mutex_exit(&lfs_lock);
 
 	cnt = blkcnt;
 
@@ -791,6 +791,12 @@ lfs_bmapv(struct lwp *l, fsid_t *fsidp, 
 
 	KASSERTMSG((numrefed == 0), "lfs_bmapv: numrefed=%d", numrefed);
 
+	mutex_enter(&lfs_lock);
+	KASSERTMSG(fs->lfs_cleaner_thread == curlwp, "cleaner thread is %p",
+	    fs->lfs_cleaner_thread);
+	fs->lfs_cleaner_thread = NULL;
+	mutex_exit(&lfs_lock);
+out:
 	vfs_unbusy(mntp);
 
 	return 0;
@@ -833,11 +839,9 @@ sys_lfs_segclean(struct lwp *l, const st
 	if ((error = vfs_busy(mntp)) != 0)
 		return (error);
 
-	KERNEL_LOCK(1, NULL);
 	lfs_prelock(fs, 0);
 	error = lfs_do_segclean(fs, segnum, l->l_cred, l);
 	lfs_preunlock(fs);
-	KERNEL_UNLOCK_ONE(NULL);
 	vfs_unbusy(mntp);
 	return error;
 }
diff -r 4fbd288ac1da -r ab8e67a9238a sys/ufs/lfs/lfs_vfsops.c
--- a/sys/ufs/lfs/lfs_vfsops.c	Mon Aug 10 13:36:10 2026 +0000
+++ b/sys/ufs/lfs/lfs_vfsops.c	Sun Aug 23 20:38:52 2026 +0000
@@ -1184,6 +1184,7 @@ lfs_mountfs(struct vnode *devvp, struct 
 	mp->mnt_stat.f_namemax = LFS_MAXNAMLEN;
 	mp->mnt_stat.f_iosize = lfs_sb_getbsize(fs);
 	mp->mnt_flag |= MNT_LOCAL;
+	mp->mnt_iflag |= IMNT_MPSAFE;
 	mp->mnt_iflag |= IMNT_SHRLOOKUP;
 	mp->mnt_fs_bshift = lfs_sb_getbshift(fs);
 	mp->mnt_iflag |= IMNT_CAN_RWTORO;
diff -r 4fbd288ac1da -r ab8e67a9238a sys/ufs/lfs/lfs_vnops.c
--- a/sys/ufs/lfs/lfs_vnops.c	Mon Aug 10 13:36:10 2026 +0000
+++ b/sys/ufs/lfs/lfs_vnops.c	Sun Aug 23 20:38:52 2026 +0000
@@ -547,10 +547,8 @@ lfs_set_dirop(struct vnode *dvp, struct 
 		if ((error = mtsleep(&lfs_dirvcount,
 		    PCATCH | PUSER | PNORELOCK, "lfs_maxdirop", 0,
 		    &lfs_lock)) != 0) {
-			mutex_exit(&lfs_lock);
 			goto unreserve;
 		}
-		mutex_exit(&lfs_lock);
 		goto restart;
 	}
 


Home | Main Index | Thread Index | Old Index