1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  *	Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  *	Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/list.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <nfs/nfs4_clnt.h>
38*7c478bd9Sstevel@tonic-gate #include <nfs/rnode4.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate /*
41*7c478bd9Sstevel@tonic-gate  * Recovery kstats
42*7c478bd9Sstevel@tonic-gate  */
43*7c478bd9Sstevel@tonic-gate typedef struct rkstat {
44*7c478bd9Sstevel@tonic-gate 	kstat_named_t	badhandle;
45*7c478bd9Sstevel@tonic-gate 	kstat_named_t	badowner;
46*7c478bd9Sstevel@tonic-gate 	kstat_named_t	clientid;
47*7c478bd9Sstevel@tonic-gate 	kstat_named_t	dead_file;
48*7c478bd9Sstevel@tonic-gate 	kstat_named_t	delay;
49*7c478bd9Sstevel@tonic-gate 	kstat_named_t	fail_relock;
50*7c478bd9Sstevel@tonic-gate 	kstat_named_t	file_diff;
51*7c478bd9Sstevel@tonic-gate 	kstat_named_t	no_grace;
52*7c478bd9Sstevel@tonic-gate 	kstat_named_t	not_responding;
53*7c478bd9Sstevel@tonic-gate 	kstat_named_t	opens_changed;
54*7c478bd9Sstevel@tonic-gate 	kstat_named_t	siglost;
55*7c478bd9Sstevel@tonic-gate 	kstat_named_t	unexp_action;
56*7c478bd9Sstevel@tonic-gate 	kstat_named_t	unexp_errno;
57*7c478bd9Sstevel@tonic-gate 	kstat_named_t	unexp_status;
58*7c478bd9Sstevel@tonic-gate 	kstat_named_t	wrongsec;
59*7c478bd9Sstevel@tonic-gate 	kstat_named_t	lost_state_bad_op;
60*7c478bd9Sstevel@tonic-gate } rkstat_t;
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate static rkstat_t rkstat_template = {
63*7c478bd9Sstevel@tonic-gate 	{ "badhandle",		KSTAT_DATA_ULONG },
64*7c478bd9Sstevel@tonic-gate 	{ "badowner",		KSTAT_DATA_ULONG },
65*7c478bd9Sstevel@tonic-gate 	{ "clientid",		KSTAT_DATA_ULONG },
66*7c478bd9Sstevel@tonic-gate 	{ "dead_file",		KSTAT_DATA_ULONG },
67*7c478bd9Sstevel@tonic-gate 	{ "delay",		KSTAT_DATA_ULONG },
68*7c478bd9Sstevel@tonic-gate 	{ "fail_relock",	KSTAT_DATA_ULONG },
69*7c478bd9Sstevel@tonic-gate 	{ "file_diff",		KSTAT_DATA_ULONG },
70*7c478bd9Sstevel@tonic-gate 	{ "no_grace",		KSTAT_DATA_ULONG },
71*7c478bd9Sstevel@tonic-gate 	{ "not_responding",	KSTAT_DATA_ULONG },
72*7c478bd9Sstevel@tonic-gate 	{ "opens_changed",	KSTAT_DATA_ULONG },
73*7c478bd9Sstevel@tonic-gate 	{ "siglost",		KSTAT_DATA_ULONG },
74*7c478bd9Sstevel@tonic-gate 	{ "unexp_action",	KSTAT_DATA_ULONG },
75*7c478bd9Sstevel@tonic-gate 	{ "unexp_errno",	KSTAT_DATA_ULONG },
76*7c478bd9Sstevel@tonic-gate 	{ "unexp_status",	KSTAT_DATA_ULONG },
77*7c478bd9Sstevel@tonic-gate 	{ "wrongsec",		KSTAT_DATA_ULONG },
78*7c478bd9Sstevel@tonic-gate 	{ "bad_op",		KSTAT_DATA_ULONG },
79*7c478bd9Sstevel@tonic-gate };
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /* maximum number of messages allowed on the mi's mi_msg_list */
82*7c478bd9Sstevel@tonic-gate int nfs4_msg_max = NFS4_MSG_MAX;
83*7c478bd9Sstevel@tonic-gate #define	DEFAULT_LEASE	180
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate static char *strdup(const char *);
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate /*
88*7c478bd9Sstevel@tonic-gate  * Sets the appropiate fields of "ep", given "id" and various parameters.
89*7c478bd9Sstevel@tonic-gate  * Assumes that ep's fields have been initialized to zero/null, except for
90*7c478bd9Sstevel@tonic-gate  * re_type and mount point info, which are already set.
91*7c478bd9Sstevel@tonic-gate  */
92*7c478bd9Sstevel@tonic-gate static void
93*7c478bd9Sstevel@tonic-gate set_event(nfs4_event_type_t id, nfs4_revent_t *ep, mntinfo4_t *mi,
94*7c478bd9Sstevel@tonic-gate     rnode4_t *rp1, rnode4_t *rp2, uint_t count, pid_t pid, nfsstat4 nfs4_error,
95*7c478bd9Sstevel@tonic-gate     char *server1, char *why, nfs4_tag_type_t tag1, nfs4_tag_type_t tag2,
96*7c478bd9Sstevel@tonic-gate     seqid4 seqid1, seqid4 seqid2)
97*7c478bd9Sstevel@tonic-gate {
98*7c478bd9Sstevel@tonic-gate 	int len;
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	switch (id) {
101*7c478bd9Sstevel@tonic-gate 	case RE_BAD_SEQID:
102*7c478bd9Sstevel@tonic-gate 		ep->re_mi = mi;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 		/* bad seqid'd file <path/component name> */
105*7c478bd9Sstevel@tonic-gate 		if (rp1 && rp1->r_svnode.sv_name)
106*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
107*7c478bd9Sstevel@tonic-gate 		else
108*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
109*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 		/* for LOCK/LOCKU */
112*7c478bd9Sstevel@tonic-gate 		ep->re_pid = pid;
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 		ep->re_stat4 = nfs4_error;
115*7c478bd9Sstevel@tonic-gate 		ep->re_tag1 = tag1;
116*7c478bd9Sstevel@tonic-gate 		ep->re_tag2 = tag2;
117*7c478bd9Sstevel@tonic-gate 		ep->re_seqid1 = seqid1;
118*7c478bd9Sstevel@tonic-gate 		ep->re_seqid2 = seqid2;
119*7c478bd9Sstevel@tonic-gate 		break;
120*7c478bd9Sstevel@tonic-gate 	case RE_BADHANDLE:
121*7c478bd9Sstevel@tonic-gate 		ASSERT(rp1 != NULL);
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 		/* dead file <path/component name> */
124*7c478bd9Sstevel@tonic-gate 		if (rp1->r_svnode.sv_name)
125*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
126*7c478bd9Sstevel@tonic-gate 		else
127*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
128*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
129*7c478bd9Sstevel@tonic-gate 		break;
130*7c478bd9Sstevel@tonic-gate 	case RE_CLIENTID:
131*7c478bd9Sstevel@tonic-gate 		ep->re_mi = mi;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 		/* the error we failed with */
134*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;
135*7c478bd9Sstevel@tonic-gate 		ep->re_stat4 = nfs4_error;
136*7c478bd9Sstevel@tonic-gate 		break;
137*7c478bd9Sstevel@tonic-gate 	case RE_DEAD_FILE:
138*7c478bd9Sstevel@tonic-gate 		ASSERT(rp1 != NULL);
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 		/* dead file <path/component name> */
141*7c478bd9Sstevel@tonic-gate 		if (rp1->r_svnode.sv_name)
142*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
143*7c478bd9Sstevel@tonic-gate 		else
144*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
145*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 		/* why the file got killed */
148*7c478bd9Sstevel@tonic-gate 		if (why) {
149*7c478bd9Sstevel@tonic-gate 			len = strlen(why);
150*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = kmem_alloc(len + 1, KM_SLEEP);
151*7c478bd9Sstevel@tonic-gate 			bcopy(why, ep->re_char2, len);
152*7c478bd9Sstevel@tonic-gate 			ep->re_char2[len] = '\0';
153*7c478bd9Sstevel@tonic-gate 		} else
154*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = NULL;
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 		ep->re_stat4 = nfs4_error;
157*7c478bd9Sstevel@tonic-gate 		break;
158*7c478bd9Sstevel@tonic-gate 	case RE_END:
159*7c478bd9Sstevel@tonic-gate 		/* first rnode */
160*7c478bd9Sstevel@tonic-gate 		if (rp1 && rp1->r_svnode.sv_name)
161*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
162*7c478bd9Sstevel@tonic-gate 		else
163*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
164*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 		/* second rnode */
167*7c478bd9Sstevel@tonic-gate 		if (rp2 && rp2->r_svnode.sv_name)
168*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = fn_path(rp2->r_svnode.sv_name);
169*7c478bd9Sstevel@tonic-gate 		else
170*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = NULL;
171*7c478bd9Sstevel@tonic-gate 		ep->re_rp2 = rp2;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 		ep->re_mi = mi;
174*7c478bd9Sstevel@tonic-gate 		break;
175*7c478bd9Sstevel@tonic-gate 	case RE_FAIL_RELOCK:
176*7c478bd9Sstevel@tonic-gate 		ASSERT(rp1 != NULL);
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 		/* error on fail relock */
179*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 		/* process that failed */
182*7c478bd9Sstevel@tonic-gate 		ep->re_pid = pid;
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 		/* nfs4 error */
185*7c478bd9Sstevel@tonic-gate 		ep->re_stat4 = nfs4_error;
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 		/* file <path/component name> */
188*7c478bd9Sstevel@tonic-gate 		if (rp1->r_svnode.sv_name)
189*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
190*7c478bd9Sstevel@tonic-gate 		else
191*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
192*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
193*7c478bd9Sstevel@tonic-gate 		break;
194*7c478bd9Sstevel@tonic-gate 	case RE_FAIL_REMAP_LEN:
195*7c478bd9Sstevel@tonic-gate 		/* length of returned filehandle */
196*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;
197*7c478bd9Sstevel@tonic-gate 		break;
198*7c478bd9Sstevel@tonic-gate 	case RE_FAIL_REMAP_OP:
199*7c478bd9Sstevel@tonic-gate 		break;
200*7c478bd9Sstevel@tonic-gate 	case RE_FAILOVER:
201*7c478bd9Sstevel@tonic-gate 		/* server we're failing over to (if not picking original) */
202*7c478bd9Sstevel@tonic-gate 		if (server1 != NULL) {
203*7c478bd9Sstevel@tonic-gate 			len = strlen(server1);
204*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = kmem_alloc(len + 1, KM_SLEEP);
205*7c478bd9Sstevel@tonic-gate 			bcopy(server1, ep->re_char1, len);
206*7c478bd9Sstevel@tonic-gate 			ep->re_char1[len] = '\0';
207*7c478bd9Sstevel@tonic-gate 		} else {
208*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
209*7c478bd9Sstevel@tonic-gate 		}
210*7c478bd9Sstevel@tonic-gate 		break;
211*7c478bd9Sstevel@tonic-gate 	case RE_FILE_DIFF:
212*7c478bd9Sstevel@tonic-gate 		ASSERT(rp1 != NULL);
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 		/* dead file <path/component name> */
215*7c478bd9Sstevel@tonic-gate 		if (rp1->r_svnode.sv_name)
216*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
217*7c478bd9Sstevel@tonic-gate 		else
218*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
219*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
220*7c478bd9Sstevel@tonic-gate 		break;
221*7c478bd9Sstevel@tonic-gate 	case RE_LOST_STATE:
222*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;		/* op number */
223*7c478bd9Sstevel@tonic-gate 		if (rp1 && rp1->r_svnode.sv_name)
224*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
225*7c478bd9Sstevel@tonic-gate 		else
226*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
227*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
228*7c478bd9Sstevel@tonic-gate 		if (rp2 && rp2->r_svnode.sv_name)
229*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = fn_path(rp2->r_svnode.sv_name);
230*7c478bd9Sstevel@tonic-gate 		else
231*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = NULL;
232*7c478bd9Sstevel@tonic-gate 		ep->re_rp2 = rp2;
233*7c478bd9Sstevel@tonic-gate 		break;
234*7c478bd9Sstevel@tonic-gate 	case RE_OPENS_CHANGED:
235*7c478bd9Sstevel@tonic-gate 		ep->re_mi = mi;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 		/* original number of open files */
238*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;
239*7c478bd9Sstevel@tonic-gate 		/* new number of open files */
240*7c478bd9Sstevel@tonic-gate 		ep->re_pid = pid;
241*7c478bd9Sstevel@tonic-gate 		break;
242*7c478bd9Sstevel@tonic-gate 	case RE_SIGLOST:
243*7c478bd9Sstevel@tonic-gate 	case RE_SIGLOST_NO_DUMP:
244*7c478bd9Sstevel@tonic-gate 		ASSERT(rp1 != NULL);
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 		/* file <path/component name> */
247*7c478bd9Sstevel@tonic-gate 		if (rp1->r_svnode.sv_name)
248*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
249*7c478bd9Sstevel@tonic-gate 		else
250*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
251*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
252*7c478bd9Sstevel@tonic-gate 		ep->re_pid = pid;
253*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;
254*7c478bd9Sstevel@tonic-gate 		ep->re_stat4 = nfs4_error;
255*7c478bd9Sstevel@tonic-gate 		break;
256*7c478bd9Sstevel@tonic-gate 	case RE_START:
257*7c478bd9Sstevel@tonic-gate 		/* file <path/component name> */
258*7c478bd9Sstevel@tonic-gate 		if (rp1 && rp1->r_svnode.sv_name)
259*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
260*7c478bd9Sstevel@tonic-gate 		else
261*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
262*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 		/* file <path/component name> */
265*7c478bd9Sstevel@tonic-gate 		if (rp2 && rp2->r_svnode.sv_name)
266*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = fn_path(rp2->r_svnode.sv_name);
267*7c478bd9Sstevel@tonic-gate 		else
268*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = NULL;
269*7c478bd9Sstevel@tonic-gate 		ep->re_rp2 = rp2;
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 		ep->re_mi = mi;
272*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;
273*7c478bd9Sstevel@tonic-gate 		break;
274*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_ACTION:
275*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_ERRNO:
276*7c478bd9Sstevel@tonic-gate 		/* the error that is unexpected */
277*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;
278*7c478bd9Sstevel@tonic-gate 		break;
279*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_STATUS:
280*7c478bd9Sstevel@tonic-gate 		/* nfsstat4 error */
281*7c478bd9Sstevel@tonic-gate 		ep->re_stat4 = nfs4_error;
282*7c478bd9Sstevel@tonic-gate 		break;
283*7c478bd9Sstevel@tonic-gate 	case RE_WRONGSEC:
284*7c478bd9Sstevel@tonic-gate 		/* the error we failed with */
285*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 		/* file <path/component name> */
288*7c478bd9Sstevel@tonic-gate 		if (rp1 && rp1->r_svnode.sv_name)
289*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
290*7c478bd9Sstevel@tonic-gate 		else
291*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = NULL;
292*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 		/* file <path/component name> */
295*7c478bd9Sstevel@tonic-gate 		if (rp2 && rp2->r_svnode.sv_name)
296*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = fn_path(rp2->r_svnode.sv_name);
297*7c478bd9Sstevel@tonic-gate 		else
298*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = NULL;
299*7c478bd9Sstevel@tonic-gate 		ep->re_rp2 = rp2;
300*7c478bd9Sstevel@tonic-gate 		break;
301*7c478bd9Sstevel@tonic-gate 	case RE_LOST_STATE_BAD_OP:
302*7c478bd9Sstevel@tonic-gate 		ep->re_uint = count;	/* the unexpected op */
303*7c478bd9Sstevel@tonic-gate 		ep->re_pid = pid;
304*7c478bd9Sstevel@tonic-gate 		ep->re_rp1 = rp1;
305*7c478bd9Sstevel@tonic-gate 		if (rp1 != NULL && rp1->r_svnode.sv_name != NULL)
306*7c478bd9Sstevel@tonic-gate 			ep->re_char1 = fn_path(rp1->r_svnode.sv_name);
307*7c478bd9Sstevel@tonic-gate 		ep->re_rp2 = rp2;
308*7c478bd9Sstevel@tonic-gate 		if (rp2 != NULL && rp2->r_svnode.sv_name != NULL)
309*7c478bd9Sstevel@tonic-gate 			ep->re_char2 = fn_path(rp2->r_svnode.sv_name);
310*7c478bd9Sstevel@tonic-gate 		break;
311*7c478bd9Sstevel@tonic-gate 	default:
312*7c478bd9Sstevel@tonic-gate 		break;
313*7c478bd9Sstevel@tonic-gate 	}
314*7c478bd9Sstevel@tonic-gate }
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate /*
317*7c478bd9Sstevel@tonic-gate  * Sets the appropiate fields of the 'fact' for this 'id'.
318*7c478bd9Sstevel@tonic-gate  */
319*7c478bd9Sstevel@tonic-gate static void
320*7c478bd9Sstevel@tonic-gate set_fact(nfs4_fact_type_t id, nfs4_rfact_t *fp, nfsstat4 stat4,
321*7c478bd9Sstevel@tonic-gate     nfs4_recov_t raction, nfs_opnum4 op, bool_t reboot, int error,
322*7c478bd9Sstevel@tonic-gate     vnode_t *vp)
323*7c478bd9Sstevel@tonic-gate {
324*7c478bd9Sstevel@tonic-gate 	rnode4_t *rp1;
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	switch (id) {
327*7c478bd9Sstevel@tonic-gate 	case RF_BADOWNER:
328*7c478bd9Sstevel@tonic-gate 		fp->rf_op = op;
329*7c478bd9Sstevel@tonic-gate 		fp->rf_reboot = reboot;
330*7c478bd9Sstevel@tonic-gate 		fp->rf_stat4 = stat4;
331*7c478bd9Sstevel@tonic-gate 		break;
332*7c478bd9Sstevel@tonic-gate 	case RF_RENEW_EXPIRED:
333*7c478bd9Sstevel@tonic-gate 		break;
334*7c478bd9Sstevel@tonic-gate 	case RF_ERR:
335*7c478bd9Sstevel@tonic-gate 		fp->rf_op = op;
336*7c478bd9Sstevel@tonic-gate 		fp->rf_reboot = reboot;
337*7c478bd9Sstevel@tonic-gate 		fp->rf_stat4 = stat4;
338*7c478bd9Sstevel@tonic-gate 		fp->rf_action = raction;
339*7c478bd9Sstevel@tonic-gate 		fp->rf_error = error;
340*7c478bd9Sstevel@tonic-gate 		break;
341*7c478bd9Sstevel@tonic-gate 	case RF_SRV_OK:
342*7c478bd9Sstevel@tonic-gate 		break;
343*7c478bd9Sstevel@tonic-gate 	case RF_SRV_NOT_RESPOND:
344*7c478bd9Sstevel@tonic-gate 		break;
345*7c478bd9Sstevel@tonic-gate 	case RF_SRVS_OK:
346*7c478bd9Sstevel@tonic-gate 		break;
347*7c478bd9Sstevel@tonic-gate 	case RF_SRVS_NOT_RESPOND:
348*7c478bd9Sstevel@tonic-gate 		gethrestime(&fp->rf_time);
349*7c478bd9Sstevel@tonic-gate 		break;
350*7c478bd9Sstevel@tonic-gate 	case RF_DELMAP_CB_ERR:
351*7c478bd9Sstevel@tonic-gate 		fp->rf_op = op;
352*7c478bd9Sstevel@tonic-gate 		fp->rf_stat4 = stat4;
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 		rp1 = VTOR4(vp);
355*7c478bd9Sstevel@tonic-gate 		fp->rf_rp1 = rp1;
356*7c478bd9Sstevel@tonic-gate 		if (rp1 && rp1->r_svnode.sv_name)
357*7c478bd9Sstevel@tonic-gate 			fp->rf_char1 = fn_path(rp1->r_svnode.sv_name);
358*7c478bd9Sstevel@tonic-gate 		else
359*7c478bd9Sstevel@tonic-gate 			fp->rf_char1 = NULL;
360*7c478bd9Sstevel@tonic-gate 		break;
361*7c478bd9Sstevel@tonic-gate 	default:
362*7c478bd9Sstevel@tonic-gate 		zcmn_err(getzoneid(), CE_NOTE, "illegal fact %d", id);
363*7c478bd9Sstevel@tonic-gate 		break;
364*7c478bd9Sstevel@tonic-gate 	}
365*7c478bd9Sstevel@tonic-gate }
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate /*
368*7c478bd9Sstevel@tonic-gate  * Returns 1 if the event/fact is of a successful communication
369*7c478bd9Sstevel@tonic-gate  * from the server; 0 otherwise.
370*7c478bd9Sstevel@tonic-gate  */
371*7c478bd9Sstevel@tonic-gate static int
372*7c478bd9Sstevel@tonic-gate successful_comm(nfs4_debug_msg_t *msgp)
373*7c478bd9Sstevel@tonic-gate {
374*7c478bd9Sstevel@tonic-gate 	if (msgp->msg_type == RM_EVENT) {
375*7c478bd9Sstevel@tonic-gate 		switch (msgp->rmsg_u.msg_event.re_type) {
376*7c478bd9Sstevel@tonic-gate 		case RE_BAD_SEQID:
377*7c478bd9Sstevel@tonic-gate 		case RE_BADHANDLE:
378*7c478bd9Sstevel@tonic-gate 		case RE_FAIL_REMAP_LEN:
379*7c478bd9Sstevel@tonic-gate 		case RE_FAIL_REMAP_OP:
380*7c478bd9Sstevel@tonic-gate 		case RE_FILE_DIFF:
381*7c478bd9Sstevel@tonic-gate 		case RE_START:
382*7c478bd9Sstevel@tonic-gate 		case RE_UNEXPECTED_ACTION:
383*7c478bd9Sstevel@tonic-gate 		case RE_UNEXPECTED_ERRNO:
384*7c478bd9Sstevel@tonic-gate 		case RE_UNEXPECTED_STATUS:
385*7c478bd9Sstevel@tonic-gate 		case RE_WRONGSEC:
386*7c478bd9Sstevel@tonic-gate 			return (1);
387*7c478bd9Sstevel@tonic-gate 		case RE_CLIENTID:
388*7c478bd9Sstevel@tonic-gate 		case RE_DEAD_FILE:
389*7c478bd9Sstevel@tonic-gate 		case RE_END:
390*7c478bd9Sstevel@tonic-gate 		case RE_FAIL_RELOCK:
391*7c478bd9Sstevel@tonic-gate 		case RE_FAILOVER:
392*7c478bd9Sstevel@tonic-gate 		case RE_LOST_STATE:
393*7c478bd9Sstevel@tonic-gate 		case RE_OPENS_CHANGED:
394*7c478bd9Sstevel@tonic-gate 		case RE_SIGLOST:
395*7c478bd9Sstevel@tonic-gate 		case RE_SIGLOST_NO_DUMP:
396*7c478bd9Sstevel@tonic-gate 		case RE_LOST_STATE_BAD_OP:
397*7c478bd9Sstevel@tonic-gate 			return (0);
398*7c478bd9Sstevel@tonic-gate 		default:
399*7c478bd9Sstevel@tonic-gate 			return (0);
400*7c478bd9Sstevel@tonic-gate 		}
401*7c478bd9Sstevel@tonic-gate 	} else {
402*7c478bd9Sstevel@tonic-gate 		switch (msgp->rmsg_u.msg_fact.rf_type) {
403*7c478bd9Sstevel@tonic-gate 		case RF_BADOWNER:
404*7c478bd9Sstevel@tonic-gate 		case RF_ERR:
405*7c478bd9Sstevel@tonic-gate 		case RF_RENEW_EXPIRED:
406*7c478bd9Sstevel@tonic-gate 		case RF_SRV_OK:
407*7c478bd9Sstevel@tonic-gate 		case RF_SRVS_OK:
408*7c478bd9Sstevel@tonic-gate 		case RF_DELMAP_CB_ERR:
409*7c478bd9Sstevel@tonic-gate 			return (1);
410*7c478bd9Sstevel@tonic-gate 		case RF_SRV_NOT_RESPOND:
411*7c478bd9Sstevel@tonic-gate 		case RF_SRVS_NOT_RESPOND:
412*7c478bd9Sstevel@tonic-gate 			return (0);
413*7c478bd9Sstevel@tonic-gate 		default:
414*7c478bd9Sstevel@tonic-gate 			return (0);
415*7c478bd9Sstevel@tonic-gate 		}
416*7c478bd9Sstevel@tonic-gate 	}
417*7c478bd9Sstevel@tonic-gate }
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate /*
420*7c478bd9Sstevel@tonic-gate  * Iterate backwards through the mi's mi_msg_list to find the earliest
421*7c478bd9Sstevel@tonic-gate  * message that we should find relevant facts to investigate.
422*7c478bd9Sstevel@tonic-gate  */
423*7c478bd9Sstevel@tonic-gate static nfs4_debug_msg_t *
424*7c478bd9Sstevel@tonic-gate find_beginning(nfs4_debug_msg_t *first_msg, mntinfo4_t *mi)
425*7c478bd9Sstevel@tonic-gate {
426*7c478bd9Sstevel@tonic-gate 	nfs4_debug_msg_t	*oldest_msg, *cur_msg;
427*7c478bd9Sstevel@tonic-gate 	time_t			lease;
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&mi->mi_msg_list_lock));
430*7c478bd9Sstevel@tonic-gate 	if (mi->mi_lease_period > 0)
431*7c478bd9Sstevel@tonic-gate 		lease = 2 * mi->mi_lease_period;
432*7c478bd9Sstevel@tonic-gate 	else
433*7c478bd9Sstevel@tonic-gate 		lease = DEFAULT_LEASE;
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	oldest_msg = first_msg;
436*7c478bd9Sstevel@tonic-gate 	cur_msg = list_prev(&mi->mi_msg_list, first_msg);
437*7c478bd9Sstevel@tonic-gate 	while (cur_msg &&
438*7c478bd9Sstevel@tonic-gate 	    first_msg->msg_time.tv_sec - cur_msg->msg_time.tv_sec < lease) {
439*7c478bd9Sstevel@tonic-gate 		oldest_msg = cur_msg;
440*7c478bd9Sstevel@tonic-gate 		if ((cur_msg->msg_type == RM_FACT) &&
441*7c478bd9Sstevel@tonic-gate 		    (cur_msg->rmsg_u.msg_fact.rf_type == RF_SRV_OK)) {
442*7c478bd9Sstevel@tonic-gate 			/* find where we lost contact with the server */
443*7c478bd9Sstevel@tonic-gate 			while (cur_msg) {
444*7c478bd9Sstevel@tonic-gate 				if ((cur_msg->msg_type == RM_FACT) &&
445*7c478bd9Sstevel@tonic-gate 				    (cur_msg->rmsg_u.msg_fact.rf_type ==
446*7c478bd9Sstevel@tonic-gate 				    RF_SRV_NOT_RESPOND))
447*7c478bd9Sstevel@tonic-gate 					break;
448*7c478bd9Sstevel@tonic-gate 				oldest_msg = cur_msg;
449*7c478bd9Sstevel@tonic-gate 				cur_msg = list_prev(&mi->mi_msg_list, cur_msg);
450*7c478bd9Sstevel@tonic-gate 			}
451*7c478bd9Sstevel@tonic-gate 			/*
452*7c478bd9Sstevel@tonic-gate 			 * Find the first successful message before
453*7c478bd9Sstevel@tonic-gate 			 * we lost contact with the server.
454*7c478bd9Sstevel@tonic-gate 			 */
455*7c478bd9Sstevel@tonic-gate 			if (cur_msg) {
456*7c478bd9Sstevel@tonic-gate 				cur_msg = list_prev(&mi->mi_msg_list, cur_msg);
457*7c478bd9Sstevel@tonic-gate 				while (cur_msg && !successful_comm(cur_msg)) {
458*7c478bd9Sstevel@tonic-gate 					oldest_msg = cur_msg;
459*7c478bd9Sstevel@tonic-gate 					cur_msg = list_prev(&mi->mi_msg_list,
460*7c478bd9Sstevel@tonic-gate 					    cur_msg);
461*7c478bd9Sstevel@tonic-gate 				}
462*7c478bd9Sstevel@tonic-gate 			}
463*7c478bd9Sstevel@tonic-gate 			/*
464*7c478bd9Sstevel@tonic-gate 			 * If we're not at the dummy head pointer,
465*7c478bd9Sstevel@tonic-gate 			 * set the oldest and current message.
466*7c478bd9Sstevel@tonic-gate 			 */
467*7c478bd9Sstevel@tonic-gate 			if (cur_msg) {
468*7c478bd9Sstevel@tonic-gate 				first_msg = cur_msg;
469*7c478bd9Sstevel@tonic-gate 				oldest_msg = cur_msg;
470*7c478bd9Sstevel@tonic-gate 				cur_msg = list_prev(&mi->mi_msg_list, cur_msg);
471*7c478bd9Sstevel@tonic-gate 			}
472*7c478bd9Sstevel@tonic-gate 		} else
473*7c478bd9Sstevel@tonic-gate 			cur_msg = list_prev(&mi->mi_msg_list, cur_msg);
474*7c478bd9Sstevel@tonic-gate 	}
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	return (oldest_msg);
477*7c478bd9Sstevel@tonic-gate }
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate /*
480*7c478bd9Sstevel@tonic-gate  * Returns 1 if facts have been found; 0 otherwise.
481*7c478bd9Sstevel@tonic-gate  */
482*7c478bd9Sstevel@tonic-gate static int
483*7c478bd9Sstevel@tonic-gate get_facts(nfs4_debug_msg_t *msgp, nfs4_rfact_t *ret_fp, char **mnt_pt,
484*7c478bd9Sstevel@tonic-gate mntinfo4_t *mi)
485*7c478bd9Sstevel@tonic-gate {
486*7c478bd9Sstevel@tonic-gate 	nfs4_debug_msg_t	*cur_msg, *oldest_msg;
487*7c478bd9Sstevel@tonic-gate 	nfs4_rfact_t		*cur_fp;
488*7c478bd9Sstevel@tonic-gate 	int			found_a_fact = 0;
489*7c478bd9Sstevel@tonic-gate 	int			len;
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 	cur_msg = msgp;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	/* find the oldest msg to search backwards to */
494*7c478bd9Sstevel@tonic-gate 	oldest_msg = find_beginning(cur_msg, mi);
495*7c478bd9Sstevel@tonic-gate 	ASSERT(oldest_msg != NULL);
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	/*
498*7c478bd9Sstevel@tonic-gate 	 * Create a fact sheet by searching from our current message
499*7c478bd9Sstevel@tonic-gate 	 * backwards to the 'oldest_msg', recording facts along the way
500*7c478bd9Sstevel@tonic-gate 	 * until we found facts that have been inspected by another time.
501*7c478bd9Sstevel@tonic-gate 	 */
502*7c478bd9Sstevel@tonic-gate 	while (cur_msg && cur_msg != list_prev(&mi->mi_msg_list, oldest_msg)) {
503*7c478bd9Sstevel@tonic-gate 		if (cur_msg->msg_type != RM_FACT) {
504*7c478bd9Sstevel@tonic-gate 			cur_msg = list_prev(&mi->mi_msg_list, cur_msg);
505*7c478bd9Sstevel@tonic-gate 			continue;
506*7c478bd9Sstevel@tonic-gate 		}
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 		cur_fp = &cur_msg->rmsg_u.msg_fact;
509*7c478bd9Sstevel@tonic-gate 		/*
510*7c478bd9Sstevel@tonic-gate 		 * If this fact has already been looked at, then so
511*7c478bd9Sstevel@tonic-gate 		 * have all preceding facts.  Return Now.
512*7c478bd9Sstevel@tonic-gate 		 */
513*7c478bd9Sstevel@tonic-gate 		if (cur_fp->rf_status == RFS_INSPECT)
514*7c478bd9Sstevel@tonic-gate 			return (found_a_fact);
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 		cur_fp->rf_status = RFS_INSPECT;
517*7c478bd9Sstevel@tonic-gate 		found_a_fact = 1;
518*7c478bd9Sstevel@tonic-gate 		switch (cur_fp->rf_type) {
519*7c478bd9Sstevel@tonic-gate 		case RF_BADOWNER:
520*7c478bd9Sstevel@tonic-gate 			break;
521*7c478bd9Sstevel@tonic-gate 		case RF_ERR:
522*7c478bd9Sstevel@tonic-gate 			/*
523*7c478bd9Sstevel@tonic-gate 			 * Don't want to overwrite a fact that was
524*7c478bd9Sstevel@tonic-gate 			 * previously found during our current search.
525*7c478bd9Sstevel@tonic-gate 			 */
526*7c478bd9Sstevel@tonic-gate 			if (!ret_fp->rf_reboot)
527*7c478bd9Sstevel@tonic-gate 				ret_fp->rf_reboot = cur_fp->rf_reboot;
528*7c478bd9Sstevel@tonic-gate 			if (!ret_fp->rf_stat4)
529*7c478bd9Sstevel@tonic-gate 				ret_fp->rf_stat4 = cur_fp->rf_stat4;
530*7c478bd9Sstevel@tonic-gate 			if (!ret_fp->rf_action)
531*7c478bd9Sstevel@tonic-gate 				ret_fp->rf_action = cur_fp->rf_action;
532*7c478bd9Sstevel@tonic-gate 			break;
533*7c478bd9Sstevel@tonic-gate 		case RF_RENEW_EXPIRED:
534*7c478bd9Sstevel@tonic-gate 			if (cur_msg->msg_mntpt && !(*mnt_pt)) {
535*7c478bd9Sstevel@tonic-gate 				len = strlen(cur_msg->msg_mntpt) + 1;
536*7c478bd9Sstevel@tonic-gate 				*mnt_pt = kmem_alloc(len, KM_SLEEP);
537*7c478bd9Sstevel@tonic-gate 				bcopy(cur_msg->msg_mntpt, *mnt_pt, len);
538*7c478bd9Sstevel@tonic-gate 			}
539*7c478bd9Sstevel@tonic-gate 			break;
540*7c478bd9Sstevel@tonic-gate 		case RF_SRV_OK:
541*7c478bd9Sstevel@tonic-gate 			break;
542*7c478bd9Sstevel@tonic-gate 		case RF_SRV_NOT_RESPOND:
543*7c478bd9Sstevel@tonic-gate 			/*
544*7c478bd9Sstevel@tonic-gate 			 * Okay to overwrite this fact as
545*7c478bd9Sstevel@tonic-gate 			 * we want the earliest time.
546*7c478bd9Sstevel@tonic-gate 			 */
547*7c478bd9Sstevel@tonic-gate 			ret_fp->rf_time = cur_fp->rf_time;
548*7c478bd9Sstevel@tonic-gate 			break;
549*7c478bd9Sstevel@tonic-gate 		case RF_SRVS_OK:
550*7c478bd9Sstevel@tonic-gate 			break;
551*7c478bd9Sstevel@tonic-gate 		case RF_SRVS_NOT_RESPOND:
552*7c478bd9Sstevel@tonic-gate 			break;
553*7c478bd9Sstevel@tonic-gate 		case RF_DELMAP_CB_ERR:
554*7c478bd9Sstevel@tonic-gate 			break;
555*7c478bd9Sstevel@tonic-gate 		default:
556*7c478bd9Sstevel@tonic-gate 			zcmn_err(getzoneid(), CE_NOTE,
557*7c478bd9Sstevel@tonic-gate 			    "get facts: illegal fact %d", cur_fp->rf_type);
558*7c478bd9Sstevel@tonic-gate 			break;
559*7c478bd9Sstevel@tonic-gate 		}
560*7c478bd9Sstevel@tonic-gate 		cur_msg = list_prev(&mi->mi_msg_list, cur_msg);
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	return (found_a_fact);
564*7c478bd9Sstevel@tonic-gate }
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate /*
567*7c478bd9Sstevel@tonic-gate  * Returns 1 if this fact is identical to the last fact recorded
568*7c478bd9Sstevel@tonic-gate  * (only checks for a match within the last 2 lease periods).
569*7c478bd9Sstevel@tonic-gate  */
570*7c478bd9Sstevel@tonic-gate static int
571*7c478bd9Sstevel@tonic-gate facts_same(nfs4_debug_msg_t *cur_msg, nfs4_debug_msg_t *new_msg,
572*7c478bd9Sstevel@tonic-gate     mntinfo4_t *mi)
573*7c478bd9Sstevel@tonic-gate {
574*7c478bd9Sstevel@tonic-gate 	nfs4_rfact_t	*fp1, *fp2;
575*7c478bd9Sstevel@tonic-gate 	int		lease, len;
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&mi->mi_msg_list_lock));
578*7c478bd9Sstevel@tonic-gate 	if (mi->mi_lease_period > 0)
579*7c478bd9Sstevel@tonic-gate 		lease = 2 * mi->mi_lease_period;
580*7c478bd9Sstevel@tonic-gate 	else
581*7c478bd9Sstevel@tonic-gate 		lease = DEFAULT_LEASE;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 	fp2 = &new_msg->rmsg_u.msg_fact;
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 	while (cur_msg &&
586*7c478bd9Sstevel@tonic-gate 	    new_msg->msg_time.tv_sec - cur_msg->msg_time.tv_sec < lease) {
587*7c478bd9Sstevel@tonic-gate 		if (cur_msg->msg_type != RM_FACT) {
588*7c478bd9Sstevel@tonic-gate 			cur_msg = list_prev(&mi->mi_msg_list, cur_msg);
589*7c478bd9Sstevel@tonic-gate 			continue;
590*7c478bd9Sstevel@tonic-gate 		}
591*7c478bd9Sstevel@tonic-gate 		fp1 = &cur_msg->rmsg_u.msg_fact;
592*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_type != fp2->rf_type)
593*7c478bd9Sstevel@tonic-gate 			return (0);
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 		/* now actually compare the facts */
596*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_action != fp2->rf_action)
597*7c478bd9Sstevel@tonic-gate 			return (0);
598*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_stat4 != fp2->rf_stat4)
599*7c478bd9Sstevel@tonic-gate 			return (0);
600*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_reboot != fp2->rf_reboot)
601*7c478bd9Sstevel@tonic-gate 			return (0);
602*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_op != fp2->rf_op)
603*7c478bd9Sstevel@tonic-gate 			return (0);
604*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_time.tv_sec != fp2->rf_time.tv_sec)
605*7c478bd9Sstevel@tonic-gate 			return (0);
606*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_error != fp2->rf_error)
607*7c478bd9Sstevel@tonic-gate 			return (0);
608*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_rp1 != fp2->rf_rp1)
609*7c478bd9Sstevel@tonic-gate 			return (0);
610*7c478bd9Sstevel@tonic-gate 		if (cur_msg->msg_srv != NULL) {
611*7c478bd9Sstevel@tonic-gate 			if (new_msg->msg_srv == NULL)
612*7c478bd9Sstevel@tonic-gate 				return (0);
613*7c478bd9Sstevel@tonic-gate 			len = strlen(cur_msg->msg_srv);
614*7c478bd9Sstevel@tonic-gate 			if (strncmp(cur_msg->msg_srv, new_msg->msg_srv,
615*7c478bd9Sstevel@tonic-gate 				len) != 0)
616*7c478bd9Sstevel@tonic-gate 				return (0);
617*7c478bd9Sstevel@tonic-gate 		} else if (new_msg->msg_srv != NULL) {
618*7c478bd9Sstevel@tonic-gate 			return (0);
619*7c478bd9Sstevel@tonic-gate 		}
620*7c478bd9Sstevel@tonic-gate 		if (cur_msg->msg_mntpt != NULL) {
621*7c478bd9Sstevel@tonic-gate 			if (new_msg->msg_mntpt == NULL)
622*7c478bd9Sstevel@tonic-gate 				return (0);
623*7c478bd9Sstevel@tonic-gate 			len = strlen(cur_msg->msg_mntpt);
624*7c478bd9Sstevel@tonic-gate 			if (strncmp(cur_msg->msg_mntpt, new_msg->msg_mntpt,
625*7c478bd9Sstevel@tonic-gate 				len) != 0)
626*7c478bd9Sstevel@tonic-gate 				return (0);
627*7c478bd9Sstevel@tonic-gate 		} else if (new_msg->msg_mntpt != NULL) {
628*7c478bd9Sstevel@tonic-gate 			return (0);
629*7c478bd9Sstevel@tonic-gate 		}
630*7c478bd9Sstevel@tonic-gate 		if (fp1->rf_char1 != NULL) {
631*7c478bd9Sstevel@tonic-gate 			if (fp2->rf_char1 == NULL)
632*7c478bd9Sstevel@tonic-gate 				return (0);
633*7c478bd9Sstevel@tonic-gate 			len = strlen(fp1->rf_char1);
634*7c478bd9Sstevel@tonic-gate 			if (strncmp(fp1->rf_char1, fp2->rf_char1, len) != 0)
635*7c478bd9Sstevel@tonic-gate 				return (0);
636*7c478bd9Sstevel@tonic-gate 		} else if (fp2->rf_char1 != NULL) {
637*7c478bd9Sstevel@tonic-gate 			return (0);
638*7c478bd9Sstevel@tonic-gate 		}
639*7c478bd9Sstevel@tonic-gate 		return (1);
640*7c478bd9Sstevel@tonic-gate 	}
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 	return (0);
643*7c478bd9Sstevel@tonic-gate }
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate /*
646*7c478bd9Sstevel@tonic-gate  * Returns 1 if these two messages are identical; 0 otherwise.
647*7c478bd9Sstevel@tonic-gate  */
648*7c478bd9Sstevel@tonic-gate static int
649*7c478bd9Sstevel@tonic-gate events_same(nfs4_debug_msg_t *cur_msg, nfs4_debug_msg_t *new_msg,
650*7c478bd9Sstevel@tonic-gate     mntinfo4_t *mi)
651*7c478bd9Sstevel@tonic-gate {
652*7c478bd9Sstevel@tonic-gate 	nfs4_revent_t	*ep1, *ep2;
653*7c478bd9Sstevel@tonic-gate 	int		len;
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 	/* find the last event, bypassing all facts */
656*7c478bd9Sstevel@tonic-gate 	while (cur_msg && cur_msg->msg_type != RM_EVENT)
657*7c478bd9Sstevel@tonic-gate 		cur_msg = list_prev(&mi->mi_msg_list, cur_msg);
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	if (!cur_msg)
660*7c478bd9Sstevel@tonic-gate 		return (0);
661*7c478bd9Sstevel@tonic-gate 
662*7c478bd9Sstevel@tonic-gate 	if (cur_msg->msg_type != RM_EVENT)
663*7c478bd9Sstevel@tonic-gate 		return (0);
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	ep1 = &cur_msg->rmsg_u.msg_event;
666*7c478bd9Sstevel@tonic-gate 	ep2 = &new_msg->rmsg_u.msg_event;
667*7c478bd9Sstevel@tonic-gate 	if (ep1->re_type != ep2->re_type)
668*7c478bd9Sstevel@tonic-gate 		return (0);
669*7c478bd9Sstevel@tonic-gate 
670*7c478bd9Sstevel@tonic-gate 	/*
671*7c478bd9Sstevel@tonic-gate 	 * Since we zalloc the buffer, then the two nfs4_debug_msg's
672*7c478bd9Sstevel@tonic-gate 	 * must match up even if all the fields weren't filled in
673*7c478bd9Sstevel@tonic-gate 	 * the first place.
674*7c478bd9Sstevel@tonic-gate 	 */
675*7c478bd9Sstevel@tonic-gate 	if (ep1->re_mi != ep2->re_mi)
676*7c478bd9Sstevel@tonic-gate 		return (0);
677*7c478bd9Sstevel@tonic-gate 	if (ep1->re_uint != ep2->re_uint)
678*7c478bd9Sstevel@tonic-gate 		return (0);
679*7c478bd9Sstevel@tonic-gate 	if (ep1->re_stat4 != ep2->re_stat4)
680*7c478bd9Sstevel@tonic-gate 		return (0);
681*7c478bd9Sstevel@tonic-gate 	if (ep1->re_pid != ep2->re_pid)
682*7c478bd9Sstevel@tonic-gate 		return (0);
683*7c478bd9Sstevel@tonic-gate 	if (ep1->re_rp1 != ep2->re_rp1)
684*7c478bd9Sstevel@tonic-gate 		return (0);
685*7c478bd9Sstevel@tonic-gate 	if (ep1->re_rp2 != ep2->re_rp2)
686*7c478bd9Sstevel@tonic-gate 		return (0);
687*7c478bd9Sstevel@tonic-gate 	if (ep1->re_tag1 != ep2->re_tag1)
688*7c478bd9Sstevel@tonic-gate 		return (0);
689*7c478bd9Sstevel@tonic-gate 	if (ep1->re_tag2 != ep2->re_tag2)
690*7c478bd9Sstevel@tonic-gate 		return (0);
691*7c478bd9Sstevel@tonic-gate 	if (ep1->re_seqid1 != ep2->re_seqid1)
692*7c478bd9Sstevel@tonic-gate 		return (0);
693*7c478bd9Sstevel@tonic-gate 	if (ep1->re_seqid2 != ep2->re_seqid2)
694*7c478bd9Sstevel@tonic-gate 		return (0);
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	if (cur_msg->msg_srv != NULL) {
697*7c478bd9Sstevel@tonic-gate 		if (new_msg->msg_srv == NULL)
698*7c478bd9Sstevel@tonic-gate 			return (0);
699*7c478bd9Sstevel@tonic-gate 		len = strlen(cur_msg->msg_srv);
700*7c478bd9Sstevel@tonic-gate 		if (strncmp(cur_msg->msg_srv, new_msg->msg_srv, len) != 0)
701*7c478bd9Sstevel@tonic-gate 			return (0);
702*7c478bd9Sstevel@tonic-gate 	} else if (new_msg->msg_srv != NULL) {
703*7c478bd9Sstevel@tonic-gate 		return (0);
704*7c478bd9Sstevel@tonic-gate 	}
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 	if (ep1->re_char1 != NULL) {
707*7c478bd9Sstevel@tonic-gate 		if (ep2->re_char1 == NULL)
708*7c478bd9Sstevel@tonic-gate 			return (0);
709*7c478bd9Sstevel@tonic-gate 		len = strlen(ep1->re_char1);
710*7c478bd9Sstevel@tonic-gate 		if (strncmp(ep1->re_char1, ep2->re_char1, len) != 0)
711*7c478bd9Sstevel@tonic-gate 			return (0);
712*7c478bd9Sstevel@tonic-gate 	} else if (ep2->re_char1 != NULL) {
713*7c478bd9Sstevel@tonic-gate 		return (0);
714*7c478bd9Sstevel@tonic-gate 	}
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	if (ep1->re_char2 != NULL) {
717*7c478bd9Sstevel@tonic-gate 		if (ep2->re_char2 == NULL)
718*7c478bd9Sstevel@tonic-gate 			return (0);
719*7c478bd9Sstevel@tonic-gate 		len = strlen(ep1->re_char2);
720*7c478bd9Sstevel@tonic-gate 		if (strncmp(ep1->re_char2, ep2->re_char2, len) != 0)
721*7c478bd9Sstevel@tonic-gate 			return (0);
722*7c478bd9Sstevel@tonic-gate 	} else if (ep2->re_char2 != NULL) {
723*7c478bd9Sstevel@tonic-gate 		return (0);
724*7c478bd9Sstevel@tonic-gate 	}
725*7c478bd9Sstevel@tonic-gate 
726*7c478bd9Sstevel@tonic-gate 	if (cur_msg->msg_mntpt != NULL) {
727*7c478bd9Sstevel@tonic-gate 		if (new_msg->msg_mntpt == NULL)
728*7c478bd9Sstevel@tonic-gate 			return (0);
729*7c478bd9Sstevel@tonic-gate 		len = strlen(cur_msg->msg_mntpt);
730*7c478bd9Sstevel@tonic-gate 		if (strncmp(cur_msg->msg_mntpt, cur_msg->msg_mntpt, len) != 0)
731*7c478bd9Sstevel@tonic-gate 			return (0);
732*7c478bd9Sstevel@tonic-gate 	} else if (new_msg->msg_mntpt != NULL) {
733*7c478bd9Sstevel@tonic-gate 		return (0);
734*7c478bd9Sstevel@tonic-gate 	}
735*7c478bd9Sstevel@tonic-gate 
736*7c478bd9Sstevel@tonic-gate 	return (1);
737*7c478bd9Sstevel@tonic-gate }
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate /*
740*7c478bd9Sstevel@tonic-gate  * Free up a recovery event.
741*7c478bd9Sstevel@tonic-gate  */
742*7c478bd9Sstevel@tonic-gate static void
743*7c478bd9Sstevel@tonic-gate free_event(nfs4_revent_t *ep)
744*7c478bd9Sstevel@tonic-gate {
745*7c478bd9Sstevel@tonic-gate 	int	len;
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate 	if (ep->re_char1) {
748*7c478bd9Sstevel@tonic-gate 		len = strlen(ep->re_char1) + 1;
749*7c478bd9Sstevel@tonic-gate 		kmem_free(ep->re_char1, len);
750*7c478bd9Sstevel@tonic-gate 	}
751*7c478bd9Sstevel@tonic-gate 	if (ep->re_char2) {
752*7c478bd9Sstevel@tonic-gate 		len = strlen(ep->re_char2) + 1;
753*7c478bd9Sstevel@tonic-gate 		kmem_free(ep->re_char2, len);
754*7c478bd9Sstevel@tonic-gate 	}
755*7c478bd9Sstevel@tonic-gate }
756*7c478bd9Sstevel@tonic-gate 
757*7c478bd9Sstevel@tonic-gate /*
758*7c478bd9Sstevel@tonic-gate  * Free up a recovery fact.
759*7c478bd9Sstevel@tonic-gate  */
760*7c478bd9Sstevel@tonic-gate static void
761*7c478bd9Sstevel@tonic-gate free_fact(nfs4_rfact_t *fp)
762*7c478bd9Sstevel@tonic-gate {
763*7c478bd9Sstevel@tonic-gate 	int	len;
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 	if (fp->rf_char1) {
766*7c478bd9Sstevel@tonic-gate 		len = strlen(fp->rf_char1) + 1;
767*7c478bd9Sstevel@tonic-gate 		kmem_free(fp->rf_char1, len);
768*7c478bd9Sstevel@tonic-gate 	}
769*7c478bd9Sstevel@tonic-gate }
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate /*
772*7c478bd9Sstevel@tonic-gate  * Free up the message.
773*7c478bd9Sstevel@tonic-gate  */
774*7c478bd9Sstevel@tonic-gate void
775*7c478bd9Sstevel@tonic-gate nfs4_free_msg(nfs4_debug_msg_t *msg)
776*7c478bd9Sstevel@tonic-gate {
777*7c478bd9Sstevel@tonic-gate 	int len;
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	if (msg->msg_type == RM_EVENT)
780*7c478bd9Sstevel@tonic-gate 		free_event(&msg->rmsg_u.msg_event);
781*7c478bd9Sstevel@tonic-gate 	else
782*7c478bd9Sstevel@tonic-gate 		free_fact(&msg->rmsg_u.msg_fact);
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 	if (msg->msg_srv) {
785*7c478bd9Sstevel@tonic-gate 		len = strlen(msg->msg_srv) + 1;
786*7c478bd9Sstevel@tonic-gate 		kmem_free(msg->msg_srv, len);
787*7c478bd9Sstevel@tonic-gate 	}
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate 	if (msg->msg_mntpt) {
790*7c478bd9Sstevel@tonic-gate 		len = strlen(msg->msg_mntpt) + 1;
791*7c478bd9Sstevel@tonic-gate 		kmem_free(msg->msg_mntpt, len);
792*7c478bd9Sstevel@tonic-gate 	}
793*7c478bd9Sstevel@tonic-gate 
794*7c478bd9Sstevel@tonic-gate 	/* free up the data structure itself */
795*7c478bd9Sstevel@tonic-gate 	kmem_free(msg, sizeof (*msg));
796*7c478bd9Sstevel@tonic-gate }
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate /*
799*7c478bd9Sstevel@tonic-gate  * Prints out the interesting facts for recovery events:
800*7c478bd9Sstevel@tonic-gate  * -DEAD_FILE
801*7c478bd9Sstevel@tonic-gate  * -SIGLOST(_NO_DUMP)
802*7c478bd9Sstevel@tonic-gate  */
803*7c478bd9Sstevel@tonic-gate static void
804*7c478bd9Sstevel@tonic-gate print_facts(nfs4_debug_msg_t *msg, mntinfo4_t *mi)
805*7c478bd9Sstevel@tonic-gate {
806*7c478bd9Sstevel@tonic-gate 	nfs4_rfact_t *fp;
807*7c478bd9Sstevel@tonic-gate 	char *mount_pt;
808*7c478bd9Sstevel@tonic-gate 	int len;
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 	if (msg->rmsg_u.msg_event.re_type != RE_DEAD_FILE &&
811*7c478bd9Sstevel@tonic-gate 	    msg->rmsg_u.msg_event.re_type != RE_SIGLOST &&
812*7c478bd9Sstevel@tonic-gate 	    msg->rmsg_u.msg_event.re_type != RE_SIGLOST_NO_DUMP)
813*7c478bd9Sstevel@tonic-gate 		return;
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 	fp = kmem_zalloc(sizeof (*fp), KM_SLEEP);
816*7c478bd9Sstevel@tonic-gate 	mount_pt = NULL;
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate 	if (get_facts(msg, fp, &mount_pt, mi)) {
819*7c478bd9Sstevel@tonic-gate 		char	time[256];
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate 		if (fp->rf_time.tv_sec)
823*7c478bd9Sstevel@tonic-gate 			(void) snprintf(time, 256, "%ld",
824*7c478bd9Sstevel@tonic-gate 			    (gethrestime_sec() - fp->rf_time.tv_sec)/60);
825*7c478bd9Sstevel@tonic-gate 		zcmn_err(mi->mi_zone->zone_id, CE_NOTE,
826*7c478bd9Sstevel@tonic-gate 		    "!NFS4 FACT SHEET: %s%s %s%s %s %s%s%s %s%s",
827*7c478bd9Sstevel@tonic-gate 		    fp->rf_action ? "\n Action: " : "",
828*7c478bd9Sstevel@tonic-gate 		    fp->rf_action ? nfs4_recov_action_to_str(fp->rf_action) :
829*7c478bd9Sstevel@tonic-gate 		    "",
830*7c478bd9Sstevel@tonic-gate 		    fp->rf_stat4 ? "\n NFS4 error: " : "",
831*7c478bd9Sstevel@tonic-gate 		    fp->rf_stat4 ? nfs4_stat_to_str(fp->rf_stat4) : "",
832*7c478bd9Sstevel@tonic-gate 		    fp->rf_reboot ? "\n Suspected server reboot. " : "",
833*7c478bd9Sstevel@tonic-gate 		    fp->rf_time.tv_sec ? "\n Server was down for " : "",
834*7c478bd9Sstevel@tonic-gate 		    fp->rf_time.tv_sec ? time : "",
835*7c478bd9Sstevel@tonic-gate 		    fp->rf_time.tv_sec ? " minutes." : "",
836*7c478bd9Sstevel@tonic-gate 		    mount_pt ? " \n Client's lease expired on mount " : "",
837*7c478bd9Sstevel@tonic-gate 		    mount_pt ? mount_pt : "");
838*7c478bd9Sstevel@tonic-gate 	}
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 	if (mount_pt) {
841*7c478bd9Sstevel@tonic-gate 		len = strlen(mount_pt) + 1;
842*7c478bd9Sstevel@tonic-gate 		kmem_free(mount_pt, len);
843*7c478bd9Sstevel@tonic-gate 	}
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate 	/* free the fact struct itself */
846*7c478bd9Sstevel@tonic-gate 	if (fp)
847*7c478bd9Sstevel@tonic-gate 		kmem_free(fp, sizeof (*fp));
848*7c478bd9Sstevel@tonic-gate }
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate /*
851*7c478bd9Sstevel@tonic-gate  * Print an event message to /var/adm/messages
852*7c478bd9Sstevel@tonic-gate  * The last argument to this fuction dictates the repeat status
853*7c478bd9Sstevel@tonic-gate  * of the event. If set to 1, it means that we are dumping this
854*7c478bd9Sstevel@tonic-gate  * event and it will _never_ be printed after this time. Else if
855*7c478bd9Sstevel@tonic-gate  * set to 0 it will be printed again.
856*7c478bd9Sstevel@tonic-gate  */
857*7c478bd9Sstevel@tonic-gate static void
858*7c478bd9Sstevel@tonic-gate queue_print_event(nfs4_debug_msg_t *msg, mntinfo4_t *mi, int dump)
859*7c478bd9Sstevel@tonic-gate {
860*7c478bd9Sstevel@tonic-gate 	nfs4_revent_t		*ep;
861*7c478bd9Sstevel@tonic-gate 	zoneid_t		zoneid;
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 	ep = &msg->rmsg_u.msg_event;
864*7c478bd9Sstevel@tonic-gate 	zoneid = mi->mi_zone->zone_id;
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 	switch (ep->re_type) {
867*7c478bd9Sstevel@tonic-gate 	case RE_BAD_SEQID:
868*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
869*7c478bd9Sstevel@tonic-gate 		    "Operation %s for file %s (rnode_pt 0x%p), pid %d using "
870*7c478bd9Sstevel@tonic-gate 		    "seqid %d got %s.  Last good seqid was %d for "
871*7c478bd9Sstevel@tonic-gate 		    "operation %s.",
872*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt,
873*7c478bd9Sstevel@tonic-gate 		    nfs4_ctags[ep->re_tag1].ct_str, ep->re_char1,
874*7c478bd9Sstevel@tonic-gate 		    (void *)ep->re_rp1, ep->re_pid, ep->re_seqid1,
875*7c478bd9Sstevel@tonic-gate 		    nfs4_stat_to_str(ep->re_stat4), ep->re_seqid2,
876*7c478bd9Sstevel@tonic-gate 		    nfs4_ctags[ep->re_tag2].ct_str);
877*7c478bd9Sstevel@tonic-gate 		break;
878*7c478bd9Sstevel@tonic-gate 	case RE_BADHANDLE:
879*7c478bd9Sstevel@tonic-gate 		ASSERT(ep->re_rp1 != NULL);
880*7c478bd9Sstevel@tonic-gate 		if (ep->re_char1 != NULL) {
881*7c478bd9Sstevel@tonic-gate 			zcmn_err(zoneid, CE_NOTE,
882*7c478bd9Sstevel@tonic-gate 			    "![NFS4][Server: %s][Mntpt: %s]"
883*7c478bd9Sstevel@tonic-gate 			    "server %s said filehandle was "
884*7c478bd9Sstevel@tonic-gate 			    "invalid for file: %s (rnode_pt 0x%p) on mount %s",
885*7c478bd9Sstevel@tonic-gate 			    msg->msg_srv, msg->msg_mntpt, msg->msg_srv,
886*7c478bd9Sstevel@tonic-gate 			    ep->re_char1, (void *)ep->re_rp1, msg->msg_mntpt);
887*7c478bd9Sstevel@tonic-gate 		} else {
888*7c478bd9Sstevel@tonic-gate 			zcmn_err(zoneid, CE_NOTE,
889*7c478bd9Sstevel@tonic-gate 			    "![NFS4][Server: %s][Mntpt: %s]"
890*7c478bd9Sstevel@tonic-gate 			    "server %s said filehandle was "
891*7c478bd9Sstevel@tonic-gate 			    "invalid for file: (rnode_pt 0x%p) on mount %s"
892*7c478bd9Sstevel@tonic-gate 			    " for fh:", msg->msg_srv, msg->msg_mntpt,
893*7c478bd9Sstevel@tonic-gate 			    msg->msg_srv, (void *)ep->re_rp1, msg->msg_mntpt);
894*7c478bd9Sstevel@tonic-gate 			sfh4_printfhandle(ep->re_rp1->r_fh);
895*7c478bd9Sstevel@tonic-gate 		}
896*7c478bd9Sstevel@tonic-gate 		break;
897*7c478bd9Sstevel@tonic-gate 	case RE_CLIENTID:
898*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
899*7c478bd9Sstevel@tonic-gate 		    "Can't recover clientid on mount point %s "
900*7c478bd9Sstevel@tonic-gate 		    "(mi 0x%p) due to error %d (%s), for server %s.  Marking "
901*7c478bd9Sstevel@tonic-gate 		    "file system as unusable.",
902*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt, msg->msg_mntpt,
903*7c478bd9Sstevel@tonic-gate 		    (void *)ep->re_mi, ep->re_uint,
904*7c478bd9Sstevel@tonic-gate 		    nfs4_stat_to_str(ep->re_stat4),
905*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv);
906*7c478bd9Sstevel@tonic-gate 		break;
907*7c478bd9Sstevel@tonic-gate 	case RE_DEAD_FILE:
908*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
909*7c478bd9Sstevel@tonic-gate 		    "File %s (rnode_pt: %p) was closed due to NFS "
910*7c478bd9Sstevel@tonic-gate 		    "recovery error on server %s(%s %s)", msg->msg_srv,
911*7c478bd9Sstevel@tonic-gate 		    msg->msg_mntpt, ep->re_char1, (void *)ep->re_rp1,
912*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, ep->re_char2 ? ep->re_char2 : "",
913*7c478bd9Sstevel@tonic-gate 		    ep->re_stat4 ? nfs4_stat_to_str(ep->re_stat4) : "");
914*7c478bd9Sstevel@tonic-gate 		break;
915*7c478bd9Sstevel@tonic-gate 	case RE_END:
916*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
917*7c478bd9Sstevel@tonic-gate 		    "NFS Recovery done for mount %s (mi 0x%p) "
918*7c478bd9Sstevel@tonic-gate 		    "on server %s, rnode_pt1 %s (0x%p), "
919*7c478bd9Sstevel@tonic-gate 		    "rnode_pt2 %s (0x%p)", msg->msg_srv, msg->msg_mntpt,
920*7c478bd9Sstevel@tonic-gate 		    msg->msg_mntpt, (void *)ep->re_mi, msg->msg_srv,
921*7c478bd9Sstevel@tonic-gate 		    ep->re_char1, (void *)ep->re_rp1, ep->re_char2,
922*7c478bd9Sstevel@tonic-gate 		    (void *)ep->re_rp2);
923*7c478bd9Sstevel@tonic-gate 		break;
924*7c478bd9Sstevel@tonic-gate 	case RE_FAIL_RELOCK:
925*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
926*7c478bd9Sstevel@tonic-gate 		    "Couldn't reclaim lock for pid %d for "
927*7c478bd9Sstevel@tonic-gate 		    "file %s (rnode_pt 0x%p) on (server %s): error %d",
928*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt, ep->re_pid, ep->re_char1,
929*7c478bd9Sstevel@tonic-gate 		    (void *)ep->re_rp1, msg->msg_srv,
930*7c478bd9Sstevel@tonic-gate 		    ep->re_uint ? ep->re_uint : ep->re_stat4);
931*7c478bd9Sstevel@tonic-gate 		break;
932*7c478bd9Sstevel@tonic-gate 	case RE_FAIL_REMAP_LEN:
933*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
934*7c478bd9Sstevel@tonic-gate 		    "remap_lookup: server %s returned bad "
935*7c478bd9Sstevel@tonic-gate 		    "fhandle length (%d)", msg->msg_srv, msg->msg_mntpt,
936*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, ep->re_uint);
937*7c478bd9Sstevel@tonic-gate 		break;
938*7c478bd9Sstevel@tonic-gate 	case RE_FAIL_REMAP_OP:
939*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
940*7c478bd9Sstevel@tonic-gate 		    "remap_lookup: didn't get expected OP_GETFH"
941*7c478bd9Sstevel@tonic-gate 		    " for server %s", msg->msg_srv, msg->msg_mntpt,
942*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv);
943*7c478bd9Sstevel@tonic-gate 		break;
944*7c478bd9Sstevel@tonic-gate 	case RE_FAILOVER:
945*7c478bd9Sstevel@tonic-gate 		if (ep->re_char1)
946*7c478bd9Sstevel@tonic-gate 			zcmn_err(zoneid, CE_NOTE,
947*7c478bd9Sstevel@tonic-gate 			    "![NFS4][Server: %s][Mntpt: %s]"
948*7c478bd9Sstevel@tonic-gate 			    "failing over from %s to %s", msg->msg_srv,
949*7c478bd9Sstevel@tonic-gate 			    msg->msg_mntpt, msg->msg_srv, ep->re_char1);
950*7c478bd9Sstevel@tonic-gate 		else
951*7c478bd9Sstevel@tonic-gate 			zcmn_err(zoneid, CE_NOTE,
952*7c478bd9Sstevel@tonic-gate 			    "![NFS4][Server: %s][Mntpt: %s]"
953*7c478bd9Sstevel@tonic-gate 			    "NFS4: failing over: selecting "
954*7c478bd9Sstevel@tonic-gate 			    "original server %s", msg->msg_srv, msg->msg_mntpt,
955*7c478bd9Sstevel@tonic-gate 			    msg->msg_srv);
956*7c478bd9Sstevel@tonic-gate 		break;
957*7c478bd9Sstevel@tonic-gate 	case RE_FILE_DIFF:
958*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
959*7c478bd9Sstevel@tonic-gate 		    "File %s (rnode_pt: %p) on server %s was closed "
960*7c478bd9Sstevel@tonic-gate 		    "and failed attempted failover since its is different than "
961*7c478bd9Sstevel@tonic-gate 		    "the original file", msg->msg_srv, msg->msg_mntpt,
962*7c478bd9Sstevel@tonic-gate 		    ep->re_char1, (void *)ep->re_rp1, msg->msg_srv);
963*7c478bd9Sstevel@tonic-gate 		break;
964*7c478bd9Sstevel@tonic-gate 	case RE_LOST_STATE:
965*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
966*7c478bd9Sstevel@tonic-gate 		    "Lost %s request for fs %s, file %s (rnode_pt: 0x%p), "
967*7c478bd9Sstevel@tonic-gate 		    "dir %s (0x%p) for server %s", msg->msg_srv, msg->msg_mntpt,
968*7c478bd9Sstevel@tonic-gate 		    nfs4_op_to_str(ep->re_uint), msg->msg_mntpt,
969*7c478bd9Sstevel@tonic-gate 		    ep->re_char1, (void *)ep->re_rp1, ep->re_char2,
970*7c478bd9Sstevel@tonic-gate 		    (void *)ep->re_rp2, msg->msg_srv);
971*7c478bd9Sstevel@tonic-gate 		break;
972*7c478bd9Sstevel@tonic-gate 	case RE_OPENS_CHANGED:
973*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
974*7c478bd9Sstevel@tonic-gate 		    "The number of open files to reopen changed "
975*7c478bd9Sstevel@tonic-gate 		    "for mount %s mi 0x%p (old %d, new %d) on server %s",
976*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt, msg->msg_mntpt,
977*7c478bd9Sstevel@tonic-gate 		    (void *)ep->re_mi, ep->re_uint, ep->re_pid, msg->msg_srv);
978*7c478bd9Sstevel@tonic-gate 		break;
979*7c478bd9Sstevel@tonic-gate 	case RE_SIGLOST:
980*7c478bd9Sstevel@tonic-gate 	case RE_SIGLOST_NO_DUMP:
981*7c478bd9Sstevel@tonic-gate 		if (ep->re_uint)
982*7c478bd9Sstevel@tonic-gate 			zcmn_err(zoneid, CE_NOTE,
983*7c478bd9Sstevel@tonic-gate 			    "![NFS4][Server: %s][Mntpt: %s]"
984*7c478bd9Sstevel@tonic-gate 			    "Process %d lost its locks on "
985*7c478bd9Sstevel@tonic-gate 			    "file %s (rnode_pt: %p) due to NFS recovery error "
986*7c478bd9Sstevel@tonic-gate 			    "(%d) on server %s.", msg->msg_srv, msg->msg_mntpt,
987*7c478bd9Sstevel@tonic-gate 			    ep->re_pid, ep->re_char1, (void *)ep->re_rp1,
988*7c478bd9Sstevel@tonic-gate 			    ep->re_uint, msg->msg_srv);
989*7c478bd9Sstevel@tonic-gate 		else
990*7c478bd9Sstevel@tonic-gate 			zcmn_err(zoneid, CE_NOTE,
991*7c478bd9Sstevel@tonic-gate 			    "![NFS4][Server: %s][Mntpt: %s]"
992*7c478bd9Sstevel@tonic-gate 			    "Process %d lost its locks on "
993*7c478bd9Sstevel@tonic-gate 			    "file %s (rnode_pt: %p) due to NFS recovery error "
994*7c478bd9Sstevel@tonic-gate 			    "(%s) on server %s.", msg->msg_srv, msg->msg_mntpt,
995*7c478bd9Sstevel@tonic-gate 			    ep->re_pid, ep->re_char1, (void *)ep->re_rp1,
996*7c478bd9Sstevel@tonic-gate 			    nfs4_stat_to_str(ep->re_stat4), msg->msg_srv);
997*7c478bd9Sstevel@tonic-gate 		break;
998*7c478bd9Sstevel@tonic-gate 	case RE_START:
999*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1000*7c478bd9Sstevel@tonic-gate 		    "NFS Starting recovery for mount %s "
1001*7c478bd9Sstevel@tonic-gate 		    "(mi 0x%p mi_recovflags [0x%x]) on server %s, "
1002*7c478bd9Sstevel@tonic-gate 		    "rnode_pt1 %s (0x%p), rnode_pt2 %s (0x%p)", msg->msg_srv,
1003*7c478bd9Sstevel@tonic-gate 		    msg->msg_mntpt, msg->msg_mntpt, (void *)ep->re_mi,
1004*7c478bd9Sstevel@tonic-gate 		    ep->re_uint, msg->msg_srv, ep->re_char1, (void *)ep->re_rp1,
1005*7c478bd9Sstevel@tonic-gate 		    ep->re_char2, (void *)ep->re_rp2);
1006*7c478bd9Sstevel@tonic-gate 		break;
1007*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_ACTION:
1008*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1009*7c478bd9Sstevel@tonic-gate 		    "NFS recovery: unexpected action (%s) on server %s",
1010*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt,
1011*7c478bd9Sstevel@tonic-gate 		    nfs4_recov_action_to_str(ep->re_uint), msg->msg_srv);
1012*7c478bd9Sstevel@tonic-gate 		break;
1013*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_ERRNO:
1014*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1015*7c478bd9Sstevel@tonic-gate 		    "NFS recovery: unexpected errno (%d) on server %s",
1016*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt, ep->re_uint, msg->msg_srv);
1017*7c478bd9Sstevel@tonic-gate 		break;
1018*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_STATUS:
1019*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1020*7c478bd9Sstevel@tonic-gate 		    "NFS recovery: unexpected NFS status code (%s) "
1021*7c478bd9Sstevel@tonic-gate 		    "on server %s", msg->msg_srv, msg->msg_mntpt,
1022*7c478bd9Sstevel@tonic-gate 		    nfs4_stat_to_str(ep->re_stat4),
1023*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv);
1024*7c478bd9Sstevel@tonic-gate 		break;
1025*7c478bd9Sstevel@tonic-gate 	case RE_WRONGSEC:
1026*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1027*7c478bd9Sstevel@tonic-gate 		    "NFS can't recover from NFS4ERR_WRONGSEC."
1028*7c478bd9Sstevel@tonic-gate 		    "  error %d for server %s: rnode_pt1 %s (0x%p)"
1029*7c478bd9Sstevel@tonic-gate 		    " rnode_pt2 %s (0x%p)", msg->msg_srv, msg->msg_mntpt,
1030*7c478bd9Sstevel@tonic-gate 		    ep->re_uint, msg->msg_srv, ep->re_char1, (void *)ep->re_rp1,
1031*7c478bd9Sstevel@tonic-gate 		    ep->re_char2, (void *)ep->re_rp2);
1032*7c478bd9Sstevel@tonic-gate 		break;
1033*7c478bd9Sstevel@tonic-gate 	case RE_LOST_STATE_BAD_OP:
1034*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1035*7c478bd9Sstevel@tonic-gate 		    "NFS lost state with unrecognized op (%d)."
1036*7c478bd9Sstevel@tonic-gate 		    "  fs %s, server %s, pid %d, file %s (rnode_pt: 0x%p), "
1037*7c478bd9Sstevel@tonic-gate 		    "dir %s (0x%p)", msg->msg_srv, msg->msg_mntpt,
1038*7c478bd9Sstevel@tonic-gate 		    ep->re_uint, msg->msg_mntpt, msg->msg_srv, ep->re_pid,
1039*7c478bd9Sstevel@tonic-gate 		    ep->re_char1, (void *)ep->re_rp1, ep->re_char2,
1040*7c478bd9Sstevel@tonic-gate 		    (void *)ep->re_rp2);
1041*7c478bd9Sstevel@tonic-gate 		break;
1042*7c478bd9Sstevel@tonic-gate 	default:
1043*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_WARN,
1044*7c478bd9Sstevel@tonic-gate 		    "!queue_print_event: illegal event %d", ep->re_type);
1045*7c478bd9Sstevel@tonic-gate 		break;
1046*7c478bd9Sstevel@tonic-gate 	}
1047*7c478bd9Sstevel@tonic-gate 
1048*7c478bd9Sstevel@tonic-gate 	print_facts(msg, mi);
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate 	/*
1051*7c478bd9Sstevel@tonic-gate 	 * If set this event will not be printed again and is considered
1052*7c478bd9Sstevel@tonic-gate 	 * dumped.
1053*7c478bd9Sstevel@tonic-gate 	 */
1054*7c478bd9Sstevel@tonic-gate 	if (dump)
1055*7c478bd9Sstevel@tonic-gate 		msg->msg_status = NFS4_MS_NO_DUMP;
1056*7c478bd9Sstevel@tonic-gate }
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate /*
1059*7c478bd9Sstevel@tonic-gate  * Print a fact message to /var/adm/messages
1060*7c478bd9Sstevel@tonic-gate  */
1061*7c478bd9Sstevel@tonic-gate static void
1062*7c478bd9Sstevel@tonic-gate queue_print_fact(nfs4_debug_msg_t *msg, int dump)
1063*7c478bd9Sstevel@tonic-gate {
1064*7c478bd9Sstevel@tonic-gate 	nfs4_rfact_t	*fp;
1065*7c478bd9Sstevel@tonic-gate 	zoneid_t	zoneid;
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate 	fp = &msg->rmsg_u.msg_fact;
1068*7c478bd9Sstevel@tonic-gate 	zoneid = getzoneid();
1069*7c478bd9Sstevel@tonic-gate 
1070*7c478bd9Sstevel@tonic-gate 	switch (fp->rf_type) {
1071*7c478bd9Sstevel@tonic-gate 	case RF_BADOWNER:
1072*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1073*7c478bd9Sstevel@tonic-gate 		    "NFSMAPID_DOMAIN does not match the server: %s domain\n"
1074*7c478bd9Sstevel@tonic-gate 		    "Please check configuration", msg->msg_srv, msg->msg_mntpt,
1075*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv);
1076*7c478bd9Sstevel@tonic-gate 		break;
1077*7c478bd9Sstevel@tonic-gate 	case RF_ERR:
1078*7c478bd9Sstevel@tonic-gate 		if (fp->rf_error)
1079*7c478bd9Sstevel@tonic-gate 			zcmn_err(zoneid, CE_NOTE,
1080*7c478bd9Sstevel@tonic-gate 			    "![NFS4][Server: %s][Mntpt: %s]NFS op %s got "
1081*7c478bd9Sstevel@tonic-gate 			    "error %d causing recovery action %s.%s",
1082*7c478bd9Sstevel@tonic-gate 			    msg->msg_srv, msg->msg_mntpt,
1083*7c478bd9Sstevel@tonic-gate 			    nfs4_op_to_str(fp->rf_op), fp->rf_error,
1084*7c478bd9Sstevel@tonic-gate 			    nfs4_recov_action_to_str(fp->rf_action),
1085*7c478bd9Sstevel@tonic-gate 			    fp->rf_reboot ?
1086*7c478bd9Sstevel@tonic-gate 			    "  Client also suspects that the server rebooted,"
1087*7c478bd9Sstevel@tonic-gate 			    " or experienced a network partition." : "");
1088*7c478bd9Sstevel@tonic-gate 		else
1089*7c478bd9Sstevel@tonic-gate 			zcmn_err(zoneid, CE_NOTE,
1090*7c478bd9Sstevel@tonic-gate 			    "![NFS4][Server: %s][Mntpt: %s]NFS op %s got "
1091*7c478bd9Sstevel@tonic-gate 			    "error %s causing recovery action %s.%s",
1092*7c478bd9Sstevel@tonic-gate 			    msg->msg_srv, msg->msg_mntpt,
1093*7c478bd9Sstevel@tonic-gate 			    nfs4_op_to_str(fp->rf_op),
1094*7c478bd9Sstevel@tonic-gate 			    nfs4_stat_to_str(fp->rf_stat4),
1095*7c478bd9Sstevel@tonic-gate 			    nfs4_recov_action_to_str(fp->rf_action),
1096*7c478bd9Sstevel@tonic-gate 			    fp->rf_reboot ?
1097*7c478bd9Sstevel@tonic-gate 			    "  Client also suspects that the server rebooted,"
1098*7c478bd9Sstevel@tonic-gate 			    " or experienced a network partition." : "");
1099*7c478bd9Sstevel@tonic-gate 		break;
1100*7c478bd9Sstevel@tonic-gate 	case RF_RENEW_EXPIRED:
1101*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1102*7c478bd9Sstevel@tonic-gate 		    "NFS4 renew thread detected client's "
1103*7c478bd9Sstevel@tonic-gate 		    "lease has expired. Current open files/locks/IO may fail",
1104*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt);
1105*7c478bd9Sstevel@tonic-gate 		break;
1106*7c478bd9Sstevel@tonic-gate 	case RF_SRV_NOT_RESPOND:
1107*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1108*7c478bd9Sstevel@tonic-gate 		    "NFS server %s not responding; still trying\n",
1109*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt, msg->msg_srv);
1110*7c478bd9Sstevel@tonic-gate 		break;
1111*7c478bd9Sstevel@tonic-gate 	case RF_SRV_OK:
1112*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1113*7c478bd9Sstevel@tonic-gate 		    "NFS server %s ok", msg->msg_srv, msg->msg_mntpt,
1114*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv);
1115*7c478bd9Sstevel@tonic-gate 		break;
1116*7c478bd9Sstevel@tonic-gate 	case RF_SRVS_NOT_RESPOND:
1117*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1118*7c478bd9Sstevel@tonic-gate 		    "NFS servers %s not responding; still trying", msg->msg_srv,
1119*7c478bd9Sstevel@tonic-gate 		    msg->msg_mntpt, msg->msg_srv);
1120*7c478bd9Sstevel@tonic-gate 		break;
1121*7c478bd9Sstevel@tonic-gate 	case RF_SRVS_OK:
1122*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1123*7c478bd9Sstevel@tonic-gate 		    "NFS servers %s ok", msg->msg_srv, msg->msg_mntpt,
1124*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv);
1125*7c478bd9Sstevel@tonic-gate 		break;
1126*7c478bd9Sstevel@tonic-gate 	case RF_DELMAP_CB_ERR:
1127*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_NOTE, "![NFS4][Server: %s][Mntpt: %s]"
1128*7c478bd9Sstevel@tonic-gate 		    "NFS op %s got error %s when executing delmap on file %s "
1129*7c478bd9Sstevel@tonic-gate 		    "(rnode_pt 0x%p).",
1130*7c478bd9Sstevel@tonic-gate 		    msg->msg_srv, msg->msg_mntpt, nfs4_op_to_str(fp->rf_op),
1131*7c478bd9Sstevel@tonic-gate 		    nfs4_stat_to_str(fp->rf_stat4), fp->rf_char1,
1132*7c478bd9Sstevel@tonic-gate 		    (void *)fp->rf_rp1);
1133*7c478bd9Sstevel@tonic-gate 		break;
1134*7c478bd9Sstevel@tonic-gate 	default:
1135*7c478bd9Sstevel@tonic-gate 		zcmn_err(zoneid, CE_WARN, "!queue_print_fact: illegal fact %d",
1136*7c478bd9Sstevel@tonic-gate 		    fp->rf_type);
1137*7c478bd9Sstevel@tonic-gate 	}
1138*7c478bd9Sstevel@tonic-gate 
1139*7c478bd9Sstevel@tonic-gate 	/*
1140*7c478bd9Sstevel@tonic-gate 	 * If set this fact will not be printed again and is considered
1141*7c478bd9Sstevel@tonic-gate 	 * dumped.
1142*7c478bd9Sstevel@tonic-gate 	 */
1143*7c478bd9Sstevel@tonic-gate 	if (dump)
1144*7c478bd9Sstevel@tonic-gate 		msg->msg_status = NFS4_MS_NO_DUMP;
1145*7c478bd9Sstevel@tonic-gate }
1146*7c478bd9Sstevel@tonic-gate 
1147*7c478bd9Sstevel@tonic-gate /*
1148*7c478bd9Sstevel@tonic-gate  * Returns 1 if the entire queue should be dumped, 0 otherwise.
1149*7c478bd9Sstevel@tonic-gate  */
1150*7c478bd9Sstevel@tonic-gate static int
1151*7c478bd9Sstevel@tonic-gate id_to_dump_queue(nfs4_event_type_t id)
1152*7c478bd9Sstevel@tonic-gate {
1153*7c478bd9Sstevel@tonic-gate 	switch (id) {
1154*7c478bd9Sstevel@tonic-gate 	case RE_DEAD_FILE:
1155*7c478bd9Sstevel@tonic-gate 	case RE_SIGLOST:
1156*7c478bd9Sstevel@tonic-gate 	case RE_WRONGSEC:
1157*7c478bd9Sstevel@tonic-gate 	case RE_CLIENTID:
1158*7c478bd9Sstevel@tonic-gate 		return (1);
1159*7c478bd9Sstevel@tonic-gate 	default:
1160*7c478bd9Sstevel@tonic-gate 		return (0);
1161*7c478bd9Sstevel@tonic-gate 	}
1162*7c478bd9Sstevel@tonic-gate }
1163*7c478bd9Sstevel@tonic-gate 
1164*7c478bd9Sstevel@tonic-gate /*
1165*7c478bd9Sstevel@tonic-gate  * Returns 1 if the event (but not the entire queue) should be printed;
1166*7c478bd9Sstevel@tonic-gate  * 0 otherwise.
1167*7c478bd9Sstevel@tonic-gate  */
1168*7c478bd9Sstevel@tonic-gate static int
1169*7c478bd9Sstevel@tonic-gate id_to_dump_solo_event(nfs4_event_type_t id)
1170*7c478bd9Sstevel@tonic-gate {
1171*7c478bd9Sstevel@tonic-gate 	switch (id) {
1172*7c478bd9Sstevel@tonic-gate 	case RE_BAD_SEQID:
1173*7c478bd9Sstevel@tonic-gate 	case RE_BADHANDLE:
1174*7c478bd9Sstevel@tonic-gate 	case RE_FAIL_REMAP_LEN:
1175*7c478bd9Sstevel@tonic-gate 	case RE_FAIL_REMAP_OP:
1176*7c478bd9Sstevel@tonic-gate 	case RE_FAILOVER:
1177*7c478bd9Sstevel@tonic-gate 	case RE_OPENS_CHANGED:
1178*7c478bd9Sstevel@tonic-gate 	case RE_SIGLOST_NO_DUMP:
1179*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_ACTION:
1180*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_ERRNO:
1181*7c478bd9Sstevel@tonic-gate 	case RE_UNEXPECTED_STATUS:
1182*7c478bd9Sstevel@tonic-gate 	case RE_LOST_STATE_BAD_OP:
1183*7c478bd9Sstevel@tonic-gate 		return (1);
1184*7c478bd9Sstevel@tonic-gate 	default:
1185*7c478bd9Sstevel@tonic-gate 		return (0);
1186*7c478bd9Sstevel@tonic-gate 	}
1187*7c478bd9Sstevel@tonic-gate }
1188*7c478bd9Sstevel@tonic-gate 
1189*7c478bd9Sstevel@tonic-gate /*
1190*7c478bd9Sstevel@tonic-gate  * Returns 1 if the fact (but not the entire queue) should be printed;
1191*7c478bd9Sstevel@tonic-gate  * 0 otherwise.
1192*7c478bd9Sstevel@tonic-gate  */
1193*7c478bd9Sstevel@tonic-gate static int
1194*7c478bd9Sstevel@tonic-gate id_to_dump_solo_fact(nfs4_fact_type_t id)
1195*7c478bd9Sstevel@tonic-gate {
1196*7c478bd9Sstevel@tonic-gate 	switch (id) {
1197*7c478bd9Sstevel@tonic-gate 	case RF_SRV_NOT_RESPOND:
1198*7c478bd9Sstevel@tonic-gate 	case RF_SRV_OK:
1199*7c478bd9Sstevel@tonic-gate 	case RF_SRVS_NOT_RESPOND:
1200*7c478bd9Sstevel@tonic-gate 	case RF_SRVS_OK:
1201*7c478bd9Sstevel@tonic-gate 		return (1);
1202*7c478bd9Sstevel@tonic-gate 	default:
1203*7c478bd9Sstevel@tonic-gate 		return (0);
1204*7c478bd9Sstevel@tonic-gate 	}
1205*7c478bd9Sstevel@tonic-gate }
1206*7c478bd9Sstevel@tonic-gate 
1207*7c478bd9Sstevel@tonic-gate /*
1208*7c478bd9Sstevel@tonic-gate  * Update a kernel stat
1209*7c478bd9Sstevel@tonic-gate  */
1210*7c478bd9Sstevel@tonic-gate static void
1211*7c478bd9Sstevel@tonic-gate update_recov_kstats(nfs4_debug_msg_t *msg, mntinfo4_t *mi)
1212*7c478bd9Sstevel@tonic-gate {
1213*7c478bd9Sstevel@tonic-gate 	rkstat_t	*rsp;
1214*7c478bd9Sstevel@tonic-gate 
1215*7c478bd9Sstevel@tonic-gate 	if (!mi->mi_recov_ksp)
1216*7c478bd9Sstevel@tonic-gate 		return;
1217*7c478bd9Sstevel@tonic-gate 
1218*7c478bd9Sstevel@tonic-gate 	rsp = (rkstat_t *)mi->mi_recov_ksp->ks_data;
1219*7c478bd9Sstevel@tonic-gate 
1220*7c478bd9Sstevel@tonic-gate 	if (msg->msg_type == RM_EVENT) {
1221*7c478bd9Sstevel@tonic-gate 		switch (msg->rmsg_u.msg_event.re_type) {
1222*7c478bd9Sstevel@tonic-gate 		case RE_BADHANDLE:
1223*7c478bd9Sstevel@tonic-gate 			rsp->badhandle.value.ul++;
1224*7c478bd9Sstevel@tonic-gate 			break;
1225*7c478bd9Sstevel@tonic-gate 		case RE_CLIENTID:
1226*7c478bd9Sstevel@tonic-gate 			rsp->clientid.value.ul++;
1227*7c478bd9Sstevel@tonic-gate 			break;
1228*7c478bd9Sstevel@tonic-gate 		case RE_DEAD_FILE:
1229*7c478bd9Sstevel@tonic-gate 			rsp->dead_file.value.ul++;
1230*7c478bd9Sstevel@tonic-gate 			break;
1231*7c478bd9Sstevel@tonic-gate 		case RE_FAIL_RELOCK:
1232*7c478bd9Sstevel@tonic-gate 			rsp->fail_relock.value.ul++;
1233*7c478bd9Sstevel@tonic-gate 			break;
1234*7c478bd9Sstevel@tonic-gate 		case RE_FILE_DIFF:
1235*7c478bd9Sstevel@tonic-gate 			rsp->file_diff.value.ul++;
1236*7c478bd9Sstevel@tonic-gate 			break;
1237*7c478bd9Sstevel@tonic-gate 		case RE_OPENS_CHANGED:
1238*7c478bd9Sstevel@tonic-gate 			rsp->opens_changed.value.ul++;
1239*7c478bd9Sstevel@tonic-gate 			break;
1240*7c478bd9Sstevel@tonic-gate 		case RE_SIGLOST:
1241*7c478bd9Sstevel@tonic-gate 		case RE_SIGLOST_NO_DUMP:
1242*7c478bd9Sstevel@tonic-gate 			rsp->siglost.value.ul++;
1243*7c478bd9Sstevel@tonic-gate 			break;
1244*7c478bd9Sstevel@tonic-gate 		case RE_UNEXPECTED_ACTION:
1245*7c478bd9Sstevel@tonic-gate 			rsp->unexp_action.value.ul++;
1246*7c478bd9Sstevel@tonic-gate 			break;
1247*7c478bd9Sstevel@tonic-gate 		case RE_UNEXPECTED_ERRNO:
1248*7c478bd9Sstevel@tonic-gate 			rsp->unexp_errno.value.ul++;
1249*7c478bd9Sstevel@tonic-gate 			break;
1250*7c478bd9Sstevel@tonic-gate 		case RE_UNEXPECTED_STATUS:
1251*7c478bd9Sstevel@tonic-gate 			rsp->unexp_status.value.ul++;
1252*7c478bd9Sstevel@tonic-gate 			break;
1253*7c478bd9Sstevel@tonic-gate 		case RE_WRONGSEC:
1254*7c478bd9Sstevel@tonic-gate 			rsp->wrongsec.value.ul++;
1255*7c478bd9Sstevel@tonic-gate 			break;
1256*7c478bd9Sstevel@tonic-gate 		case RE_LOST_STATE_BAD_OP:
1257*7c478bd9Sstevel@tonic-gate 			rsp->lost_state_bad_op.value.ul++;
1258*7c478bd9Sstevel@tonic-gate 			break;
1259*7c478bd9Sstevel@tonic-gate 		default:
1260*7c478bd9Sstevel@tonic-gate 			break;
1261*7c478bd9Sstevel@tonic-gate 		}
1262*7c478bd9Sstevel@tonic-gate 	} else if (msg->msg_type == RM_FACT) {
1263*7c478bd9Sstevel@tonic-gate 		switch (msg->rmsg_u.msg_fact.rf_type) {
1264*7c478bd9Sstevel@tonic-gate 		case RF_BADOWNER:
1265*7c478bd9Sstevel@tonic-gate 			rsp->badowner.value.ul++;
1266*7c478bd9Sstevel@tonic-gate 			break;
1267*7c478bd9Sstevel@tonic-gate 		case RF_SRV_NOT_RESPOND:
1268*7c478bd9Sstevel@tonic-gate 			rsp->not_responding.value.ul++;
1269*7c478bd9Sstevel@tonic-gate 			break;
1270*7c478bd9Sstevel@tonic-gate 		default:
1271*7c478bd9Sstevel@tonic-gate 			break;
1272*7c478bd9Sstevel@tonic-gate 		}
1273*7c478bd9Sstevel@tonic-gate 	}
1274*7c478bd9Sstevel@tonic-gate }
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate /*
1277*7c478bd9Sstevel@tonic-gate  * Dump the mi's mi_msg_list of recovery messages.
1278*7c478bd9Sstevel@tonic-gate  */
1279*7c478bd9Sstevel@tonic-gate static void
1280*7c478bd9Sstevel@tonic-gate dump_queue(mntinfo4_t *mi, nfs4_debug_msg_t *msg)
1281*7c478bd9Sstevel@tonic-gate {
1282*7c478bd9Sstevel@tonic-gate 	nfs4_debug_msg_t *tmp_msg;
1283*7c478bd9Sstevel@tonic-gate 
1284*7c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&mi->mi_msg_list_lock));
1285*7c478bd9Sstevel@tonic-gate 
1286*7c478bd9Sstevel@tonic-gate 	/* update kstats */
1287*7c478bd9Sstevel@tonic-gate 	update_recov_kstats(msg, mi);
1288*7c478bd9Sstevel@tonic-gate 
1289*7c478bd9Sstevel@tonic-gate 	/*
1290*7c478bd9Sstevel@tonic-gate 	 * If we aren't supposed to dump the queue then see if we
1291*7c478bd9Sstevel@tonic-gate 	 * should just print this single message, then return.
1292*7c478bd9Sstevel@tonic-gate 	 */
1293*7c478bd9Sstevel@tonic-gate 	if (!id_to_dump_queue(msg->rmsg_u.msg_event.re_type)) {
1294*7c478bd9Sstevel@tonic-gate 		if (id_to_dump_solo_event(msg->rmsg_u.msg_event.re_type))
1295*7c478bd9Sstevel@tonic-gate 			queue_print_event(msg, mi, 0);
1296*7c478bd9Sstevel@tonic-gate 		return;
1297*7c478bd9Sstevel@tonic-gate 	}
1298*7c478bd9Sstevel@tonic-gate 
1299*7c478bd9Sstevel@tonic-gate 	/*
1300*7c478bd9Sstevel@tonic-gate 	 * Write all events/facts in the queue that haven't been
1301*7c478bd9Sstevel@tonic-gate 	 * previously written to disk.
1302*7c478bd9Sstevel@tonic-gate 	 */
1303*7c478bd9Sstevel@tonic-gate 	tmp_msg = list_head(&mi->mi_msg_list);
1304*7c478bd9Sstevel@tonic-gate 	while (tmp_msg) {
1305*7c478bd9Sstevel@tonic-gate 		if (tmp_msg->msg_status == NFS4_MS_DUMP) {
1306*7c478bd9Sstevel@tonic-gate 			if (tmp_msg->msg_type == RM_EVENT)
1307*7c478bd9Sstevel@tonic-gate 				queue_print_event(tmp_msg, mi, 1);
1308*7c478bd9Sstevel@tonic-gate 			else if (tmp_msg->msg_type == RM_FACT)
1309*7c478bd9Sstevel@tonic-gate 				queue_print_fact(tmp_msg, 1);
1310*7c478bd9Sstevel@tonic-gate 		}
1311*7c478bd9Sstevel@tonic-gate 		tmp_msg = list_next(&mi->mi_msg_list, tmp_msg);
1312*7c478bd9Sstevel@tonic-gate 	}
1313*7c478bd9Sstevel@tonic-gate }
1314*7c478bd9Sstevel@tonic-gate 
1315*7c478bd9Sstevel@tonic-gate /*
1316*7c478bd9Sstevel@tonic-gate  * Places the event into mi's debug recovery message queue.  Some of the
1317*7c478bd9Sstevel@tonic-gate  * fields can be overloaded to be a generic value, depending on the event
1318*7c478bd9Sstevel@tonic-gate  * type.  These include "count", "why".
1319*7c478bd9Sstevel@tonic-gate  */
1320*7c478bd9Sstevel@tonic-gate void
1321*7c478bd9Sstevel@tonic-gate nfs4_queue_event(nfs4_event_type_t id, mntinfo4_t *mi, char *server1,
1322*7c478bd9Sstevel@tonic-gate     uint_t count, vnode_t *vp1, vnode_t *vp2, nfsstat4 nfs4_error,
1323*7c478bd9Sstevel@tonic-gate     char *why, pid_t pid, nfs4_tag_type_t tag1, nfs4_tag_type_t tag2,
1324*7c478bd9Sstevel@tonic-gate     seqid4 seqid1, seqid4 seqid2)
1325*7c478bd9Sstevel@tonic-gate {
1326*7c478bd9Sstevel@tonic-gate 	nfs4_debug_msg_t	*msg;
1327*7c478bd9Sstevel@tonic-gate 	nfs4_revent_t		*ep;
1328*7c478bd9Sstevel@tonic-gate 	char			*cur_srv;
1329*7c478bd9Sstevel@tonic-gate 	rnode4_t		*rp1 = NULL, *rp2 = NULL;
1330*7c478bd9Sstevel@tonic-gate 	refstr_t		*mntpt;
1331*7c478bd9Sstevel@tonic-gate 
1332*7c478bd9Sstevel@tonic-gate 	ASSERT(mi != NULL);
1333*7c478bd9Sstevel@tonic-gate 	if (vp1)
1334*7c478bd9Sstevel@tonic-gate 		rp1 = VTOR4(vp1);
1335*7c478bd9Sstevel@tonic-gate 	if (vp2)
1336*7c478bd9Sstevel@tonic-gate 		rp2 = VTOR4(vp2);
1337*7c478bd9Sstevel@tonic-gate 
1338*7c478bd9Sstevel@tonic-gate 	/*
1339*7c478bd9Sstevel@tonic-gate 	 * Initialize the message with the relevent server/mount_pt/time
1340*7c478bd9Sstevel@tonic-gate 	 * information. Also place the relevent event related info.
1341*7c478bd9Sstevel@tonic-gate 	 */
1342*7c478bd9Sstevel@tonic-gate 	msg = kmem_zalloc(sizeof (*msg), KM_SLEEP);
1343*7c478bd9Sstevel@tonic-gate 	msg->msg_type = RM_EVENT;
1344*7c478bd9Sstevel@tonic-gate 	msg->msg_status = NFS4_MS_DUMP;
1345*7c478bd9Sstevel@tonic-gate 	ep = &msg->rmsg_u.msg_event;
1346*7c478bd9Sstevel@tonic-gate 	ep->re_type = id;
1347*7c478bd9Sstevel@tonic-gate 	gethrestime(&msg->msg_time);
1348*7c478bd9Sstevel@tonic-gate 
1349*7c478bd9Sstevel@tonic-gate 	cur_srv = mi->mi_curr_serv->sv_hostname;
1350*7c478bd9Sstevel@tonic-gate 	msg->msg_srv = strdup(cur_srv);
1351*7c478bd9Sstevel@tonic-gate 	mntpt = vfs_getmntpoint(mi->mi_vfsp);
1352*7c478bd9Sstevel@tonic-gate 	msg->msg_mntpt = strdup(refstr_value(mntpt));
1353*7c478bd9Sstevel@tonic-gate 	refstr_rele(mntpt);
1354*7c478bd9Sstevel@tonic-gate 
1355*7c478bd9Sstevel@tonic-gate 	set_event(id, ep, mi, rp1, rp2, count, pid, nfs4_error, server1,
1356*7c478bd9Sstevel@tonic-gate 	    why, tag1, tag2, seqid1, seqid2);
1357*7c478bd9Sstevel@tonic-gate 
1358*7c478bd9Sstevel@tonic-gate 	mutex_enter(&mi->mi_msg_list_lock);
1359*7c478bd9Sstevel@tonic-gate 
1360*7c478bd9Sstevel@tonic-gate 	/* if this event is the same as the last event, drop it */
1361*7c478bd9Sstevel@tonic-gate 	if (events_same(list_tail(&mi->mi_msg_list), msg, mi)) {
1362*7c478bd9Sstevel@tonic-gate 		mutex_exit(&mi->mi_msg_list_lock);
1363*7c478bd9Sstevel@tonic-gate 		nfs4_free_msg(msg);
1364*7c478bd9Sstevel@tonic-gate 		return;
1365*7c478bd9Sstevel@tonic-gate 	}
1366*7c478bd9Sstevel@tonic-gate 
1367*7c478bd9Sstevel@tonic-gate 	/* queue the message at the end of the list */
1368*7c478bd9Sstevel@tonic-gate 	list_insert_tail(&mi->mi_msg_list, msg);
1369*7c478bd9Sstevel@tonic-gate 
1370*7c478bd9Sstevel@tonic-gate 	dump_queue(mi, msg);
1371*7c478bd9Sstevel@tonic-gate 
1372*7c478bd9Sstevel@tonic-gate 	if (mi->mi_msg_count == nfs4_msg_max) {
1373*7c478bd9Sstevel@tonic-gate 		nfs4_debug_msg_t *rm_msg;
1374*7c478bd9Sstevel@tonic-gate 
1375*7c478bd9Sstevel@tonic-gate 		/* remove the queue'd message at the front of the list */
1376*7c478bd9Sstevel@tonic-gate 		rm_msg = list_head(&mi->mi_msg_list);
1377*7c478bd9Sstevel@tonic-gate 		list_remove(&mi->mi_msg_list, rm_msg);
1378*7c478bd9Sstevel@tonic-gate 		mutex_exit(&mi->mi_msg_list_lock);
1379*7c478bd9Sstevel@tonic-gate 		nfs4_free_msg(rm_msg);
1380*7c478bd9Sstevel@tonic-gate 	} else {
1381*7c478bd9Sstevel@tonic-gate 		mi->mi_msg_count++;
1382*7c478bd9Sstevel@tonic-gate 		mutex_exit(&mi->mi_msg_list_lock);
1383*7c478bd9Sstevel@tonic-gate 	}
1384*7c478bd9Sstevel@tonic-gate }
1385*7c478bd9Sstevel@tonic-gate 
1386*7c478bd9Sstevel@tonic-gate /*
1387*7c478bd9Sstevel@tonic-gate  * Places the fact into mi's debug recovery messages queue.
1388*7c478bd9Sstevel@tonic-gate  */
1389*7c478bd9Sstevel@tonic-gate void
1390*7c478bd9Sstevel@tonic-gate nfs4_queue_fact(nfs4_fact_type_t fid, mntinfo4_t *mi, nfsstat4 stat4,
1391*7c478bd9Sstevel@tonic-gate     nfs4_recov_t raction, nfs_opnum4 op, bool_t reboot, char *srvname,
1392*7c478bd9Sstevel@tonic-gate     int error, vnode_t *vp)
1393*7c478bd9Sstevel@tonic-gate {
1394*7c478bd9Sstevel@tonic-gate 	nfs4_debug_msg_t	*msg;
1395*7c478bd9Sstevel@tonic-gate 	nfs4_rfact_t		*fp;
1396*7c478bd9Sstevel@tonic-gate 	char			*cur_srv;
1397*7c478bd9Sstevel@tonic-gate 	refstr_t		*mntpt;
1398*7c478bd9Sstevel@tonic-gate 
1399*7c478bd9Sstevel@tonic-gate 	/*
1400*7c478bd9Sstevel@tonic-gate 	 * Initialize the message with the relevent server/mount_pt/time
1401*7c478bd9Sstevel@tonic-gate 	 * information. Also place the relevent fact related info.
1402*7c478bd9Sstevel@tonic-gate 	 */
1403*7c478bd9Sstevel@tonic-gate 	msg = kmem_zalloc(sizeof (*msg), KM_SLEEP);
1404*7c478bd9Sstevel@tonic-gate 	msg->msg_type = RM_FACT;
1405*7c478bd9Sstevel@tonic-gate 	msg->msg_status = NFS4_MS_DUMP;
1406*7c478bd9Sstevel@tonic-gate 	gethrestime(&msg->msg_time);
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate 	if (srvname)
1409*7c478bd9Sstevel@tonic-gate 		cur_srv = srvname;
1410*7c478bd9Sstevel@tonic-gate 	else
1411*7c478bd9Sstevel@tonic-gate 		cur_srv = mi->mi_curr_serv->sv_hostname;
1412*7c478bd9Sstevel@tonic-gate 
1413*7c478bd9Sstevel@tonic-gate 	msg->msg_srv = strdup(cur_srv);
1414*7c478bd9Sstevel@tonic-gate 	mntpt = vfs_getmntpoint(mi->mi_vfsp);
1415*7c478bd9Sstevel@tonic-gate 	msg->msg_mntpt = strdup(refstr_value(mntpt));
1416*7c478bd9Sstevel@tonic-gate 	refstr_rele(mntpt);
1417*7c478bd9Sstevel@tonic-gate 
1418*7c478bd9Sstevel@tonic-gate 	fp = &msg->rmsg_u.msg_fact;
1419*7c478bd9Sstevel@tonic-gate 	fp->rf_type = fid;
1420*7c478bd9Sstevel@tonic-gate 	fp->rf_status = RFS_NO_INSPECT;
1421*7c478bd9Sstevel@tonic-gate 	set_fact(fid, fp, stat4, raction, op, reboot, error, vp);
1422*7c478bd9Sstevel@tonic-gate 
1423*7c478bd9Sstevel@tonic-gate 	update_recov_kstats(msg, mi);
1424*7c478bd9Sstevel@tonic-gate 
1425*7c478bd9Sstevel@tonic-gate 	mutex_enter(&mi->mi_msg_list_lock);
1426*7c478bd9Sstevel@tonic-gate 
1427*7c478bd9Sstevel@tonic-gate 	/* if this fact is the same as the last fact, drop it */
1428*7c478bd9Sstevel@tonic-gate 	if (facts_same(list_tail(&mi->mi_msg_list), msg, mi)) {
1429*7c478bd9Sstevel@tonic-gate 		mutex_exit(&mi->mi_msg_list_lock);
1430*7c478bd9Sstevel@tonic-gate 		nfs4_free_msg(msg);
1431*7c478bd9Sstevel@tonic-gate 		return;
1432*7c478bd9Sstevel@tonic-gate 	}
1433*7c478bd9Sstevel@tonic-gate 
1434*7c478bd9Sstevel@tonic-gate 	/* queue the message at the end of the list */
1435*7c478bd9Sstevel@tonic-gate 	list_insert_tail(&mi->mi_msg_list, msg);
1436*7c478bd9Sstevel@tonic-gate 
1437*7c478bd9Sstevel@tonic-gate 	if (id_to_dump_solo_fact(msg->rmsg_u.msg_fact.rf_type))
1438*7c478bd9Sstevel@tonic-gate 		queue_print_fact(msg, 0);
1439*7c478bd9Sstevel@tonic-gate 
1440*7c478bd9Sstevel@tonic-gate 	if (mi->mi_msg_count == nfs4_msg_max) {
1441*7c478bd9Sstevel@tonic-gate 		nfs4_debug_msg_t *rm_msg;
1442*7c478bd9Sstevel@tonic-gate 
1443*7c478bd9Sstevel@tonic-gate 		/* remove the queue'd message at the front of the list */
1444*7c478bd9Sstevel@tonic-gate 		rm_msg = list_head(&mi->mi_msg_list);
1445*7c478bd9Sstevel@tonic-gate 		list_remove(&mi->mi_msg_list, rm_msg);
1446*7c478bd9Sstevel@tonic-gate 		mutex_exit(&mi->mi_msg_list_lock);
1447*7c478bd9Sstevel@tonic-gate 		nfs4_free_msg(rm_msg);
1448*7c478bd9Sstevel@tonic-gate 	} else {
1449*7c478bd9Sstevel@tonic-gate 		mi->mi_msg_count++;
1450*7c478bd9Sstevel@tonic-gate 		mutex_exit(&mi->mi_msg_list_lock);
1451*7c478bd9Sstevel@tonic-gate 	}
1452*7c478bd9Sstevel@tonic-gate }
1453*7c478bd9Sstevel@tonic-gate 
1454*7c478bd9Sstevel@tonic-gate /*
1455*7c478bd9Sstevel@tonic-gate  * Initialize the 'mi_recov_kstat' kstat.
1456*7c478bd9Sstevel@tonic-gate  */
1457*7c478bd9Sstevel@tonic-gate void
1458*7c478bd9Sstevel@tonic-gate nfs4_mnt_recov_kstat_init(vfs_t *vfsp)
1459*7c478bd9Sstevel@tonic-gate {
1460*7c478bd9Sstevel@tonic-gate 	mntinfo4_t *mi = VFTOMI4(vfsp);
1461*7c478bd9Sstevel@tonic-gate 	kstat_t		*ksp;
1462*7c478bd9Sstevel@tonic-gate 	zoneid_t	zoneid = mi->mi_zone->zone_id;
1463*7c478bd9Sstevel@tonic-gate 
1464*7c478bd9Sstevel@tonic-gate 	/*
1465*7c478bd9Sstevel@tonic-gate 	 * Create the version specific kstats.
1466*7c478bd9Sstevel@tonic-gate 	 *
1467*7c478bd9Sstevel@tonic-gate 	 * PSARC 2001/697 Contract Private Interface
1468*7c478bd9Sstevel@tonic-gate 	 * All nfs kstats are under SunMC contract
1469*7c478bd9Sstevel@tonic-gate 	 * Please refer to the PSARC listed above and contact
1470*7c478bd9Sstevel@tonic-gate 	 * SunMC before making any changes!
1471*7c478bd9Sstevel@tonic-gate 	 *
1472*7c478bd9Sstevel@tonic-gate 	 * Changes must be reviewed by Solaris File Sharing
1473*7c478bd9Sstevel@tonic-gate 	 * Changes must be communicated to contract-2001-697@sun.com
1474*7c478bd9Sstevel@tonic-gate 	 *
1475*7c478bd9Sstevel@tonic-gate 	 */
1476*7c478bd9Sstevel@tonic-gate 
1477*7c478bd9Sstevel@tonic-gate 	if ((ksp = kstat_create_zone("nfs", getminor(vfsp->vfs_dev),
1478*7c478bd9Sstevel@tonic-gate 	    "mi_recov_kstat", "misc", KSTAT_TYPE_NAMED,
1479*7c478bd9Sstevel@tonic-gate 	    sizeof (rkstat_t) / sizeof (kstat_named_t),
1480*7c478bd9Sstevel@tonic-gate 	    KSTAT_FLAG_WRITABLE, zoneid)) == NULL) {
1481*7c478bd9Sstevel@tonic-gate 		mi->mi_recov_ksp = NULL;
1482*7c478bd9Sstevel@tonic-gate 		zcmn_err(GLOBAL_ZONEID, CE_NOTE,
1483*7c478bd9Sstevel@tonic-gate 		    "!mi_recov_kstat for mi %p failed\n",
1484*7c478bd9Sstevel@tonic-gate 		    (void *)mi);
1485*7c478bd9Sstevel@tonic-gate 		return;
1486*7c478bd9Sstevel@tonic-gate 	}
1487*7c478bd9Sstevel@tonic-gate 	if (zoneid != GLOBAL_ZONEID)
1488*7c478bd9Sstevel@tonic-gate 		kstat_zone_add(ksp, GLOBAL_ZONEID);
1489*7c478bd9Sstevel@tonic-gate 	mi->mi_recov_ksp = ksp;
1490*7c478bd9Sstevel@tonic-gate 	bcopy(&rkstat_template, ksp->ks_data, sizeof (rkstat_t));
1491*7c478bd9Sstevel@tonic-gate 	kstat_install(ksp);
1492*7c478bd9Sstevel@tonic-gate }
1493*7c478bd9Sstevel@tonic-gate 
1494*7c478bd9Sstevel@tonic-gate /*
1495*7c478bd9Sstevel@tonic-gate  * Increment the "delay" kstat.
1496*7c478bd9Sstevel@tonic-gate  */
1497*7c478bd9Sstevel@tonic-gate void
1498*7c478bd9Sstevel@tonic-gate nfs4_mi_kstat_inc_delay(mntinfo4_t *mi)
1499*7c478bd9Sstevel@tonic-gate {
1500*7c478bd9Sstevel@tonic-gate 	rkstat_t    *rsp;
1501*7c478bd9Sstevel@tonic-gate 
1502*7c478bd9Sstevel@tonic-gate 	if (!mi->mi_recov_ksp)
1503*7c478bd9Sstevel@tonic-gate 		return;
1504*7c478bd9Sstevel@tonic-gate 
1505*7c478bd9Sstevel@tonic-gate 	rsp = (rkstat_t *)mi->mi_recov_ksp->ks_data;
1506*7c478bd9Sstevel@tonic-gate 	rsp->delay.value.ul++;
1507*7c478bd9Sstevel@tonic-gate }
1508*7c478bd9Sstevel@tonic-gate 
1509*7c478bd9Sstevel@tonic-gate /*
1510*7c478bd9Sstevel@tonic-gate  * Increment the "no_grace" kstat.
1511*7c478bd9Sstevel@tonic-gate  */
1512*7c478bd9Sstevel@tonic-gate void
1513*7c478bd9Sstevel@tonic-gate nfs4_mi_kstat_inc_no_grace(mntinfo4_t *mi)
1514*7c478bd9Sstevel@tonic-gate {
1515*7c478bd9Sstevel@tonic-gate 	rkstat_t	*rsp;
1516*7c478bd9Sstevel@tonic-gate 
1517*7c478bd9Sstevel@tonic-gate 	if (!mi->mi_recov_ksp)
1518*7c478bd9Sstevel@tonic-gate 		return;
1519*7c478bd9Sstevel@tonic-gate 
1520*7c478bd9Sstevel@tonic-gate 	rsp = (rkstat_t *)mi->mi_recov_ksp->ks_data;
1521*7c478bd9Sstevel@tonic-gate 	rsp->no_grace.value.ul++;
1522*7c478bd9Sstevel@tonic-gate }
1523*7c478bd9Sstevel@tonic-gate 
1524*7c478bd9Sstevel@tonic-gate /*
1525*7c478bd9Sstevel@tonic-gate  * Allocate and copy a string.  XXX There really ought to be a single
1526*7c478bd9Sstevel@tonic-gate  * strdup() for the entire kernel.
1527*7c478bd9Sstevel@tonic-gate  */
1528*7c478bd9Sstevel@tonic-gate static char *
1529*7c478bd9Sstevel@tonic-gate strdup(const char *s)
1530*7c478bd9Sstevel@tonic-gate {
1531*7c478bd9Sstevel@tonic-gate 	size_t len;
1532*7c478bd9Sstevel@tonic-gate 	char *new;
1533*7c478bd9Sstevel@tonic-gate 
1534*7c478bd9Sstevel@tonic-gate 	len = strlen(s);
1535*7c478bd9Sstevel@tonic-gate 	new = kmem_alloc(len + 1, KM_SLEEP);
1536*7c478bd9Sstevel@tonic-gate 	bcopy(s, new, len);
1537*7c478bd9Sstevel@tonic-gate 	new[len] = '\0';
1538*7c478bd9Sstevel@tonic-gate 
1539*7c478bd9Sstevel@tonic-gate 	return (new);
1540*7c478bd9Sstevel@tonic-gate }
1541