Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Feb 2013 17:37:05 +0200
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Jamie Gritton <jamie@FreeBSD.org>
Cc:        fs@FreeBSD.org
Subject:   Re: mount/kldload race
Message-ID:  <20130220153705.GE2598@kib.kiev.ua>
In-Reply-To: <5124E372.1000009@FreeBSD.org>
References:  <51244A13.8030907@FreeBSD.org> <20130220054309.GD2598@kib.kiev.ua> <5124E372.1000009@FreeBSD.org>

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

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

On Wed, Feb 20, 2013 at 07:53:38AM -0700, Jamie Gritton wrote:
> On 02/19/13 22:43, Konstantin Belousov wrote:
> > On Tue, Feb 19, 2013 at 08:59:15PM -0700, Jamie Gritton wrote:
> >> Perhaps most people don't try to mount a bunch of filesystems at the
> >> same time, at least not those that depend on kernel modules. But it
> >> turns out that's going to be a pretty common situation with jails and
> >> nullfs. And I found that when attempting such a feat will cause most of
> >> these simultaneous mounts to fail with ENODEV.
> >>
> >> It turns out that the problem is a race in vfs_byname_kld(). First it'=
ll
> >> see if the fstype is loaded, and if it isn't then it will load the
> >> module. But if the module is loaded by a different process between tho=
se
> >> two points, the resulting EEXIST from kern_kldload() will make
> >> vfs_byname_kld() error out.
> >>
> >> The fix is pretty simple: don't treat EEXIST as an error. By going on,
> >> and rechecking for the fstype, the filesystem can be mounted while sti=
ll
> >> allowing any "real" error to be caught. I'm including a small patch th=
at
> >> will accomplish this, and I'd appreciate a quick look by anyone who's
> >> familiar with this part of things before I commit it.
> >>
> >> - Jamie
> >
> >> Index: sys/kern/vfs_init.c
> >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> >> --- sys/kern/vfs_init.c	(revision 247000)
> >> +++ sys/kern/vfs_init.c	(working copy)
> >> @@ -130,13 +130,18 @@
> >>
> >>   	/* Try to load the respective module. */
> >>   	*error =3D kern_kldload(td, fstype,&fileid);
> >> +	if (*error =3D=3D EEXIST) {
> >> +		*error =3D 0;
> >> +		fileid =3D 0;
> > Why do you clear fileid ? Is this to prevent an attempt to kldunload()
> > the module which was not loaded by the current thread ?
> >
> > If yes, I would suggest to use the separate flag to track this,
> > which is cleared on EEXIST error. IMHO it is cleaner and less puzzling.
>=20
> Yes, that's why.  As a side note, I clear *error ostensibly for the sake=
=20
> of the callers, but it turns out none of the callers actually look at=20
> the returned error.
>=20
> Here's a new patch with an added flag:
I have no further comments, looks good.

>=20
>=20
> Index: sys/kern/vfs_init.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- sys/kern/vfs_init.c	(revision 247000)
> +++ sys/kern/vfs_init.c	(working copy)
> @@ -122,7 +122,7 @@
>   vfs_byname_kld(const char *fstype, struct thread *td, int *error)
>   {
>   	struct vfsconf *vfsp;
> -	int fileid;
> +	int fileid, loaded;
>=20
>   	vfsp =3D vfs_byname(fstype);
>   	if (vfsp !=3D NULL)
> @@ -130,13 +130,17 @@
>=20
>   	/* Try to load the respective module. */
>   	*error =3D kern_kldload(td, fstype, &fileid);
> +	loaded =3D (*error =3D=3D 0);
> +	if (*error =3D=3D EEXIST)
> +		*error =3D 0;
>   	if (*error)
>   		return (NULL);
>=20
>   	/* Look up again to see if the VFS was loaded. */
>   	vfsp =3D vfs_byname(fstype);
>   	if (vfsp =3D=3D NULL) {
> -		(void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE);
> +		if (loaded)
> +			(void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE);
>   		*error =3D ENODEV;
>   		return (NULL);
>   	}

--UOi+gfmBpEZPw9cU
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (FreeBSD)

iQIcBAEBAgAGBQJRJO2gAAoJEJDCuSvBvK1Bj44P/3XSMKbo4w/4W3Gf7MnCcn01
NOkmXv36TthOxkXUEOWldzKUQzYuvG4lbQ8m8w+nrlP5C5wVFY2a7jWAZBHLEs96
m/H35R5Dke3a4UEd1Q7lb47LhIhR65hmzyBYCP2ylwLKdAI4kuWxmoFPV62QFIqt
csMomk2N7FtMB4F4ryMxHTA6ERzbjh5JE+kdR2KtDFXOdWeDa7no4NYnXjAcxACK
+ikfCHrvYfgsq3goUg12CSFbQth9naKSbRtSm5qXF07akjnwNc+mtrni4mxN/+YM
8kgehvojPIFkDzOw+tTK7EnRlTovXroV0VcDm0r0rAZFo/3eJxvh5nIqbyBpM4oO
tqTs1qGk1o4XA8lytAfP2UFUb9LOD2CIarjcre6Mj/tF5t0CThZLJEZvLRjxNZ0L
Cp46C/vf6m348UsP06gu74WibtGwVBlJthr+IXwLUZnNvsKrDZLrq4EXl7n1gxJ9
VYkeIYStpKklwj/6h0GHBAZhF9sbDUsqUPQ6VFnKz6EOQIxsZTIQtytWImLOTArZ
DHZRKta7AdtylDk8YHH83p90AMEduCBFWse/ZGv7+kcUbyehtfMm1QmTkdBwPZd4
WYKd/Gy5y35xgD+MWuTvly7aqss3dwHk581CQyfAjFYEkvcW8VZtLYDrgbrk9rfu
/vE7ZFtHooVRyr6mlsV2
=PTS+
-----END PGP SIGNATURE-----

--UOi+gfmBpEZPw9cU--



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