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

📄 ccd.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: ccd.c,v 1.37.2.2 1999/03/11 19:21:31 dg Exp $ *//*	$NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $	*//* * Copyright (c) 1995 Jason R. Thorpe. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed for the NetBSD Project *	by Jason R. Thorpe. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * Copyright (c) 1988 University of Utah. * Copyright (c) 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: cd.c 1.6 90/11/28$ * *	@(#)cd.c	8.2 (Berkeley) 11/16/93 *//* * "Concatenated" disk driver. * * Dynamic configuration and disklabel support by: *	Jason R. Thorpe <thorpej@nas.nasa.gov> *	Numerical Aerodynamic Simulation Facility *	Mail Stop 258-6 *	NASA Ames Research Center *	Moffett Field, CA 94035 */#include "ccd.h"#if NCCD > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/proc.h>#include <sys/buf.h>#include <sys/malloc.h>#include <sys/namei.h>#include <sys/conf.h>#include <sys/stat.h>#include <sys/sysctl.h>#include <sys/disklabel.h>#include <ufs/ffs/fs.h> #include <sys/device.h>#include <sys/devicestat.h>#undef KERNEL			/* XXX */#include <sys/disk.h>#define KERNEL#include <sys/fcntl.h>#include <sys/vnode.h>#include <sys/ccdvar.h>#if defined(CCDDEBUG) && !defined(DEBUG)#define DEBUG#endif#ifdef DEBUG#define CCDB_FOLLOW	0x01#define CCDB_INIT	0x02#define CCDB_IO		0x04#define CCDB_LABEL	0x08#define CCDB_VNODE	0x10static int ccddebug = CCDB_FOLLOW | CCDB_INIT | CCDB_IO | CCDB_LABEL |    CCDB_VNODE;SYSCTL_INT(_debug, OID_AUTO, ccddebug, CTLFLAG_RW, &ccddebug, 0, "");#undef DEBUG#endif#define	ccdunit(x)	dkunit(x)#define ccdpart(x)	dkpart(x)/*   This is how mirroring works (only writes are special):   When initiating a write, ccdbuffer() returns two "struct ccdbuf *"s   linked together by the cb_mirror field.  "cb_pflags &   CCDPF_MIRROR_DONE" is set to 0 on both of them.   When a component returns to ccdiodone(), it checks if "cb_pflags &   CCDPF_MIRROR_DONE" is set or not.  If not, it sets the partner's   flag and returns.  If it is, it means its partner has already   returned, so it will go to the regular cleanup. */struct ccdbuf {	struct buf	cb_buf;		/* new I/O buf */	struct buf	*cb_obp;	/* ptr. to original I/O buf */	int		cb_unit;	/* target unit */	int		cb_comp;	/* target component */	int		cb_pflags;	/* mirror/parity status flag */	struct ccdbuf	*cb_mirror;	/* mirror counterpart */};/* bits in cb_pflags */#define CCDPF_MIRROR_DONE 1	/* if set, mirror counterpart is done */#define	getccdbuf()		\	((struct ccdbuf *)malloc(sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK))#define putccdbuf(cbp)		\	free((caddr_t)(cbp), M_DEVBUF)#define CCDLABELDEV(dev)	\	(makedev(major((dev)), dkmakeminor(ccdunit((dev)), 0, RAW_PART)))static d_open_t ccdopen;static d_read_t	ccdread;static d_write_t ccdwrite;static d_close_t ccdclose;static d_strategy_t ccdstrategy;static d_ioctl_t ccdioctl;static d_dump_t ccddump;static d_psize_t ccdsize;#define CDEV_MAJOR 74#define BDEV_MAJOR 21static struct cdevsw ccd_cdevsw = {	  ccdopen,	ccdclose,	ccdread,	ccdwrite,	  ccdioctl,	nostop,		nullreset,	nodevtotty,	  seltrue,	nommap,		ccdstrategy,	"ccd",	  NULL, 	-1,		ccddump,	ccdsize,	  D_DISK,	0,		-1 };/* Called by main() during pseudo-device attachment */static void	ccdattach __P((void *));PSEUDO_SET(ccdattach, ccd);/* called by biodone() at interrupt time */static	void ccdiodone __P((struct ccdbuf *cbp));static	void ccdstart __P((struct ccd_softc *, struct buf *));static	void ccdinterleave __P((struct ccd_softc *, int));static	void ccdintr __P((struct ccd_softc *, struct buf *));static	int ccdinit __P((struct ccddevice *, char **, struct proc *));static	int ccdlookup __P((char *, struct proc *p, struct vnode **));static	void ccdbuffer __P((struct ccdbuf **ret, struct ccd_softc *,		struct buf *, daddr_t, caddr_t, long));static	void ccdgetdisklabel __P((dev_t));static	void ccdmakedisklabel __P((struct ccd_softc *));static	int ccdlock __P((struct ccd_softc *));static	void ccdunlock __P((struct ccd_softc *));#ifdef DEBUGstatic	void printiinfo __P((struct ccdiinfo *));#endif/* Non-private for the benefit of libkvm. */struct	ccd_softc *ccd_softc;struct	ccddevice *ccddevs;static	int numccd = 0;static int ccd_devsw_installed = 0;/* * Number of blocks to untouched in front of a component partition. * This is to avoid violating its disklabel area when it starts at the * beginning of the slice. */#if !defined(CCD_OFFSET)#define CCD_OFFSET 16#endif/* * Called by main() during pseudo-device attachment.  All we need * to do is allocate enough space for devices to be configured later, and * add devsw entries. */static voidccdattach(dummy)	void *dummy;{	int i;	int num = NCCD;	if (num > 1)		printf("ccd0-%d: Concatenated disk drivers\n", num-1);	else		printf("ccd0: Concatenated disk driver\n");	ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc),	    M_DEVBUF, M_NOWAIT);	ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice),	    M_DEVBUF, M_NOWAIT);	if ((ccd_softc == NULL) || (ccddevs == NULL)) {		printf("WARNING: no memory for concatenated disks\n");		if (ccd_softc != NULL)			free(ccd_softc, M_DEVBUF);		if (ccddevs != NULL)			free(ccddevs, M_DEVBUF);		return;	}	numccd = num;	bzero(ccd_softc, num * sizeof(struct ccd_softc));	bzero(ccddevs, num * sizeof(struct ccddevice));	/* XXX: is this necessary? */	for (i = 0; i < numccd; ++i)		ccddevs[i].ccd_dk = -1;	if( ! ccd_devsw_installed ) {		cdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &ccd_cdevsw);		ccd_devsw_installed = 1;    	}	else {		printf("huh?\n");	}}static intccdinit(ccd, cpaths, p)	struct ccddevice *ccd;	char **cpaths;	struct proc *p;{	register struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit];	register struct ccdcinfo *ci = NULL;	/* XXX */	register size_t size;	register int ix;	struct vnode *vp;	struct vattr va;	size_t minsize;	int maxsecsize;	struct partinfo dpart;	struct ccdgeom *ccg = &cs->sc_geom;	char tmppath[MAXPATHLEN];	int error;#ifdef DEBUG	if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))		printf("ccdinit: unit %d\n", ccd->ccd_unit);#endif	cs->sc_size = 0;	cs->sc_ileave = ccd->ccd_interleave;	cs->sc_nccdisks = ccd->ccd_ndev;	/* Allocate space for the component info. */	cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo),	    M_DEVBUF, M_WAITOK);	/*	 * Verify that each component piece exists and record	 * relevant information about it.	 */	maxsecsize = 0;	minsize = 0;	for (ix = 0; ix < cs->sc_nccdisks; ix++) {		vp = ccd->ccd_vpp[ix];		ci = &cs->sc_cinfo[ix];		ci->ci_vp = vp;		/*		 * Copy in the pathname of the component.		 */		bzero(tmppath, sizeof(tmppath));	/* sanity */		if (error = copyinstr(cpaths[ix], tmppath,		    MAXPATHLEN, &ci->ci_pathlen)) {#ifdef DEBUG			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))				printf("ccd%d: can't copy path, error = %d\n",				    ccd->ccd_unit, error);#endif			while (ci > cs->sc_cinfo) {				ci--;				free(ci->ci_path, M_DEVBUF);			}			free(cs->sc_cinfo, M_DEVBUF);			return (error);		}		ci->ci_path = malloc(ci->ci_pathlen, M_DEVBUF, M_WAITOK);		bcopy(tmppath, ci->ci_path, ci->ci_pathlen);		/*		 * XXX: Cache the component's dev_t.		 */		if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) {#ifdef DEBUG			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))				printf("ccd%d: %s: getattr failed %s = %d\n",				    ccd->ccd_unit, ci->ci_path,				    "error", error);#endif			while (ci >= cs->sc_cinfo) {				free(ci->ci_path, M_DEVBUF);				ci--;			}			free(cs->sc_cinfo, M_DEVBUF);			return (error);		}		ci->ci_dev = va.va_rdev;		/*		 * Get partition information for the component.		 */		if (error = VOP_IOCTL(vp, DIOCGPART, (caddr_t)&dpart,		    FREAD, p->p_ucred, p)) {#ifdef DEBUG			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))				 printf("ccd%d: %s: ioctl failed, error = %d\n",				     ccd->ccd_unit, ci->ci_path, error);#endif			while (ci >= cs->sc_cinfo) {				free(ci->ci_path, M_DEVBUF);				ci--;			}			free(cs->sc_cinfo, M_DEVBUF);			return (error);		}		if (dpart.part->p_fstype == FS_BSDFFS) {			maxsecsize =			    ((dpart.disklab->d_secsize > maxsecsize) ?			    dpart.disklab->d_secsize : maxsecsize);			size = dpart.part->p_size - CCD_OFFSET;		} else {#ifdef DEBUG			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))				printf("ccd%d: %s: incorrect partition type\n",				    ccd->ccd_unit, ci->ci_path);#endif			while (ci >= cs->sc_cinfo) {				free(ci->ci_path, M_DEVBUF);				ci--;			}			free(cs->sc_cinfo, M_DEVBUF);			return (EFTYPE);		}		/*		 * Calculate the size, truncating to an interleave		 * boundary if necessary.		 */		if (cs->sc_ileave > 1)			size -= size % cs->sc_ileave;		if (size == 0) {#ifdef DEBUG			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))				printf("ccd%d: %s: size == 0\n",				    ccd->ccd_unit, ci->ci_path);#endif			while (ci >= cs->sc_cinfo) {				free(ci->ci_path, M_DEVBUF);				ci--;			}			free(cs->sc_cinfo, M_DEVBUF);			return (ENODEV);		}		if (minsize == 0 || size < minsize)			minsize = size;		ci->ci_size = size;		cs->sc_size += size;	}	/*	 * Don't allow the interleave to be smaller than	 * the biggest component sector.	 */	if ((cs->sc_ileave > 0) &&	    (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) {#ifdef DEBUG		if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))			printf("ccd%d: interleave must be at least %d\n",			    ccd->ccd_unit, (maxsecsize / DEV_BSIZE));#endif		while (ci >= cs->sc_cinfo) {			free(ci->ci_path, M_DEVBUF);			ci--;		}		free(cs->sc_cinfo, M_DEVBUF);		return (EINVAL);	}	/*	 * If uniform interleave is desired set all sizes to that of	 * the smallest component.	 */	if (ccd->ccd_flags & CCDF_UNIFORM) {		for (ci = cs->sc_cinfo;		     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)			ci->ci_size = minsize;		if (ccd->ccd_flags & CCDF_MIRROR) {			/*			 * Check to see if an even number of components			 * have been specified.			 */			if (cs->sc_nccdisks % 2) {				printf("ccd%d: mirroring requires an even number of disks\n", ccd->ccd_unit );				while (ci > cs->sc_cinfo) {					ci--;					free(ci->ci_path, M_DEVBUF);				}				free(cs->sc_cinfo, M_DEVBUF);				return (EINVAL);			}			cs->sc_size = (cs->sc_nccdisks/2) * minsize;		}		else if (ccd->ccd_flags & CCDF_PARITY)			cs->sc_size = (cs->sc_nccdisks-1) * minsize;		else			cs->sc_size = cs->sc_nccdisks * minsize;	}	/*	 * Construct the interleave table.	 */	ccdinterleave(cs, ccd->ccd_unit);	/*	 * Create pseudo-geometry based on 1MB cylinders.  It's	 * pretty close.	 */	ccg->ccg_secsize = maxsecsize;	ccg->ccg_ntracks = 1;	ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize);	ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors;	/*	 * Add an devstat entry for this device.	 */	devstat_add_entry(&cs->device_stats, "ccd", ccd->ccd_unit,			  ccg->ccg_secsize, DEVSTAT_ALL_SUPPORTED,			  DEVSTAT_TYPE_ASC0 |DEVSTAT_TYPE_IF_OTHER,			  DEVSTAT_PRIORITY_CCD);	cs->sc_flags |= CCDF_INITED;	cs->sc_cflags = ccd->ccd_flags;	/* So we can find out later... */	cs->sc_unit = ccd->ccd_unit;	return (0);}static voidccdinterleave(cs, unit)	register struct ccd_softc *cs;	int unit;{	register struct ccdcinfo *ci, *smallci;	register struct ccdiinfo *ii;	register daddr_t bn, lbn;	register int ix;	u_long size;#ifdef DEBUG	if (ccddebug & CCDB_INIT)		printf("ccdinterleave(%x): ileave %d\n", cs, cs->sc_ileave);#endif

⌨️ 快捷键说明

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