hptraid.c

来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 921 行 · 第 1/2 页

C
921
字号
		/* If this ever fails we're doomed */		if (!bh1)			BUG();			/*		 * dupe the bufferhead and update the parts that need to be		 * different		 */		memcpy(bh1, bh, sizeof(*bh));				bh1->b_end_io = ataraid_end_request;		bh1->b_private = private;		bh1->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; /* partition offset */		bh1->b_rdev = raid[device].disk[i].device;		/* update the last known head position for the drive */		raid[device].disk[i].last_pos = bh1->b_rsector+(bh1->b_size>>9);		if( raid[device].raid01 ) {			if( hptraid0_compute_request(						raid[device].raid01 +							(bh1->b_rdev-1),						q, rw, bh1) != 1 ) {				/*				 * If a split is requested then it is requested				 * in the first iteration. This is true because				 * of the cutoff is not used in raid 0+1.				 */				if(unlikely(i)) {					BUG();				}				else {					kfree(private);					return -1;				}			}		}		generic_make_request(rw,bh1);	}	return 0;}static int hptraid1_make_request (request_queue_t *q, int rw, struct buffer_head * bh) {	/*	 * Read and Write are totally different cases; split them totally	 * here	 */	if (rw==READA)		rw = READ;		if (rw==READ)		return hptraid1_read_request(q,rw,bh);	else		return hptraid1_write_request(q,rw,bh);}static int hptraid01_read_request (request_queue_t *q, int rw, struct buffer_head * bh){	int rsector=bh->b_rsector;	int rdev=bh->b_rdev;		/* select mirror volume */	hptraid1_read_request(q, rw, bh);		/* stripe volume is selected by "bh->b_rdev" */	if( hptraid0_compute_request(				raid[(bh->b_rdev >> SHIFT)&MAJOR_MASK].					raid01 + (bh->b_rdev-1) ,				q, rw, bh) != 1 ) {			/* request must be split => restore sector and device */		bh->b_rsector = rsector;		bh->b_rdev = rdev;		return -1;	}	return 1;}static int hptraid01_make_request (request_queue_t *q, int rw, struct buffer_head * bh) {	/*	 * Read and Write are totally different cases; split them totally	 * here	 */	if (rw==READA)		rw = READ;		if (rw==READ)		return hptraid01_read_request(q,rw,bh);	else		return hptraid1_write_request(q,rw,bh);}static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize){	int ret = -EINVAL;	struct buffer_head *bh = NULL;	kdev_t dev = MKDEV(major,minor);		if (blksize_size[major]==NULL)	 /* device doesn't exist */		return -EINVAL;		/* Superblock is at 4096+412 bytes */	set_blocksize (dev, 4096);	bh = bread (dev, 1, 4096);		if (bh) {		memcpy (buffer, bh->b_data, bufsize);	} else {		printk(KERN_ERR "hptraid: Error reading superblock.\n");		goto abort;	}	ret = 0;abort:	if (bh)		brelse (bh);	return ret;}static unsigned long maxsectors (int major,int minor){	unsigned long lba = 0;	kdev_t dev;	ide_drive_t *ideinfo;		dev = MKDEV(major,minor);	ideinfo = ide_info_ptr (dev, 0);	if (ideinfo==NULL)		return 0;			/* first sector of the last cluster */	if (ideinfo->head==0) 		return 0;	if (ideinfo->sect==0)		return 0;	lba = (ideinfo->capacity);	return lba;}static void writeentry(struct hptraid * raid, struct hptraid_dev * disk,		int index, struct highpoint_raid_conf * prom) {	int j=0;	struct gendisk *gd;	struct block_device *bdev;	bdev = bdget(MKDEV(disk->major,disk->minor));	if (bdev && blkdev_get(bdev,FMODE_READ|FMODE_WRITE,0,BDEV_RAW) == 0) {		raid->disk[index].bdev = bdev;        	/*		 * This is supposed to prevent others from stealing our		 * underlying disks now blank the /proc/partitions table for 		 * the wrong partition table, so that scripts don't		 * accidentally mount it and crash the kernel		 */		 /* XXX: the 0 is an utter hack  --hch */		gd=get_gendisk(MKDEV(disk->major, 0));		if (gd!=NULL) { 			if (gd->major==disk->major) 				for (j=1+(disk->minor<<gd->minor_shift);					j<((disk->minor+1)<<gd->minor_shift);					j++) gd->part[j].nr_sects=0;							}        }	raid->disk[index].device = MKDEV(disk->major,disk->minor);	raid->disk[index].sectors = maxsectors(disk->major,disk->minor);	raid->stride = (1<<prom->raid0_shift);	raid->disks = prom->raid_disks;	raid->sectors = prom->total_secs;	raid->sectors += raid->sectors&1?1:0;	raid->magic_0=prom->magic_0;	raid->magic_1=prom->magic_1;}static int probedisk(struct hptraid_dev *disk, int device, u_int8_t type){	int i, j;        struct highpoint_raid_conf *prom;	static unsigned char block[4096];	 	if (disk->device != -1)	/* disk is occupied? */ 		return 0;  	if (maxsectors(disk->major,disk->minor)==0)		return 0;	        if (read_disk_sb(disk->major,disk->minor,(unsigned char*)&block,sizeof(block)))        	return 0;                                                                                                                         prom = (struct highpoint_raid_conf*)&block[512];                        if (prom->magic!=  0x5a7816f0)        	return 0;        switch (prom->type) {		case HPT_T_SPAN:		case HPT_T_RAID_0:		case HPT_T_RAID_1:		case HPT_T_RAID_01_RAID_0:			if(prom->type != type)				return 0;			break;		default:			printk(KERN_INFO "hptraid: unknown raid level-id %i\n",					prom->type);			return 0;        } 		/* disk from another array? */	if (raid[device].disks) {	/* only check if raid is not empty */		if (type == HPT_T_RAID_01_RAID_0 ) {			if( prom->magic_1 != raid[device].magic_1) {				return 0;			}		}		else if (prom->magic_0 != raid[device].magic_0) {				return 0;		}	}	i = prom->disk_number;	if (i<0)		return 0;	if (i>8) 		return 0;	if ( type == HPT_T_RAID_01_RAID_0 ) {			/* allocate helper raid devices for level 0+1 */		if (raid[device].raid01 == NULL ) {			raid[device].raid01=				kmalloc(2 * sizeof(struct hptraid),GFP_KERNEL);			if ( raid[device].raid01 == NULL ) {				printk(KERN_ERR "hptraid: out of memory\n");				raid[device].disks=-1;				return -ENOMEM;			}			memset(raid[device].raid01, 0,					2 * sizeof(struct hptraid));		}			/* find free sub-stucture */		for (j=0; j<2; j++) {			if ( raid[device].raid01[j].disks == 0 ||			     raid[device].raid01[j].magic_0 == prom->magic_0 )			{				writeentry(raid[device].raid01+j, disk,						i, prom);				break;			}		}			/* no free slot */		if(j == 2)			return 0;		raid[device].stride=raid[device].raid01[j].stride;		raid[device].disks=j+1;		raid[device].sectors=raid[device].raid01[j].sectors;		raid[device].disk[j].sectors=raid[device].raid01[j].sectors;		raid[device].magic_1=prom->magic_1;	}	else {		writeentry(raid+device, disk, i, prom);	}	disk->device=device;				return 1;}static void fill_cutoff(struct hptraid * device){	int i,j;	unsigned long smallest;	unsigned long bar;	int count;		bar = 0;	for (i=0;i<8;i++) {		smallest = ~0;		for (j=0;j<8;j++) 			if ((device->disk[j].sectors < smallest) && (device->disk[j].sectors>bar))				smallest = device->disk[j].sectors;		count = 0;		for (j=0;j<8;j++) 			if (device->disk[j].sectors >= smallest)				count++;				smallest = smallest * count;				bar = smallest;		device->cutoff[i] = smallest;		device->cutoff_disks[i] = count;			}}static int count_disks(struct hptraid * raid) {	int i, count=0;	for (i=0;i<8;i++) {		if (raid->disk[i].device!=0) {			printk(KERN_INFO "Drive %i is %li Mb \n",				i,raid->disk[i].sectors/2048);			count++;		}	}	return count;}static void raid1_fixup(struct hptraid * raid) {	int i, count=0;	for (i=0;i<8;i++) {			/* disknumbers and total disks values are bogus */		if (raid->disk[i].device!=0) {			raid->disk[count]=raid->disk[i];			if(i > count) {				memset(raid->disk+i, 0, sizeof(struct hptdisk));			}			count++;		}	}	raid->disks=count;}static int hptraid_init_one(int device, u_int8_t type, const char * label){	int i,count;	memset(raid+device, 0, sizeof(struct hptraid));	for (i=0; i < 14; i++) {		if( probedisk(devlist+i, device, type) < 0 )			return -EINVAL;	}	/* Initialize raid levels */	switch (type) {		case HPT_T_RAID_0:			fill_cutoff(raid+device);			break;		case HPT_T_RAID_1:			raid1_fixup(raid+device);			break;		case HPT_T_RAID_01_RAID_0:			for(i=0; i < 2 && raid[device].raid01 && 					raid[device].raid01[i].disks; i++) {				fill_cutoff(raid[device].raid01+i);					/* initialize raid 0+1 volumes */				raid[device].disk[i].device=i+1;			}			break;	}	/* Verify that we have all disks */	count=count_disks(raid+device);			if (count != raid[device].disks) {		printk(KERN_INFO "%s consists of %i drives but found %i drives\n",				label, raid[device].disks, count);		return -ENODEV;	}	else if (count) {		printk(KERN_INFO "%s consists of %i drives.\n",				label, count);		if (type == HPT_T_RAID_01_RAID_0 ) {			for(i=0;i<raid[device].disks;i++) {				count=count_disks(raid[device].raid01+i);				if(count == raid[device].raid01[i].disks) {					printk(KERN_ERR "Sub-Raid %i array consists of %i drives.\n",							i, count);				}				else {					printk(KERN_ERR "Sub-Raid %i array consists of %i drives but found %i disk members.\n",							i, raid[device].raid01[i].disks,							count);					return -ENODEV;				}			}			printk(KERN_WARNING "ataraid%i: raid-0+1 disk failover is not implemented!\n",					device);		}		else if (type == HPT_T_RAID_1) {			printk(KERN_WARNING "ataraid%i: raid-1 disk failover is not implemented!\n",					device);		}			/* Initialize the gendisk structure */			ataraid_register_disk(device,raid[device].sectors);		return 0;	}		return -ENODEV; /* No more raid volumes */}static int hptraid_init(void){ 	int retval=-ENODEV;	int device,i,count=0;  		printk(KERN_INFO "Highpoint HPT370 Softwareraid driver for linux version 0.03\n");	for(i=0; oplist[i].op; i++) {		do		{			device=ataraid_get_device(oplist[i].op);			if (device<0)				return (count?0:-ENODEV);			retval = hptraid_init_one(device, oplist[i].type,					oplist[i].label);			if (retval)				ataraid_release_device(device);			else				count++;		} while(!retval);	} 	return (count?0:retval);}static void __exit hptraid_exit (void){	int i,device;	for (device = 0; device<14; device++) {		for (i=0;i<8;i++)  {			struct block_device *bdev = raid[device].disk[i].bdev;			raid[device].disk[i].bdev = NULL;			if (bdev)				blkdev_put(bdev, BDEV_RAW);		}       		if (raid[device].sectors) {			ataraid_release_device(device);			if( raid[device].raid01 ) {				kfree(raid[device].raid01);			}		}	}}static int hptraid_open(struct inode * inode, struct file * filp) {	MOD_INC_USE_COUNT;	return 0;}static int hptraid_release(struct inode * inode, struct file * filp){		MOD_DEC_USE_COUNT;	return 0;}module_init(hptraid_init);module_exit(hptraid_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?