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 + -
显示快捷键?