最近的计划是学习磁盘相关的知识。所以在看linux那些事儿、Guide to the implementation of SCSI in Linux 2.6.X kernel,linux kernel code,这算是学习笔记吧。
- if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC)
-
goto out;
结构体struct scsi_device有个char类型的成员变量type,用来表征是那种scsi设备,我们最常用的是TYPE_DISK,也就是常见的scsi磁盘,其他两种并不常见,不赘述。
接下来分配的是结构体scsi_disk,和结构体struct gendisk。
- sdkp = kzalloc(sizeof(*sdkp), GFP_KERNEL);
-
if (!sdkp)
-
goto out;
-
-
gd = alloc_disk(16);
这里需要离开主线,描述下函数alloc_disk这个函数
- struct gendisk *alloc_disk_node(int minors, int node_id)
-
{
-
struct gendisk *disk;
-
-
disk = kmalloc_node(sizeof(struct gendisk),
-
GFP_KERNEL | __GFP_ZERO, node_id);
-
if (disk) {
-
if (!init_disk_stats(disk)) {
-
kfree(disk);
-
return NULL;
-
}
-
if (minors > 1) {
-
int size = (minors - 1) * sizeof(struct hd_struct *);
-
disk->part = kmalloc_node(size,
-
GFP_KERNEL | __GFP_ZERO, node_id);
-
if (!disk->part) {
-
free_disk_stats(disk);
-
kfree(disk);
-
return NULL;
-
}
-
}
-
disk->minors = minors;
-
rand_initialize_disk(disk);
-
disk->dev.class = &block_class;
-
disk->dev.type = &disk_type;
-
device_initialize(&disk->dev);
-
INIT_WORK(&disk->async_notify,
-
media_change_notify_thread);
-
}
-
return disk;
-
}
我们看到了,首先是分配kmalloc_node,分配gendisk这个结构体,其次是磁盘的分区。对于磁盘来讲,我们看到alloc_disk传入的参数是16,每个磁盘最多可以有15个分区。我们从part可以看到。part是个指针数组,每个指针指向一个
hd_struct 类型的,这个hd_struct 类型就是分区的类型。
后面的函数掠过不谈。再次回到我们的sd_probe函数
- if (!idr_pre_get(&sd_index_idr, GFP_KERNEL))
-
goto out_put;
-
-
spin_lock(&sd_index_lock);
-
error = idr_get_new(&sd_index_idr, NULL, &index);
-
spin_unlock(&sd_index_lock);
- if (index >= SD_MAX_DISKS)
-
error = -EBUSY;
-
#define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26)
接下来是判断的分配的小数字是否大于((26 * 26) + 26 + 1) * 26)。这个宏定义好像很奇怪。这个其实比较好理解。下文还有如下代码:
- if (index < 26) {
-
sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
-
} else if (index < (26 + 1) * 26) {
-
sprintf(gd->disk_name, "sd%c%c",
-
'a' + index / 26 - 1,'a' + index % 26);
-
} else {
-
const unsigned int m1 = (index / 26 - 1) / 26 - 1;
-
const unsigned int m2 = (index / 26 - 1) % 26;
-
const unsigned int m3 = index % 26;
-
sprintf(gd->disk_name, "sd%c%c%c",
-
'a' + m1, 'a' + m2, 'a' + m3);
-
}
这部分代码是什么意思呢?这与磁盘的命名方式是有关系的。如果我有5个磁盘那么,我这五个磁盘会被操作系统命名为 sda sdb sdc sdd sde,同理我有26个磁盘,那么,命名就从sda ~ sdz。但是如果有三十个磁盘怎么办呢? 第27个磁盘被命名位sdaa,第二十八个磁盘被命名为sdab,OK,只要磁盘的个数小于(26+1)*26,用这种方法都可以命名。 如果大于(26+1)*27的话,换句话说sdzz也已经投入使用了。没办法,只能从sdaaa开始,sdaab,sdaac....sdzzz。
前面这些代码描述的就是这个命名的过程。至于你说如果比(((26 * 26) + 26 + 1) * 26)个磁盘还多,I'm sorry,LINUX已经无能为力了。但是一般不会有那个系统会挂着这么多的磁盘。SD_MAX_DISKS个磁盘已经足够变态了,如果你非要挂比这多的磁盘,我这能奉劝这位大哥,莫装逼,装逼被雷劈了
阅读(6432) | 评论(2) | 转发(0) |