presto.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,363 行 · 第 1/2 页
C
1,363 行
if (vflag) { (void) fprintf(stdout, "%s: PRSETSTATE call ok\n", Myname); }#endif /* REMOTE */ return (0); } else { int ret; if (prstate == PRDOWN) op_on_enabled(prfd, PRDISABLE); ret = ioctl(prfd, PRSETSTATE, &prstate); if (ret < 0) { (void) fprintf(stderr, "%s: PRSETSTATE %s failed: ", Myname, prstate == PRUP ? "UP" : "DOWN"); perror(""); return (ret); } else if (vflag) { (void) fprintf(stdout, "%s: PRSETSTATE %s\n", Myname, prstate == PRUP ? "UP" : "DOWN"); } if (prstate == PRUP && doall) { if (mnt_presto_op(prfd, PRENABLE) < 0) ret = -1; } return (ret); }}/* * Scan the kernel mount table and perform the specified operation on it * if it matches the requirements for a "prestoized" entry. */intmnt_presto_op(prfd, op) int prfd; int op; /* PRENABLE or PRDISABLE */{ register struct fs_data *fd; int loc = 0, ret; if (!mountbuffer) { mountbuffer = (struct fs_data *) malloc(MSIZE); if (mountbuffer == NULL) { perror("malloc"); exit(1); } } ret = getmnt(&loc, mountbuffer, MSIZE, NOSTAT_MANY, 0); if (ret < 0) { perror("getmnt"); (void) fprintf(stdout, "%s: cannot get mount info\n", Myname); exit(1); } /* * enable/disable all local, r/w filesystems */ for (fd = mountbuffer; fd < &mountbuffer[ret]; fd++) { if (vflag) { (void) fprintf(stdout, "%s: scanning %s entry\n", Myname, fd->fd_devname); } if (fd->fd_fstype != GT_ULTRIX) { if (vflag) { (void) fprintf(stdout, "%s: type is %s\n", Myname, gt_names[fd->fd_fstype]); } continue; } if (fd->fd_flags & M_RONLY) { if (vflag) { (void) fprintf(stdout, "%s: mounted read-only\n", Myname); } continue; } enabledisable(prfd, fd->fd_devname, op); } return (0);}/* * Set presto memory size. * Returns -1 if error, 0 otherwise. */intsetsize(prfd, size, clnt) int prfd; u_int size; CLIENT *clnt;{ if (hflag) {#ifdef REMOTE presto_modstat *res; res = prestoctl_setbytes_3(&size, clnt); if (res == 0) { (void) fprintf(stderr, "%s: PRSETMEMSZ failed", Myname); clnt_perror(clnt, ""); return (-1); } if (! res->ps_status) { (void) fprintf(stderr, "%s: PRSETMEMSZ remote failure: %s\n", Myname, res->presto_modstat_u.ps_errmsg); return (-1); } if (vflag) { (void) fprintf(stdout, "%s: PRSETMEMSZ to 0x%x bytes\n", Myname, size); }#endif /* REMOTE */ return (0); } else { int ret; ret = ioctl(prfd, PRSETMEMSZ, &size); if (ret < 0) { (void) fprintf(stderr, "%s: PRSETMEMSZ 0x%x failed: ", Myname, size); perror(""); } else if (vflag) { (void) fprintf(stdout, "%s: PRSETMEMSIZ to 0x%x bytes\n", Myname, size); } return (ret); }}/* * Flush the presto device. * Returns -1 if error, 0 otherwise. */intprflush(prfd) int prfd;{ int ret; if (hflag) { (void) fprintf(stderr, "%s: warning: -F ignored; cannot flush remote machines.\n", Myname); return (-1); } ret = ioctl(prfd, PRFLUSH); if (ret < 0) { (void) fprintf(stderr, "%s: PRFLUSH failed: ", Myname); perror(""); } else if (vflag) { (void) fprintf(stdout, "%s: PRFLUSH\n", Myname); } return (ret);}/* * Reset the presto status. * Returns -1 if error, 0 otherwise. */intreset(prfd) int prfd;{ int ret; if (hflag) { (void) fprintf(stderr, "%s: warning: -R ignored; cannot reset remote machines.\n", Myname); return (-1); } ret = ioctl(prfd, PRRESET); if (ret < 0) { (void) fprintf(stderr, "%s: PRRESET failed: ", Myname); perror(""); } else if (vflag) { (void) fprintf(stdout, "%s: PRRESET\n", Myname); } return (ret);}/* * Print out the status information for the given presto structure. */voidprint_status(prstatus) struct presto_status *prstatus;{ char *pr_state; int sdwhp; /* synchronous dirty write hit percentage */ switch (prstatus->pr_state) { case PRUP: pr_state = "UP"; break; case PRDOWN: pr_state = "DOWN"; break; case PRERROR: pr_state = "ERROR"; break; default: pr_state = "???"; break; } (void) fprintf(stdout, "state = %s, size = 0x%x ", pr_state, prstatus->pr_cursize); if (prstatus->pr_cursize == prstatus->pr_maxsize) { (void) fprintf(stdout, "bytes\n"); } else { (void) fprintf(stdout, "/ 0x%x bytes\n", prstatus->pr_maxsize); } print_interval(prstatus->pr_seconds); sdwhp = prstatus->pr_wrstats.total - prstatus->pr_wrstats.pass; if (sdwhp > 0) { sdwhp = (prstatus->pr_wrstats.hitdirty * 1005) / (sdwhp * 10); } else { sdwhp = 0; } (void) printf("write cache efficiency: %u%%\n", sdwhp); /* inform the user of the battery states */ { register int low_batt = 0; register int i; for (i = 0; i < prstatus->pr_battcnt; i++) { if (prstatus->pr_batt[i] == BAT_LOW) { (void) fprintf(stdout, "battery %d is low!\n", i + 1); low_batt = 1; } else if (prstatus->pr_batt[i] == BAT_DISABLED) { (void) fprintf(stdout, "battery %d is disabled!\n", i + 1); low_batt = 1; } } if (!low_batt) (void) fprintf(stdout, "All batteries are ok\n"); }}voidprint_interval(secs) u_int secs;{ u_int ndays, nhours, nmin, nsecs;#define MINSEC (60)#define HOURSEC (60*MINSEC)#define DAYSEC (24*HOURSEC) (void) printf("statistics interval: "); nsecs = secs; ndays = nsecs / DAYSEC; nsecs = nsecs % DAYSEC; if (ndays > 0) { (void) printf("%d day", ndays); if (ndays != 1) (void) printf("s, "); else (void) printf(", "); } nhours = nsecs / HOURSEC; nsecs = nsecs % HOURSEC; nmin = nsecs / MINSEC; nsecs = nsecs % MINSEC; (void) printf("%02d:%02d:%02d (%u seconds)\n", nhours, nmin, nsecs, secs);}/* * Data structure organized to keep track of per device bits. * This structure is used as a linked list of local major devices * using Prestoserve. We keep one bit per minor so that we will * later be able to tell if there are any unmounted block devices that * we didn't report on when trying to list all the Presto-ized filesystems * and devices. */struct devdisp { struct devdisp *dd_next; u_int dd_bmajordev; struct prbits dd_disp;} *Devdisp;/* * Mark the given dev as displayed in global state. * Use haddev() routine (below) to test. */voidmarkdev(dev) dev_t dev;{ register struct devdisp **ddpp, *ddp; u_int maj_d, min_d; maj_d = major(dev); min_d = minor(dev); /* look for an already existing devdisp structure for this major */ for (ddpp = &Devdisp; *ddpp != NULL; ddpp = &(*ddpp)->dd_next) { ddp = *ddpp; if (ddp->dd_bmajordev == maj_d) { break; } } if (*ddpp == NULL) { /* allocate new structure for this major dev */ *ddpp = ddp = (struct devdisp *)calloc(1, sizeof (*ddp)); if (ddp == NULL) { (void) fprintf(stderr, "%s: out of memory!\n", Myname); return; } ddp->dd_bmajordev = maj_d; } /* mark the given minor bit for this device */ setbit(ddp->dd_disp.bits, min_d);}/* * Return a TRUE/FALSE indicator of whether markdev() was called with this dev. */bool_thaddev(dev) dev_t dev;{ register struct devdisp **ddpp, *ddp; u_int maj_d, min_d; maj_d = major(dev); min_d = minor(dev); /* look for an already existing devdisp structure for this major */ for (ddpp = &Devdisp; *ddpp != NULL; ddpp = &(*ddpp)->dd_next) { ddp = *ddpp; if (ddp->dd_bmajordev == maj_d) { /* got it - see if the minor bit for dev was set */ return (isset(ddp->dd_disp.bits, min_d)); } } return (FALSE);}voidshow_local_status(prfd, devname, dirname) int prfd; char *devname; char *dirname;{ struct uprtab uprtab; struct stat stats; presto_status ps; /* * map this device name to a block device number */ if (stat(devname, &stats) < 0) { if (vflag) perror(devname); return; } if ((stats.st_mode & S_IFMT) != S_IFBLK) { if (vflag) (void) fprintf(stdout, "%s: %s is not a block device\n", Myname, devname); return; } /* * query enabled status for this device from presto driver */ uprtab.upt_bmajordev = major(stats.st_rdev); if (vflag) { (void) fprintf(stdout, "%s: PRGETUPRTAB for block device 0x%x\n", Myname, uprtab.upt_bmajordev); } if (ioctl(prfd, PRGETSTATUS, &ps) < 0) { perror(prioctl_to_str[IOCTL_NUM(PRGETSTATUS)]); return; } if (ioctl(prfd, PRGETUPRTAB, &uprtab) < 0) { perror(prioctl_to_str[IOCTL_NUM(PRGETUPRTAB)]); return; } if (uprtab.upt_bmajordev == NODEV) /* got the requested device? */ return; if (vflag || Lflag) { int open = 0; (void) fprintf(stdout, "%s on %s", devname, dirname); if (isset(uprtab.upt_bounceio.bits, minor(stats.st_rdev))) { (void) fprintf(stdout, " (bounceio"); ++open; } if (isclr(uprtab.upt_enabled.bits, minor(stats.st_rdev))) { if (open) (void) fprintf(stdout, " disabled"); else (void) fprintf(stdout, " (disabled"); ++open; } if (open) (void) fprintf(stdout, ")\n"); else (void) fprintf(stdout, "\n"); } else if (ps.pr_state == PRUP && isset(uprtab.upt_enabled.bits, minor(stats.st_rdev))) { (void) fprintf(stdout, "%s on %s\n", devname, dirname); } markdev(stats.st_rdev);}voidshow_remote_status(fsname, dirname, hname) char *fsname; char *dirname; char *hname;{#ifdef REMOTE presto_get_fs_status *status; CLIENT *clnt; char *fs, *rhost; /* * Parse the NFS fsname entry into host/fs name pairs. */ if ((fs = index(fsname, ':')) == 0) { (void) fprintf(stderr, "%s: missing ':' in NFS mount fsname field of %s\n", Myname, fsname); return; } rhost = fsname; *fs++ = '\0'; if (hname != NULL && strcmp(rhost, hname) != 0) { if (vflag) (void) fprintf(stdout, "%s: %s does not match %s\n", Myname, rhost, hname); return; } if (*fs == '(') { if (vflag) (void) fprintf(stdout, "%s: %s:%s looks like an automounter entry, so punt\n", Myname, rhost, fs); return; } if (vflag) { (void) fprintf(stdout, "%s: requesting status of %s:%s\n", Myname, rhost, fs); } /* establish a connection with the remote server */ if ((clnt = openclnt(rhost, vflag)) == NULL) return; status = prestoctl_get_fs_status_3(&fs, clnt);#define PFS (status->presto_get_fs_status_u.status) if (status == NULL) { (void) fprintf(stderr, "%s: get_fs_status failed", Myname); clnt_perror(clnt, ""); } else if (!status->succeeded) { (void) fprintf(stderr, "%s: get_fs_status failed : %s\n", Myname, status->presto_get_fs_status_u.errmsg); } else if (PFS.pfs_prestoized) { if (vflag || Lflag) { int open = 0; (void) fprintf(stdout, "%s:%s on %s", rhost, fs, dirname); if (PFS.pfs_bounceio) { (void) fprintf(stdout, " (bounceio"); ++open; } if (PFS.pfs_state != PRUP || !PFS.pfs_enabled) { if (open) (void) fprintf(stdout, " disabled"); else (void) fprintf(stdout, " (disabled"); ++open; } if (open) (void) fprintf(stdout, ")\n"); else (void) fprintf(stdout, "\n"); } else if (PFS.pfs_state == PRUP && PFS.pfs_enabled) { (void) fprintf(stdout, "%s:%s on %s\n", rhost, fs, dirname); } }#undef PFS#endif /* REMOTE */}voidlist(prfd, hname) int prfd; char *hname; /* host name for remote list */{ register struct fs_data *fd; register struct prbits *enabled; register int min_d; struct uprtab uprtab; int loc = 0, nmounted; if (!mountbuffer) { mountbuffer = (struct fs_data *) malloc(MSIZE); if (mountbuffer == NULL) { perror("malloc"); exit(1); } } nmounted = getmnt(&loc, mountbuffer, MSIZE, NOSTAT_MANY, 0); if (nmounted < 0) { perror("getmnt"); (void) fprintf(stdout, "%s: cannot get mount info\n", Myname); exit(1); } /* * Show presto status for each mounted filesystem, * whether it is local or remotely mounted via NFS. * For each local dev found, mark a bit. */ for (fd = mountbuffer; fd < &mountbuffer[nmounted]; fd++) { if (vflag) { (void) fprintf(stdout, "%s: scanning mount entry %s\n", Myname, fd->fd_devname); } if (fd->fd_fstype == GT_NFS) { show_remote_status(fd->fd_devname, fd->fd_path, hname); } else if (prfd != -1 && fd->fd_fstype == GT_ULTRIX) { show_local_status(prfd, fd->fd_devname, fd->fd_path); } /* else it is some unknown file system type, ignore it */ } if (prfd == -1) return; /* no local presto device, all done */ /* * Now use presto ioctl's to get all the presto-ized devices. * List any currently enabled devices that weren't already printed. */ for (uprtab.upt_bmajordev = NODEV;;) { if (ioctl(prfd, PRNEXTUPRTAB, &uprtab) < 0) { perror(prioctl_to_str[IOCTL_NUM(PRNEXTUPRTAB)]); return; } if (uprtab.upt_bmajordev == NODEV) return; /* got the last one */ enabled = &uprtab.upt_enabled; for (min_d = 0; min_d < NBBY * sizeof (*enabled); min_d++) { if (isclr(enabled->bits, min_d)) { /* not enabled, just skip */ continue; } /* we got a presto-ized block device */ if (haddev(makedev(uprtab.upt_bmajordev, min_d))) { /* already printed */ continue; } /* * Maybe we should go through the work of * mapping the device to a name in /dev? */ if (vflag || Lflag) { (void) fprintf(stdout, "*unmounted* block device (%d, %d)", uprtab.upt_bmajordev, min_d); if (isset(uprtab.upt_bounceio.bits, min_d)) (void) fprintf(stdout, " (bounceio)"); (void) fprintf(stdout, "\n"); } else { (void) fprintf(stdout, "*unmounted* block device (%d, %d)\n", uprtab.upt_bmajordev, min_d); } } }}/* * Print out the given struct io stats with the given header. */voidprintio(s, iop) char *s; struct io *iop;{ double hits; double hitpct; hits = iop->hitclean + iop->hitdirty; if (iop->total != (u_int)0) { hitpct = (hits * 1005) / (iop->total * 10); /* round */ } else { hitpct = 100; } (void) fprintf(stdout, "%6s %12d%11d%%%12d%12d%12d%12d\n", s, iop->total, (u_int)hitpct, iop->hitclean, iop->hitdirty, iop->alloc, iop->pass);}/* * Print out the statistics from the given presto structure. */voidprintstats(prstatus) struct presto_status *prstatus;{ struct io total; total.total = prstatus->pr_wrstats.total + prstatus->pr_rdstats.total; total.hitclean = prstatus->pr_wrstats.hitclean + prstatus->pr_rdstats.hitclean; total.hitdirty = prstatus->pr_wrstats.hitdirty + prstatus->pr_rdstats.hitdirty; total.alloc = prstatus->pr_wrstats.alloc + prstatus->pr_rdstats.alloc; total.pass = prstatus->pr_wrstats.pass + prstatus->pr_rdstats.pass; (void) fprintf(stdout, "dirty = %d, clean = %d, inval = %d, active = %d\n", prstatus->pr_ndirty, prstatus->pr_nclean, prstatus->pr_ninval, prstatus->pr_nactive); (void) fprintf(stdout, "%6s %12s%12s%12s%12s%12s%12s\n", "", "count", "hit rate", "clean hits", "dirty hits", "allocations", "passes"); printio("write:", &prstatus->pr_wrstats); printio("read:", &prstatus->pr_rdstats); printio("total:", &total);}/* * Print usage message and exit with error condition. */voidusage(){ (void) fprintf(stderr,"usage:\n %s [-plLFRv] [-s size] [-u|d [filesystem ...]]\n", Myname); (void) fprintf(stderr," %s -h hostname [-plLv] [-s size] [-u|d]\n", Myname); exit(1); /* NOTREACHED */}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?