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

📄 ccd.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * If all done, "interrupt".	 */	bp->b_resid -= count;	if (bp->b_resid < 0)		panic("ccdiodone: count");	if (bp->b_resid == 0)		ccdintr(&ccd_softc[unit], bp);	splx(s);}static intccdioctl(dev, cmd, data, flag, p)	dev_t dev;	u_long cmd;	caddr_t data;	int flag;	struct proc *p;{	int unit = ccdunit(dev);	int i, j, lookedup = 0, error = 0;	int part, pmask, s;	struct ccd_softc *cs;	struct ccd_ioctl *ccio = (struct ccd_ioctl *)data;	struct ccddevice ccd;	char **cpp;	struct vnode **vpp;	if (unit >= numccd)		return (ENXIO);	cs = &ccd_softc[unit];	bzero(&ccd, sizeof(ccd));	switch (cmd) {	case CCDIOCSET:		if (cs->sc_flags & CCDF_INITED)			return (EBUSY);		if ((flag & FWRITE) == 0)			return (EBADF);		if (error = ccdlock(cs))			return (error);		/* Fill in some important bits. */		ccd.ccd_unit = unit;		ccd.ccd_interleave = ccio->ccio_ileave;		if (ccd.ccd_interleave == 0 &&		    ((ccio->ccio_flags & CCDF_MIRROR) ||		     (ccio->ccio_flags & CCDF_PARITY))) {			printf("ccd%d: disabling mirror/parity, interleave is 0\n", unit);			ccio->ccio_flags &= ~(CCDF_MIRROR | CCDF_PARITY);		}		if ((ccio->ccio_flags & CCDF_MIRROR) &&		    (ccio->ccio_flags & CCDF_PARITY)) {			printf("ccd%d: can't specify both mirror and parity, using mirror\n", unit);			ccio->ccio_flags &= ~CCDF_PARITY;		}		if ((ccio->ccio_flags & (CCDF_MIRROR | CCDF_PARITY)) &&		    !(ccio->ccio_flags & CCDF_UNIFORM)) {			printf("ccd%d: mirror/parity forces uniform flag\n",			       unit);			ccio->ccio_flags |= CCDF_UNIFORM;		}		ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK;		/*		 * Allocate space for and copy in the array of		 * componet pathnames and device numbers.		 */		cpp = malloc(ccio->ccio_ndisks * sizeof(char *),		    M_DEVBUF, M_WAITOK);		vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *),		    M_DEVBUF, M_WAITOK);		error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp,		    ccio->ccio_ndisks * sizeof(char **));		if (error) {			free(vpp, M_DEVBUF);			free(cpp, M_DEVBUF);			ccdunlock(cs);			return (error);		}#ifdef DEBUG		if (ccddebug & CCDB_INIT)			for (i = 0; i < ccio->ccio_ndisks; ++i)				printf("ccdioctl: component %d: 0x%x\n",				    i, cpp[i]);#endif		for (i = 0; i < ccio->ccio_ndisks; ++i) {#ifdef DEBUG			if (ccddebug & CCDB_INIT)				printf("ccdioctl: lookedup = %d\n", lookedup);#endif			if (error = ccdlookup(cpp[i], p, &vpp[i])) {				for (j = 0; j < lookedup; ++j)					(void)vn_close(vpp[j], FREAD|FWRITE,					    p->p_ucred, p);				free(vpp, M_DEVBUF);				free(cpp, M_DEVBUF);				ccdunlock(cs);				return (error);			}			++lookedup;		}		ccd.ccd_cpp = cpp;		ccd.ccd_vpp = vpp;		ccd.ccd_ndev = ccio->ccio_ndisks;		/*		 * Initialize the ccd.  Fills in the softc for us.		 */		if (error = ccdinit(&ccd, cpp, p)) {			for (j = 0; j < lookedup; ++j)				(void)vn_close(vpp[j], FREAD|FWRITE,				    p->p_ucred, p);			bzero(&ccd_softc[unit], sizeof(struct ccd_softc));			free(vpp, M_DEVBUF);			free(cpp, M_DEVBUF);			ccdunlock(cs);			return (error);		}		/*		 * The ccd has been successfully initialized, so		 * we can place it into the array and read the disklabel.		 */		bcopy(&ccd, &ccddevs[unit], sizeof(ccd));		ccio->ccio_unit = unit;		ccio->ccio_size = cs->sc_size;		ccdgetdisklabel(dev);		ccdunlock(cs);		break;	case CCDIOCCLR:		if ((cs->sc_flags & CCDF_INITED) == 0)			return (ENXIO);		if ((flag & FWRITE) == 0)			return (EBADF);		if (error = ccdlock(cs))			return (error);		/*		 * Don't unconfigure if any other partitions are open		 * or if both the character and block flavors of this		 * partition are open.		 */		part = ccdpart(dev);		pmask = (1 << part);		if ((cs->sc_dkdev.dk_openmask & ~pmask) ||		    ((cs->sc_dkdev.dk_bopenmask & pmask) &&		    (cs->sc_dkdev.dk_copenmask & pmask))) {			ccdunlock(cs);			return (EBUSY);		}		/*		 * Free ccd_softc information and clear entry.		 */		/* Close the components and free their pathnames. */		for (i = 0; i < cs->sc_nccdisks; ++i) {			/*			 * XXX: this close could potentially fail and			 * cause Bad Things.  Maybe we need to force			 * the close to happen?			 */#ifdef DEBUG			if (ccddebug & CCDB_VNODE)				vprint("CCDIOCCLR: vnode info",				    cs->sc_cinfo[i].ci_vp);#endif			(void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE,			    p->p_ucred, p);			free(cs->sc_cinfo[i].ci_path, M_DEVBUF);		}		/* Free interleave index. */		for (i = 0; cs->sc_itable[i].ii_ndisk; ++i)			free(cs->sc_itable[i].ii_index, M_DEVBUF);		/* Free component info and interleave table. */		free(cs->sc_cinfo, M_DEVBUF);		free(cs->sc_itable, M_DEVBUF);		cs->sc_flags &= ~CCDF_INITED;		/*		 * Free ccddevice information and clear entry.		 */		free(ccddevs[unit].ccd_cpp, M_DEVBUF);		free(ccddevs[unit].ccd_vpp, M_DEVBUF);		ccd.ccd_dk = -1;		bcopy(&ccd, &ccddevs[unit], sizeof(ccd));		/* This must be atomic. */		s = splhigh();		ccdunlock(cs);		bzero(cs, sizeof(struct ccd_softc));		splx(s);		break;	case DIOCGDINFO:		if ((cs->sc_flags & CCDF_INITED) == 0)			return (ENXIO);		*(struct disklabel *)data = cs->sc_dkdev.dk_label;		break;	case DIOCGPART:		if ((cs->sc_flags & CCDF_INITED) == 0)			return (ENXIO);		((struct partinfo *)data)->disklab = &cs->sc_dkdev.dk_label;		((struct partinfo *)data)->part =		    &cs->sc_dkdev.dk_label.d_partitions[ccdpart(dev)];		break;	case DIOCWDINFO:	case DIOCSDINFO:		if ((cs->sc_flags & CCDF_INITED) == 0)			return (ENXIO);		if ((flag & FWRITE) == 0)			return (EBADF);		if (error = ccdlock(cs))			return (error);		cs->sc_flags |= CCDF_LABELLING;		error = setdisklabel(&cs->sc_dkdev.dk_label,		    (struct disklabel *)data, 0);				/*, &cs->sc_dkdev.dk_cpulabel); */		if (error == 0) {			if (cmd == DIOCWDINFO)				error = writedisklabel(CCDLABELDEV(dev),				    ccdstrategy, &cs->sc_dkdev.dk_label);				/*				    &cs->sc_dkdev.dk_cpulabel); */		}		cs->sc_flags &= ~CCDF_LABELLING;		ccdunlock(cs);		if (error)			return (error);		break;	case DIOCWLABEL:		if ((cs->sc_flags & CCDF_INITED) == 0)			return (ENXIO);		if ((flag & FWRITE) == 0)			return (EBADF);		if (*(int *)data != 0)			cs->sc_flags |= CCDF_WLABEL;		else			cs->sc_flags &= ~CCDF_WLABEL;		break;	default:		return (ENOTTY);	}	return (0);}static intccdsize(dev)	dev_t dev;{	struct ccd_softc *cs;	int part, size;	if (ccdopen(dev, 0, S_IFBLK, curproc))		return (-1);	cs = &ccd_softc[ccdunit(dev)];	part = ccdpart(dev);	if ((cs->sc_flags & CCDF_INITED) == 0)		return (-1);	if (cs->sc_dkdev.dk_label.d_partitions[part].p_fstype != FS_SWAP)		size = -1;	else		size = cs->sc_dkdev.dk_label.d_partitions[part].p_size;	if (ccdclose(dev, 0, S_IFBLK, curproc))		return (-1);	return (size);}static intccddump(dev)	dev_t dev;{	/* Not implemented. */	return ENXIO;}/* * Lookup the provided name in the filesystem.  If the file exists, * is a valid block device, and isn't being used by anyone else, * set *vpp to the file's vnode. */static intccdlookup(path, p, vpp)	char *path;	struct proc *p;	struct vnode **vpp;	/* result */{	struct nameidata nd;	struct vnode *vp;	struct vattr va;	int error;	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p);	if (error = vn_open(&nd, FREAD|FWRITE, 0)) {#ifdef DEBUG		if (ccddebug & CCDB_FOLLOW|CCDB_INIT)			printf("ccdlookup: vn_open error = %d\n", error);#endif		return (error);	}	vp = nd.ni_vp;	if (vp->v_usecount > 1) {		VOP_UNLOCK(vp, 0, p);		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);		return (EBUSY);	}	if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) {#ifdef DEBUG		if (ccddebug & CCDB_FOLLOW|CCDB_INIT)			printf("ccdlookup: getattr error = %d\n", error);#endif		VOP_UNLOCK(vp, 0, p);		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);		return (error);	}	/* XXX: eventually we should handle VREG, too. */	if (va.va_type != VBLK) {		VOP_UNLOCK(vp, 0, p);		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);		return (ENOTBLK);	}#ifdef DEBUG	if (ccddebug & CCDB_VNODE)		vprint("ccdlookup: vnode info", vp);#endif	VOP_UNLOCK(vp, 0, p);	*vpp = vp;	return (0);}/* * Read the disklabel from the ccd.  If one is not present, fake one * up. */static voidccdgetdisklabel(dev)	dev_t dev;{	int unit = ccdunit(dev);	struct ccd_softc *cs = &ccd_softc[unit];	char *errstring;	struct disklabel *lp = &cs->sc_dkdev.dk_label;	struct ccdgeom *ccg = &cs->sc_geom;	bzero(lp, sizeof(*lp));	lp->d_secperunit = cs->sc_size;	lp->d_secsize = ccg->ccg_secsize;	lp->d_nsectors = ccg->ccg_nsectors;	lp->d_ntracks = ccg->ccg_ntracks;	lp->d_ncylinders = ccg->ccg_ncylinders;	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;	strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename));	lp->d_type = DTYPE_CCD;	strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));	lp->d_rpm = 3600;	lp->d_interleave = 1;	lp->d_flags = 0;	lp->d_partitions[RAW_PART].p_offset = 0;	lp->d_partitions[RAW_PART].p_size = cs->sc_size;	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;	lp->d_npartitions = RAW_PART + 1;	lp->d_bbsize = BBSIZE;				/* XXX */	lp->d_sbsize = SBSIZE;				/* XXX */	lp->d_magic = DISKMAGIC;	lp->d_magic2 = DISKMAGIC;	lp->d_checksum = dkcksum(&cs->sc_dkdev.dk_label);	/*	 * Call the generic disklabel extraction routine.	 */	if (errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy,	    &cs->sc_dkdev.dk_label))		ccdmakedisklabel(cs);#ifdef DEBUG	/* It's actually extremely common to have unlabeled ccds. */	if (ccddebug & CCDB_LABEL)		if (errstring != NULL)			printf("ccd%d: %s\n", unit, errstring);#endif}/* * Take care of things one might want to take care of in the event * that a disklabel isn't present. */static voidccdmakedisklabel(cs)	struct ccd_softc *cs;{	struct disklabel *lp = &cs->sc_dkdev.dk_label;	/*	 * For historical reasons, if there's no disklabel present	 * the raw partition must be marked FS_BSDFFS.	 */	lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS;	strncpy(lp->d_packname, "default label", sizeof(lp->d_packname));}/* * Wait interruptibly for an exclusive lock. * * XXX * Several drivers do this; it should be abstracted and made MP-safe. */static intccdlock(cs)	struct ccd_softc *cs;{	int error;	while ((cs->sc_flags & CCDF_LOCKED) != 0) {		cs->sc_flags |= CCDF_WANTED;		if ((error = tsleep(cs, PRIBIO | PCATCH, "ccdlck", 0)) != 0)			return (error);	}	cs->sc_flags |= CCDF_LOCKED;	return (0);}/* * Unlock and wake up any waiters. */static voidccdunlock(cs)	struct ccd_softc *cs;{	cs->sc_flags &= ~CCDF_LOCKED;	if ((cs->sc_flags & CCDF_WANTED) != 0) {		cs->sc_flags &= ~CCDF_WANTED;		wakeup(cs);	}}#ifdef DEBUGstatic voidprintiinfo(ii)	struct ccdiinfo *ii;{	register int ix, i;	for (ix = 0; ii->ii_ndisk; ix++, ii++) {		printf(" itab[%d]: #dk %d sblk %d soff %d",		       ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);		for (i = 0; i < ii->ii_ndisk; i++)			printf(" %d", ii->ii_index[i]);		printf("\n");	}}#endif#endif /* NCCD > 0 *//* Local Variables: *//* c-argdecl-indent: 8 *//* c-continued-statement-offset: 8 *//* c-indent-level: 8 *//* End: */

⌨️ 快捷键说明

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