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
  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
 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
 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 }