kern_subr.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,141 行 · 第 1/2 页

C
1,141
字号
doexechooks(p)	struct proc *p;{	struct exechook_desc *edp;	for (edp = LIST_FIRST(&exechook_list);	     edp != NULL;	     edp = LIST_NEXT(edp, ehk_list)) {		(*edp->ehk_fn)(p, edp->ehk_arg);	}}/* * Determine the root device and, if instructed to, the root file system. */#include "md.h"#if NMD == 0#undef MEMORY_DISK_HOOKS#endif#ifdef MEMORY_DISK_HOOKSstatic struct device fakemdrootdev[NMD];#endif#include "raid.h"#if NRAID == 1#define BOOT_FROM_RAID_HOOKS 1#endif#ifdef BOOT_FROM_RAID_HOOKSextern int numraid;extern struct device *raidrootdev;#endifvoidsetroot(bootdv, bootpartition)	struct device *bootdv;	int bootpartition;{	struct device *dv;	int len;#ifdef MEMORY_DISK_HOOKS	int i;#endif	dev_t nrootdev;	dev_t ndumpdev = NODEV;	char buf[128];	const char *rootdevname;	const char *dumpdevname;	struct device *rootdv = NULL;		/* XXX gcc -Wuninitialized */	struct device *dumpdv = NULL;	struct ifnet *ifp;	const char *deffsname;	struct vfsops *vops;	extern int (*mountroot) __P((void));#ifdef MEMORY_DISK_HOOKS	for (i = 0; i < NMD; i++) {		fakemdrootdev[i].dv_class  = DV_DISK;		fakemdrootdev[i].dv_cfdata = NULL;		fakemdrootdev[i].dv_unit   = i;		fakemdrootdev[i].dv_parent = NULL;		sprintf(fakemdrootdev[i].dv_xname, "md%d", i);	}#endif /* MEMORY_DISK_HOOKS */#ifdef MEMORY_DISK_IS_ROOT	bootdv = &fakemdrootdev[0];	bootpartition = 0;#endif	/*	 * If NFS is specified as the file system, and we found	 * a DV_DISK boot device (or no boot device at all), then	 * find a reasonable network interface for "rootspec".	 */	vops = vfs_getopsbyname("nfs");	if (vops != NULL && vops->vfs_mountroot == mountroot &&	    rootspec == NULL &&	    (bootdv == NULL || bootdv->dv_class != DV_IFNET)) {		for (ifp = ifnet.tqh_first; ifp != NULL;		    ifp = ifp->if_list.tqe_next)			if ((ifp->if_flags &			     (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)				break;		if (ifp == NULL) {			/*			 * Can't find a suitable interface; ask the			 * user.			 */			boothowto |= RB_ASKNAME;		} else {			/*			 * Have a suitable interface; behave as if			 * the user specified this interface.			 */			rootspec = (const char *)ifp->if_xname;		}	}	/*	 * If wildcarded root and we the boot device wasn't determined,	 * ask the user.	 */	if (rootspec == NULL && bootdv == NULL)		boothowto |= RB_ASKNAME; top:	if (boothowto & RB_ASKNAME) {		struct device *defdumpdv;		for (;;) {			printf("root device");			if (bootdv != NULL) {				printf(" (default %s", bootdv->dv_xname);				if (bootdv->dv_class == DV_DISK)					printf("%c", bootpartition + 'a');				printf(")");			}			printf(": ");			len = cngetsn(buf, sizeof(buf));			if (len == 0 && bootdv != NULL) {				strcpy(buf, bootdv->dv_xname);				len = strlen(buf);			}			if (len > 0 && buf[len - 1] == '*') {				buf[--len] = '\0';				dv = getdisk(buf, len, 1, &nrootdev, 0);				if (dv != NULL) {					rootdv = dv;					break;				}			}			dv = getdisk(buf, len, bootpartition, &nrootdev, 0);			if (dv != NULL) {				rootdv = dv;				break;			}		}		/*		 * Set up the default dump device.  If root is on		 * a network device, there is no default dump		 * device, since we don't support dumps to the		 * network.		 */		if (rootdv->dv_class == DV_IFNET)			defdumpdv = NULL;		else			defdumpdv = rootdv;		for (;;) {			printf("dump device");			if (defdumpdv != NULL) {				/*				 * Note, we know it's a disk if we get here.				 */				printf(" (default %sb)", defdumpdv->dv_xname);			}			printf(": ");			len = cngetsn(buf, sizeof(buf));			if (len == 0) {				if (defdumpdv != NULL) {					ndumpdev = MAKEDISKDEV(major(nrootdev),					    DISKUNIT(nrootdev), 1);				}				dumpdv = defdumpdv;				break;			}			if (len == 4 && strcmp(buf, "none") == 0) {				dumpdv = NULL;				break;			}			dv = getdisk(buf, len, 1, &ndumpdev, 1);			if (dv != NULL) {				dumpdv = dv;				break;			}		}		rootdev = nrootdev;		dumpdev = ndumpdev;		for (vops = LIST_FIRST(&vfs_list); vops != NULL;		     vops = LIST_NEXT(vops, vfs_list)) {			if (vops->vfs_mountroot != NULL &&			    vops->vfs_mountroot == mountroot)			break;		}		if (vops == NULL) {			mountroot = NULL;			deffsname = "generic";		} else			deffsname = vops->vfs_name;		for (;;) {			printf("file system (default %s): ", deffsname);			len = cngetsn(buf, sizeof(buf));			if (len == 0)				break;			if (len == 4 && strcmp(buf, "halt") == 0)				cpu_reboot(RB_HALT, NULL);			else if (len == 7 && strcmp(buf, "generic") == 0) {				mountroot = NULL;				break;			}			vops = vfs_getopsbyname(buf);			if (vops == NULL || vops->vfs_mountroot == NULL) {				printf("use one of: generic");				for (vops = LIST_FIRST(&vfs_list);				     vops != NULL;				     vops = LIST_NEXT(vops, vfs_list)) {					if (vops->vfs_mountroot != NULL)						printf(" %s", vops->vfs_name);				}				printf(" halt\n");			} else {				mountroot = vops->vfs_mountroot;				break;			}		}	} else if (rootspec == NULL) {		int majdev;		/*		 * Wildcarded root; use the boot device.		 */		rootdv = bootdv;		majdev = findblkmajor(bootdv->dv_xname);		if (majdev >= 0) {			/*			 * Root is on a disk.  `bootpartition' is root.			 */			rootdev = MAKEDISKDEV(majdev, bootdv->dv_unit,			    bootpartition);		}	} else {		/*		 * `root on <dev> ...'		 */		/*		 * If it's a network interface, we can bail out		 * early.		 */		dv = finddevice(rootspec);		if (dv != NULL && dv->dv_class == DV_IFNET) {			rootdv = dv;			goto haveroot;		}		rootdevname = findblkname(major(rootdev));		if (rootdevname == NULL) {			printf("unknown device major 0x%x\n", rootdev);			boothowto |= RB_ASKNAME;			goto top;		}		memset(buf, 0, sizeof(buf));		sprintf(buf, "%s%d", rootdevname, DISKUNIT(rootdev));		rootdv = finddevice(buf);		if (rootdv == NULL) {			printf("device %s (0x%x) not configured\n",			    buf, rootdev);			boothowto |= RB_ASKNAME;			goto top;		}	} haveroot:	root_device = rootdv;	switch (rootdv->dv_class) {	case DV_IFNET:		printf("root on %s", rootdv->dv_xname);		break;	case DV_DISK:		printf("root on %s%c", rootdv->dv_xname,		    DISKPART(rootdev) + 'a');		break;	default:		printf("can't determine root device\n");		boothowto |= RB_ASKNAME;		goto top;	}	/*	 * Now configure the dump device.	 *	 * If we haven't figured out the dump device, do so, with	 * the following rules:	 *	 *	(a) We already know dumpdv in the RB_ASKNAME case.	 *	 *	(b) If dumpspec is set, try to use it.  If the device	 *	    is not available, punt.	 *	 *	(c) If dumpspec is not set, the dump device is	 *	    wildcarded or unspecified.  If the root device	 *	    is DV_IFNET, punt.  Otherwise, use partition b	 *	    of the root device.	 */	if (boothowto & RB_ASKNAME) {		/* (a) */		if (dumpdv == NULL)			goto nodumpdev;	} else if (dumpspec != NULL) {		/* (b) */		if (strcmp(dumpspec, "none") == 0 || dumpdev == NODEV) {			/*			 * Operator doesn't want a dump device.			 * Or looks like they tried to pick a network			 * device.  Oops.			 */			goto nodumpdev;		}		dumpdevname = findblkname(major(dumpdev));		if (dumpdevname == NULL)			goto nodumpdev;		memset(buf, 0, sizeof(buf));		sprintf(buf, "%s%d", dumpdevname, DISKUNIT(dumpdev));		dumpdv = finddevice(buf);		if (dumpdv == NULL) {			/*			 * Device not configured.			 */			goto nodumpdev;		}	} else {				/* (c) */		if (rootdv->dv_class == DV_IFNET)			goto nodumpdev;		else {			dumpdv = rootdv;			dumpdev = MAKEDISKDEV(major(rootdev),			    dumpdv->dv_unit, 1);		}	}	printf(" dumps on %s%c\n", dumpdv->dv_xname, DISKPART(dumpdev) + 'a');	return; nodumpdev:	dumpdev = NODEV;	printf("\n");}static intfindblkmajor(name)	const char *name;{	int i;	for (i = 0; dev_name2blk[i].d_name != NULL; i++)		if (strncmp(name, dev_name2blk[i].d_name,		    strlen(dev_name2blk[i].d_name)) == 0)			return (dev_name2blk[i].d_maj);	return (-1);}const char *findblkname(maj)	int maj;{	int i;	for (i = 0; dev_name2blk[i].d_name != NULL; i++)		if (dev_name2blk[i].d_maj == maj)			return (dev_name2blk[i].d_name);	return (NULL);}static struct device *finddevice(name)	const char *name;{	struct device *dv;#ifdef BOOT_FROM_RAID_HOOKS	int j;	for (j = 0; j < numraid; j++) {		if (strcmp(name, raidrootdev[j].dv_xname) == 0) {			dv = &raidrootdev[j];			return (dv);		}	}#endif	for (dv = TAILQ_FIRST(&alldevs); dv != NULL;	    dv = TAILQ_NEXT(dv, dv_list))		if (strcmp(dv->dv_xname, name) == 0)			break;	return (dv);}static struct device *getdisk(str, len, defpart, devp, isdump)	char *str;	int len, defpart;	dev_t *devp;	int isdump;{	struct device	*dv;#ifdef MEMORY_DISK_HOOKS	int		i;#endif#ifdef BOOT_FROM_RAID_HOOKS	int 		j;#endif	if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {		printf("use one of:");#ifdef MEMORY_DISK_HOOKS		if (isdump == 0)			for (i = 0; i < NMD; i++)				printf(" %s[a-%c]", fakemdrootdev[i].dv_xname,				    'a' + MAXPARTITIONS - 1);#endif#ifdef BOOT_FROM_RAID_HOOKS		if (isdump == 0)			for (j = 0; j < numraid; j++)				printf(" %s[a-%c]", raidrootdev[j].dv_xname,				    'a' + MAXPARTITIONS - 1);#endif		for (dv = alldevs.tqh_first; dv != NULL;		    dv = dv->dv_list.tqe_next) {			if (dv->dv_class == DV_DISK)				printf(" %s[a-%c]", dv->dv_xname,				    'a' + MAXPARTITIONS - 1);			if (isdump == 0 && dv->dv_class == DV_IFNET)				printf(" %s", dv->dv_xname);		}		if (isdump)			printf(" none");		printf(" halt\n");	}	return (dv);}static struct device *parsedisk(str, len, defpart, devp)	char *str;	int len, defpart;	dev_t *devp;{	struct device *dv;	char *cp, c;	int majdev, part;#ifdef MEMORY_DISK_HOOKS	int i;#endif	if (len == 0)		return (NULL);	if (len == 4 && strcmp(str, "halt") == 0)		cpu_reboot(RB_HALT, NULL);	cp = str + len - 1;	c = *cp;	if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) {		part = c - 'a';		*cp = '\0';	} else		part = defpart;#ifdef MEMORY_DISK_HOOKS	for (i = 0; i < NMD; i++)		if (strcmp(str, fakemdrootdev[i].dv_xname) == 0) {			dv = &fakemdrootdev[i];			goto gotdisk;		}#endif	dv = finddevice(str);	if (dv != NULL) {		if (dv->dv_class == DV_DISK) {#ifdef MEMORY_DISK_HOOKS gotdisk:#endif			majdev = findblkmajor(dv->dv_xname);			if (majdev < 0)				panic("parsedisk");			*devp = MAKEDISKDEV(majdev, dv->dv_unit, part);		}		if (dv->dv_class == DV_IFNET)			*devp = NODEV;	}	*cp = c;	return (dv);}/* * snprintf() `bytes' into `buf', reformatting it so that the number, * plus a possible `x' + suffix extension) fits into len bytes (including * the terminating NUL). * Returns the number of bytes stored in buf, or -1 if there was a problem. * E.g, given a len of 9 and a suffix of `B': *	bytes		result *	-----		------ *	99999		`99999 B' *	100000		`97 KB' *	66715648	`65152 KB' *	252215296	`240 MB' */inthumanize_number(buf, len, bytes, suffix, divisor)	char		*buf;	size_t		 len;	u_int64_t	 bytes;	const char	*suffix;	int 		divisor;{		/* prefixes are: (none), Kilo, Mega, Giga, Tera, Peta, Exa */	static const char prefixes[] = " KMGTPE";	int		i, r;	u_int64_t	max;	size_t		suffixlen;	if (buf == NULL || suffix == NULL)		return (-1);	if (len > 0)		buf[0] = '\0';	suffixlen = strlen(suffix);			/* check if enough room for `x y' + suffix + `\0' */	if (len < 4 + suffixlen)		return (-1);	max = 1;	for (i = 0; i < len - suffixlen - 3; i++)		max *= 10;	for (i = 0; bytes >= max && i < sizeof(prefixes); i++)		bytes /= divisor;	r = snprintf(buf, len, "%qu%s%c%s", (unsigned long long)bytes,	    i == 0 ? "" : " ", prefixes[i], suffix);	return (r);}intformat_bytes(buf, len, bytes)	char		*buf;	size_t		 len;	u_int64_t	 bytes;{	int	rv;	size_t	nlen;	rv = humanize_number(buf, len, bytes, "B", 1024);	if (rv != -1) {			/* nuke the trailing ` B' if it exists */		nlen = strlen(buf) - 2;		if (strcmp(&buf[nlen], " B") == 0)			buf[nlen] = '\0';	}	return (rv);}#endif /*OSKIT*/

⌨️ 快捷键说明

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