⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 medley.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		    rsect % r->chunk_size;	}	dprintk("medley_make_request :-), disk=%d, rsect=%ul\n", disk,		rsect);	bh->b_rdev = r->members[disk];	bh->b_rsector = rsect;	return 1;}/* * Find out which array a drive belongs to, and add it to that array. * If it is not a member of a detected array, add a new array for it. */void medley_add_raiddrive(kdev_t dev, struct medley_metadata *md){	int c;	dprintk("Candidate drive %02x:%02x - drive %d of %d, stride %d, "		"sectors %ul (%d MB)\n",		MAJOR(dev), MINOR(dev), md->drive_number,		md->drives_per_striped_set, md->chunk_size,		md->total_sectors_low,		md->total_sectors_low / 1024 / 1024 / 2);	for (c = 0; c < medley_arrays; c++) {		if ((raid[c].timestamp[0] == md->creation_timestamp[0]) &&		    (raid[c].timestamp[1] == md->creation_timestamp[1]) &&		    (raid[c].timestamp[2] == md->creation_timestamp[2]) &&		    (raid[c].drives == md->drives_per_striped_set) &&		    (raid[c].chunk_size == md->chunk_size) &&		    ((raid[c].present & (1 << md->drive_number)) == 0)) {			dprintk("Existing array %d\n", c);			raid[c].present |= (1 << md->drive_number);			raid[c].members[md->drive_number] = dev;			break;		}	}	if (c == medley_arrays) {		dprintk("New array %d\n", medley_arrays);		if (medley_arrays == MAX_MEDLEY_ARRAYS) {			printk(KERN_ERR "Medley RAID: "			       "Too many RAID sets detected - you can change "			       "the max in the driver.\n");		} else {			raid[c].timestamp[0] = md->creation_timestamp[0];			raid[c].timestamp[1] = md->creation_timestamp[1];			raid[c].timestamp[2] = md->creation_timestamp[2];			raid[c].drives = md->drives_per_striped_set;			raid[c].chunk_size = md->chunk_size;			raid[c].sectors_per_row = md->chunk_size *			    md->drives_per_striped_set;			/* Speedup if chunk size is a power of 2 */			if (((raid[c].chunk_size - 1) &			     (raid[c].chunk_size)) == 0) {				raid[c].chunk_size_log =				    ffs(raid[c].chunk_size) - 1;			} else {				raid[c].chunk_size_log = 0;			}			raid[c].present = (1 << md->drive_number);			raid[c].members[md->drive_number] = dev;			if (md->major_ver == 1) {				raid[c].sectors = ((u32 *) (md))[27];			} else {				raid[c].sectors = md->total_sectors_low;			}			medley_arrays++;		}	}}/* * Read the Medley metadata from a drive. * Returns the bh if it was found, otherwise NULL. */struct buffer_head *medley_get_metadata(kdev_t dev){	struct buffer_head *bh = NULL;	struct pci_dev *pcidev;	u32 lba;	int pos;	struct medley_metadata *md;	ide_drive_t *drvinfo = ide_info_ptr(dev, 0);	if ((drvinfo == NULL) || drvinfo->capacity < 1) {		return NULL;	}	dprintk("Probing %02x:%02x\n", MAJOR(dev), MINOR(dev));	/* If this drive is not on a PCI controller, it is not Medley RAID.	 * Medley matches the PCI device ID with the metadata to check if	 * it is valid. Unfortunately it is the only reliable way to identify	 * the superblock */	pcidev = drvinfo->hwif ? drvinfo->hwif->pci_dev : NULL;	if (!pcidev) {		return NULL;	}	/*	 * 4 copies of the metadata exist, in the following 4 sectors:	 * last, last-0x200, last-0x400, last-0x600.	 *	 * We must try each of these in order, until we find the metadata.	 * FIXME: This does not take into account drives with 48/64-bit LBA	 * addressing, even though the Medley RAID version 2 supports these.	 */	lba = drvinfo->capacity - 1;	for (pos = 0; pos < 4; pos++, lba -= 0x200) {		bh = bread(dev, lba, 512);		if (!bh) {			printk(KERN_ERR "Medley RAID (%02x:%02x): "			       "Error reading metadata (lba=%d)\n",			       MAJOR(dev), MINOR(dev), lba);			break;		}		/* A valid Medley RAID has the PCI vendor/device ID of its		 * IDE controller, and the correct checksum. */		md = (void *) (bh->b_data);		if (pcidev->vendor == md->vendor_id &&		    pcidev->device == md->product_id) {			u16 checksum = 0;			u16 *p = (void *) (bh->b_data);			int c;			for (c = 0; c < 160; c++) {				checksum += *p++;			}			dprintk			    ("Probing %02x:%02x csum=%d, major_ver=%d\n",			     MAJOR(dev), MINOR(dev), checksum,			     md->major_ver);			if (((checksum == 0xffff) && (md->major_ver == 1))			    || (checksum == 0)) {				dprintk("Probing %02x:%02x VALID\n",					MAJOR(dev), MINOR(dev));				break;			}		}		/* Was not a valid superblock */		if (bh) {			brelse(bh);			bh = NULL;		}	}	return bh;}/* * Determine if this drive belongs to a Medley array. */static void medley_probe_drive(int major, int minor){	struct buffer_head *bh;	kdev_t dev = MKDEV(major, minor);	struct medley_metadata *md;	bh = medley_get_metadata(dev);	if (!bh)		return;	md = (void *) (bh->b_data);	if (md->raid_type != 0x0) {		printk(KERN_INFO "Medley RAID (%02x:%02x): "		       "Sorry, this driver currently only supports "		       "striped sets (RAID level 0).\n", major, minor);	} else if (md->major_ver == 2 && md->total_sectors_high != 0) {		printk(KERN_ERR "Medley RAID (%02x:%02x):"		       "Sorry, the driver only supports 32 bit LBA disks "		       "(disk too big).\n", major, minor);	} else if (md->major_ver > 0 && md->major_ver > 2) {		printk(KERN_INFO "Medley RAID (%02x:%02x): "		       "Unsupported version (%d.%d) - this driver supports "		       "Medley version 1.x and 2.x\n",		       major, minor, md->major_ver, md->minor_ver);	} else if (md->drives_per_striped_set > MAX_DRIVES_PER_SET) {		printk(KERN_ERR "Medley RAID (%02x:%02x): "		       "Striped set too large (%d drives) - please report "		       "this (and change max in driver).\n",		       major, minor, md->drives_per_striped_set);	} else if ((md->drive_number > md->drives_per_striped_set) ||		   (md->drives_per_striped_set < 1) ||		   (md->chunk_size < 1)) {		printk(KERN_ERR "Medley RAID (%02x:%02x): "		       "Metadata appears to be corrupt.\n", major, minor);	} else {		/* We have a good candidate, put it in the correct array */		medley_add_raiddrive(dev, md);	}	if (bh) {		brelse(bh);	}}/* * Taken from hptraid.c, this is called to prevent the device * from disappearing from under us and also nullifies the (incorrect) * partitions of the underlying disk. */struct block_device *get_device_lock(kdev_t member){	struct block_device *bdev = bdget(member);	struct gendisk *gd;	int minor = MINOR(member);	int j;	if (bdev	    && blkdev_get(bdev, FMODE_READ | FMODE_WRITE, 0,			  BDEV_RAW) == 0) {		/*		 * 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(MAJOR(member), 0));		if (gd != NULL) {			if (gd->major == MAJOR(member)) {				for (j = 1 + (minor << gd->minor_shift);				     j < ((minor + 1) << gd->minor_shift);				     j++)					gd->part[j].nr_sects = 0;			}		}	}	return bdev;}/* * Initialise the driver. */static __init int medley_init(void){	int c, d;	memset(raid, 0, MAX_MEDLEY_ARRAYS * sizeof(struct medley_array));	/* Probe each of the drives on our list */	for (c = 0; probelist[c] != MKDEV(0, 0); c++) {		medley_probe_drive(MAJOR(probelist[c]),				   MINOR(probelist[c]));	}	/* Check if the detected sets are complete */	for (c = 0; c < medley_arrays; c++) {		if (raid[c].present != (1 << raid[c].drives) - 1) {			printk(KERN_ERR "Medley RAID: "			       "Incomplete RAID set deleted - disks:");			for (d = 0; c < raid[c].drives; c++) {				if (raid[c].present & (1 << d)) {					printk(" %02x:%02x",					       MAJOR(raid[c].members[d]),					       MINOR(raid[c].members[d]));				}			}			printk("\n");			if (c + 1 < medley_arrays) {				memmove(raid + c + 1, raid + c,					(medley_arrays - c -					 1) * sizeof(struct medley_array));			}			medley_arrays--;		}	}	/* Register any remaining array(s) */	for (c = 0; c < medley_arrays; c++) {		int device = ataraid_get_device(&medley_ops);		if (device < 0) {			printk(KERN_ERR "Medley RAID: "			       "Could not get ATARAID device.\n");			break;		}		if (c == 0) {			/* First array, compute offset to our device ID's */			medley_devid_offset = device;			dprintk("Medley_devid_offset: %d\n",				medley_devid_offset);		} else if (device - medley_devid_offset != c) {			printk(KERN_ERR "Medley RAID: "			       "ATARAID gave us an illegal device ID.\n");			ataraid_release_device(device);			break;		}		printk(KERN_INFO "Medley RAID: "		       "Striped set %d consists of %d disks, total %dMiB "		       "- disks:",		       c, raid[c].drives,		       raid[c].sectors / 1024 / 1024 / 2);		for (d = 0; d < raid[c].drives; d++) {			printk(" %02x:%02x", MAJOR(raid[c].members[d]),			       MINOR(raid[c].members[d]));			raid[c].bdev[d] = get_device_lock(raid[c].members[d]);		}		printk("\n");		raid[c].registered = 1;		atomic_set(&(raid[c].valid), 1);		ataraid_register_disk(c, raid[c].sectors);	}	if (medley_arrays > 0) {		printk(KERN_INFO "Medley RAID: %d active RAID set%s\n",		       medley_arrays, medley_arrays == 1 ? "" : "s");		return 0;	}	printk(KERN_INFO "Medley RAID: No usable RAID sets found\n");	return -ENODEV;}/* * Remove the arrays and clean up. */static void __exit medley_exit(void){	int device, d;	for (device = 0; device < medley_arrays; device++) {		for (d = 0; d < raid[device].drives; d++) {			if (raid[device].bdev[d]) {				blkdev_put(raid[device].bdev[d], BDEV_RAW);				raid[device].bdev[d] = NULL;			}		}		if (raid[device].registered) {			ataraid_release_device(device +					       medley_devid_offset);			raid[device].registered = 0;		}	}}/* * Called to open the virtual device */static int medley_open(struct inode *inode, struct file *filp){	int device = ((inode->i_rdev >> SHIFT) & MAJOR_MASK) -	    medley_devid_offset;	dprintk("medley_open\n");	if (device < medley_arrays) {		while (!atomic_read(&(raid[device].valid)))			sleep_on(&medley_wait_open);		raid[device].access++;		MOD_INC_USE_COUNT;		return (0);	}	return -ENODEV;}/* * Called to release the handle on the virtual device */static int medley_release(struct inode *inode, struct file *filp){	int device = ((inode->i_rdev >> SHIFT) & MAJOR_MASK) -	    medley_devid_offset;	dprintk("medley_release\n");	raid[device].access--;	MOD_DEC_USE_COUNT;	return 0;}module_init(medley_init);module_exit(medley_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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