A Bug in linker_reference_module() ?

John Baldwin jhb at freebsd.org
Fri Sep 22 11:58:45 PDT 2006


On Thursday 21 September 2006 21:57, Intron is my alias on the Internet wrote:
> John Baldwin wrote:
> 
> > On Thursday 21 September 2006 14:12, Intron is my alias on the Internet 
wrote:
> >> Please have a look at the function linker_reference_module() in
> >> /sys/kern/kern_linker.c of 7.0-CURRENT. If the module is loaded on 
demand,
> >> why not increase its reference counter after loading? In my opinion,
> >> linker_reference_module() behaves differently from linker_load_file().
> > 
> > This is because a new kld loaded via linker_load_module() starts off
> > with a refcount of 1.  Thus, if you do:
> > 
> > 	linker_reference_module(...);
> > 	...
> > 	linker_release_module(...);
> > 
> > Then with the current code the release_module() call drops the reference
> > count to 0 and the module is unloaded.  This is the desired operation for
> > reference_module/release_module.  This model is commonly used in the 
kernel.
> > For example, when creating a credential, one just does 'crget()' and later
> > a 'crfree()' to free it instead of doing 'crget(); crhold()' to create 
one.
> 
> This model is a little confusing. If a module is loaded on demand as
> dependency, its reference counter is set to 1. And if the module is loaded
> by kldload(2), its reference counter is also set to 1, though in fact
> no other loaded module depends on it.

kldload(2) is a way for to specify a user reference on the module, and 
kldunload(2) is how you drop that user reference.

> Although this "shift" model can work correctly, I want to know whether
> there's a more reasonable way, such as setting up an auto-unloadable flag.

There is this effectively done with the userref flag.  When you kldload a 
module, it sets userref to 1, and you can only kldunload a module when 
userref == 1.  This lets the following work:

	thread 1		thread 2

	kldload(foo)		...
	...			linker_reference_module(foo)

(now foo has userref == 1 and refs == 2)

	kldunload(foo)		...

(now foo has userref == 0 and refs == 1, kldunload reports success, but module 
isn't unloaded due to in-kernel reference)

	...			linker_release_module(foo)

(now refs drops to 0 and module is actually unloaded)

The simpler cases also work fine if you try them out.

-- 
John Baldwin


More information about the freebsd-hackers mailing list