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



The following reply was made to PR kern/60504; it has been noted by GNATS.

From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: Shinichi Doyashiki <clare%csel.org@localhost>
Cc: gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost, perseant%NetBSD.org@localhost
Subject: Re: kern/60504: lfs_cleanerd can kernel crash on load in lfs_fcntl;
	lfs_sp == NULL
Date: Thu, 27 Aug 2026 02:22:18 +0000

 This is a multi-part message in MIME format.
 --=_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS
 
 > 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?
 
 --=_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS
 Content-Type: text/plain; charset="ISO-8859-1"; name="lfskernellock"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment; filename="lfskernellock.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);
 =20
 -	KERNEL_LOCK(1, NULL);
  	blkiov =3D lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
  	if ((error =3D copyin(SCARG(uap, blkiov), blkiov,
  			    blkcnt * sizeof(BLOCK_INFO))) !=3D 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);
 =20
 -	KERNEL_LOCK(1, NULL);
  	blkiov =3D lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
  	blkiov15 =3D lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO_15), LFS_NB_BLKIOV=
 );
  	if ((error =3D 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 =3D lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
  	if ((error =3D copyin(SCARG(uap, blkiov), blkiov,
  			    blkcnt * sizeof(BLOCK_INFO))) !=3D 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 =3D SCARG(uap, blkcnt);
  	if ((size_t) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO))
  		return (EINVAL);
 -	KERNEL_LOCK(1, NULL);
  	blkiov =3D lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
  	blkiov15 =3D lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO_15), LFS_NB_BLKIOV=
 );
  	if ((error =3D 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,=20
  	ump =3D VFSTOULFS(mntp);
  	fs =3D ump->um_lfs;
 =20
 -	if (fs->lfs_cleaner_thread =3D=3D NULL)
 +	mutex_enter(&lfs_lock);
 +	if (fs->lfs_cleaner_thread =3D=3D NULL) {
  		fs->lfs_cleaner_thread =3D curlwp;
 +	} else if (fs->lfs_cleaner_thread !=3D curlwp) {
 +		error =3D EBUSY;
 +		mutex_exit(&lfs_lock);
 +		goto out;
 +	}
 +	panic("cleaning");
  	KASSERT(fs->lfs_cleaner_thread =3D=3D curlwp);
 +	mutex_exit(&lfs_lock);
 =20
  	cnt =3D blkcnt;
 =20
 @@ -791,6 +791,12 @@ lfs_bmapv(struct lwp *l, fsid_t *fsidp,=20
 =20
  	KASSERTMSG((numrefed =3D=3D 0), "lfs_bmapv: numrefed=3D%d", numrefed);
 =20
 +	mutex_enter(&lfs_lock);
 +	KASSERTMSG(fs->lfs_cleaner_thread =3D=3D curlwp, "cleaner thread is %p",
 +	    fs->lfs_cleaner_thread);
 +	fs->lfs_cleaner_thread =3D NULL;
 +	mutex_exit(&lfs_lock);
 +out:
  	vfs_unbusy(mntp);
 =20
  	return 0;
 @@ -833,11 +839,9 @@ sys_lfs_segclean(struct lwp *l, const st
  	if ((error =3D vfs_busy(mntp)) !=3D 0)
  		return (error);
 =20
 -	KERNEL_LOCK(1, NULL);
  	lfs_prelock(fs, 0);
  	error =3D 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=20
  	mp->mnt_stat.f_namemax =3D LFS_MAXNAMLEN;
  	mp->mnt_stat.f_iosize =3D lfs_sb_getbsize(fs);
  	mp->mnt_flag |=3D MNT_LOCAL;
 +	mp->mnt_iflag |=3D IMNT_MPSAFE;
  	mp->mnt_iflag |=3D IMNT_SHRLOOKUP;
  	mp->mnt_fs_bshift =3D lfs_sb_getbshift(fs);
  	mp->mnt_iflag |=3D 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=20
  		if ((error =3D mtsleep(&lfs_dirvcount,
  		    PCATCH | PUSER | PNORELOCK, "lfs_maxdirop", 0,
  		    &lfs_lock)) !=3D 0) {
 -			mutex_exit(&lfs_lock);
  			goto unreserve;
  		}
 -		mutex_exit(&lfs_lock);
  		goto restart;
  	}
 =20
 
 --=_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS--
 



Home | Main Index | Thread Index | Old Index