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

📄 ccd.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * Allocate an interleave table.	 * Chances are this is too big, but we don't care.	 */	size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo);	cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);	bzero((caddr_t)cs->sc_itable, size);	/*	 * Trivial case: no interleave (actually interleave of disk size).	 * Each table entry represents a single component in its entirety.	 */	if (cs->sc_ileave == 0) {		bn = 0;		ii = cs->sc_itable;		for (ix = 0; ix < cs->sc_nccdisks; ix++) {			/* Allocate space for ii_index. */			ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK);			ii->ii_ndisk = 1;			ii->ii_startblk = bn;			ii->ii_startoff = 0;			ii->ii_index[0] = ix;			bn += cs->sc_cinfo[ix].ci_size;			ii++;		}		ii->ii_ndisk = 0;#ifdef DEBUG		if (ccddebug & CCDB_INIT)			printiinfo(cs->sc_itable);#endif		return;	}	/*	 * The following isn't fast or pretty; it doesn't have to be.	 */	size = 0;	bn = lbn = 0;	for (ii = cs->sc_itable; ; ii++) {		/* Allocate space for ii_index. */		ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks),		    M_DEVBUF, M_WAITOK);		/*		 * Locate the smallest of the remaining components		 */		smallci = NULL;		for (ci = cs->sc_cinfo;		     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)			if (ci->ci_size > size &&			    (smallci == NULL ||			     ci->ci_size < smallci->ci_size))				smallci = ci;		/*		 * Nobody left, all done		 */		if (smallci == NULL) {			ii->ii_ndisk = 0;			break;		}		/*		 * Record starting logical block and component offset		 */		ii->ii_startblk = bn / cs->sc_ileave;		ii->ii_startoff = lbn;		/*		 * Determine how many disks take part in this interleave		 * and record their indices.		 */		ix = 0;		for (ci = cs->sc_cinfo;		     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)			if (ci->ci_size >= smallci->ci_size)				ii->ii_index[ix++] = ci - cs->sc_cinfo;		ii->ii_ndisk = ix;		bn += ix * (smallci->ci_size - size);		lbn = smallci->ci_size / cs->sc_ileave;		size = smallci->ci_size;	}#ifdef DEBUG	if (ccddebug & CCDB_INIT)		printiinfo(cs->sc_itable);#endif}/* ARGSUSED */static intccdopen(dev, flags, fmt, p)	dev_t dev;	int flags, fmt;	struct proc *p;{	int unit = ccdunit(dev);	struct ccd_softc *cs;	struct disklabel *lp;	int error = 0, part, pmask;#ifdef DEBUG	if (ccddebug & CCDB_FOLLOW)		printf("ccdopen(%x, %x)\n", dev, flags);#endif	if (unit >= numccd)		return (ENXIO);	cs = &ccd_softc[unit];	if (error = ccdlock(cs))		return (error);	lp = &cs->sc_dkdev.dk_label;	part = ccdpart(dev);	pmask = (1 << part);	/*	 * If we're initialized, check to see if there are any other	 * open partitions.  If not, then it's safe to update	 * the in-core disklabel.	 */	if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0))		ccdgetdisklabel(dev);	/* Check that the partition exists. */	if (part != RAW_PART && ((part >= lp->d_npartitions) ||	    (lp->d_partitions[part].p_fstype == FS_UNUSED))) {		error = ENXIO;		goto done;	}	/* Prevent our unit from being unconfigured while open. */	switch (fmt) {	case S_IFCHR:		cs->sc_dkdev.dk_copenmask |= pmask;		break;	case S_IFBLK:		cs->sc_dkdev.dk_bopenmask |= pmask;		break;	}	cs->sc_dkdev.dk_openmask =	    cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; done:	ccdunlock(cs);	return (0);}/* ARGSUSED */static intccdclose(dev, flags, fmt, p)	dev_t dev;	int flags, fmt;	struct proc *p;{	int unit = ccdunit(dev);	struct ccd_softc *cs;	int error = 0, part;#ifdef DEBUG	if (ccddebug & CCDB_FOLLOW)		printf("ccdclose(%x, %x)\n", dev, flags);#endif	if (unit >= numccd)		return (ENXIO);	cs = &ccd_softc[unit];	if (error = ccdlock(cs))		return (error);	part = ccdpart(dev);	/* ...that much closer to allowing unconfiguration... */	switch (fmt) {	case S_IFCHR:		cs->sc_dkdev.dk_copenmask &= ~(1 << part);		break;	case S_IFBLK:		cs->sc_dkdev.dk_bopenmask &= ~(1 << part);		break;	}	cs->sc_dkdev.dk_openmask =	    cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;	ccdunlock(cs);	return (0);}static intccdread(dev_t dev, struct uio *uio, int ioflag){	return (physio(ccdstrategy, NULL, dev, 1, minphys, uio));}static intccdwrite(dev_t dev, struct uio *uio, int ioflag){	return (physio(ccdstrategy, NULL, dev, 0, minphys, uio));}static voidccdstrategy(bp)	register struct buf *bp;{	register int unit = ccdunit(bp->b_dev);	register struct ccd_softc *cs = &ccd_softc[unit];	register int s;	int wlabel;	struct disklabel *lp;#ifdef DEBUG	if (ccddebug & CCDB_FOLLOW)		printf("ccdstrategy(%x): unit %d\n", bp, unit);#endif	if ((cs->sc_flags & CCDF_INITED) == 0) {		bp->b_error = ENXIO;		bp->b_flags |= B_ERROR;		goto done;	}	/* If it's a nil transfer, wake up the top half now. */	if (bp->b_bcount == 0)		goto done;	lp = &cs->sc_dkdev.dk_label;	/*	 * Do bounds checking and adjust transfer.  If there's an	 * error, the bounds check will flag that for us.	 */	wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);	if (ccdpart(bp->b_dev) != RAW_PART)		if (bounds_check_with_label(bp, lp, wlabel) <= 0)			goto done;	bp->b_resid = bp->b_bcount;	/*	 * "Start" the unit.	 */	s = splbio();	ccdstart(cs, bp);	splx(s);	return;done:	biodone(bp);}static voidccdstart(cs, bp)	register struct ccd_softc *cs;	register struct buf *bp;{	register long bcount, rcount;	struct ccdbuf *cbp[4];	/* XXX! : 2 reads and 2 writes for RAID 4/5 */	caddr_t addr;	daddr_t bn;	struct partition *pp;#ifdef DEBUG	if (ccddebug & CCDB_FOLLOW)		printf("ccdstart(%x, %x)\n", cs, bp);#endif	/* Record the transaction start  */	devstat_start_transaction(&cs->device_stats);	/*	 * Translate the partition-relative block number to an absolute.	 */	bn = bp->b_blkno;	if (ccdpart(bp->b_dev) != RAW_PART) {		pp = &cs->sc_dkdev.dk_label.d_partitions[ccdpart(bp->b_dev)];		bn += pp->p_offset;	}	/*	 * Allocate component buffers and fire off the requests	 */	addr = bp->b_data;	for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {		ccdbuffer(cbp, cs, bp, bn, addr, bcount);		rcount = cbp[0]->cb_buf.b_bcount;		if ((cbp[0]->cb_buf.b_flags & B_READ) == 0)			cbp[0]->cb_buf.b_vp->v_numoutput++;		VOP_STRATEGY(cbp[0]->cb_buf.b_vp, &cbp[0]->cb_buf);		if (cs->sc_cflags & CCDF_MIRROR &&		    (cbp[0]->cb_buf.b_flags & B_READ) == 0) {			/* mirror, start another write */			cbp[1]->cb_buf.b_vp->v_numoutput++;			VOP_STRATEGY(cbp[1]->cb_buf.b_vp, &cbp[1]->cb_buf);		}		bn += btodb(rcount);		addr += rcount;	}}/* * Build a component buffer header. */static voidccdbuffer(cb, cs, bp, bn, addr, bcount)	register struct ccdbuf **cb;	register struct ccd_softc *cs;	struct buf *bp;	daddr_t bn;	caddr_t addr;	long bcount;{	register struct ccdcinfo *ci, *ci2 = NULL;	/* XXX */	register struct ccdbuf *cbp;	register daddr_t cbn, cboff;      register off_t cbc;#ifdef DEBUG	if (ccddebug & CCDB_IO)		printf("ccdbuffer(%x, %x, %d, %x, %d)\n",		       cs, bp, bn, addr, bcount);#endif	/*	 * Determine which component bn falls in.	 */	cbn = bn;	cboff = 0;	/*	 * Serially concatenated	 */	if (cs->sc_ileave == 0) {		register daddr_t sblk;		sblk = 0;		for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)			sblk += ci->ci_size;		cbn -= sblk;	}	/*	 * Interleaved	 */	else {		register struct ccdiinfo *ii;		int ccdisk, off;		cboff = cbn % cs->sc_ileave;		cbn /= cs->sc_ileave;		for (ii = cs->sc_itable; ii->ii_ndisk; ii++)			if (ii->ii_startblk > cbn)				break;		ii--;		off = cbn - ii->ii_startblk;		if (ii->ii_ndisk == 1) {			ccdisk = ii->ii_index[0];			cbn = ii->ii_startoff + off;		} else {			if (cs->sc_cflags & CCDF_MIRROR) {				ccdisk = ii->ii_index[off % (ii->ii_ndisk/2)];				cbn = ii->ii_startoff + off / (ii->ii_ndisk/2);				/* mirrored data */				ci2 = &cs->sc_cinfo[ccdisk + ii->ii_ndisk/2];			}			else if (cs->sc_cflags & CCDF_PARITY) {				ccdisk = ii->ii_index[off % (ii->ii_ndisk-1)];				cbn = ii->ii_startoff + off / (ii->ii_ndisk-1);				if (cbn % ii->ii_ndisk <= ccdisk)					ccdisk++;			}			else {				ccdisk = ii->ii_index[off % ii->ii_ndisk];				cbn = ii->ii_startoff + off / ii->ii_ndisk;			}		}		cbn *= cs->sc_ileave;		ci = &cs->sc_cinfo[ccdisk];	}	/*	 * Fill in the component buf structure.	 */	cbp = getccdbuf();	bzero(cbp, sizeof (struct ccdbuf));	cbp->cb_buf.b_flags = bp->b_flags | B_CALL;	cbp->cb_buf.b_iodone = (void (*)(struct buf *))ccdiodone;	cbp->cb_buf.b_proc = bp->b_proc;	cbp->cb_buf.b_dev = ci->ci_dev;		/* XXX */	cbp->cb_buf.b_blkno = cbn + cboff + CCD_OFFSET;	cbp->cb_buf.b_offset = dbtob(cbn + cboff + CCD_OFFSET);	cbp->cb_buf.b_data = addr;	cbp->cb_buf.b_vp = ci->ci_vp;	LIST_INIT(&cbp->cb_buf.b_dep);	cbp->cb_buf.b_resid = 0;	if (cs->sc_ileave == 0)              cbc = dbtob((off_t)(ci->ci_size - cbn));	else              cbc = dbtob((off_t)(cs->sc_ileave - cboff));      cbp->cb_buf.b_bcount = (cbc < bcount) ? cbc : bcount; 	cbp->cb_buf.b_bufsize = cbp->cb_buf.b_bcount;	/*	 * context for ccdiodone	 */	cbp->cb_obp = bp;	cbp->cb_unit = cs - ccd_softc;	cbp->cb_comp = ci - cs->sc_cinfo;#ifdef DEBUG	if (ccddebug & CCDB_IO)		printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",		       ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno,		       cbp->cb_buf.b_data, cbp->cb_buf.b_bcount);#endif	cb[0] = cbp;	if (cs->sc_cflags & CCDF_MIRROR &&	    (cbp->cb_buf.b_flags & B_READ) == 0) {		/* mirror, start one more write */		cbp = getccdbuf();		bzero(cbp, sizeof (struct ccdbuf));		*cbp = *cb[0];		cbp->cb_buf.b_dev = ci2->ci_dev;		cbp->cb_buf.b_vp = ci2->ci_vp;		LIST_INIT(&cbp->cb_buf.b_dep);		cbp->cb_comp = ci2 - cs->sc_cinfo;		cb[1] = cbp;		/* link together the ccdbuf's and clear "mirror done" flag */		cb[0]->cb_mirror = cb[1];		cb[1]->cb_mirror = cb[0];		cb[0]->cb_pflags &= ~CCDPF_MIRROR_DONE;		cb[1]->cb_pflags &= ~CCDPF_MIRROR_DONE;	}}static voidccdintr(cs, bp)	register struct ccd_softc *cs;	register struct buf *bp;{#ifdef DEBUG	if (ccddebug & CCDB_FOLLOW)		printf("ccdintr(%x, %x)\n", cs, bp);#endif	/*	 * Request is done for better or worse, wakeup the top half.	 */	/* Record device statistics */	devstat_end_transaction(&cs->device_stats,				bp->b_bcount - bp->b_resid,				(bp->b_flags & B_ORDERED) ?				DEVSTAT_TAG_ORDERED : DEVSTAT_TAG_SIMPLE,				(bp->b_flags & B_READ) ? DEVSTAT_READ :				DEVSTAT_WRITE);	if (bp->b_flags & B_ERROR)		bp->b_resid = bp->b_bcount;	biodone(bp);}/* * Called at interrupt time. * Mark the component as done and if all components are done, * take a ccd interrupt. */static voidccdiodone(cbp)	struct ccdbuf *cbp;{	register struct buf *bp = cbp->cb_obp;	register int unit = cbp->cb_unit;	int count, s;	s = splbio();#ifdef DEBUG	if (ccddebug & CCDB_FOLLOW)		printf("ccdiodone(%x)\n", cbp);	if (ccddebug & CCDB_IO) {		printf("ccdiodone: bp %x bcount %d resid %d\n",		       bp, bp->b_bcount, bp->b_resid);		printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",		       cbp->cb_buf.b_dev, cbp->cb_comp, cbp,		       cbp->cb_buf.b_blkno, cbp->cb_buf.b_data,		       cbp->cb_buf.b_bcount);	}#endif	if (cbp->cb_buf.b_flags & B_ERROR) {		bp->b_flags |= B_ERROR;		bp->b_error = cbp->cb_buf.b_error ? cbp->cb_buf.b_error : EIO;#ifdef DEBUG		printf("ccd%d: error %d on component %d\n",		       unit, bp->b_error, cbp->cb_comp);#endif	}	if (ccd_softc[unit].sc_cflags & CCDF_MIRROR &&	    (cbp->cb_buf.b_flags & B_READ) == 0)		if ((cbp->cb_pflags & CCDPF_MIRROR_DONE) == 0) {			/* I'm done before my counterpart, so just set			   partner's flag and return */			cbp->cb_mirror->cb_pflags |= CCDPF_MIRROR_DONE;			putccdbuf(cbp);			splx(s);			return;		}			count = cbp->cb_buf.b_bcount;	putccdbuf(cbp);

⌨️ 快捷键说明

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