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