Part of the struct super_block structure definition is presented below:
struct super_block {
//...
dev_t s_dev; /* identifier */
unsigned char s_blocksize_bits; /* block size in bits */
unsigned long s_blocksize; /* block size in bytes */
unsigned char s_dirt; /* dirty flag */
loff_t s_maxbytes; /* max file size */
struct file_system_type *s_type; /* filesystem type */
struct super_operations *s_op; /* superblock methods */
//...
unsigned long s_flags; /* mount flags */
unsigned long s_magic; /* filesystem’s magic number */
struct dentry *s_root; /* directory mount point */
//...
char s_id[32]; /* informational name */
void *s_fs_info; /* filesystem private info */
};
I am a little confused in s_blocksize_bits
field. For example, if I set s_blocksize=512
, the correct way of writing is to set s_blocksize_bits=9
. But the binary representation of 512 is 1000000000, this means it needs 10 bits to store it. Why the Linux kernel requires one bit less.
Here I am attaching the source code of hexadecimal conversion in the Linux kernel:
/* assumes size > 256 */
static inline unsigned int blksize_bits(unsigned int size)
{
unsigned int bits = 8;
do {
bits++;
size >>= 1;
} while (size > 256);
return bits;
}