The idea has always been "don't process strings in the kernel "! In fact, it should be so!
The Linux kernel block device driver can read the serial number of the disk, which is stored in the disk's control chip ROM. In what form should the kernel present the serial number to the caller? Let's take a look at this directory:
/Dev/disk/by-id
Ll/dev/disk/by-id/
...
Lrwxrwxrwx 1 root 9 October 17 10:11 scsi-SATA_ST3500413AS_Z2A2AGQA->.../sdb
We can see that a disk can be indexed by the traditional/dev/sdX or by-YY, where by-id is the serial number. In the above output, the underline is followed by the serial number. Similarly, we can use the hdparm tool program to read and read the same results. In the code implementation of hdparm, we can see the following code snippet:
Static char * strip (char * s)
{
Char * e;
While (* s = '') ++ s;
If (* s)
For (e = s + strlen (s); * -- e = ''; * e = '\ 0 ');
Return s;
}
Static void dump_identity (_ 2010* idw)
{
Int I;
Char pmodes [64] = {0,}, dmodes [128] = {0,}, umodes [128] = {0 ,};
Char * model = strip (strndup (char *) & idw [27], 40 ));
Char * fwrev = strip (strndup (char *) & idw [23], 8 ));
Char * serno = strip (strndup (char *) & idw [10], 20 ));
_ U8 tPIO;
Printf ("\ n Model = %. 40 s, FwRev = %. 8 s, SerialNo = %. 20 s", model, fwrev, serno );
...
}
Obviously, strip removes the leading and trailing spaces when displaying the serial number, because the spaces are meaningless. This is normal. However...
However, in earlier versions of 2.6, such as 2.6.8, we can see the following calls in do_identify:
Ide_fixstring (id-> serial_no, sizeof (id-> serial_no), bswap );
So what is ide_fixstring? Its implementation is as follows. A detailed comment has provided the answer:
Void ide_fixstring (u8 * s, const int bytecount, const int byteswap)
{
U8 * p = s, * end = & s [bytecount &~ 1];/* bytecount must be even */
If (byteswap ){
/* Convert from big-endian to host byte order */
For (p = end; p! = S ;){
Unsigned short * pp = (unsigned short *) (p-= 2 );
* Pp = ntohs (* pp );
}
}
/* Strip leading blanks */
While (s! = End & * s = '')
++ S;
/* Compress internal blanks and strip trailing blanks */
While (s! = End & * s ){
If (* s ++! = ''| (S! = End & * s! = ''))
* P ++ = x (S-1 );
}
/* Wipe out trailing garbage */
While (p! = End)
* P ++ = '\ 0 ';
}
It is almost a replica of hdparm strip in a more strict sense! What's the problem? A big problem. This kernel cannot present an original disk serial number, that is, the serial number itself. Why not leave the processing to the application?
The Linux kernel should quickly return the original binary information and leave the parsing task to the application. This is not only about efficiency, but also about how the kernel does not know how to interpret this information! Fortunately, the kernel of the higher version does not process the disk serial number, but only returns the original information. Unfortunately, it causes a problem!
If it weren't for any problems at work, I wouldn't be idle about any device drivers. The system only upgrades the kernel. However, before and after the upgrade, you must read the disk serial number and compare the saved serial number, the kernel of the old version and the new version have different results in reading the disk serial number, so the kernel is no longer transparent to the application! What should we do? We had to modify the kernel driver of a later version to cater to the incorrect method of the earlier version!
Linux Kernel: click here
Linux Kernel: click here
Recommended reading:
Linux 3.12 code Suicidal Squirrel
How to install Linux 3.11 Kernel on Ubuntu
The Ubuntu 13.10 (Saucy Salamander) Kernel has been upgraded to Linux Kernel 3.10 RC5
Linux Kernel 3.4.62 LTS is now available for download