Where do you store user context in Linux character drivers? - linux-kernel

It's been a while since I worked on a Linux kernel module, and I seem to remember that there was a place to stash context in your open() open implementation that would be available in your other file_operations... For example, if I want to maintain some state associated with everyone that opens my device node, if either the inode structure or the file structure that is passed to all the file_operations functions had a void* I could fill, I could very easily support any number of users.... Is this possible?

Found the answer. the "struct file*" that's passed to all the file_operations functions has a field called "private_data"... It's a void*, so you can populate in open, use it in read(), write() and ioctl() and free it in release()..

Related

When is an inode's file_operations linked to its character device file_operations?

I am reading the LDD3, and I would like to understand how the device driver file operations are called at the time a system call is performed.
From my understanding, when the open system call is performed, the struct file *filp gets its f_op attribute populated from the inode's i_fop.
But when/where does the inode get its i_fop attribute populated with the cdev's ops attribute?
My intuition is that when we call cdev_add in the driver, our device is added to the cdev_map with the MAJOR and MINOR numbers, but the inode is not yet linked to the character device. The inode would only be linked either when mknod is called to create the device file in the /dev directory, or when the device file is opened through the syscall.
The struct inode's i_fop member gets set to &def_chr_fops (in "fs/char_dev.c") for character special files by the init_special_inode() function (in "fs/inode.c"). That is called by the underlying filesystem (e.g. when it is populating its directory structures and inodes when mounted or when a new character special file is created in the filesystem by mknod().
When opening the file, the struct inode's i_fop is copied to the struct file's f_op member by the do_dentry_open() function called from the vfs_open() function (in "fs/open.c"). do_dentry_open() calls the open file operation handler. For character special files, the open file operation handler from def_chr_fops is the chrdev_open() function (in "fs/char_dev.c").
The chrdev_open() function looks up the struct cdev (if any) associated with the MAJOR/MINOR device number (from the inode's i_rdev member), copies the ops member from the struct cdev to the struct file's f_op member to replace the file operations, and calls the replacement open handler if there is one.

How to handle device removal in Linux Kernel Driver?

You have done it a thousand times: you unplug some USB equipment and any device associated with that USB equipment is removed by the driver. Any program that uses some previously opened file handle will get an error. Somehow most Linux drivers take care of that.
I am currently struggling to implement the same in a simple driver. My driver creates a character device. When the device is opened, I set the private_data member of struct file to the address of some management data that exists once per character device. That management data also includes a mutex that I use to synchronize operations like read, write, and ioctl.
The problem now arises when the USB equipment is unplugged. I must not free the memory where that management data lives. First, any currently running read, write, or ioctl should finish. Any such running call will likely also hold a lock on the mutex and will attempt to unlock it. So the memory where the mutex lives will be accessed.
Any read, write, or ioctl call subsequent to unplugging the equipment should fail, so every such call must read some variable telling whether the USB equipment is still plugged in or not. Again, that variable must live somewhere and the memory where it lives must stay allocated as long as there are open file handles.
Long story short, it seems to me that I must do some sort reference counting: The management data must stay allocated until all file handles have been closed. I could implement that myself, but I have the feeling that I would reinvent the wheel. Such a thing must already exist, I'm not the first to have this problem.
Does Linux internally keep track of the number of open file handles? Can I define a callback that is called when all file handles have been closed? Is that even a viable thing? What is the proper way to remove a character device from the system?
Global variables shall not be avoided, since any number of USB devices can be attached.
As suggested by 0andriy, I have used reference counting to track the number of open file handles. Per character device, I have added a new struct containing a mutex, a kref, the cdev struct, and a pointer to further data. I use kref_get to increase the reference counter when a new file handle is opened. Accordingly, I use kref_put when file handles are released or the USB equipment is unplugged.
Since all I/O operations (read, write, ioctl, etc.) use the mutex, I can safely change the pointer to NULL when the USB equipment is unplugged. The I/O operations then start reporting errors.
The kref reference counter only returns to zero when the USB equipment is unplugged and all file handles are closed. So then I can also free the memory of the new struct.
This seems to work. It was a surprise that the cdev struct is referenced by file handles. It seems to be needed as long as there are open file handles.
But I'm still surprised that I had to go down this route. It seems redundant to implement that in every driver.
UPDATE: As it turns out, doing reference counting yourself is dangerous. In particular counting the number of open file handles is wrong. There is a whole reference-count-based garbage collection system in Linux and you need to use it.
For example, Linux calls cdev_get when a process opens a character device and cdev_put when the process exists and the file handle is still open. Unfortunately, the call to cdev_put would occur after the file handle's release function. As we would free the memory after the last file handle has been released, we would end up freeing the underlying memory of the cdev and the mutex before cdev_put is called.
The solution is to assign a parent to the cdev via cdev_set_parent. The parent kobject will have its reference counter increased whenever cdev_get is called and decreased after cdev_put is called. The kobject then can have its own release function which frees any memory required by the cdev. Basically I replaced the kref in my struct with a kobject.
Lesson learned: don't do reference counting on your own. Use the existing hierarchy of kobjects, which is the kernel's way of doing garbage collection.
UPDATE2: It turns out, we reinvented the wheel again. The device struct includes a release hook, which is called when the internal kobject reached a reference count of zero. This is the mechanism typically used in the kernel to release resources associated with an device - including the device struct itself.
I was looking for a release hook in the cdev struct. There was none. But it turns out I should have looked one step up in the hierarchy for such a hook.
Long story short: Use cdev_device_add in combination with the device release hook. cdev_device_add will internally call cdev_set_parent, so the device becomes the parent of the cdev. Those are the mechanism other kernel drivers (e.g. evdev) use to release their resources.

cdev_alloc() vs cdev_init()

In Linux kernel modules, two different approaches can be followed when creating a struct cdev, as suggested in this site and in this answer:
First approach, cdev_alloc()
struct cdev *my_dev;
...
static int __init example_module_init(void) {
...
my_dev = cdev_alloc();
if (my_dev != NULL) {
my_dev->ops = &my_fops; /* The file_operations structure */
my_dev->owner = THIS_MODULE;
}
else
...
}
Second approach, cdev_init()
static struct cdev my_cdev;
...
static int __init example_module_init(void) {
...
cdev_init(&my_cdev, my_fops);
my_cdev.owner = THIS_MODULE;
...
}
(assuming that my_fops is a pointer to an initialized struct file_operations).
Is the first approach deprecated, or still in use?
Can cdev_init() be used also in the first approach, with cdev_alloc()? If no, why?
The second question is also in a comment in the linked answer.
Can cdev_init() be used also in the first approach, with cdev_alloc()?
No, cdev_init shouldn't be used for a character device, allocated with cdev_alloc.
At some extent, cdev_alloc is equivalent to kmalloc plus cdev_init. So calling cdev_init for a character device, created with cdev_alloc, has no sense.
Moreover, a character device allocated with cdev_alloc contains a hint that the device should be deallocated when no longer be used. Calling cdev_init for that device will clear that hint, so you will get a memory leakage.
Selection between cdev_init and cdev_alloc depends on a lifetime you want a character device to have.
Usually, one wants lifetime of a character device to be the same as lifetime of the module. In that case:
Define a static or global variable of type struct cdev.
Create the character device in the module's init function using cdev_init.
Destroy the character device in the module's exit function using cdev_del.
Make sure that file operations for the character device have .owner field set to THIS_MODULE.
In complex cases, one wants to create a character device at specific point after module's initializing. E.g. a module could provide a driver for some hardware, and a character device should be bound with that hardware. In that case the character device cannot be created in the module's init function (because a hardware is not detected yet), and, more important, the character device cannot be destroyed in the module's exit function. In that case:
Define a field inside a structure, describing a hardware, of pointer type struct cdev*.
Create the character device with cdev_alloc in the function which creates (probes) a hardware.
Destroy the character device with cdev_del in the function which destroys (disconnects) a hardware.
In the first case cdev_del is called at the time, when the character device is not used by a user. This guarantee is provided by THIS_MODULE in the file operations: a module cannot be unloaded if a file, corresponded to the character device, is opened by a user.
In the second case there is no such guarantee (because cdev_del is called NOT in the module's exit function). So, at the time when cdev_del returns, a character device can be still in use by a user. And here cdev_alloc really matters: deallocation of the character device will be deferred until a user closes all file descriptors associated with the character device. Such behavior cannot be obtained without cdev_alloc.
They do different things. The preference would be usual - prefer not to use dynamic allocation when not needed and allocate on stack when it's possible.
cdev_alloc() dynamically allocates my_dev, so it will call kfree(pointer) when cdev_del().
cdev_init() will not free the pointer.
Most importantly, the lifetime of the structure my_cdev is different. In cdev_init() case struct cdev my_cdev is bound to the containing lexical scope, while cdev_alloc() returns dynamically allocate pointer valid up until free-d.

What does open() system call is transferred to Kernel Module?

I am writing a character device driver. In the sample code which I found over internet, mentions that we need to attach some file operations to this character device. In those file_operations there is one function named as open. But in that open call, there are not doing anything significant.
But if we want to use this character device, first we need to open the device and then only we can read/write anything on it. So I want to know how open() call is working exactly. Here is the link I am referring for character device driver :
http://appusajeev.wordpress.com/2011/06/18/writing-a-linux-character-device-driver/
The sequence for open() on the user side is very straightforward: it will invoke sys_open() on the kernel path, will do some path resolution and permission checking, then will path everything its got to dev_open() (and would not do anything else).
dev_open() gets parameters you have passed to it through the open() system call (+ quite a lot of information specific to kernel vfs subsystem, but this is rarely of concern).
Notice, that you're getting struct file parameter passed in. It has several useful fields:
struct file {
....
struct path f_path; // path of the file passed to open()
....
unsigned int f_flags; // 'flags' + 'mode' as passed to open()
fmode_t f_mode; // 'mode' as set by kernel (FMODE_READ/FMODE_WRITE)
loff_t f_pos; // position in file used by _llseek
struct fown_struct f_owner; // opening process credentials, like uid and euid
....
}
The rest you can dig out yourself by checking out examples in the source.

what does `ioctl` do in `struct tty_driver`?

What does ioctl do in the structure struct tty_driver?
I know the ioctl() function provides the means to control the hardware (Keyboard, Mouse, Print) but for example a driver to control the leds on the keyboard I think that the ioctl is more than enough to do this task...
So why I need a tty_driver? I know tty_driver is a struct
P.D I've never tried to program a Device Driver. I've only read a bit of code in some books.
When developing a new driver, the struct tty_driver structure is used to register a tty_driver (using tty_register_driver() 1). This code creates a new device file and set the file operations to some tty specific functions.
The ioctl entry in the newly created file operations is set to tty_ioctl() 2 which after handling some of the basic commands will call the .ioctl function set in the struct tty_operations 3 referenced in the struct tty_driver.
By defining ioctl (note that it is checked if it is not NULL in 3) the developer can implement ioctl commands specific to its device or simply be notified of some other standard commands.

Resources