Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 5 Aug 2008 18:32:21 +0300
From:      Kostik Belousov <kostikbel@gmail.com>
To:        Rick Macklem <rmacklem@uoguelph.ca>
Cc:        freebsd-fs@freebsd.org
Subject:   Re: doing vfs_hash_get when vnode locked
Message-ID:  <20080805153221.GG97161@deviant.kiev.zoral.com.ua>
In-Reply-To: <Pine.GSO.4.63.0808051052350.27663@muncher.cs.uoguelph.ca>
References:  <Pine.GSO.4.63.0808041657200.3482@muncher.cs.uoguelph.ca> <20080805083229.GB97161@deviant.kiev.zoral.com.ua> <Pine.GSO.4.63.0808051052350.27663@muncher.cs.uoguelph.ca>

next in thread | previous in thread | raw e-mail | index | archive | help

--vt4ed5MNefdcgji4
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Tue, Aug 05, 2008 at 11:09:00AM -0400, Rick Macklem wrote:
>=20
>=20
> On Tue, 5 Aug 2008, Kostik Belousov wrote:
>=20
> >On Mon, Aug 04, 2008 at 05:04:58PM -0400, Rick Macklem wrote:
> >>There's a place in my nfsv4 client where I need to vfs_hash_get() when
> >>another blocked thread may be holding a lock on the vnode. (It's during
> >>a recovery case where the other threads are blocked, so there isn't a
> >>race problem, as far as I understand it.)
> >>
> >>For FreeBSD7, all I did was call vfs_hash_get() with flags =3D=3D 0 and=
 it
> >>gave me what I wanted (the vnode for the file handle with a reference
> >>count, but no lock).
> >>
> >>For FreeBSD-CURRENT/8, this no longer works, because vfs_hash_get() cal=
ls
> >>vget(), which calls _vn_lock() and _vn_lock() now complains if the lock
> >>type field of "flags" is 0. I came up with a really ugly workaround, by
> >>setting the flags arg. to LK_EXCLOTHER for vfs_hash_get() and then
> >>providing my own VOP_LOCK1() which just VI_UNLOCK()s and returns 0 for
> >>this case (doing the same as vop_stdlock() for other cases). Yuck!!
> >>
> >>Is it possible to re-enable the case of _vn_lock() getting a locktype
> >>field =3D=3D 0 (or defining one that says "just return 0 unless VI_DOOM=
ED"),
> >>so I don't need the dirty hack?
> >
> >I do not quite understand what you really need there. The non-locked
> >vnode may be reclaimed at any moment, so the check for !VI_DOOMED
> >returns no useful information.
> >
> I need a referenced vnode (v_usecount incremented, which I thought would
> avoid it being recycled) when another blocked thread in the kernel has
No, this is a wrong assumption. Use count does not prevent the vnode
from being reclaimed.

Unless you held the vnode lock, it may be reclaimed. To set the
VI_DOOMED flag, both exclusive vnode lock and vnode interlock must be
held.

> the vnode locked. (This thread is doing recovery while the other blocked
> thread is waiting for that recovery to complete.)
If you can guarantee that the other thread does not relinquish the vnode
lock while curthread operates on the vnode, you may use vref() and
direct check on VI_DOOMED. I shall admit that this is quite perversive
and fragile.

>=20
> For FreeBSD7, I call vfs_hash_get(mntp, hash, 0, td, &nvp, mycmpfh, nfhp)
> for this case. It:
> - calls vget() with (0 | LK_INTERLOCK) for flags
>   - it calls vn_lock() with the flags as above
>     - _vn_lock() simply checks for VI_DOOMED and then, otherwise,
>       returns 0 because (flags & LK_TYPE_MASK) =3D=3D 0
>   - vget then calls v_upgrade_usecount(), incrementing the use count
>    (so it won't be recycled, as I understand it)
> --> and I get the vnode with an incremented usecount that I need. When
>     this thread is done with it, it simply vrele(vp)'s it.
>=20
> For FreeBSD-CURRENT, this panics because there is now a check at the
> beginning of _vn_lock() requiring an non-zero LK_TYPE_MASK field.
> (I worked around it by using LK_EXCLOTHER instead of 0 as the argument to
>  vfs_hash_get() and then implemented by own nfs_lock1() VOP, that handles
>  the bogus case of the LK_TYPE_MASK being set to LK_EXCLOTHER by just
>  returning 0 after VI_UNLOCK(vp) if LK_INTERLOCK is set. For all other
>  cases, it calls _lockmgr_args() just like vop_stdlock().)
>=20
> Did this help or just muddy the waters? rick

--vt4ed5MNefdcgji4
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (FreeBSD)

iEYEARECAAYFAkiYcoQACgkQC3+MBN1Mb4h/YgCfYezNLwy1TYRk9F9Q65+ZkfUq
u7cAnA7Gz1log01tAtCfserHWUqQkHqU
=tQt9
-----END PGP SIGNATURE-----

--vt4ed5MNefdcgji4--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080805153221.GG97161>