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
sdbc_discover(kstat_ctl_t * kc)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
sdbc_update(kstat_ctl_t * kc)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
sdbc_report()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
sdbc_header()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 *
sdbc_getstat(char * vn)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
sdbc_addstat(sdbcstat_t * sdbcstat)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 *
sdbc_delstat(sdbcstat_t * sdbcstat)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
sdbc_value_check(sdbcstat_t * sdbcstat)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
sdbc_validate(kstat_t * ksp)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
sdbc_getvalues(sdbcstat_t * sdbcstat,sdbcvals_t * vals,int flags)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
sdbc_getdelta(sdbcstat_t * sdbcstat,char * name)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
center(int size,char * hdr)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