Subject: Re: patch for kern/36331
To: Blair Sadewitz <blair.sadewitz@gmail.com>
From: Andrew Doran <ad@netbsd.org>
List: tech-kern
Date: 05/21/2007 23:00:04
On Mon, May 21, 2007 at 01:46:26PM -0400, Blair Sadewitz wrote:

> This patch does what ad@ suggested on netbsd-bugs.
> I have tested it with lfs and ffs, and I haven't had any more deadlocks 
> thusfar.
>
> +	if ((*vpp = ufs_ihashget(dev, ino, 0)) != NULL) {

Nit: don't need the *vpp = here. :-)

> --- sys/ufs/ufs/ufs_ihash.c	27 Feb 2007 16:11:51 -0000	1.22
> +++ sys/ufs/ufs/ufs_ihash.c	21 May 2007 16:47:47 -0000
> @@ -145,11 +145,13 @@
>  	LIST_FOREACH(ip, ipp, i_hash) {
>  		if (inum == ip->i_number && dev == ip->i_dev) {
>  			vp = ITOV(ip);
> -			simple_lock(&vp->v_interlock);
>  			mutex_exit(&ufs_ihash_lock);
> -			if (vget(vp, flags | LK_INTERLOCK))
> -				goto loop;
> -			return (vp);
> +			if (flags != 0) {
> +				simple_lock(&vp->v_interlock);
> +				if (vget(vp, flags | LK_INTERLOCK))
> +					goto loop;
> +			}

You need to hold ufs_ihash_lock while locking vp->v_interlock, to ensure
that the vnode doesn't disappear off the list as soon as you unlock. It does
not make a difference right now since this is all covered by the kernel_lock
but to be correct it's needed. Otherwise the changes are pretty much as I
described.

There are a few other file systems that need similar modifications. The
inode hash is something that could made abstracted and made a function of
genfs, since the ufs code has been cut-n-pasted all over the place. It could
also do with being per-mount. All of those are other projects though. :-)

Thanks,
Andrew