44

Going through the linux 2.6.36 source code at lxr.linux.no, I could not find the ioctl() method in file_operations. Instead I found two new calls: unlocked_ioctl() and compat_ioctl(). What is the difference between ioctl(), unlocked_ioctl(), and compat_ioctl()?

Navaneeth Sen
  • 9,369
  • 17
  • 58
  • 65

2 Answers2

46

Meta-answer: All the raw stuff happening to the Linux kernel goes through lkml (the Linux kernel mailing list). For explicative summaries, read or search lwn (Linux weekly news).

Answer: From The new way of ioctl() by Jonathan Corbet:

ioctl() is one of the remaining parts of the kernel which runs under the Big Kernel Lock (BKL). In the past, the usage of the BKL has made it possible for long-running ioctl() methods to create long latencies for unrelated processes.

Follows an explanation of the patch that introduced unlocked_ioctl and compat_ioctl into 2.6.11. The removal of the ioctl field happened a lot later, in 2.6.36.

Explanation: When ioctl was executed, it took the Big Kernel Lock (BKL), so nothing else could execute at the same time. This is very bad on a multiprocessor machine, so there was a big effort to get rid of the BKL. First, unlocked_ioctl was introduced. It lets each driver writer choose what lock to use instead. This can be difficult, so there was a period of transition during which old drivers still worked (using ioctl) but new drivers could use the improved interface (unlocked_ioctl). Eventually all drivers were converted and ioctl could be removed.

compat_ioctl is actually unrelated, even though it was added at the same time. Its purpose is to allow 32-bit userland programs to make ioctl calls on a 64-bit kernel. The meaning of the last argument to ioctl depends on the driver, so there is no way to do a driver-independent conversion.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • 1
    I was looking over the latest ioctl source and saw that the syscall does a few checks and then jumps [here](https://github.com/torvalds/linux/blob/master/fs/ioctl.c#L43). Do you know where I could gather more information on the ioctl system? I am interested in how ioctl commands on character files get routed to the appropriate driver. Is it through `unlocked_ioctl` that this happens? The fact that a function pointer is used *per file* (in this case a `struct file`) it seems I may be close. Is the `unlocked_ioctl` registered for character files on driver initialization after `mknod`? – sherrellbc Jan 05 '17 at 09:59
  • 1
    @sherrellbc The device driver registers the file handling methods such as `unlocked_ioctl` in a `struct file_ops` when it starts, and they are populated from the `struct file_ops` into the file object when the file is opened. `mknod` plays no role in this. – Gilles 'SO- stop being evil' Jan 05 '17 at 14:06
  • I see. I was thinking a device driver must first `mknod` to expose its interface through a character device before redirecting the associated file operations to itself (via `unlocked_ioctl`). – sherrellbc Jan 05 '17 at 14:09
4

There are cases when the replacement of (include/linux/fs.h) struct file_operations method ioctl() to compat_ioctl() in kernel 2.6.36 does not work (e.g. for some device drivers) and unlocked_ioctl() must be used.