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

📄 medley.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * MEDLEY SOFTWARE RAID DRIVER (Silicon Image 3112 and others) * * Copyright (C) 2003 Thomas Horsten <thomas@horsten.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA * Copyright (C) 2003 Thomas Horsten <thomas@horsten.com> * All Rights Reserved. * * This driver uses the ATA RAID driver framework and is based on * code from Arjan van de Ven's silraid.c and hptraid.c. * * It is a driver for the Medley software RAID, which is used by * some IDE controllers, including the Silicon Image 3112 SATA * controller found onboard many modern motherboards, and the * CMD680 stand-alone PCI RAID controller. * * The author has only tested this on the Silicon Image SiI3112. * If you have any luck using more than 2 drives, and/or more * than one RAID set, and/or any other chip than the SiI3112, * please let me know by sending me mail at the above address. * * Currently, only striped mode is supported for these RAIDs. * * You are welcome to contact me if you have any questions or * suggestions for improvement. * * Change history: * * 20040310 - thomas@horsten.com *   Removed C99 style variable declarations that confused gcc-2.x *   Fixed a bug where more than one RAID set would not be detected correctly *   General cleanup for submission to kernel * * 20031012 - thomas@horsten.com *   Added support for BLKRRPART ioctl to re-read partition table * * 20030801 - thomas@horsten.com *   First test release * */#include <linux/version.h>#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/blkdev.h>#include <linux/blkpg.h>#include <linux/genhd.h>#include <linux/ioctl.h>#include <linux/ide.h>#include <asm/uaccess.h>#include "ataraid.h"/* * These options can be tuned if the need should occur. * * Even better, this driver could be changed to allocate the structures * dynamically. */#define MAX_DRIVES_PER_SET 8#define MAX_MEDLEY_ARRAYS 4/* * Set to 1 only if you are debugging the driver, or if it doesn't work * the way you expect and you want to to report it. * * This will produce lots of kernel messages, some of which might * help me figure out what is going wrong). */#define DEBUGGING_MEDLEY 0#if DEBUGGING_MEDLEY#define dprintk(fmt, args...) printk(fmt, ##args)#else#define dprintk(fmt, args...)#endif/* * Medley RAID metadata structure. * * The metadata structure is based on the ATA drive ID from the drive itself, * with the RAID information in the vendor specific regions. * * We do not use all the fields, since we only support Striped Sets. */struct medley_metadata {	u8  driveid0[46];	u8  ascii_version[8];	u8  driveid1[52];	u32 total_sectors_low;	u32 total_sectors_high;	u16 reserved0;	u8  driveid2[142];	u16 product_id;	u16 vendor_id;	u16 minor_ver;	u16 major_ver;	u16 creation_timestamp[3];	u16 chunk_size;	u16 reserved1;	u8  drive_number;	u8  raid_type;	u8  drives_per_striped_set;	u8  striped_set_number;	u8  drives_per_mirrored_set;	u8  mirrored_set_number;	u32 rebuild_ptr_low;	u32 rebuild_ptr_high;	u32 incarnation_no;	u8  member_status;	u8  mirrored_set_state;	u8  reported_device_location;	u8  member_location;	u8  auto_rebuild;	u8  reserved3[17];	u16 checksum;};/* * This struct holds the information about a Medley array */struct medley_array {	u8       drives;	u16      chunk_size;	u32      sectors_per_row;	u8       chunk_size_log;	u16      present;	u16      timestamp[3];	u32      sectors;	int      registered;	atomic_t valid;	int      access;	kdev_t   members[MAX_DRIVES_PER_SET];	struct   block_device *bdev[MAX_DRIVES_PER_SET];};static struct medley_array raid[MAX_MEDLEY_ARRAYS];/* * Here we keep the offset of the ATARAID device ID's compared to our * own (this will normally be 0, unless another ATARAID driver has * registered some arrays before us). */static int medley_devid_offset = 0;/* * This holds the number of detected arrays. */static int medley_arrays = 0;/* * Wait queue for opening device (used when re-reading partition table) */static DECLARE_WAIT_QUEUE_HEAD(medley_wait_open);/* * The interface functions used by the ataraid framework. */static int medley_open(struct inode *inode, struct file *filp);static int medley_release(struct inode *inode, struct file *filp);static int medley_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg);static int medley_make_request(request_queue_t * q, int rw,			       struct buffer_head *bh);static struct raid_device_operations medley_ops = {	open:         medley_open,	release:      medley_release,	ioctl:        medley_ioctl,	make_request: medley_make_request};/* * This is the list of devices to probe. */static const kdev_t probelist[] = {	MKDEV(IDE0_MAJOR, 0),	MKDEV(IDE0_MAJOR, 64),	MKDEV(IDE1_MAJOR, 0),	MKDEV(IDE1_MAJOR, 64),	MKDEV(IDE2_MAJOR, 0),	MKDEV(IDE2_MAJOR, 64),	MKDEV(IDE3_MAJOR, 0),	MKDEV(IDE3_MAJOR, 64),	MKDEV(IDE4_MAJOR, 0),	MKDEV(IDE4_MAJOR, 64),	MKDEV(IDE5_MAJOR, 0),	MKDEV(IDE5_MAJOR, 64),	MKDEV(IDE6_MAJOR, 0),	MKDEV(IDE6_MAJOR, 64),	MKDEV(0, 0)};/* * Handler for ioctl calls to the virtual device */static int medley_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	unsigned int minor;	unsigned long sectors;	int devminor = (inode->i_rdev >> SHIFT) & MAJOR_MASK;	int device = devminor - medley_devid_offset;	int partition;	dprintk("medley_ioctl\n");	minor = MINOR(inode->i_rdev) >> SHIFT;	switch (cmd) {	case BLKGETSIZE:	/* Return device size */		if (!arg)			return -EINVAL;		sectors =		    ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects;		dprintk("medley_ioctl: BLKGETSIZE\n");		if (MINOR(inode->i_rdev) & 15)			return put_user(sectors, (unsigned long *) arg);		return put_user(raid[minor - medley_devid_offset].sectors,				(unsigned long *) arg);		break;	case HDIO_GETGEO: {			struct hd_geometry *loc =			    (struct hd_geometry *) arg;			unsigned short bios_cyl = (unsigned short)			    (raid[minor].sectors / 255 / 63);	/* truncate */			dprintk("medley_ioctl: HDIO_GETGEO\n");			if (!loc)				return -EINVAL;			if (put_user(255, (byte *) & loc->heads))				return -EFAULT;			if (put_user(63, (byte *) & loc->sectors))				return -EFAULT;			if (put_user			    (bios_cyl, (unsigned short *) &loc->cylinders))				return -EFAULT;			if (put_user			    ((unsigned) ataraid_gendisk.			     part[MINOR(inode->i_rdev)].start_sect,			     (unsigned long *) &loc->start))				return -EFAULT;			return 0;		}	case HDIO_GETGEO_BIG: {			struct hd_big_geometry *loc =			    (struct hd_big_geometry *) arg;			dprintk("medley_ioctl: HDIO_GETGEO_BIG\n");			if (!loc)				return -EINVAL;			if (put_user(255, (byte *) & loc->heads))				return -EFAULT;			if (put_user(63, (byte *) & loc->sectors))				return -EFAULT;			if (put_user			    (raid[minor - medley_devid_offset].sectors /			     255 / 63, (unsigned int *) &loc->cylinders))				return -EFAULT;			if (put_user			    ((unsigned) ataraid_gendisk.			     part[MINOR(inode->i_rdev)].start_sect,			     (unsigned long *) &loc->start))				return -EFAULT;			return 0;		}	case BLKROSET:	case BLKROGET:	case BLKSSZGET:		dprintk("medley_ioctl: BLK*\n");		return blk_ioctl(inode->i_rdev, cmd, arg);	case BLKRRPART:	/* Re-read partition tables */		if (!capable(CAP_SYS_ADMIN))			return -EACCES;		if (minor != 0)			return -EINVAL;		if (atomic_read(&(raid[device].valid)) == 0)			return -EINVAL;		atomic_set(&(raid[device].valid), 0);		if (raid[device].access != 1) {			atomic_set(&(raid[device].valid), 1);			return -EBUSY;		}		for (partition = 15; partition >= 0; partition--) {			invalidate_device(MKDEV(ATARAID_MAJOR,						partition + devminor), 1);			ataraid_gendisk.part[partition +					     devminor].start_sect = 0;			ataraid_gendisk.part[partition +					     devminor].nr_sects = 0;		}		ataraid_register_disk(device, raid[device].sectors);		atomic_set(&(raid[device].valid), 1);		wake_up(&medley_wait_open);		return 0;	default:		return -EINVAL;	}	return 0;}/* * Handler to map a request to the real device. * If the request cannot be made because it spans multiple disks, * we return -1, otherwise we modify the request and return 1. */static int medley_make_request(request_queue_t * q, int rw,			       struct buffer_head *bh){	u8 disk;	u32 rsect = bh->b_rsector;	int device =	    ((bh->b_rdev >> SHIFT) & MAJOR_MASK) - medley_devid_offset;	struct medley_array *r = raid + device;	/* Add the partition offset */	rsect = rsect + ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect;	dprintk("medley_make_request, rsect=%ul\n", rsect);	/* Detect if the request crosses a chunk barrier */	if (r->chunk_size_log) {		if (((rsect & (r->chunk_size - 1)) +		     (bh->b_size / 512)) > (1 << r->chunk_size_log)) {			return -1;		}	} else {		if ((rsect / r->chunk_size) !=		    ((rsect + (bh->b_size / 512) - 1) / r->chunk_size)) {			return -1;		}	}	/*	 * Medley arrays are simple enough, since the smallest disk decides the	 * number of sectors used per disk. So there is no need for the cutoff	 * magic found in other drivers like hptraid.	 */	if (r->chunk_size_log) {		/* We save some expensive operations (1 div, 1 mul, 1 mod),		 * if the chunk size is a power of 2, which is true in most		 * cases (at least with my version of the RAID BIOS).		 */		disk = (rsect >> r->chunk_size_log) % r->drives;		rsect = ((rsect / r->sectors_per_row) <<			 r->chunk_size_log) + (rsect & (r->chunk_size -							1));	} else {		disk = (rsect / r->chunk_size) % r->drives;		rsect = rsect / r->sectors_per_row * r->chunk_size +

⌨️ 快捷键说明

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