磁盘槽位和盘符绑定方案

Linux下的SCSI设备都是按照设备的发现顺序命名的,对于磁盘盘符名称就是sda,sdb,sdc等等。存储设备一般都配有很多块磁盘,盘符名称和槽位号没有对应关系,当磁盘插入,拔出时对应的盘符可能会变化。这给使用和运维带来很多不便。

对于SCSI磁盘可通过修改sd_mod模块中的sd_probe(drivers/scsi/sd.c)来完成“磁盘槽位和盘符”的绑定。

/**
 *	sd_probe - called during driver initialization and whenever a
 *	new scsi device is attached to the system. It is called once
 *	for each scsi device (not just disks) present.
 *	@dev: pointer to device object
 *
 *	Returns 0 if successful (or not interested in this scsi device 
 *	(e.g. scanner)); 1 when there is an error.
 *
 *	Note: this function is invoked from the scsi mid-level.
 *	This function sets up the mapping between a given 
 *	<host,channel,id,lun> (found in sdp) and new device name 
 *	(e.g. /dev/sda). More precisely it is the block device major 
 *	and minor number that is chosen here.
 *
 *	Assume sd_attach is not re-entrant (for time being)
 *	Also think about sd_attach() and sd_remove() running coincidentally.
 **/
static int sd_probe(struct device *dev)
{
	struct scsi_device *sdp = to_scsi_device(dev);
	struct scsi_disk *sdkp;
	struct gendisk *gd;
	u32 index;
	int error;

	error = -ENODEV;
	if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC)
		goto out;

	SCSI_LOG_HLQUEUE(3, sdev_printk(KERN_INFO, sdp,
					"sd_attach\n"));

	error = -ENOMEM;
	sdkp = kzalloc(sizeof(*sdkp), GFP_KERNEL);
	if (!sdkp)
		goto out;

	gd = alloc_disk(SD_MINORS);
	if (!gd)
		goto out_free;

	do {
		if (!ida_pre_get(&sd_index_ida, GFP_KERNEL))
			goto out_put;

		spin_lock(&sd_index_lock);
		error = ida_get_new(&sd_index_ida, &index);
		spin_unlock(&sd_index_lock);
	} while (error == -EAGAIN);

	if (error)
		goto out_put;

	if (index >= SD_MAX_DISKS) {
		error = -ENODEV;
		sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name space exhausted.\n");
		goto out_free_index;
	}

	error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
	if (error)
		goto out_free_index;
        
      sdkp->device = sdp;
      sdkp->driver = &sd_template;                                                                       
      sdkp->disk = gd;
      sdkp->index = index;                                                                               
      sdkp->openers = 0;
      sdkp->previous_state = 1;  
        ......

}

具体负责给gendisk分配磁盘名称的就是 sd_format_disk_name,而决定磁盘名称的index这个参数。index通过ida_get_new(include/linux/idr.h)获取。ida是基于idr(底层是radix tree)实现的id分配器。从ida分配的index会被赋值给scsi_disk(drivers/scsi/sd.h)中的index,这个域作为SCSI磁盘的索引,系统内唯一,不仅确定了设备名而且确定了设备的主设备号和次设备号(关于scsi_disk->index如何确定设备号可参见sd_probe_async)。为了完成槽位和盘符绑定我们需要一个磁盘槽位和index的对应关系,这个对应关系可以根据系统中的一些不变量,如磁盘控制器的SCSI host号(系统范围内唯一编号,用于标识这个主机适配器)来确定。Linux系统中SATA磁盘控制器上的每个磁盘都会被映射到一个单独的SCSI host,对于只使用SATA控制器的阵列而言,可以采用如下方式绑定磁盘槽位和盘符。

以下是笔者根据scsi host(针对某款特定主板)确定SATA磁盘盘符对应关系的Patch:

将sd_probe中ida_get_new替换为ida_get_new_above,这样每次分配的index == host_no。

do {
        if (!ida_pre_get(&sd_index_ida, GFP_KERNEL))
            goto out_put;

        host_no = sdp->host->host_no;
        spin_lock(&sd_index_lock);
        //error = ida_get_new(&sd_index_ida, &index);
        error = ida_get_new_above(&sd_index_ida, host_no, &index);
        spin_unlock(&sd_index_lock);
} while (error == -EAGAIN);


转载请注明出处:http://blog.csdn.net/lkkey80/article/details/50263083

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值