我们以Redhat Enterprise Linux 6内核源码2.6.32-71.e16版本为例,分析Linux内核SCSI层是如何给硬盘分配盘符的,即/dev/sda、/dev/sdb … /dev/sdm等盘符的由来。
sd_probe()函数
系统中有新的SCSI磁盘(包括USB硬盘)插入,就会调用sd_probe()函数。
哪里决定盘符?
index的值决定了盘符(sd_probe()函数中第2277行)。
若index=0,则分配给此块SCSI硬盘的盘符为sda;
若index=1,则分配给此块SCSI硬盘的盘符为sdb;
… …
若index=25,则分配给此块SCSI硬盘的盘符为sdz;
函数在文件drivers/scsi/sd.c中。
02248: staticint sd_probe(structdevice*dev)
02249: {
02250: structscsi_device*sdp=to_scsi_device(dev);
02251: structscsi_disk*sdkp;
02252: structgendisk*gd;
02253: u32index;
02254: interror;
02255:
02256: error=-ENODEV;
02257: if(sdp–>type !=TYPE_DISK&&sdp–>type !=TYPE_MOD &&sdp–>type !=
02257: TYPE_RBC)
02258: goto¯out;
02259:
02260: SCSI_LOG_HLQUEUE(3,sdev_printk(KERN_INFO,sdp,
02261: “sd_attach\n”));
02262:
02263: error=-ENOMEM;
02264: sdkp=kzalloc(sizeof(*sdkp),GFP_KERNEL);
02265: if(!sdkp)
02266: goto¯out;
02267:
02268: gd=alloc_disk(SD_MINORS);
02269: if(!gd)
02270: goto¯out_free;
02271:
02272: do{
02273: if(!ida_pre_get(&sd_index_ida,GFP_KERNEL))
02274: goto¯out_put;
02275:
02276: spin_lock(&sd_index_lock);
02277: error=ida_get_new(&sd_index_ida,&index);
02278: spin_unlock(&sd_index_lock);
02279: } while(error==-EAGAIN);
02280:
02281: if(error)
02282: goto¯out_put;
02283:
02284: error=sd_format_disk_name(“sd“,index,gd–>disk_name,DISK_NAME_LEN);
02285: if(error)
02286: goto¯out_free_index;
02287:
02288: sdkp–>device= sdp;
02289: sdkp–>driver= &sd_template;
02290: sdkp–>disk= gd;
02291: sdkp–>index=index;
02292: sdkp–>openers= 0;
02293: sdkp–>previous_state= 1;
02294:
02295: if(!sdp–>request_queue->rq_timeout){
02296: if(sdp–>type !=TYPE_MOD)
02297: blk_queue_rq_timeout(sdp–>request_queue,SD_TIMEOUT);
02298: else
02299: blk_queue_rq_timeout(sdp–>request_queue,
02300: SD_MOD_TIMEOUT);
02301: }
02302:
02303: device_initialize(&sdkp–>dev);
02304: sdkp–>dev.parent= &sdp–>sdev_gendev;
02305: sdkp–>dev.class=&sd_disk_class;
02306: dev_set_name(&sdkp–>dev,dev_name(&sdp–>sdev_gendev));
02307:
02308: if(device_add(&sdkp–>dev))
02309: goto¯out_free_index;
02310:
02311: get_device(&sdp–>sdev_gendev);
02312:
02313: get_device(&sdkp–>dev); /*preventreleasebeforeasync_schedule*/
02314: async_schedule(sd_probe_async,sdkp);
02315:
02316: return0;
那么,刚开机时,那么多盘同时启动,我是如何判断哪个盘先进probe去分配盘符呢。