该函数是的作用其实很简单,就是为了取得超级快的信息。但是比较麻烦的地方是,如果没有超级块的信息,我们对硬盘还一无所知,怎么读取到想要的信息?
//从data参数中读取超级块的块号“sb=XXXX”
unsigned long sb_block = get_sb_block(&data);
static unsigned long get_sb_block(void **data)
{
unsigned long sb_block;
char *options = (char *) *data;
if (!options || strncmp(options, "sb=", 3) != 0)
return 1; /* Default location */
options += 3;
sb_block = simple_strtoul(options, &options, 0);
if (*options && *options != ',') {
printk("EXT2-fs: Invalid sb specification: %s\n",(char *) *data);
return 1;
}
if (*options == ',')
options++;
*data = (void *) options;
return sb_block;
}
get_sb_block函数其实就是简单的从data中提取信息,simple_strtoul函数也很简单,把各种进制的字符串转换成数字。
//为ext2_sb_info分配空间
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
这里我们还是不知道blocksize的具体的值,但是block_device中保存的值是可以取到的。在取blocksize值后要去设置super_block中的属性,这时候就要判断大小合不合适。如果太小,比512都小,那block_device搞不定这么小的值啊。或者说这个值不是2的幂级,等等。
blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
int sb_min_blocksize(struct super_block *sb, int size)
{
/*
* super_block->block_device->request_queue->hardsect_size
* 默认是512
*/
int minsize = bdev_hardsect_size(sb->s_bdev);
if (size < minsize)
size = minsize;
return sb_set_blocksize(sb, size);
}
刚才从data中取到的sb_block是按照块大小为BLOCK_SIZE来的,如果blocksize不是这个值,那现在的sb_block也应该不是真正的块号了吧?还可能不在一个块的边界上!
if (blocksize != BLOCK_SIZE) {
logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
offset = (sb_block*BLOCK_SIZE) % blocksize;
} else {
logic_sb_block = sb_block;
}
下面就开始读ext2_super_block的内容了,读取的过程由sb_bread来完成(貌似读取没那么简单,这个过程以后补充)。根据offset设置es指针:
if (!(bh = sb_bread(sb, logic_sb_block))) {
printk ("EXT2-fs: unable to read superblock\n");
goto failed_sbi;
}
es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
在设置完一些默认属性之后开始根据mount时带的data参数来设置对应的属性,这个里面的