Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the kernel using the default block driver instead of my driver's code?

I wrote a block driver program which creates a dummy block device (sbd0). I registered all device operations for that block device: (Refer to include/linux/blkdev.h in 2.6.32 kernel source)

static struct block_device_operations sbd_ops = {
    .owner           = THIS_MODULE,
    .open            = sbd_open,
    .release         = sbd_close,
    .ioctl           = sbd_ioctl,
    .getgeo          = sbd_getgeo,
    .locked_ioctl    = sbd_locked_ioctl,
    .compat_ioctl    = sbd_compat_ioctl,
    .direct_access   = sbd_direct_access,
    .media_changed   = sbd_media_changed,
    .revalidate_disk = sbd_revalidate_disk
};

I compiled the driver program. I inserted the module and /dev/sbd0 was created. Now I want to test my driver code. So I wrote an application as below.

fd = open("/dev/sbd0", O_RDONLY); 
retval = ioctl(fd, BLKBSZGET, &blksz); //trying to get logical block size

Output is :4096

I wondered: I didn't implement ioctl for BLKBSZGET. It didn't invoke my sbd_ioctl, instead it used the default driver and gave me the result. For open, close calls it executed sbd_open and sbd_close (that I implemented). And then I tried:

retval = ioctl(fd, HDIO_GETGEO, &geoinfo);

It invoked sbd_getgeo but I thought it would invoke sbd_ioctl.

Here are my questions:

  1. I implemented a driver and created a device. If I perform any operation on that device, it has to invoke my driver application. But how does it use a few of my driver functions and few default driver functions?
  2. ioctl(fd, HDIO_GETGEO, ..) didn't invoke .ioctl call, but it invoked .getgeo. How is this possible?
like image 289
gangadhars Avatar asked Apr 24 '14 10:04

gangadhars


People also ask

What is the difference between the kernel and device driver?

Instead, a kernel module is a collection of subroutines and data. A device driver is a kernel module that forms a software interface to an input/output (I/O) device. The subroutines in a device driver provide entry points to the device.

What is block device driver?

Devices that support a file system are known as block devices. Drivers written for these devices are known as block device drivers. Block device drivers take a file system request, in the form of a buf(9S) structure, and issue the I/O operations to the disk to transfer the specified block.

What are the two types of drivers in Linux?

The Linux kernel supports two main types of USB drivers: drivers on a host system and drivers on a device.

What is block driver in Linux?

A block driver provides access to devices that transfer randomly accessible data in fixed-size blocks—disk drives, primarily. The Linux kernel sees block devices as being fundamentally different from char devices; as a result, block drivers have a distinct interface and their own particular challenges.

What is character driver and block driver?

Block device drivers manage devices with physically addressable storage media, such as disks. All other devices are considered character devices. Two types of character device drivers are standard character device drivers and STREAMS device drivers.


1 Answers

The ioctl dispatching is handled by the blkdev_ioctl function, which will process some of the ioctls directly, without calling into your driver's specific routine.

For HDIO_GETGEO, it calls your driver's getgeo function directly (from kernel 3.13.6, doesn't appear to have changed much since 2.6.32):

[...]
/*
 * We need to set the startsect first, the driver may
 * want to override it.
 */
memset(&geo, 0, sizeof(geo));
geo.start = get_start_sect(bdev);
ret = disk->fops->getgeo(bdev, &geo); /* <- here */
[...]

For BLKBSZGET, it calls block_size(bdev)), which simply returns bdev->bd_block_size.

You'll find blkdev_ioctl in block/ioctl.c if you need to know what happens for other ioctls.

like image 119
Mat Avatar answered Oct 14 '22 13:10

Mat