Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 Apr 2012 21:10:55 -0600
From:      Warner Losh <imp@bsdimp.com>
To:        Konstantin Belousov <kostikbel@gmail.com>
Cc:        Ian Lepore <freebsd@damnhippie.dyndns.org>, current@FreeBSD.org, drivers@FreeBSD.org
Subject:   Re: device_attach(9) and driver initialization
Message-ID:  <CCBC36A4-CC13-465B-A151-A41DEDF7E55B@bsdimp.com>
In-Reply-To: <20120407145728.GV2358@deviant.kiev.zoral.com.ua>
References:  <20120407125056.GS2358@deviant.kiev.zoral.com.ua> <1333810001.1082.36.camel@revolution.hippie.lan> <20120407145728.GV2358@deviant.kiev.zoral.com.ua>

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

On Apr 7, 2012, at 8:57 AM, Konstantin Belousov wrote:

> On Sat, Apr 07, 2012 at 08:46:41AM -0600, Ian Lepore wrote:
>> On Sat, 2012-04-07 at 15:50 +0300, Konstantin Belousov wrote:
>>> Hello,
>>> there seems to be a problem with device attach sequence offered by =
newbus.
>>> Basically, when device attach method is executing, device is not =
fully
>>> initialized yet. Also the device state in the newbus part of the =
world
>>> is DS_ALIVE. There is definitely no shattering news in the =
statements,
>>> but drivers that e.g. create devfs node to communicate with =
consumers
>>> are prone to a race.
>>>=20
>>> If /dev node is created inside device attach method, then usermode
>>> can start calling cdevsw methods before device fully initialized =
itself.
>>> Even more, if device tries to use newbus helpers in cdevsw methods,
>>> like device_busy(9), then panic occurs "called for unatteched =
device".
>>> I get reports from users about this issues, to it is not something
>>> that only could happen.
>>>=20
>>> I propose to add DEVICE_AFTER_ATTACH() driver method, to be called
>>> from newbus right after device attach finished and newbus considers
>>> the device fully initialized. Driver then could create devfs node
>>> in the after_attach method instead of attach. Please see the patch =
below.
>>>=20
>>> diff --git a/sys/kern/device_if.m b/sys/kern/device_if.m
>>> index eb720eb..9db74e2 100644
>>> --- a/sys/kern/device_if.m
>>> +++ b/sys/kern/device_if.m
>>> @@ -43,6 +43,10 @@ INTERFACE device;
>>> # Default implementations of some methods.
>>> #
>>> CODE {
>>> +	static void null_after_attach(device_t dev)
>>> +	{
>>> +	}
>>> +
>>> 	static int null_shutdown(device_t dev)
>>> 	{
>>> 	    return 0;
>>> @@ -199,6 +203,21 @@ METHOD int attach {
>>> };
>>>=20
>>> /**
>>> + * @brief Notify the driver that device is in attached state
>>> + *
>>> + * Called after driver is successfully attached to the device and
>>> + * corresponding device_t is fully operational. Driver now may =
expose
>>> + * the device to the consumers, e.g. create devfs nodes.
>>> + *
>>> + * @param dev		the device to probe
>>> + *
>>> + * @see DEVICE_ATTACH()
>>> + */
>>> +METHOD void after_attach {
>>> +	device_t dev;
>>> +} DEFAULT null_after_attach;
>>> +
>>> +/**
>>>  * @brief Detach a driver from a device.
>>>  *
>>>  * This can be called if the user is replacing the
>>> diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
>>> index d485b9f..6d849cb 100644
>>> --- a/sys/kern/subr_bus.c
>>> +++ b/sys/kern/subr_bus.c
>>> @@ -2743,6 +2743,7 @@ device_attach(device_t dev)
>>> 	dev->state =3D DS_ATTACHED;
>>> 	dev->flags &=3D ~DF_DONENOMATCH;
>>> 	devadded(dev);
>>> +	DEVICE_AFTER_ATTACH(dev);
>>> 	return (0);
>>> }
>>>=20
>>=20
>> Does device_get_softc() work before attach is completed?  (I don't =
have
>> time to go look in the code right now).  If so, then a mutex =
initialized
>> and acquired early in the driver's attach routine, and also acquired =
in
>> the driver's cdev implementation routines before using any newbus
>> functions other than device_get_softc(), would solve the problem =
without
>> a driver api change that would make it harder to backport/MFC driver
>> changes.
> No, 'a mutex' does not solve anything. It only adds enourmous burden
> on the driver developers, because you cannot sleep under mutex. =
Changing
> the mutex to the sleepable lock also does not byy you much, since
> you need to somehow solve the issues with some cdevsw call waking up
> thread sleeping into another cdevsw call, just for example.
>=20
> Singlethreading a driver due to this race is just silly.
>=20
> And, what do you mean by 'making it harder to MFC' ? How ?

driver_attach()
{
	...
	softc->flags =3D 0; // redundant, since softc is initialized to =
0.
	softc->cdev =3D device_create...();
	...
	softc->flags |=3D READY;
}

driver_open(...)
{
	if (!(softc->flags & READY))
		return ENXIO;
	...
}

What's the big burden here?

Warner=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CCBC36A4-CC13-465B-A151-A41DEDF7E55B>