Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3207152
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8556
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类: LINUX

2011-10-09 22:17:57

  最近的计划是学习磁盘相关的知识。所以在看linux那些事儿、Guide to the implementation of SCSI in Linux 2.6.X kernel,linux kernel code,这算是学习笔记吧。


  1. if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC)
  2.         goto out;
    结构体struct scsi_device有个char类型的成员变量type,用来表征是那种scsi设备,我们最常用的是TYPE_DISK,也就是常见的scsi磁盘,其他两种并不常见,不赘述。

    接下来分配的是结构体scsi_disk,和结构体struct gendisk。
  
  1. sdkp = kzalloc(sizeof(*sdkp), GFP_KERNEL);
  2.     if (!sdkp)
  3.         goto out;

  4. gd = alloc_disk(16);
这里需要离开主线,描述下函数alloc_disk这个函数
  1. struct gendisk *alloc_disk_node(int minors, int node_id)
  2. {
  3.     struct gendisk *disk;

  4.     disk = kmalloc_node(sizeof(struct gendisk),
  5.                 GFP_KERNEL | __GFP_ZERO, node_id);
  6.     if (disk) {
  7.         if (!init_disk_stats(disk)) {
  8.             kfree(disk);
  9.             return NULL;
  10.         }
  11.         if (minors > 1) {
  12.             int size = (minors - 1) * sizeof(struct hd_struct *);
  13.             disk->part = kmalloc_node(size,
  14.                 GFP_KERNEL | __GFP_ZERO, node_id);
  15.             if (!disk->part) {
  16.                 free_disk_stats(disk);
  17.                 kfree(disk);
  18.                 return NULL;
  19.             }
  20.         }
  21.         disk->minors = minors;
  22.         rand_initialize_disk(disk);
  23.         disk->dev.class = &block_class;
  24.         disk->dev.type = &disk_type;
  25.         device_initialize(&disk->dev);
  26.         INIT_WORK(&disk->async_notify,
  27.             media_change_notify_thread);
  28.     }
  29.     return disk;
  30. }
    我们看到了,首先是分配kmalloc_node,分配gendisk这个结构体,其次是磁盘的分区。对于磁盘来讲,我们看到alloc_disk传入的参数是16,每个磁盘最多可以有15个分区。我们从part可以看到。part是个指针数组,每个指针指向一个
hd_struct 类型的,这个hd_struct 类型就是分区的类型。

    后面的函数掠过不谈。再次回到我们的sd_probe函数

  1. if (!idr_pre_get(&sd_index_idr, GFP_KERNEL))
  2.         goto out_put;

  3.     spin_lock(&sd_index_lock);
  4.     error = idr_get_new(&sd_index_idr, NULL, &index);
  5.     spin_unlock(&sd_index_lock);
     熟悉本博客的看官知道,前面我曾有博文提到这个idr机制。详情请看博文 idr机制--integer ID management(一),这里只是简单的讲讲分配一个独一无二的较小的数字来表示这个设备

    
  1. if (index >= SD_MAX_DISKS)
  2.         error = -EBUSY;

  3. #define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26)
    接下来是判断的分配的小数字是否大于((26 * 26) + 26 + 1) * 26)。这个宏定义好像很奇怪。这个其实比较好理解。下文还有如下代码:

  1. if (index < 26) {
  2.         sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
  3.     } else if (index < (26 + 1) * 26) {
  4.         sprintf(gd->disk_name, "sd%c%c",
  5.             'a' + index / 26 - 1,'a' + index % 26);
  6.     } else {
  7.         const unsigned int m1 = (index / 26 - 1) / 26 - 1;
  8.         const unsigned int m2 = (index / 26 - 1) % 26;
  9.         const unsigned int m3 = index % 26;
  10.         sprintf(gd->disk_name, "sd%c%c%c",
  11.             'a' + m1, 'a' + m2, 'a' + m3);
  12.     }

    这部分代码是什么意思呢?这与磁盘的命名方式是有关系的。如果我有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个磁盘已经足够变态了,如果你非要挂比这多的磁盘,我这能奉劝这位大哥,莫装逼,装逼被雷劈了
阅读(4613) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

Bean_lee2011-10-11 23:40:46

GFree_Wind: 兄弟是做存储的?.....
是的,做云存储相关的。硬件相关的懂得比较少,需要补补

GFree_Wind2011-10-11 12:05:14

兄弟是做存储的?