1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <libintl.h>
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #include <kstat.h>
36 #include <sys/fs/cachefs_log.h>
37 #include <string.h>
38 #include <assert.h>
39 #include <ndbm.h>
40 #include <malloc.h>
41 #include <locale.h>
42 #include "stats.h"
43 
44 void usage(char *);
45 void pr_err(char *, ...);
46 
47 static int aflag = 0;
48 
49 int
main(int argc,char ** argv)50 main(int argc, char **argv)
51 {
52 	int rc = 0;
53 	int c, errflg = 0;
54 	int len1, len2;
55 	char *ar, *progname;
56 	void *record;
57 	caddr_t vfsp;
58 	char *path;
59 
60 	stats_cookie_t *sc = NULL;
61 
62 	datum key;
63 	struct cachefs_log_logfile_header *lh;
64 
65 	mount_info *mip;
66 
67 	(void) setlocale(LC_ALL, "");
68 #if !defined(TEXT_DOMAIN)
69 #define	TEXT_DOMAIN "SYS_TEST"
70 #endif /* TEXT_DOMAIN */
71 	(void) textdomain(TEXT_DOMAIN);
72 
73 	if (progname = strrchr(argv[0], '/'))
74 		++progname;
75 	else
76 		progname = argv[0];
77 
78 	if ((sc = stats_create_unbound(progname)) == NULL) {
79 		pr_err(gettext("Cannot initialize stats library\n"));
80 		rc = 1;
81 		goto out;
82 	}
83 
84 	while ((c = getopt(argc, argv, "a")) != EOF)
85 		switch (c) {
86 		case 'a':
87 			++aflag;
88 			break;
89 
90 		case '?':
91 		default:
92 			++errflg;
93 			break;
94 		}
95 
96 	if (errflg) {
97 		usage(NULL);
98 		rc = -1;
99 		goto out;
100 	}
101 
102 	path = argv[optind];
103 
104 	if (stats_log_logfile_open(sc, path) != 0) {
105 		pr_err(stats_errorstr(sc));
106 		rc = 1;
107 		goto out;
108 	}
109 	lh = stats_log_getheader(sc);
110 
111 	if (lh->lh_errno != 0)
112 		printf(gettext("warning: problem writing logfile: %s\n\n"),
113 		    strerror(lh->lh_errno));
114 
115 	if (aflag) {
116 		while (record = stats_log_logfile_read(sc, NULL)) {
117 			ar = stats_log_record_toascii(sc, record);
118 			if (ar == NULL)
119 				break;
120 			puts(ar);
121 			free(record);
122 		}
123 		if (stats_inerror(sc))
124 			pr_err(stats_errorstr(sc));
125 		goto out;
126 	}
127 
128 	stats_dbm_open(sc);
129 	stats_dbm_rm(sc);
130 	if (stats_inerror(sc)) {
131 		pr_err(stats_errorstr(sc));
132 		rc = stats_errno(sc);
133 		goto out;
134 	}
135 
136 	stats_log_compute_wssize(sc);
137 
138 	if (stats_inerror(sc)) {
139 		pr_err(stats_errorstr(sc));
140 		rc = stats_errno(sc);
141 		goto out;
142 	}
143 
144 	for (key = stats_dbm_firstkey(sc);
145 	    key.dptr != NULL;
146 	    key = stats_dbm_nextkey(sc)) {
147 		if (key.dsize != sizeof (vfsp))
148 			continue;
149 
150 		memcpy((caddr_t) &vfsp, key.dptr, sizeof (vfsp));
151 		mip = stats_dbm_fetch_byvfsp(sc, vfsp);
152 		if (mip == NULL)
153 			continue;
154 		if (! mip->mi_used)
155 			continue;
156 
157 		printf("\n    %s\n", mip->mi_path);
158 		if (! mip->mi_mounted)
159 			printf("    (currently unmounted)\n");
160 		printf("\t       end size: %17lldk\n", mip->mi_current / 1024);
161 		printf("\thigh water size: %17lldk\n", mip->mi_high / 1024);
162 		free(mip);
163 	}
164 
165 	printf(gettext("\n    total for cache\n"));
166 	printf(gettext("\t   initial size: %17lldk\n"),
167 	    (u_offset_t)(stats_log_wssize_init(sc) *
168 		lh->lh_maxbsize / (u_offset_t) 1024));
169 	printf(gettext("\t       end size: %17lldk\n"),
170 	    (u_offset_t)(stats_log_wssize_current(sc) / 1024));
171 	printf(gettext("\thigh water size: %17lldk\n"),
172 	    (u_offset_t)(stats_log_wssize_high(sc) / 1024));
173 
174 	if (stats_inerror(sc)) {
175 		pr_err(stats_errorstr(sc));
176 		rc = stats_errno(sc);
177 	}
178 
179 out:
180 	stats_dbm_close(sc);
181 	stats_destroy(sc);
182 
183 	return (rc);
184 }
185 
186 /*
187  *
188  *			usage
189  *
190  * Description:
191  *	Prints a short usage message.
192  * Arguments:
193  *	msgp	message to include with the usage message
194  * Returns:
195  * Preconditions:
196  */
197 
198 void
usage(char * msgp)199 usage(char *msgp)
200 {
201 	if (msgp) {
202 		pr_err("%s", msgp);
203 	}
204 
205 	fprintf(stderr,
206 	    gettext("Usage: cachefswssize logfile\n"));
207 }
208 
209 /*
210  *
211  *			pr_err
212  *
213  * Description:
214  *	Prints an error message to stderr.
215  * Arguments:
216  *	fmt	printf style format
217  *	...	arguments for fmt
218  * Returns:
219  * Preconditions:
220  *	precond(fmt)
221  */
222 
223 void
pr_err(char * fmt,...)224 pr_err(char *fmt, ...)
225 {
226 	va_list ap;
227 
228 	va_start(ap, fmt);
229 	(void) fprintf(stderr, gettext("cachefswssize: "));
230 	(void) vfprintf(stderr, fmt, ap);
231 	(void) fprintf(stderr, "\n");
232 	va_end(ap);
233 }
234