10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*633Sgt29601 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include <stdarg.h>
330Sstevel@tonic-gate #include <libintl.h>
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #include <sys/ioctl.h>
360Sstevel@tonic-gate #include <kstat.h>
370Sstevel@tonic-gate #include <locale.h>
380Sstevel@tonic-gate #include <sys/fs/cachefs_log.h>
390Sstevel@tonic-gate #include "stats.h"
400Sstevel@tonic-gate
410Sstevel@tonic-gate void usage(char *);
420Sstevel@tonic-gate void pr_err(char *, ...);
430Sstevel@tonic-gate
440Sstevel@tonic-gate static int hflag = 0;
450Sstevel@tonic-gate static char *fpath = NULL;
460Sstevel@tonic-gate static int vflag = 0;
470Sstevel@tonic-gate char *prog;
480Sstevel@tonic-gate
490Sstevel@tonic-gate static void log_show(char *, char *);
500Sstevel@tonic-gate
510Sstevel@tonic-gate int
main(int argc,char ** argv)520Sstevel@tonic-gate main(int argc, char **argv)
530Sstevel@tonic-gate {
540Sstevel@tonic-gate int rc = 0, c;
550Sstevel@tonic-gate int errflg = 0;
560Sstevel@tonic-gate stats_cookie_t *fs = NULL;
570Sstevel@tonic-gate char *logfile;
580Sstevel@tonic-gate
590Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
600Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
610Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
620Sstevel@tonic-gate #endif /* TEXT_DOMAIN */
630Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
640Sstevel@tonic-gate
650Sstevel@tonic-gate if (prog = strrchr(argv[0], '/'))
660Sstevel@tonic-gate ++prog;
670Sstevel@tonic-gate else
680Sstevel@tonic-gate prog = argv[0];
690Sstevel@tonic-gate
700Sstevel@tonic-gate while ((c = getopt(argc, argv, "hf:v")) != EOF)
710Sstevel@tonic-gate switch (c) {
720Sstevel@tonic-gate case 'h':
730Sstevel@tonic-gate if (fpath != NULL)
740Sstevel@tonic-gate ++errflg;
750Sstevel@tonic-gate else
760Sstevel@tonic-gate ++hflag;
770Sstevel@tonic-gate break;
780Sstevel@tonic-gate
790Sstevel@tonic-gate case 'f':
800Sstevel@tonic-gate if (hflag)
810Sstevel@tonic-gate ++errflg;
820Sstevel@tonic-gate else
830Sstevel@tonic-gate fpath = optarg;
840Sstevel@tonic-gate break;
850Sstevel@tonic-gate
860Sstevel@tonic-gate case 'v':
870Sstevel@tonic-gate ++vflag;
880Sstevel@tonic-gate break;
890Sstevel@tonic-gate
900Sstevel@tonic-gate case '?':
910Sstevel@tonic-gate default:
920Sstevel@tonic-gate ++errflg;
930Sstevel@tonic-gate break;
940Sstevel@tonic-gate }
950Sstevel@tonic-gate
960Sstevel@tonic-gate if ((errflg) || (optind != (argc - 1))) {
970Sstevel@tonic-gate usage(NULL);
980Sstevel@tonic-gate rc = -1;
990Sstevel@tonic-gate goto out;
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate fs = stats_create_mountpath(argv[optind], prog);
1030Sstevel@tonic-gate if (fs == NULL) {
1040Sstevel@tonic-gate pr_err(gettext("Cannot initialize cachefs library\n"));
1050Sstevel@tonic-gate rc = 1;
1060Sstevel@tonic-gate goto out;
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate if (! stats_good(fs)) {
1100Sstevel@tonic-gate pr_err(stats_errorstr(fs));
1110Sstevel@tonic-gate rc = stats_errno(fs);
1120Sstevel@tonic-gate goto out;
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate if ((logfile = stats_log_kernel_getname(fs)) == NULL) {
1160Sstevel@tonic-gate pr_err(stats_errorstr(fs));
1170Sstevel@tonic-gate rc = stats_errno(fs);
1180Sstevel@tonic-gate goto out;
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate if ((logfile[0] == '\0') && (hflag) && (! vflag)) {
1210Sstevel@tonic-gate log_show(argv[optind], logfile);
1220Sstevel@tonic-gate goto out;
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate if (fpath != NULL) {
1260Sstevel@tonic-gate if ((stats_log_kernel_setname(fs, fpath) != 0) ||
1270Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_MOUNT, 1) != 0) ||
1280Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_UMOUNT, 1) != 0) ||
1290Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_REMOVE, 1) != 0) ||
1300Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_RMDIR, 1) != 0) ||
1310Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_TRUNCATE, 1) != 0) ||
1320Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_CREATE, 1) != 0) ||
1330Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_MKDIR, 1) != 0) ||
1340Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_RENAME, 1) != 0) ||
1350Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_SYMLINK, 1) != 0) ||
1360Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_UALLOC, 1) != 0) ||
1370Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_CSYMLINK, 1) != 0) ||
1380Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_FILLDIR, 1) != 0) ||
1390Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_MDCREATE, 1) != 0) ||
1400Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_NOCACHE, 1) != 0) ||
1410Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_CALLOC, 1) != 0) ||
1420Sstevel@tonic-gate (stats_log_which(fs, CACHEFS_LOG_RFDIR, 1) != 0)) {
1430Sstevel@tonic-gate pr_err(stats_errorstr(fs));
1440Sstevel@tonic-gate rc = stats_errno(fs);
1450Sstevel@tonic-gate goto out;
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate } else if (hflag) {
1480Sstevel@tonic-gate if (stats_log_kernel_setname(fs, NULL) != 0) {
1490Sstevel@tonic-gate pr_err(stats_errorstr(fs));
1500Sstevel@tonic-gate rc = stats_errno(fs);
1510Sstevel@tonic-gate goto out;
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate if ((logfile = stats_log_kernel_getname(fs)) == NULL) {
1560Sstevel@tonic-gate pr_err(stats_errorstr(fs));
1570Sstevel@tonic-gate rc = stats_errno(fs);
1580Sstevel@tonic-gate goto out;
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate log_show(argv[optind], logfile);
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate /*
1640Sstevel@tonic-gate * if they're changing state, inform them of other filesystems
1650Sstevel@tonic-gate * that they're changing state for by way of sharing the
1660Sstevel@tonic-gate * cache.
1670Sstevel@tonic-gate *
1680Sstevel@tonic-gate * or, if they're verbose (-v flag), tell them about the
1690Sstevel@tonic-gate * others.
1700Sstevel@tonic-gate */
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate if (((fpath) || (hflag) || (vflag)) && (! stats_inerror(fs))) {
1730Sstevel@tonic-gate cachefs_kstat_key_t *k, *origk;
1740Sstevel@tonic-gate stats_cookie_t *sc;
1750Sstevel@tonic-gate int before = 0;
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate origk = stats_getkey(fs);
1780Sstevel@tonic-gate sc = stats_create_unbound(prog);
1790Sstevel@tonic-gate if (sc == NULL) {
1800Sstevel@tonic-gate pr_err(gettext("Cannot create stats object"));
1810Sstevel@tonic-gate rc = 1;
1820Sstevel@tonic-gate goto out;
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate while ((k = stats_next(sc)) != NULL) {
1860Sstevel@tonic-gate if (! k->ks_mounted) {
1870Sstevel@tonic-gate free(k);
1880Sstevel@tonic-gate continue;
1890Sstevel@tonic-gate }
190*633Sgt29601 if (strcmp((char *)(uintptr_t)origk->ks_cachedir,
191*633Sgt29601 (char *)(uintptr_t)k->ks_cachedir) != 0) {
1920Sstevel@tonic-gate free(k);
1930Sstevel@tonic-gate continue;
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate if (origk->ks_id == k->ks_id) {
1960Sstevel@tonic-gate free(k);
1970Sstevel@tonic-gate continue;
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate if (! before)
2000Sstevel@tonic-gate printf("\n");
2010Sstevel@tonic-gate before = 1;
202*633Sgt29601 log_show((char *)(uintptr_t)k->ks_mountpoint, logfile);
2030Sstevel@tonic-gate free(k);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate free(origk);
2060Sstevel@tonic-gate stats_destroy(sc);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate if (stats_inerror(fs)) {
2100Sstevel@tonic-gate pr_err(stats_errorstr(fs));
2110Sstevel@tonic-gate rc = stats_errno(fs);
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate out:
2150Sstevel@tonic-gate stats_destroy(fs);
2160Sstevel@tonic-gate return (rc);
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate static void
log_show(char * mount,char * logfile)2200Sstevel@tonic-gate log_show(char *mount, char *logfile)
2210Sstevel@tonic-gate {
2220Sstevel@tonic-gate if (logfile[0] == '\0')
2230Sstevel@tonic-gate logfile = gettext("not logged");
2240Sstevel@tonic-gate printf("%s: %s\n", logfile, mount);
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate /*
2280Sstevel@tonic-gate *
2290Sstevel@tonic-gate * usage
2300Sstevel@tonic-gate *
2310Sstevel@tonic-gate * Description:
2320Sstevel@tonic-gate * Prints a short usage message.
2330Sstevel@tonic-gate * Arguments:
2340Sstevel@tonic-gate * msgp message to include with the usage message
2350Sstevel@tonic-gate * Returns:
2360Sstevel@tonic-gate * Preconditions:
2370Sstevel@tonic-gate */
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate void
usage(char * msgp)2400Sstevel@tonic-gate usage(char *msgp)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate if (msgp) {
2430Sstevel@tonic-gate pr_err("%s", msgp);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate fprintf(stderr,
2470Sstevel@tonic-gate gettext("Usage: "
2480Sstevel@tonic-gate "cachefslog [ -v ] [-h | -f <logfile>] mountpoint\n"));
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate *
2530Sstevel@tonic-gate * pr_err
2540Sstevel@tonic-gate *
2550Sstevel@tonic-gate * Description:
2560Sstevel@tonic-gate * Prints an error message to stderr.
2570Sstevel@tonic-gate * Arguments:
2580Sstevel@tonic-gate * fmt printf style format
2590Sstevel@tonic-gate * ... arguments for fmt
2600Sstevel@tonic-gate * Returns:
2610Sstevel@tonic-gate * Preconditions:
2620Sstevel@tonic-gate * precond(fmt)
2630Sstevel@tonic-gate */
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate void
pr_err(char * fmt,...)2660Sstevel@tonic-gate pr_err(char *fmt, ...)
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate va_list ap;
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate va_start(ap, fmt);
2710Sstevel@tonic-gate (void) fprintf(stderr, gettext("cachefslog: "));
2720Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap);
2730Sstevel@tonic-gate (void) fprintf(stderr, "\n");
2740Sstevel@tonic-gate va_end(ap);
2750Sstevel@tonic-gate }
276