Linux Block device drivers <5>

Source: Internet
Author: User

Transferred from: http://blog.chinaunix.net/uid-15724196-id-128143.html

5th Chapter

+---------------------------------------------------+
| Write a block device driver |
+---------------------------------------------------+
| Zhao Lei |
| Email[email protected]|
+---------------------------------------------------+
| The copyright of the article belongs to the original author. |
| You are free to reprint this article, but the original copyright information must be retained.
| For commercial use, be sure to contact the original author if you have not obtained |
| Copyright disputes arising from the authorization shall be the sole responsibility of the infringer.
+---------------------------------------------------+

Since the end of the previous chapter we have already announced the contents of this chapter,
So in this chapter we let this block device have the ability to tell the operating system its "physical structure".

Of course, what kind of physical structure is not important for memory-based block devices,
It's like taking a mm home from a bar without asking for her name.
But if the unfortunate encounter is part-time, and take her to the non-inflow of the guest house,
It is advisable to first falsify the name, birthday and occupation information,
So that JJ rounds can be disguised as lovers.
Similarly, if the actual physical block device driver is to be implemented,
It is probably not so random to return the physical structure of the device.

For block device drivers, we now need to focus on the struct block_device_operations simp_blkdev_fops structure that currently has only one row.
So far, it exists only because it must exist, but immediately we will find another purpose for it to exist: To add an interface for block device drivers to get the physical structure of a block device.

For the very strong spirit of the best readers, probably in the first chapter will see the struct block_device_operations structure, and then will find this structure is actually quite complex:
struct Block_device_operations {
Int (*open) (struct Block_device *, fmode_t);
Int (*release) (struct Gendisk *, fmode_t);
Int (*locked_ioctl) (struct Block_device *, fmode_t, unsigned, unsigned long);
Int (*ioctl) (struct Block_device *, fmode_t, unsigned, unsigned long);
Int (*compat_ioctl) (struct Block_device *, fmode_t, unsigned, unsigned long);
Int (*direct_access) (struct Block_device *, sector_t,
void * *, unsigned long *);
Int (*media_changed) (struct gendisk *);
Int (*revalidate_disk) (struct gendisk *);
Int (*getgeo) (struct block_device *, struct hd_geometry *);
struct module *owner;
};
In the previous chapters, we met the owner of the owner variable, which is used to store the owners of the structure, which is our module, so we do the following assignment:
. Owner = This_module,
And in this chapter, we will have a close contact with its fellow sister------Getgeo.

What we are going to do is:
1: Increase the initial value of the GETGEO member variable in block_device_operations, pointing to our "Get block device Physical structure" function.
2: Implement our "Get block device Physical structure" function.

The first step is simple, let's take a name called Simp_blkdev_getgeo () for the "Get the physical structure of block device" function, and also avoid copying such a large pile of Chinese characters in the next article.
Add the. Getgeo point to the Simp_blkdev_getgeo in Simp_blkdev_fops, which is to change the SIMP_BLKDEV_FOPS structure to this look:
struct Block_device_operations simp_blkdev_fops = {
. Owner = This_module,
. Getgeo = Simp_blkdev_getgeo,
};

The second step is difficult, but also difficult to go, in the code of the struct block_device_operations simp_blkdev_fops this line before looking for an empty point of the place, the following functions inserted into:
static int Simp_blkdev_getgeo (struct block_device *bdev,
struct Hd_geometry *geo)
{
/*
* Capacity heads sectors cylinders
* 0~16m 1 1 0~32768
* 16m~512m 1 32 1024~32768
* 512M~16G 32 32 1024~32768
* 16g~ ... 255 63 2088~ ...
*/
if (Simp_blkdev_bytes < 16 * 1024 * 1024) {
Geo->heads = 1;
Geo->sectors = 1;

} else if (Simp_blkdev_bytes < 512 * 1024 * 1024) {
Geo->heads = 1;
Geo->sectors = 32;
} else if (Simp_blkdev_bytes < 16ULL * 1024 * 1024 * 1024) {
Geo->heads = 32;
Geo->sectors = 32;
} else {
Geo->heads = 255;
Geo->sectors = 63;
}

Geo->cylinders = simp_blkdev_bytes>>9/geo->heads/geo->sectors;

return 0;
}
Because we use struct hd_geometry structure here, we also want to add a line of # include <linux/hdreg.h>.

The purpose of this function is to select the appropriate physical structure information to be loaded into the struct HD_GEOMETRY *geo structure.
Of course, in order to overcome the problem that can only be divided into 2 areas in the previous chapter, we should increase the number of tracks as much as possible.
It is hoped that the reader will not understand the composition of several areas requires several tracks, which means that a track of one area, also means that each zone must be general size.
Since partitions always take track as the boundary, increasing the number of tracks as much as possible is not just to allow the block device to accommodate more partitions.
It is more important to make the actual size of the partition closer to the specified value at the time of partitioning, which is to increase the accuracy of the actual partition capacity.

