On Fri, Mar 17, 2023 at 03:23:19PM +0100, Moritz Buhl wrote: > FreeBSD fixed this in 2013: > https://github.com/freebsd/freebsd-src/commit/94f4ac214c403b99cbc44dd6e9cdf4db2cc9b297 > > Below is a diff that addresses this with a exclusive lock > using RW_SLEEPFAIL.
The FreeBSD Code puts the check_nifree label before the if (fs->fs_cs(fs, cg).cs_nifree == 0) check. Could you move this chunk a little up to keep us in sync? With that OK bluhm. > Index: ufs/ffs/ffs_alloc.c > =================================================================== > RCS file: /cvs/src/sys/ufs/ffs/ffs_alloc.c,v > retrieving revision 1.114 > diff -u -p -r1.114 ffs_alloc.c > --- ufs/ffs/ffs_alloc.c 11 Mar 2021 13:31:35 -0000 1.114 > +++ ufs/ffs/ffs_alloc.c 10 Mar 2023 15:44:52 -0000 > @@ -46,6 +46,7 @@ > #include <sys/buf.h> > #include <sys/vnode.h> > #include <sys/mount.h> > +#include <sys/rwlock.h> > #include <sys/syslog.h> > #include <sys/stdint.h> > #include <sys/time.h> > @@ -1089,6 +1090,7 @@ gotit: > } > > /* inode allocation routine */ > +struct rwlock ffs_node_lock = RWLOCK_INITIALIZER("indallck"); > daddr_t > ffs_nodealloccg(struct inode *ip, u_int cg, daddr_t ipref, int mode) > { > @@ -1115,6 +1117,9 @@ ffs_nodealloccg(struct inode *ip, u_int > return (0); > > cgp = (struct cg *)bp->b_data; > +#ifdef FFS2 > + check_nifree: > +#endif > if (cgp->cg_cs.cs_nifree == 0) { > brelse(bp); > return (0); > @@ -1201,9 +1206,12 @@ gotit: > /* Has any inode not been used at least once? */ > cgp->cg_initediblk < cgp->cg_ffs2_niblk) { > > + if (rw_enter(&ffs_node_lock, RW_WRITE | RW_SLEEPFAIL)) > + goto check_nifree; > ibp = getblk(ip->i_devvp, fsbtodb(fs, > ino_to_fsba(fs, cg * fs->fs_ipg + cgp->cg_initediblk)), > (int)fs->fs_bsize, 0, INFSLP); > + rw_exit(&ffs_node_lock); > > memset(ibp->b_data, 0, fs->fs_bsize); > dp2 = (struct ufs2_dinode *)(ibp->b_data);