presto.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,363 行 · 第 1/2 页
C
1,363 行
#ifndef lintstatic char *sccsid = "@(#)presto.c 4.2 (ULTRIX) 10/8/90";#endif lint/************************************************************************ * * * Copyright (c) 1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Portions of this software have been licensed to * Digital Equipment Company, Maynard, MA. * Copyright (c) 1990 Legato Systems, Inc. ALL RIGHTS RESERVED. *//* * * Modification history: * * 25 Aug 90 -- chet * Prestoserve V2.1 stuff. * * 25 May 90 -- chet * Added this file; it was derived from Legato sources. * *//* * Presto control program * usage * local: presto [-pRLlFv] [-s size] [-u|d [filesystem ...]] * remote: presto -h hostname [-pLlv] [-s size] [-u|d] * * l - will display "mount" like list of accelerated filesystems. * L - like above, but more information. * p - print presto statistics * u - set state to up. If blkdev (directory) specifed, also enable that * particular blkdev or filesystem list, else enable * all mounted filesystems. * d - set state to down. If blkdev (directory) specified, disable * that particular blkdev or filesystem list after flushing their * blocks from the cache, else disable * all filesystems and blkdevs after flushing cache. * R - reset presto * F - flush all dirty presto buffers * h - do it to a remote machine * s - set the cache size * v - verbose (semi-documented) * f - override presto's default device name (undocumented) */#include <stdio.h>#include <ctype.h>#include <sys/param.h>#include <fcntl.h>#include <rpc/rpc.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/file.h>#include <dirent.h>#include <sys/fs_types.h>#include <strings.h>#include <sys/mount.h>#include <errno.h>#include <sys/socket.h>#include <netdb.h>#include <sys/time.h>#ifdef DEBUG#include "prestoioctl.h"#else#include <sys/prestoioctl.h>#endif#include "prestoctl.h"extern int errno;#define REMOTE#ifndef REMOTE#define CLIENT int#endifstruct timeval TIMEOUT = { 25, 0 };struct vallist { char *value; struct vallist *next;} Vallist;char *prioctl_to_str[] = { "NOOP", "PRGETSTATUS", "PRSETSTATE", "PRSETMEMSZ", "PRRESET", "PRENABLE", "PRDISABLE", "PRNEXTOPRTAB", /* PRNEXTOPRTAB - old style prtab */ "PRGETOPRTAB", /* PRGETOPRTAB - old style prtab */ "PRNEXTUPRTAB", /* PRNEXTUPRTAB - new style, user prtab */ "PRGETUPRTAB", /* PRGETUPRTAB - new style, user prtab */ "PRFLUSH"};void handle_machine();void list();void usage();void enabledisable();void print_status();void print_interval();void show_local_service();void show_remote_service();void printio();void printstats();CLIENT *openclnt();char *Myname; /* name progam invoked under */char *rhost; /* remote host name */int vflag; /* verbose output */int pflag; /* print information */int lflag; /* list all the accelerated filesystems */int Lflag; /* like above, but more information format */int dflag; /* set state to down */int Fflag; /* flush dirty presto buffers */int Rflag; /* reset presto */int sflag; /* size presto memory */int uflag; /* set state to up */int hflag; /* do it all to a remote host */int fflag; /* default file over-ridden */char *prdev = PRDEV; /* name of generic character presto device */int memsize; /* memory size given with -s option */struct fs_data *mountbuffer;#define MSIZE (NMOUNT*sizeof(struct fs_data))main(argc, argv) int argc; char *argv[];{ int prfd = -1; /* local presto device */ struct vallist *hlist; char *opts; Myname = argv[0]; argc--; argv++; while (argc > 0 && **argv == '-') { opts = &argv[0][1]; while (*opts) { switch (*opts++) { case 'l': lflag++; break; case 'L': Lflag++; lflag++; break; case 'p': pflag++; break; case 'd': dflag++; break; case 'u': uflag++; break; case 'F': Fflag++; break; case 'R': Rflag++; break; case 'v': vflag++; break; case 's': if (*opts || argc < 2) { usage(); /* NOTREACHED */ } sflag++; argv++; argc--; memsize = getnum(*argv); break; case 'f': if (*opts || argc < 2) { usage(); /* NOTREACHED */ } fflag++; argv++; argc--; prdev = *argv; break; case 'h':#ifdef REMOTE if (*opts || argc < 2) { usage(); /* NOTREACHED */ } hflag++; argv++; argc--; rhost = *argv; break;#else (void) fprintf(stderr, "Remote operation not supported\n"); exit(2);#endif /* REMOTE */ default: usage(); /* NOTREACHED */ } } argv++; argc--; } /* * If devices given, must have * exactly one of -u or -d specified. */ if (argc > 0 && !((dflag != 0) ^ (uflag != 0))) { usage(); /* NOTREACHED */ } if (vflag && !lflag) pflag++; if (hflag) { if (fflag) { (void) fprintf(stderr,"%s: warning: -f ignored; cannot override remote device names.\n", Myname); } if (argc > 0 && (dflag || uflag)) { (void) fprintf(stderr,"%s: warning: arguments to -d and -u are ignored when -h is specified.\n", Myname); } hlist = &Vallist; hlist->value = rhost; hlist->next = (struct vallist *)NULL; } else if (pflag || uflag || dflag || Fflag || Rflag || sflag || !lflag || access(prdev, R_OK) == 0) { /* * We either will be doing one of [pudFRs] (which obviously * require the device) or none of [pudFRsl] (which will * require the device for the basic status). If we have -l * and no [pudFRs], then we want to open the device for local * device presto-ization information if it exists. */ prfd = openpr(prdev); if (prfd == -1) { exit(2); } } else { prfd = -1; } if (hflag) { /* * Maybe more than one server with Prestoserve */ for (; hlist != NULL; hlist = hlist->next) { handle_machine(hlist->value, -1, 0, (char **)NULL); } } else { handle_machine((char *)NULL, prfd, argc, argv); } exit(0);}voidhandle_machine(hname, prfd, argc, argv) char *hname; int prfd; int argc; char *argv[];{ struct presto_status status; CLIENT *clnt;#ifdef REMOTE if (hname != NULL) { if (pflag || !(uflag || dflag || sflag)) (void) fprintf(stdout, "%s:\n", hname); clnt = openclnt(hname, 1); if (clnt == NULL) return; }#endif /* REMOTE */ if (getstatus(prfd, &status, clnt) == 0) { if (pflag) { if (vflag && (Fflag || Rflag || uflag || dflag || sflag)) { /* * Print the ``before'' status. */ print_status(&status); } printstats(&status); } } if (dflag) { if (argc == 0) { /* down everything */ (void) setupdown(prfd, PRDOWN, clnt, TRUE); } else { do { enabledisable(prfd, *argv++, PRDISABLE); } while (--argc > 0); } } if (Fflag) { (void) prflush(prfd); } if (Rflag) { (void) reset(prfd); } if (sflag) { if (memsize > status.pr_maxsize) memsize = status.pr_maxsize; (void) setsize(prfd, (u_int)memsize, clnt); } if (uflag) { if (argc == 0) { /* up everything */ (void) setupdown(prfd, PRUP, clnt, TRUE); } else { /* up the basic device and then handle each dev */ (void) setupdown(prfd, PRUP, clnt, FALSE); do { enabledisable(prfd, *argv++, PRENABLE); } while (--argc > 0); } } /* * Print the new current status except when * -u, -d, -F, -R, -s, or -l is given w/o a -p. */ if ((pflag || !(uflag || dflag || Fflag || Rflag || sflag || lflag)) && getstatus(prfd, &status, clnt) == 0) { print_status(&status); } if (lflag) list(prfd, hname);#ifdef REMOTE if (hname != NULL) { clnt_destroy(clnt); }#endif /* REMOTE */}/* * enable or disable presto write caching on the specified filesystem. * prfd is the previously opened presto file descripter. * specf is either a block device name or a path naming a filesystem. */voidenabledisable(prfd, specf, op) int prfd; /* local presto device */ char *specf; int op;{ struct stat statbuf; int ret; /* * Try it first as a path to a block device, and if that fails, * try it as a path's parent filesystem. */ ret = stat(specf, &statbuf); if (ret < 0) { (void) fprintf(stderr, "%s: cannot stat %s\n", Myname, specf); return; } if ((statbuf.st_mode & S_IFMT) == S_IFBLK) { /* simple block device case */ ret = ioctl(prfd, op, &statbuf.st_rdev); } else if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { if (vflag) { (void) fprintf(stdout, "%s: %s is a directory\n", Myname, specf); } ret = ioctl(prfd, op, &statbuf.st_dev); } else { (void) fprintf(stderr, "%s: %s is not a block device or directory.\n", Myname, specf); return; } if (ret < 0) { (void) fprintf(stderr, "%s: %s failed ", Myname, prioctl_to_str[IOCTL_NUM(op)]); perror(specf); } else if (vflag) { (void) fprintf(stdout, "%s: %s %s ok\n", Myname, prioctl_to_str[IOCTL_NUM(op)], specf); }}/* * Return the number for the given string. * String should be either a decimal or a hex number. */intgetnum(str) char *str;{ int size; if (!isdigit(*str)) { usage(); /* NOTREACHED */ } if (str[0] == '0' && str[1] == 'x') { /* hex */ if (sscanf(&str[2], "%x", &size) == 0) { usage(); /* NOTREACHED */ } } else { /* decimal */ size = atoi(str); } return (size);}/* * openpr - Open the given pr device and return an fd. * Returns 0 if ok, -1 on error. */intopenpr(prname) char *prname;{ int ret; ret = open(prname, O_RDONLY|O_NDELAY, 0); if (ret < 0) { (void) fprintf(stderr, "%s: can't open `%s': ", Myname, prname); perror(""); } else if (vflag) { (void) fprintf(stdout, "%s: open `%s'\n", Myname, prname); } return (ret);}/* * get a valid RPC handle to the remote machine * Return 0 if not ok. */CLIENT *openclnt(name, verbose) char *name; int verbose;{#ifdef REMOTE struct sockaddr_in sin; struct hostent *hp; int sock; static CLIENT *clnt = NULL; static char oldname[MAXHOSTNAMELEN]; if (clnt != NULL) { /* same host as before ? */ if (strcmp(name, oldname) == 0) return (clnt); /* already created */ else clnt_destroy(clnt); } if (hp = gethostbyname(name)) (void) bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); else { fprintf(stderr,"%s: gethostbyname of %s failed\n", Myname, name); exit(1); } sin.sin_family = AF_INET; sin.sin_port=0; sock = RPC_ANYSOCK; clnt = clntudp_create(&sin, PRESTOCTLPROG, PRESTOCTLVERS, TIMEOUT, &sock); if (clnt != NULL) (void) strcpy(oldname, name); else if (verbose) { (void) fprintf(stdout, "%s: cannot reach machine %s\n", Myname, name); (void) clnt_pcreateerror(Myname); } return (clnt);#else REMOTE (void) fprintf(stderr, "Remote operation not supported\n"); return ((CLIENT *) NULL);#endif REMOTE}/* * getstatus * Returns 0 if ok, -1 on error. */intgetstatus(prfd, prstatus, clnt) int prfd; struct presto_status *prstatus; CLIENT *clnt;{ if (hflag) {#ifdef REMOTE register struct presto_modstat *ps; ps = prestoctl_getstate_3((void *)0, clnt); if (ps == 0) { (void) fprintf(stderr, "%s: PRGETSTATUS failed", Myname); clnt_perror(clnt, ""); return (-1); } if (! ps->ps_status) { (void) fprintf(stderr, "%s: PRGETSTATUS failed %s\n", Myname, ps->presto_modstat_u.ps_errmsg); return (-1); } if (vflag) { (void) fprintf(stdout, "%s: PRGETSTATUS ok\n", Myname); } *prstatus = ps->presto_modstat_u.ps_new;#endif /* REMOTE */ return (0); } else { int ret; ret = ioctl(prfd, PRGETSTATUS, prstatus); if (ret < 0) { (void) fprintf(stderr, "%s: PRGETSTATUS failed: ", Myname); perror(""); } else if (vflag) {/* (void) fprintf(stdout, "%s: PRGETSTATUS ok\n", Myname); */ } return (ret); }}/* * Perform op on all the enabled presto devices. */voidop_on_enabled(prfd, op) int prfd; int op;{ register int i; register struct prbits *enabled; int ret; dev_t dev; struct uprtab uprtab; for (uprtab.upt_bmajordev = NODEV;;) { if (ioctl(prfd, PRNEXTUPRTAB, &uprtab) < 0) { /* get next */ perror(prioctl_to_str[IOCTL_NUM(PRNEXTUPRTAB)]); return; } if (uprtab.upt_bmajordev == NODEV) /* got last one ? */ return; /* perform the op */ enabled = &uprtab.upt_enabled; for (i = 0; i < NBBY * sizeof (struct prbits); i++) { if (isset(enabled->bits, i)) { dev = makedev(uprtab.upt_bmajordev, i); ret = ioctl(prfd, op, &dev); if (ret < 0) { (void) fprintf(stderr, "%s: %s failed on dev (%d, %d): ", Myname, prioctl_to_str[IOCTL_NUM(op)], uprtab.upt_bmajordev, i); perror(""); return; } else if (vflag) { (void) fprintf(stdout, "%s: %s on dev (%d, %d)\n", Myname, prioctl_to_str[IOCTL_NUM(op)], uprtab.upt_bmajordev, i); } } } }}/* * setupdown * Set the presto state to down or up. * If we are to end up down (local case), * first disable all enabled filesystems. * Returns -1 if error, 0 otherwise. */intsetupdown(prfd, prstate, clnt, doall) int prfd; prstates prstate; /* PRUP or PRDOWN */ CLIENT *clnt; bool_t doall;{ if (hflag) {#ifdef REMOTE bool_t up = (prstate == PRUP); presto_modstat *res; res = prestoctl_toggle_3(&up, clnt); if (res == 0) { (void) fprintf(stderr, "%s: PRSETSTATE failed", Myname); clnt_perror(clnt, ""); return (-1); } if (! res->ps_status) { (void) fprintf(stderr, "%s: PRSETSTATE remote failure: %s\n", Myname, res->presto_modstat_u.ps_errmsg); return (-1); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?