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