xref: /onnv-gate/usr/src/cmd/fs.d/cachefs/common/stats_create.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  *
31*0Sstevel@tonic-gate  *			stats_create.c
32*0Sstevel@tonic-gate  *
33*0Sstevel@tonic-gate  * Routines for the `clean interface' to cachefs statistics.
34*0Sstevel@tonic-gate  */
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include <stdarg.h>
37*0Sstevel@tonic-gate #include <libintl.h>
38*0Sstevel@tonic-gate #include <sys/types.h>
39*0Sstevel@tonic-gate #include <sys/stat.h>
40*0Sstevel@tonic-gate #include <assert.h>
41*0Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
42*0Sstevel@tonic-gate #include <string.h>
43*0Sstevel@tonic-gate #include "stats.h"
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate void	*malloc(), *calloc();
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate /* forward declarations of statics */
48*0Sstevel@tonic-gate static stats_cookie_t *stats_create(char *);
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate static stats_cookie_t *
51*0Sstevel@tonic-gate stats_create(char *progname)
52*0Sstevel@tonic-gate {
53*0Sstevel@tonic-gate 	stats_cookie_t *rc;
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate 	if ((rc = (stats_cookie_t *)calloc(1, sizeof (*rc))) == NULL)
56*0Sstevel@tonic-gate 		goto out;
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate 	rc->st_magic = STATS_MAGIC;
59*0Sstevel@tonic-gate 	if (rc->st_progname = strrchr(progname, '/'))
60*0Sstevel@tonic-gate 		rc->st_progname++;
61*0Sstevel@tonic-gate 	else
62*0Sstevel@tonic-gate 		rc->st_progname = progname;
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 	if ((rc->st_kstat_cookie = kstat_open()) == NULL) {
65*0Sstevel@tonic-gate 		stats_perror(rc, SE_KERNEL,
66*0Sstevel@tonic-gate 		    gettext("Cannot initialize kstats"));
67*0Sstevel@tonic-gate 		goto out;
68*0Sstevel@tonic-gate 	}
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate out:
71*0Sstevel@tonic-gate 	return (rc);
72*0Sstevel@tonic-gate }
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate stats_cookie_t *
75*0Sstevel@tonic-gate stats_create_unbound(char *progname)
76*0Sstevel@tonic-gate {
77*0Sstevel@tonic-gate 	stats_cookie_t *st;
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	if ((st = stats_create(progname)) == NULL)
80*0Sstevel@tonic-gate 		goto out;
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	st->st_flags |= ST_VALID;
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate out:
85*0Sstevel@tonic-gate 	return (st);
86*0Sstevel@tonic-gate }
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate stats_cookie_t *
89*0Sstevel@tonic-gate stats_create_mountpath(char *mountpath, char *progname)
90*0Sstevel@tonic-gate {
91*0Sstevel@tonic-gate 	stats_cookie_t *st;
92*0Sstevel@tonic-gate 	kstat_t *key;
93*0Sstevel@tonic-gate 	cachefs_kstat_key_t *k;
94*0Sstevel@tonic-gate 	dev_t dev;
95*0Sstevel@tonic-gate 	ino64_t ino;
96*0Sstevel@tonic-gate 	struct stat64 s;
97*0Sstevel@tonic-gate 	int i, n;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	if ((st = stats_create(progname)) == NULL)
100*0Sstevel@tonic-gate 		goto out;
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	if ((key = kstat_lookup(st->st_kstat_cookie, "cachefs", 0, "key"))
103*0Sstevel@tonic-gate 	    == NULL) {
104*0Sstevel@tonic-gate 		stats_perror(st, SE_KERNEL,
105*0Sstevel@tonic-gate 		    gettext("Cannot lookup cachefs key kstat"));
106*0Sstevel@tonic-gate 		goto out;
107*0Sstevel@tonic-gate 	}
108*0Sstevel@tonic-gate 	if (kstat_read(st->st_kstat_cookie, key, NULL) < 0) {
109*0Sstevel@tonic-gate 		stats_perror(st, SE_KERNEL,
110*0Sstevel@tonic-gate 		    gettext("Cannot read cachefs key kstat"));
111*0Sstevel@tonic-gate 		goto out;
112*0Sstevel@tonic-gate 	}
113*0Sstevel@tonic-gate 	k = (cachefs_kstat_key_t *)key->ks_data;
114*0Sstevel@tonic-gate 	n = key->ks_ndata;
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	if (stat64(mountpath, &s) != 0) {
117*0Sstevel@tonic-gate 		stats_perror(st, SE_FILE,
118*0Sstevel@tonic-gate 		    gettext("Cannot stat %s"), mountpath);
119*0Sstevel@tonic-gate 		goto out;
120*0Sstevel@tonic-gate 	}
121*0Sstevel@tonic-gate 	ino = s.st_ino;
122*0Sstevel@tonic-gate 	dev = s.st_dev;
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
125*0Sstevel@tonic-gate 		k[i].ks_mountpoint += (uintptr_t)k;
126*0Sstevel@tonic-gate 		k[i].ks_backfs += (uintptr_t)k;
127*0Sstevel@tonic-gate 		k[i].ks_cachedir += (uintptr_t)k;
128*0Sstevel@tonic-gate 		k[i].ks_cacheid += (uintptr_t)k;
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 		if (! k[i].ks_mounted)
131*0Sstevel@tonic-gate 			continue;
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 		if ((stat64((char *)k[i].ks_mountpoint, &s) == 0) &&
134*0Sstevel@tonic-gate 		    (s.st_dev == dev) &&
135*0Sstevel@tonic-gate 		    (s.st_ino == ino))
136*0Sstevel@tonic-gate 			break;
137*0Sstevel@tonic-gate 	}
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	if (i >= n) {
140*0Sstevel@tonic-gate 		stats_perror(st, SE_FILE,
141*0Sstevel@tonic-gate 		    gettext("%s: not a cachefs mountpoint"), mountpath);
142*0Sstevel@tonic-gate 		goto out;
143*0Sstevel@tonic-gate 	}
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	st->st_fsid = k[i].ks_id;
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 	st->st_flags |= ST_VALID | ST_BOUND;
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate out:
150*0Sstevel@tonic-gate 	return (st);
151*0Sstevel@tonic-gate }
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate /*
154*0Sstevel@tonic-gate  * stats_next - bind the cookie to the next valid cachefs mount.
155*0Sstevel@tonic-gate  *
156*0Sstevel@tonic-gate  * returns cachefs_kstat_key_t *, which gives all the info you need.
157*0Sstevel@tonic-gate  * returns NULL if we're out of mounts, or if an error occured.
158*0Sstevel@tonic-gate  * returns malloc()ed data, which the client has to free() itself.
159*0Sstevel@tonic-gate  */
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate cachefs_kstat_key_t *
162*0Sstevel@tonic-gate stats_next(stats_cookie_t *st)
163*0Sstevel@tonic-gate {
164*0Sstevel@tonic-gate 	kstat_t *key;
165*0Sstevel@tonic-gate 	cachefs_kstat_key_t *k, *prc = NULL, *rc = NULL;
166*0Sstevel@tonic-gate 	int i, n;
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	assert(stats_good(st));
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	if (((key = kstat_lookup(st->st_kstat_cookie, "cachefs", 0,
171*0Sstevel@tonic-gate 	    "key")) == NULL) ||
172*0Sstevel@tonic-gate 	    (kstat_read(st->st_kstat_cookie, key, NULL) < 0)) {
173*0Sstevel@tonic-gate 		stats_perror(st, SE_KERNEL,
174*0Sstevel@tonic-gate 		    gettext("Cannot get cachefs key kstat"));
175*0Sstevel@tonic-gate 		goto out;
176*0Sstevel@tonic-gate 	}
177*0Sstevel@tonic-gate 	k = (cachefs_kstat_key_t *)key->ks_data;
178*0Sstevel@tonic-gate 	n = key->ks_ndata;
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate 	if (st->st_flags & ST_BOUND) {
181*0Sstevel@tonic-gate 		for (i = 0; i < n; i++)
182*0Sstevel@tonic-gate 			if (st->st_fsid == k[i].ks_id)
183*0Sstevel@tonic-gate 				break;
184*0Sstevel@tonic-gate 		++i;
185*0Sstevel@tonic-gate 		if (i < n) {
186*0Sstevel@tonic-gate 			prc = k + i;
187*0Sstevel@tonic-gate 			st->st_fsid = k[i].ks_id;
188*0Sstevel@tonic-gate 		} else
189*0Sstevel@tonic-gate 			st->st_flags &= ~ST_BOUND;
190*0Sstevel@tonic-gate 	} else if (n > 0) {
191*0Sstevel@tonic-gate 		st->st_fsid = k[0].ks_id;
192*0Sstevel@tonic-gate 		st->st_flags |= ST_BOUND;
193*0Sstevel@tonic-gate 		prc = k;
194*0Sstevel@tonic-gate 	}
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate out:
197*0Sstevel@tonic-gate 	if (prc != NULL) {
198*0Sstevel@tonic-gate 		char *s;
199*0Sstevel@tonic-gate 		int size;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 		prc->ks_mountpoint += (uintptr_t)k;
202*0Sstevel@tonic-gate 		prc->ks_backfs += (uintptr_t)k;
203*0Sstevel@tonic-gate 		prc->ks_cachedir += (uintptr_t)k;
204*0Sstevel@tonic-gate 		prc->ks_cacheid += (uintptr_t)k;
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 		size = sizeof (*rc);
207*0Sstevel@tonic-gate 		size += strlen((char *)prc->ks_mountpoint) + 1;
208*0Sstevel@tonic-gate 		size += strlen((char *)prc->ks_backfs) + 1;
209*0Sstevel@tonic-gate 		size += strlen((char *)prc->ks_cachedir) + 1;
210*0Sstevel@tonic-gate 		size += strlen((char *)prc->ks_cacheid) + 1;
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 		if ((rc = (cachefs_kstat_key_t *)
213*0Sstevel@tonic-gate 		    malloc(size)) == NULL) {
214*0Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
215*0Sstevel@tonic-gate 			    gettext("Cannot malloc return code"));
216*0Sstevel@tonic-gate 		} else {
217*0Sstevel@tonic-gate 			memcpy(rc, prc, sizeof (*rc));
218*0Sstevel@tonic-gate 			s = (char *)((uintptr_t)rc + sizeof (*rc));
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 			(void) strcpy(s, (char *)prc->ks_mountpoint);
221*0Sstevel@tonic-gate 			rc->ks_mountpoint = (uintptr_t)s;
222*0Sstevel@tonic-gate 			s += strlen(s) + 1;
223*0Sstevel@tonic-gate 			(void) strcpy(s, (char *)prc->ks_backfs);
224*0Sstevel@tonic-gate 			rc->ks_backfs = (uintptr_t)s;
225*0Sstevel@tonic-gate 			s += strlen(s) + 1;
226*0Sstevel@tonic-gate 			(void) strcpy(s, (char *)prc->ks_cachedir);
227*0Sstevel@tonic-gate 			rc->ks_cachedir = (uintptr_t)s;
228*0Sstevel@tonic-gate 			s += strlen(s) + 1;
229*0Sstevel@tonic-gate 			(void) strcpy(s, (char *)prc->ks_cacheid);
230*0Sstevel@tonic-gate 			rc->ks_cacheid = (uintptr_t)s;
231*0Sstevel@tonic-gate 		}
232*0Sstevel@tonic-gate 	}
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 	return (rc);
235*0Sstevel@tonic-gate }
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate cachefs_kstat_key_t *
238*0Sstevel@tonic-gate stats_getkey(stats_cookie_t *st)
239*0Sstevel@tonic-gate {
240*0Sstevel@tonic-gate 	kstat_t *ksp;
241*0Sstevel@tonic-gate 	cachefs_kstat_key_t *k, *key, *rc = NULL;
242*0Sstevel@tonic-gate 	int size;
243*0Sstevel@tonic-gate 	char *s;
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 	assert(stats_good(st));
246*0Sstevel@tonic-gate 	assert(st->st_flags & ST_BOUND);
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate 	if (((ksp = kstat_lookup(st->st_kstat_cookie, "cachefs", 0,
249*0Sstevel@tonic-gate 	    "key")) == NULL) ||
250*0Sstevel@tonic-gate 	    (kstat_read(st->st_kstat_cookie, ksp, NULL) < 0)) {
251*0Sstevel@tonic-gate 		stats_perror(st, SE_KERNEL,
252*0Sstevel@tonic-gate 		    gettext("Cannot get cachefs key kstat"));
253*0Sstevel@tonic-gate 		goto out;
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 	key = (cachefs_kstat_key_t *)ksp->ks_data;
256*0Sstevel@tonic-gate 	k = key + st->st_fsid - 1;
257*0Sstevel@tonic-gate 	k->ks_mountpoint += (uintptr_t)key;
258*0Sstevel@tonic-gate 	k->ks_backfs += (uintptr_t)key;
259*0Sstevel@tonic-gate 	k->ks_cachedir += (uintptr_t)key;
260*0Sstevel@tonic-gate 	k->ks_cacheid += (uintptr_t)key;
261*0Sstevel@tonic-gate 	size = sizeof (*rc);
262*0Sstevel@tonic-gate 	size += strlen((char *)k->ks_mountpoint) + 1;
263*0Sstevel@tonic-gate 	size += strlen((char *)k->ks_backfs) + 1;
264*0Sstevel@tonic-gate 	size += strlen((char *)k->ks_cachedir) + 1;
265*0Sstevel@tonic-gate 	size += strlen((char *)k->ks_cacheid) + 1;
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate 	if ((rc = (cachefs_kstat_key_t *)malloc(size)) == NULL)
268*0Sstevel@tonic-gate 		stats_perror(st, SE_NOMEM,
269*0Sstevel@tonic-gate 		    gettext("Cannot malloc return code"));
270*0Sstevel@tonic-gate 	else {
271*0Sstevel@tonic-gate 		memcpy(rc, k, sizeof (*rc));
272*0Sstevel@tonic-gate 		s = (char *)((uintptr_t)rc + sizeof (*rc));
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 		(void) strcpy(s, (char *)k->ks_mountpoint);
275*0Sstevel@tonic-gate 		rc->ks_mountpoint = (uintptr_t)s;
276*0Sstevel@tonic-gate 		s += strlen(s) + 1;
277*0Sstevel@tonic-gate 		(void) strcpy(s, (char *)k->ks_backfs);
278*0Sstevel@tonic-gate 		rc->ks_backfs = (uintptr_t)s;
279*0Sstevel@tonic-gate 		s += strlen(s) + 1;
280*0Sstevel@tonic-gate 		(void) strcpy(s, (char *)k->ks_cachedir);
281*0Sstevel@tonic-gate 		rc->ks_cachedir = (uintptr_t)s;
282*0Sstevel@tonic-gate 		s += strlen(s) + 1;
283*0Sstevel@tonic-gate 		(void) strcpy(s, (char *)k->ks_cacheid);
284*0Sstevel@tonic-gate 		rc->ks_cacheid = (uintptr_t)s;
285*0Sstevel@tonic-gate 		s += strlen(s) + 1;
286*0Sstevel@tonic-gate 	}
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 	assert(rc->ks_id == st->st_fsid);
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate out:
291*0Sstevel@tonic-gate 	return (rc);
292*0Sstevel@tonic-gate }
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate void
295*0Sstevel@tonic-gate stats_destroy(stats_cookie_t *st)
296*0Sstevel@tonic-gate {
297*0Sstevel@tonic-gate 	void free();
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate 	if (st == NULL)
300*0Sstevel@tonic-gate 		return;
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 	if (st->st_kstat_cookie != NULL)
303*0Sstevel@tonic-gate 		kstat_close(st->st_kstat_cookie);
304*0Sstevel@tonic-gate 	if (st->st_logxdr.x_ops != NULL)
305*0Sstevel@tonic-gate 		xdr_destroy(&st->st_logxdr);
306*0Sstevel@tonic-gate 	if ((st->st_logstream != NULL) && (st->st_flags & ST_LFOPEN))
307*0Sstevel@tonic-gate 		(void) fclose(st->st_logstream);
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	/*
310*0Sstevel@tonic-gate 	 * we don't want to depend on dbm (or stats_dbm), so we don't
311*0Sstevel@tonic-gate 	 * do a stats_dbm_close.  we do try to require the client to
312*0Sstevel@tonic-gate 	 * have done it, via an assert(), however.
313*0Sstevel@tonic-gate 	 */
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate 	assert(! (st->st_flags & ST_DBMOPEN));
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	st->st_magic++;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	free(st);
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate int
323*0Sstevel@tonic-gate stats_good(stats_cookie_t *st)
324*0Sstevel@tonic-gate {
325*0Sstevel@tonic-gate 	if (st == NULL)
326*0Sstevel@tonic-gate 		return (0);
327*0Sstevel@tonic-gate 	if (st->st_magic != STATS_MAGIC)
328*0Sstevel@tonic-gate 		return (0);
329*0Sstevel@tonic-gate 	if (! (st->st_flags & ST_VALID))
330*0Sstevel@tonic-gate 		return (0);
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 	return (1);
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate void
336*0Sstevel@tonic-gate /*PRINTFLIKE3*/
337*0Sstevel@tonic-gate stats_perror(stats_cookie_t *st, int Errno, char *fmt, ...)
338*0Sstevel@tonic-gate {
339*0Sstevel@tonic-gate 
340*0Sstevel@tonic-gate 	va_list ap;
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	assert(st != NULL);
343*0Sstevel@tonic-gate 	assert(st->st_magic == STATS_MAGIC);
344*0Sstevel@tonic-gate 
345*0Sstevel@tonic-gate 	va_start(ap, fmt);
346*0Sstevel@tonic-gate 	(void) vsnprintf(st->st_errorstr, sizeof (st->st_errorstr), fmt, ap);
347*0Sstevel@tonic-gate 	va_end(ap);
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 	st->st_errno = Errno;
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate 	st->st_flags |= ST_ERROR;
352*0Sstevel@tonic-gate }
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate char *
355*0Sstevel@tonic-gate stats_errorstr(stats_cookie_t *st)
356*0Sstevel@tonic-gate {
357*0Sstevel@tonic-gate 	assert(st != NULL);
358*0Sstevel@tonic-gate 	assert(st->st_magic == STATS_MAGIC);
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate 	return (st->st_errorstr);
361*0Sstevel@tonic-gate }
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate int
364*0Sstevel@tonic-gate stats_errno(stats_cookie_t *st)
365*0Sstevel@tonic-gate {
366*0Sstevel@tonic-gate 	assert(st != NULL);
367*0Sstevel@tonic-gate 	assert(st->st_magic == STATS_MAGIC);
368*0Sstevel@tonic-gate 
369*0Sstevel@tonic-gate 	return (st->st_errno);
370*0Sstevel@tonic-gate }
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate int
373*0Sstevel@tonic-gate stats_inerror(stats_cookie_t *st)
374*0Sstevel@tonic-gate {
375*0Sstevel@tonic-gate 	assert(st != NULL);
376*0Sstevel@tonic-gate 	assert(st->st_magic == STATS_MAGIC);
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 	return (st->st_flags & ST_ERROR);
379*0Sstevel@tonic-gate }
380