views:

289

answers:

3

I have a driver which compiles and loads into the linux kernel just fine. In this driver are some functions which I would like to access from the kernel file 'fs/readdir.c'. Additionally, how can I test if a driver is loaded?

I need something like the following.

if(myDriver is loaded){
    myDriver.functionCall();
}

All examples I've found on internet searches are doing it from userspace applications.

+1  A: 

fs/readdir.c would not link if the functionCall symbol is not in the kernel yet. You can only do this through indirection. Setup some ops structure in the main kernel code, init it to dummy functions, or just NULLs to tell the rest of the kernel that your driver is not loaded yet. In the driver initialization routine set the function pointers in that structure to functions in your module (reset to defaults in de-init). The structure will need some form of race protection though, so you would probably end up having a semaphore as one of its members. This can be expanded to structure per device, etc.

Nikolai N Fetissov
Hi Nikolai, thanks for this response. Your idea makes sense but can I clarify?Write my function implementation in my module/driver.Have a structure in my kernel boot up like init/main.c which contains my functions but unimplemented.In my module init change the main.c function pointers to my implemented version?If that's what you mean then, first question, how would I then call the functions from readdir.c?
cheesysam
+1  A: 

The other possibility is to use EXPORT_SYMBOL(functionCall); in your module which will make your function appear in the kernel symbol table. You can then use find_symbol("functionCall", blah, blah) to check whether the symbol exists and to find its value/location dynamically.

See linux/kernel/module.c and module.h

Dipstick
A: 

You could add a function pointer to functionCall in the kernel, initialize it to NULL, and wait for the module to set the pointer to a non-NULL value. Code in readdir would check for the pointer being non-NULL before dereferencing it. This requires the module to know about the function pointer in the kernel by either making the pointer global or similarly easy to access from a module.

If you don't want the driver to know about this modification to the kernel, you could modify readdir to look for the driver to load, then use find_symbol (as mentioned by @chrisharris) to get the address of functionCall, and assign the returned value to some private function pointer somewhere in readdir.

One way to answer the "is the driver loaded" question would be to use register_module_notifier()

static int
my_load_notify(struct notifier_block *self, unsigned long val, void *data)
{
 struct module *m = data;
 if (0 == strcmp(m->name, "myDriver")) {
  // set function pointer(s)
 }
}
static struct notifier_block module_load_nb = {
 .notifier_call = my_load_notify,
};

static int
my_init(void)
{
 ...
 register_module_notifier(&module_load_nb);
 ...
}
ctuffli