1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte /* 22*570de38fSSurya Prakki * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23fcf3ce44SJohn Forte * Use is subject to license terms. 24fcf3ce44SJohn Forte */ 25fcf3ce44SJohn Forte 26fcf3ce44SJohn Forte #include <stdio.h> 27fcf3ce44SJohn Forte #include <stdlib.h> 28fcf3ce44SJohn Forte #include <string.h> 29fcf3ce44SJohn Forte #include <unistd.h> 30fcf3ce44SJohn Forte #include <errno.h> 31fcf3ce44SJohn Forte #include <inttypes.h> 32fcf3ce44SJohn Forte 33fcf3ce44SJohn Forte #include <kstat.h> 34fcf3ce44SJohn Forte 35fcf3ce44SJohn Forte #include <sys/nsctl/nsctl.h> 36fcf3ce44SJohn Forte #include <sys/nsctl/sd_bcache.h> 37fcf3ce44SJohn Forte 38fcf3ce44SJohn Forte #include "sdbc_stats.h" 39fcf3ce44SJohn Forte 40fcf3ce44SJohn Forte #include "dsstat.h" 41fcf3ce44SJohn Forte #include "common.h" 42fcf3ce44SJohn Forte #include "report.h" 43fcf3ce44SJohn Forte 44fcf3ce44SJohn Forte static sdbcstat_t *sdbc_top; 45fcf3ce44SJohn Forte kstat_t *sdbc_global = NULL; 46fcf3ce44SJohn Forte 47fcf3ce44SJohn Forte void sdbc_header(); 48fcf3ce44SJohn Forte int sdbc_value_check(sdbcstat_t *); 49fcf3ce44SJohn Forte int sdbc_validate(kstat_t *); 50fcf3ce44SJohn Forte uint32_t sdbc_getdelta(sdbcstat_t *, char *); 51fcf3ce44SJohn Forte 52fcf3ce44SJohn Forte void sdbc_addstat(sdbcstat_t *); 53fcf3ce44SJohn Forte sdbcstat_t *sdbc_delstat(sdbcstat_t *); 54fcf3ce44SJohn Forte void center(int, char *); 55fcf3ce44SJohn Forte 56fcf3ce44SJohn Forte /* 57fcf3ce44SJohn Forte * sdbc_discover() - looks for new statistics to be monitored. 58fcf3ce44SJohn Forte * Verifies that any statistics found are now already being 59fcf3ce44SJohn Forte * monitored. 60fcf3ce44SJohn Forte * 61fcf3ce44SJohn Forte */ 62fcf3ce44SJohn Forte int 63fcf3ce44SJohn Forte sdbc_discover(kstat_ctl_t *kc) 64fcf3ce44SJohn Forte { 65fcf3ce44SJohn Forte static int validated = 0; 66fcf3ce44SJohn Forte 67fcf3ce44SJohn Forte kstat_t *ksp; 68fcf3ce44SJohn Forte 69fcf3ce44SJohn Forte for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 70fcf3ce44SJohn Forte int kinst; 71fcf3ce44SJohn Forte char kname[KSTAT_STRLEN + 1]; 72fcf3ce44SJohn Forte sdbcstat_t *cur; 73fcf3ce44SJohn Forte sdbcstat_t *sdbcstat = NULL; 74fcf3ce44SJohn Forte kstat_t *io_ksp; 75fcf3ce44SJohn Forte 76fcf3ce44SJohn Forte if (strcmp(ksp->ks_module, SDBC_KSTAT_MODULE) != 0 || 77fcf3ce44SJohn Forte strncmp(ksp->ks_name, SDBC_KSTAT_CDSTATS, 2) != 0) 78fcf3ce44SJohn Forte continue; 79fcf3ce44SJohn Forte 80fcf3ce44SJohn Forte if (kstat_read(kc, ksp, NULL) == -1) 81fcf3ce44SJohn Forte continue; 82fcf3ce44SJohn Forte 83fcf3ce44SJohn Forte /* 84fcf3ce44SJohn Forte * Validate kstat structure 85fcf3ce44SJohn Forte */ 86fcf3ce44SJohn Forte if (! validated) { 87fcf3ce44SJohn Forte if (sdbc_validate(ksp)) 88fcf3ce44SJohn Forte return (EINVAL); 89fcf3ce44SJohn Forte 90fcf3ce44SJohn Forte validated++; 91fcf3ce44SJohn Forte } 92fcf3ce44SJohn Forte 93fcf3ce44SJohn Forte /* 94fcf3ce44SJohn Forte * Duplicate check 95fcf3ce44SJohn Forte */ 96fcf3ce44SJohn Forte for (cur = sdbc_top; cur; cur = cur->next) { 97fcf3ce44SJohn Forte char *cur_vname, *tst_vname; 98fcf3ce44SJohn Forte 99fcf3ce44SJohn Forte cur_vname = kstat_value(cur->pre_set, 100fcf3ce44SJohn Forte SDBC_CDKSTAT_VOL_NAME); 101fcf3ce44SJohn Forte 102fcf3ce44SJohn Forte tst_vname = kstat_value(ksp, 103fcf3ce44SJohn Forte SDBC_CDKSTAT_VOL_NAME); 104fcf3ce44SJohn Forte 105fcf3ce44SJohn Forte if (strncmp(cur_vname, tst_vname, NAMED_LEN) == 0) 106fcf3ce44SJohn Forte goto next; 107fcf3ce44SJohn Forte } 108fcf3ce44SJohn Forte 109fcf3ce44SJohn Forte /* 110fcf3ce44SJohn Forte * Initialize new record 111fcf3ce44SJohn Forte */ 112fcf3ce44SJohn Forte sdbcstat = (sdbcstat_t *)calloc(1, sizeof (sdbcstat_t)); 113fcf3ce44SJohn Forte 114fcf3ce44SJohn Forte kinst = ksp->ks_instance; 115fcf3ce44SJohn Forte 116fcf3ce44SJohn Forte /* 117fcf3ce44SJohn Forte * Set kstat 118fcf3ce44SJohn Forte */ 119fcf3ce44SJohn Forte sdbcstat->pre_set = kstat_retrieve(kc, ksp); 120fcf3ce44SJohn Forte 121fcf3ce44SJohn Forte if (sdbcstat->pre_set == NULL) 122fcf3ce44SJohn Forte goto next; 123fcf3ce44SJohn Forte 124fcf3ce44SJohn Forte sdbcstat->collected |= GOT_SET_KSTAT; 125fcf3ce44SJohn Forte 126fcf3ce44SJohn Forte /* 127fcf3ce44SJohn Forte * I/O kstat 128fcf3ce44SJohn Forte */ 129*570de38fSSurya Prakki (void) sprintf(kname, "%s%d", SDBC_IOKSTAT_CDSTATS, kinst); 130fcf3ce44SJohn Forte 131fcf3ce44SJohn Forte io_ksp = kstat_lookup(kc, SDBC_KSTAT_MODULE, kinst, kname); 132fcf3ce44SJohn Forte sdbcstat->pre_io = kstat_retrieve(kc, io_ksp); 133fcf3ce44SJohn Forte 134fcf3ce44SJohn Forte if (sdbcstat->pre_io == NULL) 135fcf3ce44SJohn Forte goto next; 136fcf3ce44SJohn Forte 137fcf3ce44SJohn Forte sdbcstat->collected |= GOT_IO_KSTAT; 138fcf3ce44SJohn Forte 139fcf3ce44SJohn Forte next: 140fcf3ce44SJohn Forte /* 141fcf3ce44SJohn Forte * Check if we got a complete set of stats 142fcf3ce44SJohn Forte */ 143fcf3ce44SJohn Forte if (sdbcstat == NULL) 144fcf3ce44SJohn Forte continue; 145fcf3ce44SJohn Forte 146fcf3ce44SJohn Forte if (SDBC_COMPLETE(sdbcstat->collected)) { 147fcf3ce44SJohn Forte (void) sdbc_delstat(sdbcstat); 148fcf3ce44SJohn Forte continue; 149fcf3ce44SJohn Forte } 150fcf3ce44SJohn Forte 151fcf3ce44SJohn Forte sdbc_addstat(sdbcstat); 152fcf3ce44SJohn Forte } 153fcf3ce44SJohn Forte 154fcf3ce44SJohn Forte if (sdbc_top == NULL) 155fcf3ce44SJohn Forte return (EAGAIN); 156fcf3ce44SJohn Forte 157fcf3ce44SJohn Forte return (0); 158fcf3ce44SJohn Forte } 159fcf3ce44SJohn Forte 160fcf3ce44SJohn Forte /* 161fcf3ce44SJohn Forte * sdbc_update() - updates all of the statistics currently being monitored. 162fcf3ce44SJohn Forte * 163fcf3ce44SJohn Forte */ 164fcf3ce44SJohn Forte int 165fcf3ce44SJohn Forte sdbc_update(kstat_ctl_t *kc) 166fcf3ce44SJohn Forte { 167fcf3ce44SJohn Forte kstat_t *ksp; 168fcf3ce44SJohn Forte sdbcstat_t *cur; 169fcf3ce44SJohn Forte 170fcf3ce44SJohn Forte /* Update global kstat information */ 171fcf3ce44SJohn Forte ksp = kstat_lookup(kc, SDBC_KSTAT_MODULE, -1, SDBC_KSTAT_GSTATS); 172fcf3ce44SJohn Forte 173fcf3ce44SJohn Forte if (ksp == NULL) 174fcf3ce44SJohn Forte return (EAGAIN); 175fcf3ce44SJohn Forte 176fcf3ce44SJohn Forte if (sdbc_global) 177fcf3ce44SJohn Forte kstat_free(sdbc_global); 178fcf3ce44SJohn Forte 179fcf3ce44SJohn Forte sdbc_global = kstat_retrieve(kc, ksp); 180fcf3ce44SJohn Forte 181fcf3ce44SJohn Forte for (cur = sdbc_top; cur != NULL; cur = cur->next) { 182fcf3ce44SJohn Forte int kinst; 183fcf3ce44SJohn Forte char *kname, *cname, *pname; 184fcf3ce44SJohn Forte 185fcf3ce44SJohn Forte kstat_t *set_ksp, *io_ksp; 186fcf3ce44SJohn Forte 187fcf3ce44SJohn Forte cur->collected = 0; 188fcf3ce44SJohn Forte 189fcf3ce44SJohn Forte /* 190fcf3ce44SJohn Forte * Age off old stats 191fcf3ce44SJohn Forte */ 192fcf3ce44SJohn Forte if (cur->cur_set != NULL) { 193fcf3ce44SJohn Forte kstat_free(cur->pre_set); 194fcf3ce44SJohn Forte kstat_free(cur->pre_io); 195fcf3ce44SJohn Forte 196fcf3ce44SJohn Forte cur->pre_set = cur->cur_set; 197fcf3ce44SJohn Forte cur->pre_io = cur->cur_io; 198fcf3ce44SJohn Forte } 199fcf3ce44SJohn Forte 200fcf3ce44SJohn Forte /* 201fcf3ce44SJohn Forte * Update set kstat 202fcf3ce44SJohn Forte */ 203fcf3ce44SJohn Forte kinst = cur->pre_set->ks_instance; 204fcf3ce44SJohn Forte kname = cur->pre_set->ks_name; 205fcf3ce44SJohn Forte 206fcf3ce44SJohn Forte set_ksp = kstat_lookup(kc, SDBC_KSTAT_MODULE, kinst, kname); 207fcf3ce44SJohn Forte 208fcf3ce44SJohn Forte if ((cur->cur_set = kstat_retrieve(kc, set_ksp)) == NULL) 209fcf3ce44SJohn Forte continue; 210fcf3ce44SJohn Forte 211fcf3ce44SJohn Forte cur->collected |= GOT_SET_KSTAT; 212fcf3ce44SJohn Forte 213fcf3ce44SJohn Forte /* 214fcf3ce44SJohn Forte * Validate set 215fcf3ce44SJohn Forte */ 216fcf3ce44SJohn Forte pname = kstat_value(cur->pre_set, SDBC_CDKSTAT_VOL_NAME); 217fcf3ce44SJohn Forte cname = kstat_value(cur->cur_set, SDBC_CDKSTAT_VOL_NAME); 218fcf3ce44SJohn Forte 219fcf3ce44SJohn Forte if (strncmp(pname, cname, NAMED_LEN) != 0) 220fcf3ce44SJohn Forte continue; 221fcf3ce44SJohn Forte 222fcf3ce44SJohn Forte /* 223fcf3ce44SJohn Forte * Update I/O kstat 224fcf3ce44SJohn Forte */ 225fcf3ce44SJohn Forte kinst = cur->pre_io->ks_instance; 226fcf3ce44SJohn Forte kname = cur->pre_io->ks_name; 227fcf3ce44SJohn Forte 228fcf3ce44SJohn Forte io_ksp = kstat_lookup(kc, SDBC_KSTAT_MODULE, kinst, kname); 229fcf3ce44SJohn Forte 230fcf3ce44SJohn Forte if ((cur->cur_io = kstat_retrieve(kc, io_ksp)) == NULL) 231fcf3ce44SJohn Forte continue; 232fcf3ce44SJohn Forte 233fcf3ce44SJohn Forte cur->collected |= GOT_IO_KSTAT; 234fcf3ce44SJohn Forte } 235fcf3ce44SJohn Forte 236fcf3ce44SJohn Forte return (0); 237fcf3ce44SJohn Forte } 238fcf3ce44SJohn Forte 239fcf3ce44SJohn Forte /* 240fcf3ce44SJohn Forte * sdbc_report() - outputs statistics for the statistics currently being 241fcf3ce44SJohn Forte * monitored. Deletes statistics for volumes that have been disabled. 242fcf3ce44SJohn Forte * 243fcf3ce44SJohn Forte */ 244fcf3ce44SJohn Forte int 245fcf3ce44SJohn Forte sdbc_report() 246fcf3ce44SJohn Forte { 247fcf3ce44SJohn Forte vslist_t *vslist = vs_top; 248fcf3ce44SJohn Forte sdbcstat_t *cur, *pre = NULL; 249fcf3ce44SJohn Forte 250fcf3ce44SJohn Forte if (sdbc_top == NULL) 251fcf3ce44SJohn Forte return (0); 252fcf3ce44SJohn Forte 253fcf3ce44SJohn Forte for (cur = sdbc_top; cur != NULL; ) { /* CSTYLED */ 254fcf3ce44SJohn Forte static uint32_t linesout = 0; 255fcf3ce44SJohn Forte uint32_t *offline; 256fcf3ce44SJohn Forte 257fcf3ce44SJohn Forte char volname[NAMED_LEN + 1]; 258fcf3ce44SJohn Forte char rmode[STAT_HDR_SIZE]; 259fcf3ce44SJohn Forte char wmode[STAT_HDR_SIZE]; 260fcf3ce44SJohn Forte 261fcf3ce44SJohn Forte /* Parse volume name */ 262*570de38fSSurya Prakki (void) strncpy(volname, kstat_value(cur->pre_set, 263fcf3ce44SJohn Forte SDBC_CDKSTAT_VOL_NAME), NAMED_LEN); 264fcf3ce44SJohn Forte volname[NAMED_LEN] = '\0'; 265fcf3ce44SJohn Forte 266fcf3ce44SJohn Forte /* Check to see if the user specified this volume */ 267fcf3ce44SJohn Forte for (vslist = vs_top; vslist != NULL; vslist = vslist->next) 268fcf3ce44SJohn Forte if (strcmp(volname, vslist->volname) == 0) 269fcf3ce44SJohn Forte break; 270fcf3ce44SJohn Forte 271fcf3ce44SJohn Forte if (vs_top != NULL && vslist == NULL) 272fcf3ce44SJohn Forte goto next; 273fcf3ce44SJohn Forte 274fcf3ce44SJohn Forte /* Check if volume is offline and zflag applies */ 275fcf3ce44SJohn Forte if (zflag && sdbc_value_check(cur) == 0) 276fcf3ce44SJohn Forte goto next; 277fcf3ce44SJohn Forte 278fcf3ce44SJohn Forte /* Output volume name */ 279fcf3ce44SJohn Forte sdbc_header(); 280fcf3ce44SJohn Forte 281fcf3ce44SJohn Forte (void) printf(DATA_C16, volname); 282fcf3ce44SJohn Forte 283fcf3ce44SJohn Forte if (SDBC_COMPLETE(cur->collected)) { 284fcf3ce44SJohn Forte sdbcstat_t *next = sdbc_delstat(cur); 285fcf3ce44SJohn Forte 286fcf3ce44SJohn Forte if (! pre) 287fcf3ce44SJohn Forte cur = sdbc_top = next; 288fcf3ce44SJohn Forte else 289fcf3ce44SJohn Forte cur = pre->next = next; 290fcf3ce44SJohn Forte 291fcf3ce44SJohn Forte (void) printf(" <<volume disabled>>\n"); 292fcf3ce44SJohn Forte continue; 293fcf3ce44SJohn Forte } 294fcf3ce44SJohn Forte 295fcf3ce44SJohn Forte offline = kstat_value(cur->cur_set, SDBC_CDKSTAT_FAILED); 296fcf3ce44SJohn Forte if (*offline) { 297fcf3ce44SJohn Forte (void) printf(" <<volume offline>>\n"); 298fcf3ce44SJohn Forte linesout++; 299fcf3ce44SJohn Forte goto next; 300fcf3ce44SJohn Forte } 301fcf3ce44SJohn Forte 302fcf3ce44SJohn Forte /* Type/status flags */ 303fcf3ce44SJohn Forte if (dflags & FLAGS) { 304fcf3ce44SJohn Forte 305fcf3ce44SJohn Forte uint32_t *dhint, *nhint; 306fcf3ce44SJohn Forte uint32_t hints; 307fcf3ce44SJohn Forte 308fcf3ce44SJohn Forte dhint = kstat_value(cur->cur_set, SDBC_CDKSTAT_CDHINTS); 309fcf3ce44SJohn Forte nhint = kstat_value(sdbc_global, SDBC_GKSTAT_NODEHINTS); 310fcf3ce44SJohn Forte 311fcf3ce44SJohn Forte if (! nhint) 312fcf3ce44SJohn Forte return (EINVAL); 313fcf3ce44SJohn Forte 314fcf3ce44SJohn Forte hints = *nhint; 315fcf3ce44SJohn Forte hints &= (NSC_FORCED_WRTHRU | NSC_NO_FORCED_WRTHRU | 316fcf3ce44SJohn Forte NSC_NOCACHE); 317fcf3ce44SJohn Forte hints |= *dhint; 318fcf3ce44SJohn Forte 319fcf3ce44SJohn Forte if (hints & NSC_NOCACHE) 320fcf3ce44SJohn Forte (void) strcpy(rmode, "D"); 321fcf3ce44SJohn Forte else 322fcf3ce44SJohn Forte (void) strcpy(rmode, "C"); 323fcf3ce44SJohn Forte 324fcf3ce44SJohn Forte if ((hints & NSC_FORCED_WRTHRU) || (hints & NSC_WRTHRU)) 325fcf3ce44SJohn Forte (void) strcpy(wmode, "D"); 326fcf3ce44SJohn Forte else 327fcf3ce44SJohn Forte (void) strcpy(wmode, "C"); 328fcf3ce44SJohn Forte 329fcf3ce44SJohn Forte (void) printf(DATA_C2, rmode); 330fcf3ce44SJohn Forte (void) printf(DATA_C2, wmode); 331fcf3ce44SJohn Forte } 332fcf3ce44SJohn Forte 333fcf3ce44SJohn Forte /* Output set information */ 334fcf3ce44SJohn Forte cd_report(cur); 335fcf3ce44SJohn Forte 336fcf3ce44SJohn Forte next: 337fcf3ce44SJohn Forte pre = cur; 338fcf3ce44SJohn Forte cur = cur->next; 339fcf3ce44SJohn Forte } 340fcf3ce44SJohn Forte 341fcf3ce44SJohn Forte return (0); 342fcf3ce44SJohn Forte } 343fcf3ce44SJohn Forte 344fcf3ce44SJohn Forte /* 345fcf3ce44SJohn Forte * sdbc_header() - outputs an appropriate header by referencing the 346fcf3ce44SJohn Forte * global variables dflsgs 347fcf3ce44SJohn Forte * 348fcf3ce44SJohn Forte */ 349fcf3ce44SJohn Forte void 350fcf3ce44SJohn Forte sdbc_header() 351fcf3ce44SJohn Forte { 352fcf3ce44SJohn Forte int rcount = 0; 353fcf3ce44SJohn Forte 354fcf3ce44SJohn Forte if (hflags == HEADERS_EXL) 355fcf3ce44SJohn Forte if ((linesout % DISPLAY_LINES) != 0) 356fcf3ce44SJohn Forte return; 357fcf3ce44SJohn Forte 358fcf3ce44SJohn Forte if (hflags == HEADERS_BOR) 359fcf3ce44SJohn Forte if (linesout != 0) 360fcf3ce44SJohn Forte return; 361fcf3ce44SJohn Forte 362fcf3ce44SJohn Forte if (hflags & HEADERS_ATT) 363fcf3ce44SJohn Forte if (hflags & HEADERS_OUT) 364fcf3ce44SJohn Forte return; 365fcf3ce44SJohn Forte else 366fcf3ce44SJohn Forte hflags |= HEADERS_OUT; 367fcf3ce44SJohn Forte 368fcf3ce44SJohn Forte if (linesout) 369*570de38fSSurya Prakki (void) printf("\n"); 370fcf3ce44SJohn Forte 371fcf3ce44SJohn Forte /* first line header */ 372fcf3ce44SJohn Forte if (! (dflags & SUMMARY) && dflags != FLAGS) { 373fcf3ce44SJohn Forte 374fcf3ce44SJohn Forte (void) printf(VOL_HDR_FMT, " "); 375fcf3ce44SJohn Forte 376fcf3ce44SJohn Forte if (dflags & FLAGS) { 377fcf3ce44SJohn Forte (void) printf(STAT_HDR_FMT, " "); 378fcf3ce44SJohn Forte (void) printf(STAT_HDR_FMT, " "); 379fcf3ce44SJohn Forte } 380fcf3ce44SJohn Forte 381fcf3ce44SJohn Forte if (dflags & READ) { 382fcf3ce44SJohn Forte int size; 383fcf3ce44SJohn Forte 384fcf3ce44SJohn Forte size = KPS_HDR_SIZE * 2 + HIT_HDR_SIZE; 385fcf3ce44SJohn Forte center(size, "- read -"); 386fcf3ce44SJohn Forte rcount++; 387fcf3ce44SJohn Forte } 388fcf3ce44SJohn Forte 389fcf3ce44SJohn Forte if (dflags & WRITE) { 390fcf3ce44SJohn Forte int size; 391fcf3ce44SJohn Forte 392fcf3ce44SJohn Forte size = KPS_HDR_SIZE * 2 + HIT_HDR_SIZE; 393fcf3ce44SJohn Forte center(size, "- write -"); 394fcf3ce44SJohn Forte rcount++; 395fcf3ce44SJohn Forte } 396fcf3ce44SJohn Forte 397fcf3ce44SJohn Forte if (dflags != FLAGS) 398fcf3ce44SJohn Forte (void) printf("\n"); 399fcf3ce44SJohn Forte } 400fcf3ce44SJohn Forte 401fcf3ce44SJohn Forte /* second line header */ 402fcf3ce44SJohn Forte (void) printf(VOL_HDR_FMT, "volume"); 403fcf3ce44SJohn Forte 404fcf3ce44SJohn Forte if (dflags & FLAGS) { 405fcf3ce44SJohn Forte (void) printf(STAT_HDR_FMT, "rd"); 406fcf3ce44SJohn Forte (void) printf(STAT_HDR_FMT, "wr"); 407fcf3ce44SJohn Forte } 408fcf3ce44SJohn Forte 409fcf3ce44SJohn Forte if (dflags & SUMMARY) { 410fcf3ce44SJohn Forte (void) printf(KPS_HDR_FMT, "ckps"); 411fcf3ce44SJohn Forte (void) printf(KPS_HDR_FMT, "dkps"); 412fcf3ce44SJohn Forte (void) printf(HIT_HDR_FMT, HIT_HDR_TXT); 413fcf3ce44SJohn Forte 414fcf3ce44SJohn Forte goto out; 415fcf3ce44SJohn Forte } 416fcf3ce44SJohn Forte 417fcf3ce44SJohn Forte if (dflags & READ) { 418fcf3ce44SJohn Forte (void) printf(KPS_HDR_FMT, "ckps"); 419fcf3ce44SJohn Forte (void) printf(KPS_HDR_FMT, "dkps"); 420fcf3ce44SJohn Forte (void) printf(HIT_HDR_FMT, RHIT_HDR_TXT); 421fcf3ce44SJohn Forte } 422fcf3ce44SJohn Forte 423fcf3ce44SJohn Forte if (dflags & WRITE) { 424fcf3ce44SJohn Forte (void) printf(KPS_HDR_FMT, "ckps"); 425fcf3ce44SJohn Forte (void) printf(KPS_HDR_FMT, "dkps"); 426fcf3ce44SJohn Forte (void) printf(HIT_HDR_FMT, WHIT_HDR_TXT); 427fcf3ce44SJohn Forte } 428fcf3ce44SJohn Forte 429fcf3ce44SJohn Forte if (dflags & DESTAGED) 430fcf3ce44SJohn Forte (void) printf(KPS_HDR_FMT, "dstg"); 431fcf3ce44SJohn Forte 432fcf3ce44SJohn Forte if (dflags & WRCANCEL) 433fcf3ce44SJohn Forte (void) printf(KPS_HDR_FMT, "cwrl"); 434fcf3ce44SJohn Forte 435fcf3ce44SJohn Forte out: 436fcf3ce44SJohn Forte (void) printf("\n"); 437fcf3ce44SJohn Forte } 438fcf3ce44SJohn Forte 439fcf3ce44SJohn Forte /* 440fcf3ce44SJohn Forte * sdbc_getstat() - find cache stat by name matching 441fcf3ce44SJohn Forte * 442fcf3ce44SJohn Forte * paraemters 443fcf3ce44SJohn Forte * char *vn - the volume name to match against 444fcf3ce44SJohn Forte * returns 445fcf3ce44SJohn Forte * sdbcstat_t * - the matching strcture, NULL if not found 446fcf3ce44SJohn Forte */ 447fcf3ce44SJohn Forte sdbcstat_t * 448fcf3ce44SJohn Forte sdbc_getstat(char *vn) 449fcf3ce44SJohn Forte { 450fcf3ce44SJohn Forte sdbcstat_t *cur, *pre = NULL; 451fcf3ce44SJohn Forte 452fcf3ce44SJohn Forte for (cur = sdbc_top; cur; ) { /* CSTYLED */ 453fcf3ce44SJohn Forte char *volname = 454fcf3ce44SJohn Forte kstat_value(cur->pre_set, SDBC_CDKSTAT_VOL_NAME); 455fcf3ce44SJohn Forte 456fcf3ce44SJohn Forte if (SDBC_COMPLETE(cur->collected)) { 457fcf3ce44SJohn Forte sdbcstat_t *next = sdbc_delstat(cur); 458fcf3ce44SJohn Forte 459fcf3ce44SJohn Forte if (! pre) 460fcf3ce44SJohn Forte cur = sdbc_top = next; 461fcf3ce44SJohn Forte else 462fcf3ce44SJohn Forte cur = pre->next = next; 463fcf3ce44SJohn Forte 464fcf3ce44SJohn Forte continue; 465fcf3ce44SJohn Forte } 466fcf3ce44SJohn Forte 467fcf3ce44SJohn Forte if (strncmp(volname, vn, NAMED_LEN) == 0) 468fcf3ce44SJohn Forte return (cur); 469fcf3ce44SJohn Forte 470fcf3ce44SJohn Forte pre = cur; 471fcf3ce44SJohn Forte cur = cur->next; 472fcf3ce44SJohn Forte } 473fcf3ce44SJohn Forte 474fcf3ce44SJohn Forte return (NULL); 475fcf3ce44SJohn Forte } 476fcf3ce44SJohn Forte 477fcf3ce44SJohn Forte /* 478fcf3ce44SJohn Forte * sdbc_addstat() - adds a fully populated sdbcstat_t structure 479fcf3ce44SJohn Forte * to the linked list of currently monitored kstats. The structure 480fcf3ce44SJohn Forte * will be added in alphabetical order, using the volume name as the 481fcf3ce44SJohn Forte * key. 482fcf3ce44SJohn Forte * 483fcf3ce44SJohn Forte * parameters 484fcf3ce44SJohn Forte * sdbcstat_t *sdbcstat - to be added to the list. 485fcf3ce44SJohn Forte * 486fcf3ce44SJohn Forte */ 487fcf3ce44SJohn Forte void 488fcf3ce44SJohn Forte sdbc_addstat(sdbcstat_t *sdbcstat) 489fcf3ce44SJohn Forte { 490fcf3ce44SJohn Forte sdbcstat_t *cur; 491fcf3ce44SJohn Forte 492fcf3ce44SJohn Forte if (sdbc_top == NULL) { 493fcf3ce44SJohn Forte sdbc_top = sdbcstat; 494fcf3ce44SJohn Forte return; 495fcf3ce44SJohn Forte } 496fcf3ce44SJohn Forte 497fcf3ce44SJohn Forte for (cur = sdbc_top; cur != NULL; cur = cur->next) { 498fcf3ce44SJohn Forte char *cur_vname, *nxt_vname, *tst_vname; 499fcf3ce44SJohn Forte 500fcf3ce44SJohn Forte cur_vname = kstat_value(cur->pre_set, 501fcf3ce44SJohn Forte SDBC_CDKSTAT_VOL_NAME); 502fcf3ce44SJohn Forte tst_vname = kstat_value(sdbcstat->pre_set, 503fcf3ce44SJohn Forte SDBC_CDKSTAT_VOL_NAME); 504fcf3ce44SJohn Forte 505fcf3ce44SJohn Forte if (strncmp(cur_vname, tst_vname, NAMED_LEN) > 0) { 506fcf3ce44SJohn Forte if (cur == sdbc_top) 507fcf3ce44SJohn Forte sdbc_top = sdbcstat; 508fcf3ce44SJohn Forte 509fcf3ce44SJohn Forte sdbcstat->next = cur; 510fcf3ce44SJohn Forte 511fcf3ce44SJohn Forte return; 512fcf3ce44SJohn Forte } 513fcf3ce44SJohn Forte 514fcf3ce44SJohn Forte /* 515fcf3ce44SJohn Forte * If we get to the last item in the list, then just 516fcf3ce44SJohn Forte * add this one to the end 517fcf3ce44SJohn Forte */ 518fcf3ce44SJohn Forte if (cur->next == NULL) { 519fcf3ce44SJohn Forte cur->next = sdbcstat; 520fcf3ce44SJohn Forte return; 521fcf3ce44SJohn Forte } 522fcf3ce44SJohn Forte 523fcf3ce44SJohn Forte nxt_vname = kstat_value(cur->next->pre_set, 524fcf3ce44SJohn Forte SDBC_CDKSTAT_VOL_NAME); 525fcf3ce44SJohn Forte 526fcf3ce44SJohn Forte if (strncmp(nxt_vname, tst_vname, NAMED_LEN) > 0) { 527fcf3ce44SJohn Forte sdbcstat->next = cur->next; 528fcf3ce44SJohn Forte cur->next = sdbcstat; 529fcf3ce44SJohn Forte return; 530fcf3ce44SJohn Forte } 531fcf3ce44SJohn Forte } 532fcf3ce44SJohn Forte } 533fcf3ce44SJohn Forte 534fcf3ce44SJohn Forte /* 535fcf3ce44SJohn Forte * sdbc_delstat() - deallocate memory for the structure being 536fcf3ce44SJohn Forte * passed in. 537fcf3ce44SJohn Forte * 538fcf3ce44SJohn Forte * parameters 539fcf3ce44SJohn Forte * sdbcstat_t *sdbcstat - structure to be deallocated 540fcf3ce44SJohn Forte * 541fcf3ce44SJohn Forte * returns 542fcf3ce44SJohn Forte * sdbcstat_t * - pointer to the "next" structures in the 543fcf3ce44SJohn Forte * linked list. May be NULL if we are removing the last 544fcf3ce44SJohn Forte * structure in the linked list. 545fcf3ce44SJohn Forte */ 546fcf3ce44SJohn Forte sdbcstat_t * 547fcf3ce44SJohn Forte sdbc_delstat(sdbcstat_t *sdbcstat) 548fcf3ce44SJohn Forte { 549fcf3ce44SJohn Forte 550fcf3ce44SJohn Forte sdbcstat_t *next = sdbcstat->next; 551fcf3ce44SJohn Forte 552fcf3ce44SJohn Forte kstat_free(sdbcstat->pre_set); 553fcf3ce44SJohn Forte kstat_free(sdbcstat->pre_io); 554fcf3ce44SJohn Forte kstat_free(sdbcstat->cur_set); 555fcf3ce44SJohn Forte kstat_free(sdbcstat->cur_io); 556fcf3ce44SJohn Forte 557fcf3ce44SJohn Forte free(sdbcstat); 558fcf3ce44SJohn Forte sdbcstat = NULL; 559fcf3ce44SJohn Forte 560fcf3ce44SJohn Forte return (next); 561fcf3ce44SJohn Forte } 562fcf3ce44SJohn Forte 563fcf3ce44SJohn Forte /* 564fcf3ce44SJohn Forte * sdbc_value_check() - Checks for activity, supports -z switch 565fcf3ce44SJohn Forte * 566fcf3ce44SJohn Forte * parameters 567fcf3ce44SJohn Forte * sdbcstat_t *sdbcstat - structure to be checked 568fcf3ce44SJohn Forte * 569fcf3ce44SJohn Forte * returns 570fcf3ce44SJohn Forte * 1 - activity 571fcf3ce44SJohn Forte * 0 - no activity 572fcf3ce44SJohn Forte */ 573fcf3ce44SJohn Forte int 574fcf3ce44SJohn Forte sdbc_value_check(sdbcstat_t *sdbcstat) 575fcf3ce44SJohn Forte { 576fcf3ce44SJohn Forte if (SDBC_COMPLETE(sdbcstat->collected)) 577fcf3ce44SJohn Forte return (1); 578fcf3ce44SJohn Forte 579fcf3ce44SJohn Forte if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_CACHE_READ) != 0) 580fcf3ce44SJohn Forte return (1); 581fcf3ce44SJohn Forte 582fcf3ce44SJohn Forte if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DISK_READ) != 0) 583fcf3ce44SJohn Forte return (1); 584fcf3ce44SJohn Forte 585fcf3ce44SJohn Forte if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_CACHE_WRITE) != 0) 586fcf3ce44SJohn Forte return (1); 587fcf3ce44SJohn Forte 588fcf3ce44SJohn Forte if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DISK_WRITE) != 0) 589fcf3ce44SJohn Forte return (1); 590fcf3ce44SJohn Forte 591fcf3ce44SJohn Forte if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_WRCANCELNS) != 0) 592fcf3ce44SJohn Forte return (1); 593fcf3ce44SJohn Forte 594fcf3ce44SJohn Forte if (io_value_check(sdbcstat->pre_io->ks_data, 595fcf3ce44SJohn Forte sdbcstat->cur_io->ks_data) != 0) 596fcf3ce44SJohn Forte return (1); 597fcf3ce44SJohn Forte 598fcf3ce44SJohn Forte return (0); 599fcf3ce44SJohn Forte } 600fcf3ce44SJohn Forte 601fcf3ce44SJohn Forte /* 602fcf3ce44SJohn Forte * sdbc_validate() - validates the structure of the kstats by attempting to 603fcf3ce44SJohn Forte * lookup fields used by this module 604fcf3ce44SJohn Forte * 605fcf3ce44SJohn Forte * parameters 606fcf3ce44SJohn Forte * kstat_t *ksp - kstat to be examined 607fcf3ce44SJohn Forte * 608fcf3ce44SJohn Forte * returns 609fcf3ce44SJohn Forte * 1 - one or more fields missing 610fcf3ce44SJohn Forte * 0 - all fields present 611fcf3ce44SJohn Forte */ 612fcf3ce44SJohn Forte int 613fcf3ce44SJohn Forte sdbc_validate(kstat_t *ksp) 614fcf3ce44SJohn Forte { 615fcf3ce44SJohn Forte if (! kstat_value(ksp, SDBC_CDKSTAT_VOL_NAME) || 616fcf3ce44SJohn Forte ! kstat_value(ksp, SDBC_CDKSTAT_FAILED) || 617fcf3ce44SJohn Forte ! kstat_value(ksp, SDBC_CDKSTAT_CDHINTS) || 618fcf3ce44SJohn Forte ! kstat_value(ksp, SDBC_CDKSTAT_CACHE_READ) || 619fcf3ce44SJohn Forte ! kstat_value(ksp, SDBC_CDKSTAT_DISK_READ) || 620fcf3ce44SJohn Forte ! kstat_value(ksp, SDBC_CDKSTAT_CACHE_WRITE) || 621fcf3ce44SJohn Forte ! kstat_value(ksp, SDBC_CDKSTAT_DISK_WRITE) || 622fcf3ce44SJohn Forte ! kstat_value(ksp, SDBC_CDKSTAT_DESTAGED) || 623fcf3ce44SJohn Forte ! kstat_value(ksp, SDBC_CDKSTAT_WRCANCELNS)) 624fcf3ce44SJohn Forte return (1); 625fcf3ce44SJohn Forte 626fcf3ce44SJohn Forte return (0); 627fcf3ce44SJohn Forte } 628fcf3ce44SJohn Forte 629fcf3ce44SJohn Forte /* 630fcf3ce44SJohn Forte * sdbc_getvalues() - populates a values structure with data obtained from the 631fcf3ce44SJohn Forte * kstat 632fcf3ce44SJohn Forte * 633fcf3ce44SJohn Forte * parameters 634fcf3ce44SJohn Forte * sdbcstat_t *sdbcstat - pointer to the structure containing the kstats 635fcf3ce44SJohn Forte * sdbcvals_t *vals - pointer to the structure that will receive the values 636fcf3ce44SJohn Forte * int flags - flags that describe adjustments made to the values 637fcf3ce44SJohn Forte * 638fcf3ce44SJohn Forte * returns 639fcf3ce44SJohn Forte * 1 - failure 640fcf3ce44SJohn Forte * 0 - success 641fcf3ce44SJohn Forte */ 642fcf3ce44SJohn Forte int 643fcf3ce44SJohn Forte sdbc_getvalues(sdbcstat_t *sdbcstat, sdbcvals_t *vals, int flags) 644fcf3ce44SJohn Forte { 645fcf3ce44SJohn Forte int divisor = 0; 646fcf3ce44SJohn Forte int factors; 647fcf3ce44SJohn Forte uint64_t hr_etime; 648fcf3ce44SJohn Forte double etime; 649fcf3ce44SJohn Forte 650fcf3ce44SJohn Forte kstat_io_t *cur; 651fcf3ce44SJohn Forte kstat_io_t *pre; 652fcf3ce44SJohn Forte 653fcf3ce44SJohn Forte if (sdbcstat == NULL) 654fcf3ce44SJohn Forte return (1); 655fcf3ce44SJohn Forte 656fcf3ce44SJohn Forte cur = sdbcstat->cur_io->ks_data; 657fcf3ce44SJohn Forte pre = sdbcstat->pre_io->ks_data; 658fcf3ce44SJohn Forte 659fcf3ce44SJohn Forte hr_etime = hrtime_delta(pre->rlastupdate, cur->rlastupdate); 660fcf3ce44SJohn Forte etime = hr_etime / (double)NANOSEC; 661fcf3ce44SJohn Forte 662fcf3ce44SJohn Forte /* read data */ 663fcf3ce44SJohn Forte vals->cache_read = 664fcf3ce44SJohn Forte FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_CACHE_READ)); 665fcf3ce44SJohn Forte vals->disk_read = 666fcf3ce44SJohn Forte FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DISK_READ)); 667fcf3ce44SJohn Forte 668fcf3ce44SJohn Forte 669fcf3ce44SJohn Forte vals->total_reads = vals->cache_read + vals->disk_read; 670fcf3ce44SJohn Forte 671fcf3ce44SJohn Forte if (vals->cache_read == 0) 672fcf3ce44SJohn Forte vals->read_hit = 0.0; 673fcf3ce44SJohn Forte else 674fcf3ce44SJohn Forte vals->read_hit = 675fcf3ce44SJohn Forte ((float)vals->cache_read / vals->total_reads) * 100.0; 676fcf3ce44SJohn Forte 677fcf3ce44SJohn Forte /* write data */ 678fcf3ce44SJohn Forte vals->cache_write = 679fcf3ce44SJohn Forte FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_CACHE_WRITE)); 680fcf3ce44SJohn Forte vals->disk_write = 681fcf3ce44SJohn Forte FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DISK_WRITE)); 682fcf3ce44SJohn Forte 683fcf3ce44SJohn Forte vals->total_writes = vals->cache_write + vals->disk_write; 684fcf3ce44SJohn Forte 685fcf3ce44SJohn Forte vals->destaged = 686fcf3ce44SJohn Forte FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DESTAGED)); 687fcf3ce44SJohn Forte 688fcf3ce44SJohn Forte if (vals->cache_write == 0) 689fcf3ce44SJohn Forte vals->write_hit = 0.0; 690fcf3ce44SJohn Forte else 691fcf3ce44SJohn Forte vals->write_hit = ((float)vals->cache_write / 692fcf3ce44SJohn Forte (vals->total_writes - vals->destaged)) * 100.0; 693fcf3ce44SJohn Forte 694fcf3ce44SJohn Forte /* miscellaneous */ 695fcf3ce44SJohn Forte vals->write_cancellations = 696fcf3ce44SJohn Forte FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_WRCANCELNS)); 697fcf3ce44SJohn Forte 698fcf3ce44SJohn Forte vals->total_cache = vals->cache_read + vals->cache_write; 699fcf3ce44SJohn Forte vals->total_disk = vals->disk_read + vals->disk_write; 700fcf3ce44SJohn Forte 701fcf3ce44SJohn Forte /* total cache hit calculation */ 702fcf3ce44SJohn Forte vals->cache_hit = 0; 703fcf3ce44SJohn Forte factors = 0; 704fcf3ce44SJohn Forte 705fcf3ce44SJohn Forte if (vals->cache_read != 0) { 706fcf3ce44SJohn Forte vals->cache_hit += vals->read_hit; 707fcf3ce44SJohn Forte factors++; 708fcf3ce44SJohn Forte } 709fcf3ce44SJohn Forte 710fcf3ce44SJohn Forte if (vals->cache_write != 0) { 711fcf3ce44SJohn Forte vals->cache_hit += vals->write_hit; 712fcf3ce44SJohn Forte factors++; 713fcf3ce44SJohn Forte } 714fcf3ce44SJohn Forte 715fcf3ce44SJohn Forte if (vals->cache_hit) 716fcf3ce44SJohn Forte vals->cache_hit /= (float)factors; 717fcf3ce44SJohn Forte 718fcf3ce44SJohn Forte /* adjustments */ 719fcf3ce44SJohn Forte divisor = 1; 720fcf3ce44SJohn Forte 721fcf3ce44SJohn Forte if (flags & SDBC_KBYTES) 722fcf3ce44SJohn Forte divisor *= KILOBYTE; 723fcf3ce44SJohn Forte if ((flags & SDBC_INTAVG) && (etime > 0)) 724fcf3ce44SJohn Forte divisor *= etime; 725fcf3ce44SJohn Forte 726fcf3ce44SJohn Forte if (divisor != 1) { 727fcf3ce44SJohn Forte vals->cache_read /= divisor; 728fcf3ce44SJohn Forte vals->disk_read /= divisor; 729fcf3ce44SJohn Forte vals->total_reads /= divisor; 730fcf3ce44SJohn Forte 731fcf3ce44SJohn Forte vals->cache_write /= divisor; 732fcf3ce44SJohn Forte vals->disk_write /= divisor; 733fcf3ce44SJohn Forte vals->total_writes /= divisor; 734fcf3ce44SJohn Forte 735fcf3ce44SJohn Forte vals->total_cache /= divisor; 736fcf3ce44SJohn Forte vals->total_disk /= divisor; 737fcf3ce44SJohn Forte 738fcf3ce44SJohn Forte vals->destaged /= divisor; 739fcf3ce44SJohn Forte vals->write_cancellations /= divisor; 740fcf3ce44SJohn Forte } 741fcf3ce44SJohn Forte 742fcf3ce44SJohn Forte return (0); 743fcf3ce44SJohn Forte } 744fcf3ce44SJohn Forte 745fcf3ce44SJohn Forte /* 746fcf3ce44SJohn Forte * sdbc_getdelta() - calculates the difference between two kstat fields 747fcf3ce44SJohn Forte * 748fcf3ce44SJohn Forte * parameters 749fcf3ce44SJohn Forte * sdbcstat_t *sdbcstat - the SDBC stat strcture containing the two fields 750fcf3ce44SJohn Forte * char *name - the name of the fields 751fcf3ce44SJohn Forte * returns 752fcf3ce44SJohn Forte * uint32_t value of the differences adjusted for overflow of the data type 753fcf3ce44SJohn Forte */ 754fcf3ce44SJohn Forte uint32_t 755fcf3ce44SJohn Forte sdbc_getdelta(sdbcstat_t *sdbcstat, char *name) 756fcf3ce44SJohn Forte { 757fcf3ce44SJohn Forte uint32_t *cur_val; 758fcf3ce44SJohn Forte uint32_t *pre_val; 759fcf3ce44SJohn Forte 760fcf3ce44SJohn Forte pre_val = kstat_value(sdbcstat->pre_set, name); 761fcf3ce44SJohn Forte cur_val = kstat_value(sdbcstat->cur_set, name); 762fcf3ce44SJohn Forte 763fcf3ce44SJohn Forte return (u32_delta(*pre_val, *cur_val)); 764fcf3ce44SJohn Forte } 765fcf3ce44SJohn Forte 766fcf3ce44SJohn Forte void 767fcf3ce44SJohn Forte center(int size, char *hdr) 768fcf3ce44SJohn Forte { 769fcf3ce44SJohn Forte int lpad = 0; 770fcf3ce44SJohn Forte int rpad = 0; 771fcf3ce44SJohn Forte char fmt[10]; 772fcf3ce44SJohn Forte 773fcf3ce44SJohn Forte if (size == 0) 774fcf3ce44SJohn Forte return; 775fcf3ce44SJohn Forte 776fcf3ce44SJohn Forte if (strlen(hdr) < size) { 777fcf3ce44SJohn Forte lpad = (size - strlen(hdr)) / 2; 778fcf3ce44SJohn Forte 779fcf3ce44SJohn Forte if (lpad * 2 < size) 780fcf3ce44SJohn Forte lpad++; 781fcf3ce44SJohn Forte 782fcf3ce44SJohn Forte rpad = size - (lpad + strlen(hdr)); 783fcf3ce44SJohn Forte } 784fcf3ce44SJohn Forte 785fcf3ce44SJohn Forte output: 786fcf3ce44SJohn Forte (void) sprintf(fmt, "%%%ds%%s%%%ds", lpad, rpad); 787fcf3ce44SJohn Forte (void) printf(fmt, " ", hdr, " "); 788fcf3ce44SJohn Forte } 789