However, there is also a limit to the physical structure value of the set, which is the upper limit of the value in the struct hd_geometry.
We look at the content of struct Hd_geometry:
struct Hd_geometry {
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
The number of heads of the unsigned char and the number of sectors per track determine its upper limit of 255, and the number of tracks unsigned short determines the upper limit of 65535.
That's not the case, but in the previous chapter, we know that for modern hard drives, the number of heads and the number of sectors per track usually takes 255 and 63,
Combined with the upper limit of 65535 tracks here, the maximum block device capacity Hd_geometry can represent is 255*63*65535*512/1024/1024/1024=502g.
It is obvious that Linux currently supports a maximum hard drive capacity of more than 502G, so how does the kernel represent its physical structure through the hd_geometry structure for such block devices?
The trick is not the kernel, but the user-state program, such as Fdisk, gets the hd_geometry structure through the kernel call.
The hd_geometry.cylinders content is discarded and the number of tracks is calculated directly through the number of heads in the Hd_geometry and the number of sectors per track and the size of the hard disk.
Therefore, for more than 502G of hard disk, because the user program to draw the number of tracks and Hd_geometry.cylinders independent, so we often can see in fdisk the number of tracks of this hard disk more than 65535.

Just pulled away, and now it's time to get to the point, we decided to make this function for any size block device, always trying to return to a more beautiful physical structure.
Beauty means that the physical structure returned is guaranteed to have enough tracks, as well as to ensure that the number of heads and the number of sectors per track does not exceed 255 and 63, while preferably using a number that the programmer looks pleasing to the eye.
such as: 1, 2, 4, 8, 16, 32, 64 and so on.
Of course, we also want to find a one shot formula for all sizes of block devices, but unfortunately the author has not found it, so we used the method of piecewise calculation:
Consider a small block device first:
Even if the number of heads and sectors per track is 1 and the number of tracks is not enough, we will fix the number of heads and the number of sectors per track to 1, so that the number of tracks is as high as possible to improve the accuracy of the partition.
Therefore, the number of tracks increases with the capacity of the block device.
Although we already know that the number of tracks can actually exceed the 65535 limit of unsigned short, it is not necessary here, so we have to set an upper limit on the number of tracks.
Because you don't want to let the upper limit exceed 65535, but also hope that the upper limit is a programmer like the number, so here choose 32768.
Of course, when the number of tracks is more than 32768, it already means that the block device capacity is not so small, there is no need to use such a case of such a harsh number of heads and the number of sectors per track.
To put it simply, when the capacity of a block device is less than 1 heads, 1 sectors per track, and 32,768 tracks corresponding to the capacity-that is, 16M-we will handle this situation.
Then assume that the block device capacity is already greater than 16M:
We want to make sure that the block device contains enough tracks, and here we think 1024 tracks should be quite a bit.
The minimum value of the track occurs when the block device capacity is 16M, when using 1024 as the number of tracks, you can calculate the number of heads * Number of sectors per track = 32.
For the moment, the number of heads and the number of sectors per track are fixed to 1 and 32, and the number of tracks increases with the capacity of the block device.
At the same time, we also set the upper limit of the track to 32768, when the block device capacity is 512M.
In summary, when the block device capacity between 16M and 512M, we fixed the number of heads and the number of sectors per track to 1 and 32.
Then for block devices with a capacity greater than 512M:
Similar to the above processing, when the block device capacity between 512M and 16G, we have the number of heads and the number of sectors per track fixed to 32 and 32.
One final scenario:
The block device is large enough to be large, even if we use the head number and the upper limit of the number of sectors per track,
Can also get enough track numbers. At this point the number of heads and the number of sectors per track fixed to 255 and 63.
As for the number of tracks is how much, even more than the unsigned short limit does not matter, anyway.

As this function is explained to this end, our changes to the code are also over.

Start experimenting Now:
Compile and load:
# make
Make-c/lib/modules/2.6.27.4/build SUBDIRS=/MNT/HOST_TEST/SIMP_BLKDEV/SIMP_BLKDEV_STEP05 Modules
MAKE[1]: Entering directory '/mnt/ltt-kernel '
CC [M]/mnt/host_test/simp_blkdev/simp_blkdev_step05/simp_blkdev.o
Building modules, Stage 2.
Modpost 1 Modules
cc/mnt/host_test/simp_blkdev/simp_blkdev_step05/simp_blkdev.mod.o
LD [M]/mnt/host_test/simp_blkdev/simp_blkdev_step05/simp_blkdev.ko
MAKE[1]: Leaving directory '/mnt/ltt-kernel '
# Insmod Simp_blkdev.ko
#
To open a device file with Fdisk
# Fdisk/dev/simp_blkdev
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF Disklabel
Building a new DOS disklabel. Changes'll remain in memory only,
Until decide to write them. After that, of course, the previous
Content won ' t be recoverable.

Warning:invalid flag 0x0000 of partition Table 4 would be a corrected by W (rite)

Command (M for help):
Look at the physical structure of the device:
Command (M for help): P

Disk/dev/simp_blkdev:16 MB, 16777216 bytes
1 heads, Sectors/track, 1024x768 cylinders
Units = Cylinders of * 16384 bytes

Device Boot Start End Blocks Id System

Command (M for help):
We found that the device now has 1 heads, 32 sectors per track, and 1024 tracks.
This is in line with the processing in the code.

The contents of this chapter are not too difficult, together with the previous chapter, we have rested 2 chapters.
The wise reader may have guessed what the author intended to say.
Yes, the next chapter will have a surprise.

< not finished, to be continued >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.