xref: /titanic_44/usr/src/cmd/fs.d/cachefs/cachefslog/cachefslog.c (revision 67e3a03ed4a2813074d36330f062ed6e593a4937)
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 2005 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 <string.h>
32 #include <stdarg.h>
33 #include <libintl.h>
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
36 #include <kstat.h>
37 #include <locale.h>
38 #include <sys/fs/cachefs_log.h>
39 #include "stats.h"
40 
41 void usage(char *);
42 void pr_err(char *, ...);
43 
44 static int hflag = 0;
45 static char *fpath = NULL;
46 static int vflag = 0;
47 char *prog;
48 
49 static void log_show(char *, char *);
50 
51 int
52 main(int argc, char **argv)
53 {
54 	int rc = 0, c;
55 	int errflg = 0;
56 	stats_cookie_t *fs = NULL;
57 	char *logfile;
58 
59 	(void) setlocale(LC_ALL, "");
60 #if !defined(TEXT_DOMAIN)
61 #define	TEXT_DOMAIN "SYS_TEST"
62 #endif /* TEXT_DOMAIN */
63 	(void) textdomain(TEXT_DOMAIN);
64 
65 	if (prog = strrchr(argv[0], '/'))
66 		++prog;
67 	else
68 		prog = argv[0];
69 
70 	while ((c = getopt(argc, argv, "hf:v")) != EOF)
71 		switch (c) {
72 		case 'h':
73 			if (fpath != NULL)
74 				++errflg;
75 			else
76 				++hflag;
77 			break;
78 
79 		case 'f':
80 			if (hflag)
81 				++errflg;
82 			else
83 				fpath = optarg;
84 			break;
85 
86 		case 'v':
87 			++vflag;
88 			break;
89 
90 		case '?':
91 		default:
92 			++errflg;
93 			break;
94 		}
95 
96 	if ((errflg) || (optind != (argc - 1))) {
97 		usage(NULL);
98 		rc = -1;
99 		goto out;
100 	}
101 
102 	fs = stats_create_mountpath(argv[optind], prog);
103 	if (fs == NULL) {
104 		pr_err(gettext("Cannot initialize cachefs library\n"));
105 		rc = 1;
106 		goto out;
107 	}
108 
109 	if (! stats_good(fs)) {
110 		pr_err(stats_errorstr(fs));
111 		rc = stats_errno(fs);
112 		goto out;
113 	}
114 
115 	if ((logfile = stats_log_kernel_getname(fs)) == NULL) {
116 		pr_err(stats_errorstr(fs));
117 		rc = stats_errno(fs);
118 		goto out;
119 	}
120 	if ((logfile[0] == '\0') && (hflag) && (! vflag)) {
121 		log_show(argv[optind], logfile);
122 		goto out;
123 	}
124 
125 	if (fpath != NULL) {
126 		if ((stats_log_kernel_setname(fs, fpath) != 0) ||
127 		    (stats_log_which(fs, CACHEFS_LOG_MOUNT, 1) != 0) ||
128 		    (stats_log_which(fs, CACHEFS_LOG_UMOUNT, 1) != 0) ||
129 		    (stats_log_which(fs, CACHEFS_LOG_REMOVE, 1) != 0) ||
130 		    (stats_log_which(fs, CACHEFS_LOG_RMDIR, 1) != 0) ||
131 		    (stats_log_which(fs, CACHEFS_LOG_TRUNCATE, 1) != 0) ||
132 		    (stats_log_which(fs, CACHEFS_LOG_CREATE, 1) != 0) ||
133 		    (stats_log_which(fs, CACHEFS_LOG_MKDIR, 1) != 0) ||
134 		    (stats_log_which(fs, CACHEFS_LOG_RENAME, 1) != 0) ||
135 		    (stats_log_which(fs, CACHEFS_LOG_SYMLINK, 1) != 0) ||
136 		    (stats_log_which(fs, CACHEFS_LOG_UALLOC, 1) != 0) ||
137 		    (stats_log_which(fs, CACHEFS_LOG_CSYMLINK, 1) != 0) ||
138 		    (stats_log_which(fs, CACHEFS_LOG_FILLDIR, 1) != 0) ||
139 		    (stats_log_which(fs, CACHEFS_LOG_MDCREATE, 1) != 0) ||
140 		    (stats_log_which(fs, CACHEFS_LOG_NOCACHE, 1) != 0) ||
141 		    (stats_log_which(fs, CACHEFS_LOG_CALLOC, 1) != 0) ||
142 		    (stats_log_which(fs, CACHEFS_LOG_RFDIR, 1) != 0)) {
143 			pr_err(stats_errorstr(fs));
144 			rc = stats_errno(fs);
145 			goto out;
146 		}
147 	} else if (hflag) {
148 		if (stats_log_kernel_setname(fs, NULL) != 0) {
149 			pr_err(stats_errorstr(fs));
150 			rc = stats_errno(fs);
151 			goto out;
152 		}
153 	}
154 
155 	if ((logfile = stats_log_kernel_getname(fs)) == NULL) {
156 		pr_err(stats_errorstr(fs));
157 		rc = stats_errno(fs);
158 		goto out;
159 	}
160 
161 	log_show(argv[optind], logfile);
162 
163 	/*
164 	 * if they're changing state, inform them of other filesystems
165 	 * that they're changing state for by way of sharing the
166 	 * cache.
167 	 *
168 	 * or, if they're verbose (-v flag), tell them about the
169 	 * others.
170 	 */
171 
172 	if (((fpath) || (hflag) || (vflag)) && (! stats_inerror(fs))) {
173 		cachefs_kstat_key_t *k, *origk;
174 		stats_cookie_t *sc;
175 		int before = 0;
176 
177 		origk = stats_getkey(fs);
178 		sc = stats_create_unbound(prog);
179 		if (sc == NULL) {
180 			pr_err(gettext("Cannot create stats object"));
181 			rc = 1;
182 			goto out;
183 		}
184 
185 		while ((k = stats_next(sc)) != NULL) {
186 			if (! k->ks_mounted) {
187 				free(k);
188 				continue;
189 			}
190 			if (strcmp((char *)(uintptr_t)origk->ks_cachedir,
191 				(char *)(uintptr_t)k->ks_cachedir) != 0) {
192 				free(k);
193 				continue;
194 			}
195 			if (origk->ks_id == k->ks_id) {
196 				free(k);
197 				continue;
198 			}
199 			if (! before)
200 				printf("\n");
201 			before = 1;
202 			log_show((char *)(uintptr_t)k->ks_mountpoint, logfile);
203 			free(k);
204 		}
205 		free(origk);
206 		stats_destroy(sc);
207 	}
208 
209 	if (stats_inerror(fs)) {
210 		pr_err(stats_errorstr(fs));
211 		rc = stats_errno(fs);
212 	}
213 
214 out:
215 	stats_destroy(fs);
216 	return (rc);
217 }
218 
219 static void
220 log_show(char *mount, char *logfile)
221 {
222 	if (logfile[0] == '\0')
223 		logfile = gettext("not logged");
224 	printf("%s: %s\n", logfile, mount);
225 }
226 
227 /*
228  *
229  *			usage
230  *
231  * Description:
232  *	Prints a short usage message.
233  * Arguments:
234  *	msgp	message to include with the usage message
235  * Returns:
236  * Preconditions:
237  */
238 
239 void
240 usage(char *msgp)
241 {
242 	if (msgp) {
243 		pr_err("%s", msgp);
244 	}
245 
246 	fprintf(stderr,
247 	    gettext("Usage: "
248 	    "cachefslog [ -v ] [-h | -f <logfile>] mountpoint\n"));
249 }
250 
251 /*
252  *
253  *			pr_err
254  *
255  * Description:
256  *	Prints an error message to stderr.
257  * Arguments:
258  *	fmt	printf style format
259  *	...	arguments for fmt
260  * Returns:
261  * Preconditions:
262  *	precond(fmt)
263  */
264 
265 void
266 pr_err(char *fmt, ...)
267 {
268 	va_list ap;
269 
270 	va_start(ap, fmt);
271 	(void) fprintf(stderr, gettext("cachefslog: "));
272 	(void) vfprintf(stderr, fmt, ap);
273 	(void) fprintf(stderr, "\n");
274 	va_end(ap);
275 }
276