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