diff options
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ufs/ufs_ihash.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/sys/ufs/ufs/ufs_ihash.c b/sys/ufs/ufs/ufs_ihash.c index 758d9a8ed6e..b0d6ca3a5dd 100644 --- a/sys/ufs/ufs/ufs_ihash.c +++ b/sys/ufs/ufs/ufs_ihash.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_ihash.c,v 1.27 2024/07/07 01:39:06 jsg Exp $ */ +/* $OpenBSD: ufs_ihash.c,v 1.28 2024/09/04 17:00:08 beck Exp $ */ /* $NetBSD: ufs_ihash.c,v 1.3 1996/02/09 22:36:04 christos Exp $ */ /* @@ -36,10 +36,12 @@ #include <sys/systm.h> #include <sys/vnode.h> #include <sys/malloc.h> +#include <sys/mount.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufs_extern.h> +#include <ufs/ufs/ufsmount.h> #include <crypto/siphash.h> @@ -94,6 +96,33 @@ loop: /* XXXLOCKING unlock hash list? */ if (vget(vp, LK_EXCLUSIVE)) goto loop; + /* + * Check if the inode is valid. + * The condition has been adapted from ufs_inactive(). + * + * This is needed in case our vget above grabbed a vnode + * while ufs_inactive was reclaiming it. + * + * XXX this is a workaround and kind of a gross hack. + * realistically this should get fixed something like + * the previously committed vdoom() or this should be + * dealt with so this can't happen. + */ + if (VTOI(vp) != ip || + (DIP(ip, nlink) <= 0 && + (vp->v_mount->mnt_flag & MNT_RDONLY) == 0)) { + /* + * This should recycle the inode immediately, + * unless there are other threads that + * try to access it. + * Pause to give the threads a chance to finish + * with the inode. + */ + vput(vp); + yield(); + goto loop; + } + return (vp); } } |