xref: /illumos-gate/usr/src/uts/common/fs/nfs/nfs4_recovery.c (revision 0dee7919e2f2a6479d16b370af93747b9416b242)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * NFS Version 4 state recovery code.
31  */
32 
33 #include <nfs/nfs4_clnt.h>
34 #include <nfs/nfs4.h>
35 #include <nfs/rnode4.h>
36 #include <sys/cmn_err.h>
37 #include <sys/cred.h>
38 #include <sys/systm.h>
39 #include <sys/flock.h>
40 #include <sys/dnlc.h>
41 #include <sys/ddi.h>
42 #include <sys/disp.h>
43 #include <sys/list.h>
44 #include <sys/sdt.h>
45 
46 extern r4hashq_t *rtable4;
47 
48 /*
49  * Information that describes what needs to be done for recovery.  It is
50  * passed to a client recovery thread as well as passed to various recovery
51  * routines.  rc_mi, rc_vp1, and rc_vp2 refer to the filesystem and
52  * vnode(s) affected by recovery.  rc_vp1 and rc_vp2 are references (use
53  * VN_HOLD) or NULL.  rc_lost_rqst contains information about the lost
54  * lock or open/close request, and it holds reference counts for the
55  * various objects (vnode, etc.).  The recovery thread also uses flags set
56  * in the mntinfo4_t or vnode_t to tell it what to do.  rc_error is used
57  * to save the error that originally triggered the recovery event -- will
58  * later be used to set mi_error if recovery doesn't work.  rc_bseqid_rqst
59  * contains information about the request that got NFS4ERR_BAD_SEQID, and
60  * it holds reference count for the various objects (vnode, open owner,
61  * open stream, lock owner).
62  */
63 
64 typedef struct {
65 	mntinfo4_t *rc_mi;
66 	vnode_t *rc_vp1;
67 	vnode_t *rc_vp2;
68 	nfs4_recov_t rc_action;
69 	stateid4 rc_stateid;
70 	bool_t rc_srv_reboot;		/* server has rebooted */
71 	nfs4_lost_rqst_t *rc_lost_rqst;
72 	nfs4_error_t rc_orig_errors;	/* original errors causing recovery */
73 	int rc_error;
74 	nfs4_bseqid_entry_t *rc_bseqid_rqst;
75 } recov_info_t;
76 
77 /*
78  * How long to wait before trying again if there is an error doing
79  * recovery, in seconds.
80  */
81 
82 static int recov_err_delay = 1;
83 
84 /*
85  * How long to wait when processing NFS4ERR_GRACE or NFS4ERR_DELAY
86  * errors.  Expressed in seconds.  Default is defined as
87  * NFS4ERR_DELAY_TIME and this variable is initialized in nfs4_subr_init()
88  */
89 time_t nfs4err_delay_time = 0;
90 
91 /*
92  * Tuneable to limit how many time "exempt" ops go OTW
93  * after a recovery error.  Exempt op hints are OH_CLOSE,
94  * OH_LOCKU, OH_DELEGRETURN.  These previously always went
95  * OTW even after rnode was "dead" due to recovery errors.
96  *
97  * The tuneable below limits the number of times a start_fop
98  * invocation will retry the exempt hints.  After the limit
99  * is reached, nfs4_start_fop will return an error just like
100  * it would for non-exempt op hints.
101  */
102 int nfs4_max_recov_error_retry = 3;
103 
104 /*
105  * Number of seconds the recovery thread should pause before retry when the
106  * filesystem has been forcibly unmounted.
107  */
108 
109 int nfs4_unmount_delay = 1;
110 
111 #ifdef DEBUG
112 
113 /*
114  * How long to wait (in seconds) between recovery operations on a given
115  * file.  Normally zero, but could be set longer for testing purposes.
116  */
117 static int nfs4_recovdelay = 0;
118 
119 /*
120  * Switch that controls whether to go into the debugger when recovery
121  * fails.
122  */
123 static int nfs4_fail_recov_stop = 0;
124 
125 /*
126  * Tuneables to debug client namespace interaction with server
127  * mount points:
128  *
129  *	nfs4_srvmnt_fail_cnt:
130  *		number of times EACCES returned because client
131  *		attempted to cross server mountpoint
132  *
133  *	nfs4_srvmnt_debug:
134  *		trigger console printf whenever client attempts
135  *		to cross server mountpoint
136  */
137 int nfs4_srvmnt_fail_cnt = 0;
138 int nfs4_srvmnt_debug = 0;
139 #endif
140 
141 /* forward references, in alphabetic order */
142 static void close_after_open_resend(vnode_t *, cred_t *, uint32_t,
143 	nfs4_error_t *);
144 static void errs_to_action(recov_info_t *,
145 	nfs4_server_t *, mntinfo4_t *, stateid4 *, nfs4_lost_rqst_t *, int,
146 	nfs_opnum4, nfs4_bseqid_entry_t *);
147 static void flush_reinstate(nfs4_lost_rqst_t *);
148 static void free_milist(mntinfo4_t **, int);
149 static mntinfo4_t **make_milist(nfs4_server_t *, int *);
150 static int nfs4_check_recov_err(vnode_t *, nfs4_op_hint_t,
151 	nfs4_recov_state_t *, int, char *);
152 static int nfs4_check_srvstub(vnode_t *vp, rnode4_t *rp, nfs4_op_hint_t op);
153 static char *nfs4_getsrvnames(mntinfo4_t *, size_t *);
154 static void nfs4_recov_fh_fail(vnode_t *, int, nfsstat4);
155 static void nfs4_recov_thread(recov_info_t *);
156 static void nfs4_remove_lost_rqsts(mntinfo4_t *, nfs4_server_t *);
157 static void nfs4_resend_lost_rqsts(recov_info_t *, nfs4_server_t *);
158 static cred_t *pid_to_cr(pid_t);
159 static void reclaim_one_lock(vnode_t *, flock64_t *, nfs4_error_t *, int *);
160 static void recov_bad_seqid(recov_info_t *);
161 static void recov_badstate(recov_info_t *, vnode_t *, nfsstat4);
162 static void recov_clientid(recov_info_t *, nfs4_server_t *);
163 static void recov_done(mntinfo4_t *, recov_info_t *);
164 static void recov_filehandle(nfs4_recov_t, mntinfo4_t *, vnode_t *);
165 static void recov_newserver(recov_info_t *, nfs4_server_t **, bool_t *);
166 static void recov_openfiles(recov_info_t *, nfs4_server_t *);
167 static void recov_stale(mntinfo4_t *, vnode_t *);
168 static void nfs4_free_lost_rqst(nfs4_lost_rqst_t *, nfs4_server_t *);
169 static void recov_throttle(recov_info_t *, vnode_t *);
170 static void relock_skip_pid(locklist_t *, pid_t);
171 static void resend_lock(nfs4_lost_rqst_t *, nfs4_error_t *);
172 static void resend_one_op(nfs4_lost_rqst_t *, nfs4_error_t *, mntinfo4_t *,
173 	nfs4_server_t *);
174 static void save_bseqid_rqst(nfs4_bseqid_entry_t *, recov_info_t *);
175 static void start_recovery(recov_info_t *, mntinfo4_t *, vnode_t *, vnode_t *,
176 	nfs4_server_t *);
177 static void start_recovery_action(nfs4_recov_t, bool_t, mntinfo4_t *, vnode_t *,
178 	vnode_t *);
179 static int wait_for_recovery(mntinfo4_t *, nfs4_op_hint_t);
180 
181 /*
182  * Return non-zero if the given errno, status, and rpc status codes
183  * in the nfs4_error_t indicate that client recovery is needed.
184  * "stateful" indicates whether the call that got the error establishes or
185  * removes state on the server (open, close, lock, unlock, delegreturn).
186  */
187 
188 int
189 nfs4_needs_recovery(nfs4_error_t *ep, bool_t stateful, vfs_t *vfsp)
190 {
191 	int recov = 0;
192 	mntinfo4_t *mi;
193 
194 	/*
195 	 * Try failover if the error values justify it and if
196 	 * it's a failover mount.  Don't try if the mount is in
197 	 * progress, failures are handled explicitly by nfs4rootvp.
198 	 */
199 	if (nfs4_try_failover(ep)) {
200 		mi = VFTOMI4(vfsp);
201 		mutex_enter(&mi->mi_lock);
202 		recov = FAILOVER_MOUNT4(mi) && !(mi->mi_flags & MI4_MOUNTING);
203 		mutex_exit(&mi->mi_lock);
204 		if (recov)
205 			return (recov);
206 	}
207 
208 	if (ep->error == EINTR || NFS4_FRC_UNMT_ERR(ep->error, vfsp)) {
209 		/*
210 		 * The server may have gotten the request, so for stateful
211 		 * ops we need to resynchronize and possibly back out the
212 		 * op.
213 		 */
214 		return (stateful);
215 	}
216 	if (ep->error != 0)
217 		return (0);
218 
219 	/* stat values are listed alphabetically */
220 	/*
221 	 * There are two lists here: the errors for which we have code, and
222 	 * the errors for which we plan to have code before FCS.  For the
223 	 * second list, print a warning message but don't attempt recovery.
224 	 */
225 	switch (ep->stat) {
226 	case NFS4ERR_BADHANDLE:
227 	case NFS4ERR_BAD_SEQID:
228 	case NFS4ERR_BAD_STATEID:
229 	case NFS4ERR_DELAY:
230 	case NFS4ERR_EXPIRED:
231 	case NFS4ERR_FHEXPIRED:
232 	case NFS4ERR_GRACE:
233 	case NFS4ERR_OLD_STATEID:
234 	case NFS4ERR_RESOURCE:
235 	case NFS4ERR_STALE_CLIENTID:
236 	case NFS4ERR_STALE_STATEID:
237 	case NFS4ERR_WRONGSEC:
238 	case NFS4ERR_STALE:
239 		recov = 1;
240 		break;
241 #ifdef DEBUG
242 	case NFS4ERR_LEASE_MOVED:
243 	case NFS4ERR_MOVED:
244 		zcmn_err(VFTOMI4(vfsp)->mi_zone->zone_id,
245 		    CE_WARN, "!Can't yet recover from NFS status %d",
246 				ep->stat);
247 		break;
248 #endif
249 	}
250 
251 	return (recov);
252 }
253 
254 /*
255  * Some operations such as DELEGRETURN want to avoid invoking
256  * recovery actions that will only mark the file dead.  If
257  * better handlers are invoked for any of these errors, this
258  * routine should be modified.
259  */
260 int
261 nfs4_recov_marks_dead(nfsstat4 status)
262 {
263 	if (status == NFS4ERR_BAD_SEQID ||
264 	    status == NFS4ERR_EXPIRED ||
265 	    status == NFS4ERR_BAD_STATEID ||
266 	    status == NFS4ERR_OLD_STATEID)
267 		return (1);
268 	return (0);
269 }
270 
271 /*
272  * Transfer the state recovery information in recovp to mi's resend queue,
273  * and mark mi as having a lost state request.
274  */
275 static void
276 nfs4_enqueue_lost_rqst(recov_info_t *recovp, mntinfo4_t *mi)
277 {
278 	nfs4_lost_rqst_t *lrp = recovp->rc_lost_rqst;
279 
280 	ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
281 	    nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
282 
283 	ASSERT(lrp != NULL && lrp->lr_op != 0);
284 
285 	NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE,
286 		"nfs4_enqueue_lost_rqst %p, op %d",
287 		(void *)lrp, lrp->lr_op));
288 
289 	mutex_enter(&mi->mi_lock);
290 	mi->mi_recovflags |= MI4R_LOST_STATE;
291 	if (lrp->lr_putfirst)
292 		list_insert_head(&mi->mi_lost_state, lrp);
293 	else
294 		list_insert_tail(&mi->mi_lost_state, lrp);
295 	recovp->rc_lost_rqst = NULL;
296 	mutex_exit(&mi->mi_lock);
297 
298 	nfs4_queue_event(RE_LOST_STATE, mi, NULL, lrp->lr_op, lrp->lr_vp,
299 		lrp->lr_dvp, 0, NULL, 0, TAG_NONE, TAG_NONE, 0, 0);
300 }
301 
302 /*
303  * Transfer the bad seqid recovery information in recovp to mi's
304  * bad seqid queue, and mark mi as having a bad seqid request.
305  */
306 void
307 enqueue_bseqid_rqst(recov_info_t *recovp, mntinfo4_t *mi)
308 {
309 	ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
310 	    nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
311 	ASSERT(recovp->rc_bseqid_rqst != NULL);
312 
313 	mutex_enter(&mi->mi_lock);
314 	mi->mi_recovflags |= MI4R_BAD_SEQID;
315 	list_insert_tail(&mi->mi_bseqid_list, recovp->rc_bseqid_rqst);
316 	recovp->rc_bseqid_rqst = NULL;
317 	mutex_exit(&mi->mi_lock);
318 }
319 
320 /*
321  * Initiate recovery.
322  *
323  * The nfs4_error_t contains the return codes that triggered a recovery
324  * attempt.  mi, vp1, and vp2 refer to the filesystem and files that were
325  * being operated on.  vp1 and vp2 may be NULL.
326  *
327  * Multiple calls are okay.  If recovery is already underway, the call
328  * updates the information about what state needs recovery but does not
329  * start a new thread.  The caller should hold mi->mi_recovlock as a reader
330  * for proper synchronization with any recovery thread.
331  *
332  * This will return TRUE if recovery was aborted, and FALSE otherwise.
333  */
334 bool_t
335 nfs4_start_recovery(nfs4_error_t *ep, mntinfo4_t *mi, vnode_t *vp1,
336     vnode_t *vp2, stateid4 *sid, nfs4_lost_rqst_t *lost_rqstp, nfs_opnum4 op,
337     nfs4_bseqid_entry_t *bsep)
338 {
339 	recov_info_t *recovp;
340 	nfs4_server_t *sp;
341 	bool_t abort = FALSE;
342 	bool_t gone = FALSE;
343 
344 	ASSERT(curproc->p_zone == mi->mi_zone);
345 	mutex_enter(&mi->mi_lock);
346 	/*
347 	 * If there is lost state, we need to kick off recovery even if the
348 	 * filesystem has been unmounted or the zone is shutting down.
349 	 */
350 	gone = FS_OR_ZONE_GONE4(mi->mi_vfsp);
351 	if (gone) {
352 		ASSERT(ep->error != EINTR || lost_rqstp != NULL);
353 		if (ep->error == EIO && lost_rqstp == NULL) {
354 			/* failed due to forced unmount, no new lost state */
355 			abort = TRUE;
356 		}
357 		if ((ep->error == 0 || ep->error == ETIMEDOUT) &&
358 		    !(mi->mi_recovflags & MI4R_LOST_STATE)) {
359 			/* some other failure, no existing lost state */
360 			abort = TRUE;
361 		}
362 		if (abort) {
363 			mutex_exit(&mi->mi_lock);
364 			NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
365 				    "nfs4_start_recovery: fs unmounted"));
366 			return (TRUE);
367 		}
368 	}
369 	mi->mi_in_recovery++;
370 	mutex_exit(&mi->mi_lock);
371 
372 	recovp = kmem_alloc(sizeof (recov_info_t), KM_SLEEP);
373 	recovp->rc_orig_errors = *ep;
374 	sp = find_nfs4_server(mi);
375 	errs_to_action(recovp, sp, mi, sid, lost_rqstp,
376 		gone, op, bsep);
377 	if (sp != NULL)
378 		mutex_exit(&sp->s_lock);
379 	start_recovery(recovp, mi, vp1, vp2, sp);
380 	if (sp != NULL)
381 		nfs4_server_rele(sp);
382 	return (FALSE);
383 }
384 
385 /*
386  * Internal version of nfs4_start_recovery.  The difference is that the
387  * caller specifies the recovery action, rather than the errors leading to
388  * recovery.
389  */
390 static void
391 start_recovery_action(nfs4_recov_t what, bool_t reboot, mntinfo4_t *mi,
392 	vnode_t *vp1, vnode_t *vp2)
393 {
394 	recov_info_t *recovp;
395 
396 	ASSERT(curproc->p_zone == mi->mi_zone);
397 	mutex_enter(&mi->mi_lock);
398 	mi->mi_in_recovery++;
399 	mutex_exit(&mi->mi_lock);
400 
401 	recovp = kmem_zalloc(sizeof (recov_info_t), KM_SLEEP);
402 	recovp->rc_action = what;
403 	recovp->rc_srv_reboot = reboot;
404 	recovp->rc_error = EIO;
405 	start_recovery(recovp, mi, vp1, vp2, NULL);
406 }
407 
408 static void
409 start_recovery(recov_info_t *recovp, mntinfo4_t *mi,
410 	vnode_t *vp1, vnode_t *vp2, nfs4_server_t *sp)
411 {
412 	NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
413 		"start_recovery: mi %p, what %s", (void*)mi,
414 		nfs4_recov_action_to_str(recovp->rc_action)));
415 
416 	/*
417 	 * Bump the reference on the vfs so that we can pass it to the
418 	 * recovery thread.
419 	 */
420 	VFS_HOLD(mi->mi_vfsp);
421 
422 again:
423 	switch (recovp->rc_action) {
424 	case NR_FAILOVER:
425 		ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
426 		    nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
427 		if (mi->mi_servers->sv_next == NULL)
428 			goto out_no_thread;
429 		mutex_enter(&mi->mi_lock);
430 		mi->mi_recovflags |= MI4R_NEED_NEW_SERVER;
431 		mutex_exit(&mi->mi_lock);
432 
433 		if (recovp->rc_lost_rqst != NULL)
434 			nfs4_enqueue_lost_rqst(recovp, mi);
435 		break;
436 
437 	case NR_CLIENTID:
438 		/*
439 		 * If the filesystem has been unmounted, punt.
440 		 */
441 		if (sp == NULL)
442 			goto out_no_thread;
443 
444 		/*
445 		 * If nobody else is working on the clientid, mark the
446 		 * clientid as being no longer set.  Then mark the specific
447 		 * filesystem being worked on.
448 		 */
449 		if (!nfs4_server_in_recovery(sp)) {
450 			mutex_enter(&sp->s_lock);
451 			sp->s_flags &= ~N4S_CLIENTID_SET;
452 			mutex_exit(&sp->s_lock);
453 		}
454 		ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
455 		    nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
456 		mutex_enter(&mi->mi_lock);
457 		mi->mi_recovflags |= MI4R_NEED_CLIENTID;
458 		if (recovp->rc_srv_reboot)
459 			mi->mi_recovflags |= MI4R_SRV_REBOOT;
460 		mutex_exit(&mi->mi_lock);
461 		break;
462 
463 	case NR_OPENFILES:
464 		ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
465 		    nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
466 		mutex_enter(&mi->mi_lock);
467 		mi->mi_recovflags |= MI4R_REOPEN_FILES;
468 		if (recovp->rc_srv_reboot)
469 			mi->mi_recovflags |= MI4R_SRV_REBOOT;
470 		mutex_exit(&mi->mi_lock);
471 		break;
472 
473 	case NR_WRONGSEC:
474 		ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
475 		    nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
476 		mutex_enter(&mi->mi_lock);
477 		mi->mi_recovflags |= MI4R_NEED_SECINFO;
478 		mutex_exit(&mi->mi_lock);
479 		break;
480 
481 	case NR_EXPIRED:
482 		if (vp1 != NULL)
483 			recov_badstate(recovp, vp1, NFS4ERR_EXPIRED);
484 		if (vp2 != NULL)
485 			recov_badstate(recovp, vp2, NFS4ERR_EXPIRED);
486 		goto out_no_thread;	/* no further recovery possible */
487 
488 	case NR_BAD_STATEID:
489 		if (vp1 != NULL)
490 			recov_badstate(recovp, vp1, NFS4ERR_BAD_STATEID);
491 		if (vp2 != NULL)
492 			recov_badstate(recovp, vp2, NFS4ERR_BAD_STATEID);
493 		goto out_no_thread;	/* no further recovery possible */
494 
495 	case NR_FHEXPIRED:
496 	case NR_BADHANDLE:
497 		if (vp1 != NULL)
498 			recov_throttle(recovp, vp1);
499 		if (vp2 != NULL)
500 			recov_throttle(recovp, vp2);
501 		/*
502 		 * Recover the filehandle now, rather than using a
503 		 * separate thread.  We can do this because filehandle
504 		 * recovery is independent of any other state, and because
505 		 * we know that we are not competing with the recovery
506 		 * thread at this time.  recov_filehandle will deal with
507 		 * threads that are competing to recover this filehandle.
508 		 */
509 		ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
510 		    nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
511 		if (vp1 != NULL)
512 			recov_filehandle(recovp->rc_action, mi, vp1);
513 		if (vp2 != NULL)
514 			recov_filehandle(recovp->rc_action, mi, vp2);
515 		goto out_no_thread;	/* no further recovery needed */
516 
517 	case NR_STALE:
518 		/*
519 		 * NFS4ERR_STALE handling
520 		 * recov_stale() could set MI4R_NEED_NEW_SERVER to
521 		 * indicate that we can and should failover.
522 		 */
523 		ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
524 		    nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
525 
526 		if (vp1 != NULL)
527 			recov_stale(mi, vp1);
528 		if (vp2 != NULL)
529 			recov_stale(mi, vp2);
530 		mutex_enter(&mi->mi_lock);
531 		if ((mi->mi_recovflags & MI4R_NEED_NEW_SERVER) == 0) {
532 			mutex_exit(&mi->mi_lock);
533 			goto out_no_thread;
534 		}
535 		mutex_exit(&mi->mi_lock);
536 		recovp->rc_action = NR_FAILOVER;
537 		goto again;
538 
539 	case NR_BAD_SEQID:
540 		if (recovp->rc_bseqid_rqst) {
541 			enqueue_bseqid_rqst(recovp, mi);
542 			break;
543 		}
544 
545 		if (vp1 != NULL)
546 			recov_badstate(recovp, vp1, NFS4ERR_BAD_SEQID);
547 		if (vp2 != NULL)
548 			recov_badstate(recovp, vp2, NFS4ERR_BAD_SEQID);
549 		goto out_no_thread; /* no further recovery possible */
550 
551 	case NR_OLDSTATEID:
552 		if (vp1 != NULL)
553 			recov_badstate(recovp, vp1, NFS4ERR_OLD_STATEID);
554 		if (vp2 != NULL)
555 			recov_badstate(recovp, vp2, NFS4ERR_OLD_STATEID);
556 		goto out_no_thread;	/* no further recovery possible */
557 
558 	case NR_GRACE:
559 		nfs4_set_grace_wait(mi);
560 		goto out_no_thread; /* no further action required for GRACE */
561 
562 	case NR_DELAY:
563 		if (vp1)
564 			nfs4_set_delay_wait(vp1);
565 		goto out_no_thread; /* no further action required for DELAY */
566 
567 	case NR_LOST_STATE_RQST:
568 	case NR_LOST_LOCK:
569 		nfs4_enqueue_lost_rqst(recovp, mi);
570 		break;
571 
572 	default:
573 		nfs4_queue_event(RE_UNEXPECTED_ACTION, mi, NULL,
574 		    recovp->rc_action, NULL, NULL, 0, NULL, 0, TAG_NONE,
575 		    TAG_NONE, 0, 0);
576 		goto out_no_thread;
577 	}
578 
579 	/*
580 	 * If either file recently went through the same recovery, wait
581 	 * awhile.  This is in case there is some sort of bug; we might not
582 	 * be able to recover properly, but at least we won't bombard the
583 	 * server with calls, and we won't tie up the client.
584 	 */
585 	if (vp1 != NULL)
586 		recov_throttle(recovp, vp1);
587 	if (vp2 != NULL)
588 		recov_throttle(recovp, vp2);
589 
590 	/*
591 	 * If there's already a recovery thread, don't start another one.
592 	 */
593 
594 	mutex_enter(&mi->mi_lock);
595 	if (mi->mi_flags & MI4_RECOV_ACTIV) {
596 		mutex_exit(&mi->mi_lock);
597 		goto out_no_thread;
598 	}
599 	mi->mi_flags |= MI4_RECOV_ACTIV;
600 	mutex_exit(&mi->mi_lock);
601 	NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
602 		"start_recovery: starting new thread for mi %p", (void*)mi));
603 
604 	recovp->rc_mi = mi;
605 	recovp->rc_vp1 = vp1;
606 	if (vp1 != NULL) {
607 		ASSERT(VTOMI4(vp1) == mi);
608 		VN_HOLD(recovp->rc_vp1);
609 	}
610 	recovp->rc_vp2 = vp2;
611 	if (vp2 != NULL) {
612 		ASSERT(VTOMI4(vp2) == mi);
613 		VN_HOLD(recovp->rc_vp2);
614 	}
615 
616 	(void) zthread_create(NULL, 0, nfs4_recov_thread, recovp, 0,
617 			    minclsyspri);
618 	return;
619 
620 	/* not reached by thread creating call */
621 out_no_thread:
622 	mutex_enter(&mi->mi_lock);
623 	mi->mi_in_recovery--;
624 	cv_broadcast(&mi->mi_cv_in_recov);
625 	mutex_exit(&mi->mi_lock);
626 
627 	VFS_RELE(mi->mi_vfsp);
628 	/*
629 	 * Free up resources that were allocated for us.
630 	 */
631 	kmem_free(recovp, sizeof (recov_info_t));
632 }
633 
634 static int
635 nfs4_check_srvstub(vnode_t *vp, rnode4_t *rp, nfs4_op_hint_t op)
636 {
637 	int err = 0;
638 
639 	/*
640 	 * If tuneable does not allow client to cross srv mountpoints and
641 	 * object is a stub, then check check op hint and return EACCES for
642 	 * any hint other than access, rddir, getattr, lookup.
643 	 */
644 	if (rp->r_flags & R4SRVSTUB && op != OH_ACCESS && op != OH_GETACL &&
645 	    op != OH_GETATTR && op != OH_READDIR && op != OH_LOOKUP) {
646 		err = EACCES;
647 #ifdef DEBUG
648 		NFS4_DEBUG(nfs4_srvmnt_debug, (CE_NOTE,
649 			"nfs4_check_srvstub: op=%d err=%d rp=%p vp=%p\n"
650 			"va_nod=%llx r_mntd_fid=%llx\n"
651 			"sv_fsid=(%llx:%llx) r_srv_fsid=(%llx:%llx)",
652 			op, err, (void *)rp, (void *)vp,
653 			(u_longlong_t)rp->r_attr.va_nodeid,
654 			(u_longlong_t)rp->r_mntd_fid,
655 			(u_longlong_t)rp->r_server->sv_fsid.major,
656 			(u_longlong_t)rp->r_server->sv_fsid.minor,
657 			(u_longlong_t)rp->r_srv_fsid.major,
658 			(u_longlong_t)rp->r_srv_fsid.minor));
659 #endif
660 	}
661 
662 	return (err);
663 }
664 
665 static int
666 nfs4_check_recov_err(vnode_t *vp, nfs4_op_hint_t op,
667 			nfs4_recov_state_t *rsp, int retry_err_cnt, char *str)
668 {
669 	rnode4_t *rp;
670 	int error = 0;
671 	int exempt;
672 
673 	if (vp == NULL)
674 		return (0);
675 
676 	exempt = (op == OH_CLOSE || op == OH_LOCKU || op == OH_DELEGRETURN);
677 	rp = VTOR4(vp);
678 	mutex_enter(&rp->r_statelock);
679 
680 	/*
681 	 * If there was a recovery error, then allow op hints "exempt" from
682 	 * recov errors to retry (currently 3 times).  Either r_error or
683 	 * EIO is returned for non-exempt op hints.
684 	 *
685 	 *	Error heirarchy:
686 	 *	a) check for R4ERECOVERR
687 	 *	b) check for R4SRVSTUB (only if R4RECOVERR is not set).
688 	 */
689 	if (rp->r_flags & R4RECOVERR) {
690 		if (exempt && rsp->rs_num_retry_despite_err <=
691 				nfs4_max_recov_error_retry) {
692 
693 			/*
694 			 * Check to make sure that we haven't already inc'd
695 			 * rs_num_retry_despite_err for current nfs4_start_fop
696 			 * instance.  We don't want to double inc (if we were
697 			 * called with vp2, then the vp1 call could have
698 			 * already incremented.
699 			 */
700 			if (retry_err_cnt == rsp->rs_num_retry_despite_err)
701 				rsp->rs_num_retry_despite_err++;
702 
703 			NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
704 				"nfs4_start_fop: %s %p DEAD, cnt=%d", str,
705 				(void *)vp, rsp->rs_num_retry_despite_err));
706 		} else {
707 			error = (rp->r_error ? rp->r_error : EIO);
708 			/*
709 			 * An ESTALE error on a non-regular file is not
710 			 * "sticky".  Return the ESTALE error once, but
711 			 * clear the condition to allow future operations
712 			 * to go OTW.  This will allow the client to
713 			 * recover if the server has merely unshared then
714 			 * re-shared the file system.  For regular files,
715 			 * the unshare has destroyed the open state at the
716 			 * server and we aren't willing to do a reopen (yet).
717 			 */
718 			if (error == ESTALE && vp->v_type != VREG) {
719 				rp->r_flags &=
720 					~(R4RECOVERR|R4RECOVERRP|R4STALE);
721 				rp->r_error = 0;
722 				error = ESTALE;
723 			}
724 			NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
725 				"nfs4_start_fop: %s %p DEAD, cnt=%d error=%d",
726 				str, (void *)vp,
727 				rsp->rs_num_retry_despite_err, error));
728 		}
729 	} else {
730 		error = nfs4_check_srvstub(vp, rp, op);
731 		NFS4_DEBUG(nfs4_client_recov_stub_debug, (CE_NOTE,
732 			"nfs4_start_fop: %s %p SRVSTUB, error=%d", str,
733 			(void *)vp, error));
734 	}
735 	mutex_exit(&rp->r_statelock);
736 	return (error);
737 }
738 
739 /*
740  * Initial setup code that every operation should call if it might invoke
741  * client recovery.  Can block waiting for recovery to finish on a
742  * filesystem.  Either vnode ptr can be NULL.
743  *
744  * Returns 0 if there are no outstanding errors.  Can return an
745  * errno value under various circumstances (e.g., failed recovery, or
746  * interrupted while waiting for recovery to finish).
747  *
748  * There must be a corresponding call to nfs4_end_op() to free up any locks
749  * or resources allocated by this call (assuming this call succeeded),
750  * using the same rsp that's passed in here.
751  *
752  * The open and lock seqid synchronization must be stopped before calling this
753  * function, as it could lead to deadlock when trying to reopen a file or
754  * reclaim a lock.  The synchronization is obtained with calls to:
755  *   nfs4_start_open_seqid_sync()
756  *   nfs4_start_lock_seqid_sync()
757  *
758  * *startrecovp is set TRUE if the caller should not bother with the
759  * over-the-wire call, and just initiate recovery for the given request.
760  * This is typically used for state-releasing ops if the filesystem has
761  * been forcibly unmounted.  startrecovp may be NULL for
762  * non-state-releasing ops.
763  */
764 
765 int
766 nfs4_start_fop(mntinfo4_t *mi, vnode_t *vp1, vnode_t *vp2, nfs4_op_hint_t op,
767 		nfs4_recov_state_t *rsp, bool_t *startrecovp)
768 {
769 	int error = 0, rerr_cnt;
770 	nfs4_server_t *sp = NULL;
771 	nfs4_server_t *tsp;
772 	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
773 	time_t droplock_time;
774 #ifdef DEBUG
775 	void *fop_caller;
776 #endif
777 
778 	ASSERT(vp1 == NULL || vp1->v_vfsp == mi->mi_vfsp);
779 	ASSERT(vp2 == NULL || vp2->v_vfsp == mi->mi_vfsp);
780 
781 #ifdef	DEBUG
782 	if ((fop_caller = tsd_get(nfs4_tsd_key)) != NULL) {
783 		cmn_err(CE_PANIC, "Missing nfs4_end_fop: last caller %p",
784 			fop_caller);
785 	}
786 	(void) tsd_set(nfs4_tsd_key, caller());
787 #endif
788 
789 	rsp->rs_sp = NULL;
790 	rsp->rs_flags &= ~NFS4_RS_RENAME_HELD;
791 	rerr_cnt = rsp->rs_num_retry_despite_err;
792 
793 	/*
794 	 * Process the items that may delay() based on server response
795 	 */
796 	error = nfs4_wait_for_grace(mi, rsp);
797 	if (error)
798 		goto out;
799 
800 	if (vp1 != NULL) {
801 		error = nfs4_wait_for_delay(vp1, rsp);
802 		if (error)
803 			goto out;
804 	}
805 
806 	/* Wait for a delegation recall to complete. */
807 
808 	error = wait_for_recall(vp1, vp2, op, rsp);
809 	if (error)
810 		goto out;
811 
812 	/*
813 	 * Wait for any current recovery actions to finish.  Note that a
814 	 * recovery thread can still start up after wait_for_recovery()
815 	 * finishes.  We don't block out recovery operations until we
816 	 * acquire s_recovlock and mi_recovlock.
817 	 */
818 	error = wait_for_recovery(mi, op);
819 	if (error)
820 		goto out;
821 
822 	/*
823 	 * Check to see if the rnode is already marked with a
824 	 * recovery error.  If so, return it immediately.  But
825 	 * always pass CLOSE, LOCKU, and DELEGRETURN so we can
826 	 * clean up state on the server.
827 	 */
828 
829 	if (vp1 != NULL) {
830 		if (error = nfs4_check_recov_err(vp1, op, rsp, rerr_cnt, "vp1"))
831 			goto out;
832 		nfs4_check_remap(mi, vp1, NFS4_REMAP_CKATTRS, &e);
833 	}
834 
835 	if (vp2 != NULL) {
836 		if (error = nfs4_check_recov_err(vp2, op, rsp, rerr_cnt, "vp2"))
837 			goto out;
838 		nfs4_check_remap(mi, vp2, NFS4_REMAP_CKATTRS, &e);
839 	}
840 
841 	/*
842 	 * The lock order calls for us to acquire s_recovlock before
843 	 * mi_recovlock, but we have to hold mi_recovlock to look up sp (to
844 	 * prevent races with the failover/migration code).  So acquire
845 	 * mi_recovlock, look up sp, drop mi_recovlock, acquire
846 	 * s_recovlock and mi_recovlock, then verify that sp is still the
847 	 * right object.  XXX Can we find a simpler way to deal with this?
848 	 */
849 	if (nfs_rw_enter_sig(&mi->mi_recovlock, RW_READER,
850 	    mi->mi_flags & MI4_INT)) {
851 		error = EINTR;
852 		goto out;
853 	}
854 get_sp:
855 	sp = find_nfs4_server(mi);
856 	if (sp != NULL) {
857 		sp->s_otw_call_count++;
858 		mutex_exit(&sp->s_lock);
859 		droplock_time = gethrestime_sec();
860 	}
861 	nfs_rw_exit(&mi->mi_recovlock);
862 
863 	if (sp != NULL) {
864 		if (nfs_rw_enter_sig(&sp->s_recovlock, RW_READER,
865 			    mi->mi_flags & MI4_INT)) {
866 			error = EINTR;
867 			goto out;
868 		}
869 	}
870 	if (nfs_rw_enter_sig(&mi->mi_recovlock, RW_READER,
871 			    mi->mi_flags & MI4_INT)) {
872 		if (sp != NULL)
873 			nfs_rw_exit(&sp->s_recovlock);
874 		error = EINTR;
875 		goto out;
876 	}
877 	/*
878 	 * If the mntinfo4_t hasn't changed nfs4_sever_ts then
879 	 * there's no point in double checking to make sure it
880 	 * has switched.
881 	 */
882 	if (sp == NULL || droplock_time < mi->mi_srvsettime) {
883 		tsp = find_nfs4_server(mi);
884 		if (tsp != sp) {
885 			/* try again */
886 			if (tsp != NULL) {
887 				mutex_exit(&tsp->s_lock);
888 				nfs4_server_rele(tsp);
889 				tsp = NULL;
890 			}
891 			if (sp != NULL) {
892 				nfs_rw_exit(&sp->s_recovlock);
893 				mutex_enter(&sp->s_lock);
894 				sp->s_otw_call_count--;
895 				mutex_exit(&sp->s_lock);
896 				nfs4_server_rele(sp);
897 				sp = NULL;
898 			}
899 			goto get_sp;
900 		} else {
901 			if (tsp != NULL) {
902 				mutex_exit(&tsp->s_lock);
903 				nfs4_server_rele(tsp);
904 				tsp = NULL;
905 			}
906 		}
907 	}
908 
909 	if (sp != NULL) {
910 		rsp->rs_sp = sp;
911 	}
912 
913 	/*
914 	 * If the fileystem uses volatile filehandles, obtain a lock so
915 	 * that we synchronize with renames.  Exception: mount operations
916 	 * can change mi_fh_expire_type, which could be a problem, since
917 	 * the end_op code needs to be consistent with the start_op code
918 	 * about mi_rename_lock.  Since mounts don't compete with renames,
919 	 * it's simpler to just not acquire the rename lock for mounts.
920 	 */
921 	if (NFS4_VOLATILE_FH(mi) && op != OH_MOUNT) {
922 		if (nfs_rw_enter_sig(&mi->mi_rename_lock,
923 				    op == OH_VFH_RENAME ? RW_WRITER : RW_READER,
924 				    mi->mi_flags & MI4_INT)) {
925 			nfs_rw_exit(&mi->mi_recovlock);
926 			if (sp != NULL)
927 				nfs_rw_exit(&sp->s_recovlock);
928 			error = EINTR;
929 			goto out;
930 		}
931 		rsp->rs_flags |= NFS4_RS_RENAME_HELD;
932 	}
933 
934 	if (OH_IS_STATE_RELE(op)) {
935 		/*
936 		 * For forced unmount, letting the request proceed will
937 		 * almost always delay response to the user, so hand it off
938 		 * to the recovery thread.  For exiting lwp's, we don't
939 		 * have a good way to tell if the request will hang.  We
940 		 * generally want processes to handle their own requests so
941 		 * that they can be done in parallel, but if there is
942 		 * already a recovery thread, hand the request off to it.
943 		 * This will improve user response at no cost to overall
944 		 * system throughput.  For zone shutdown, we'd prefer
945 		 * the recovery thread to handle this as well.
946 		 */
947 		ASSERT(startrecovp != NULL);
948 		mutex_enter(&mi->mi_lock);
949 		if (FS_OR_ZONE_GONE4(mi->mi_vfsp))
950 			*startrecovp = TRUE;
951 		else if ((curthread->t_proc_flag & TP_LWPEXIT) &&
952 		    (mi->mi_flags & MI4_RECOV_ACTIV))
953 			*startrecovp = TRUE;
954 		else
955 			*startrecovp = FALSE;
956 		mutex_exit(&mi->mi_lock);
957 	} else
958 		if (startrecovp != NULL)
959 			*startrecovp = FALSE;
960 
961 	ASSERT(error == 0);
962 	return (error);
963 
964 out:
965 	ASSERT(error != 0);
966 	if (sp != NULL) {
967 		mutex_enter(&sp->s_lock);
968 		sp->s_otw_call_count--;
969 		mutex_exit(&sp->s_lock);
970 		nfs4_server_rele(sp);
971 		rsp->rs_sp = NULL;
972 	}
973 	nfs4_end_op_recall(vp1, vp2, rsp);
974 
975 #ifdef	DEBUG
976 	(void) tsd_set(nfs4_tsd_key, NULL);
977 #endif
978 	return (error);
979 }
980 
981 /*
982  * It is up to the caller to determine if rsp->rs_sp being NULL
983  * is detrimental or not.
984  */
985 int
986 nfs4_start_op(mntinfo4_t *mi, vnode_t *vp1, vnode_t *vp2,
987 	nfs4_recov_state_t *rsp)
988 {
989 	ASSERT(rsp->rs_num_retry_despite_err == 0);
990 	rsp->rs_num_retry_despite_err = 0;
991 	return (nfs4_start_fop(mi, vp1, vp2, OH_OTHER, rsp, NULL));
992 }
993 
994 /*
995  * Release any resources acquired by nfs4_start_op().
996  * 'sp' should be the nfs4_server pointer returned by nfs4_start_op().
997  *
998  * The operation hint is used to avoid a deadlock by bypassing delegation
999  * return logic for writes, which are done while returning a delegation.
1000  */
1001 
1002 void
1003 nfs4_end_fop(mntinfo4_t *mi, vnode_t *vp1, vnode_t *vp2, nfs4_op_hint_t op,
1004 		nfs4_recov_state_t *rsp, bool_t needs_recov)
1005 {
1006 	nfs4_server_t *sp = rsp->rs_sp;
1007 	rnode4_t *rp = NULL;
1008 
1009 #ifdef	lint
1010 	/*
1011 	 * The op hint isn't used any more, but might be in
1012 	 * the future.
1013 	 */
1014 	op = op;
1015 #endif
1016 
1017 #ifdef	DEBUG
1018 	ASSERT(tsd_get(nfs4_tsd_key) != NULL);
1019 	(void) tsd_set(nfs4_tsd_key, NULL);
1020 #endif
1021 
1022 	nfs4_end_op_recall(vp1, vp2, rsp);
1023 
1024 	if (rsp->rs_flags & NFS4_RS_RENAME_HELD)
1025 		nfs_rw_exit(&mi->mi_rename_lock);
1026 
1027 	if (!needs_recov) {
1028 		if (rsp->rs_flags & NFS4_RS_DELAY_MSG) {
1029 			/* may need to clear the delay interval */
1030 			if (vp1 != NULL) {
1031 				rp = VTOR4(vp1);
1032 				mutex_enter(&rp->r_statelock);
1033 				rp->r_delay_interval = 0;
1034 				mutex_exit(&rp->r_statelock);
1035 			}
1036 		}
1037 		rsp->rs_flags &= ~(NFS4_RS_GRACE_MSG|NFS4_RS_DELAY_MSG);
1038 	}
1039 
1040 	/*
1041 	 * If the corresponding nfs4_start_op() found a sp,
1042 	 * then there must still be a sp.
1043 	 */
1044 	if (sp != NULL) {
1045 		nfs_rw_exit(&mi->mi_recovlock);
1046 		nfs_rw_exit(&sp->s_recovlock);
1047 		mutex_enter(&sp->s_lock);
1048 		sp->s_otw_call_count--;
1049 		cv_broadcast(&sp->s_cv_otw_count);
1050 		mutex_exit(&sp->s_lock);
1051 		nfs4_server_rele(sp);
1052 	} else {
1053 		nfs_rw_exit(&mi->mi_recovlock);
1054 	}
1055 }
1056 
1057 void
1058 nfs4_end_op(mntinfo4_t *mi, vnode_t *vp1, vnode_t *vp2,
1059 	    nfs4_recov_state_t *rsp, bool_t needrecov)
1060 {
1061 	nfs4_end_fop(mi, vp1, vp2, OH_OTHER, rsp, needrecov);
1062 }
1063 
1064 /*
1065  * If the filesystem is going through client recovery, block until
1066  * finished.
1067  * Exceptions:
1068  * - state-releasing ops (CLOSE, LOCKU, DELEGRETURN) are allowed to proceed
1069  *   if the filesystem has been forcibly unmounted or the lwp is exiting.
1070  *
1071  * Return value:
1072  * - 0 if no errors
1073  * - EINTR if the call was interrupted
1074  * - EIO if the filesystem has been forcibly unmounted (non-state-releasing
1075  *   op)
1076  * - the errno value from the recovery thread, if recovery failed
1077  */
1078 
1079 static int
1080 wait_for_recovery(mntinfo4_t *mi, nfs4_op_hint_t op_hint)
1081 {
1082 	int error = 0;
1083 
1084 	mutex_enter(&mi->mi_lock);
1085 
1086 	while (mi->mi_recovflags != 0) {
1087 		klwp_t *lwp = ttolwp(curthread);
1088 
1089 		if (mi->mi_flags & MI4_RECOV_FAIL)
1090 			break;
1091 		if (mi->mi_vfsp->vfs_flag & VFS_UNMOUNTED)
1092 			break;
1093 		if (OH_IS_STATE_RELE(op_hint) &&
1094 		    (curthread->t_proc_flag & TP_LWPEXIT))
1095 			break;
1096 
1097 		if (lwp != NULL)
1098 			lwp->lwp_nostop++;
1099 		/* XXX - use different cv? */
1100 		if (cv_wait_sig(&mi->mi_failover_cv, &mi->mi_lock) == 0) {
1101 			error = EINTR;
1102 			if (lwp != NULL)
1103 				lwp->lwp_nostop--;
1104 			break;
1105 		}
1106 		if (lwp != NULL)
1107 			lwp->lwp_nostop--;
1108 	}
1109 
1110 	if (mi->mi_flags & MI4_RECOV_FAIL) {
1111 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
1112 			"wait_for_recovery: fail since RECOV FAIL"));
1113 		error = mi->mi_error;
1114 	} else if ((mi->mi_vfsp->vfs_flag & VFS_UNMOUNTED) &&
1115 	    !OH_IS_STATE_RELE(op_hint)) {
1116 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
1117 			"wait_for_recovery: forced unmount"));
1118 		error = EIO;
1119 	}
1120 
1121 	mutex_exit(&mi->mi_lock);
1122 
1123 	return (error);
1124 }
1125 
1126 /*
1127  * If the client received NFS4ERR_GRACE for this particular mount,
1128  * the client blocks here until it is time to try again.
1129  *
1130  * Return value:
1131  * - 0 if wait was successful
1132  * - EINTR if the call was interrupted
1133  */
1134 
1135 int
1136 nfs4_wait_for_grace(mntinfo4_t *mi, nfs4_recov_state_t *rsp)
1137 {
1138 	int error = 0;
1139 	time_t curtime, time_to_wait;
1140 
1141 	/* do a unprotected check to reduce mi_lock contention */
1142 	if (mi->mi_grace_wait != 0) {
1143 		mutex_enter(&mi->mi_lock);
1144 
1145 		if (mi->mi_grace_wait != 0) {
1146 			if (!(rsp->rs_flags & NFS4_RS_GRACE_MSG))
1147 				rsp->rs_flags |= NFS4_RS_GRACE_MSG;
1148 
1149 			curtime = gethrestime_sec();
1150 
1151 			if (curtime < mi->mi_grace_wait) {
1152 
1153 				time_to_wait = mi->mi_grace_wait - curtime;
1154 
1155 				mutex_exit(&mi->mi_lock);
1156 
1157 				delay(SEC_TO_TICK(time_to_wait));
1158 
1159 				curtime = gethrestime_sec();
1160 
1161 				mutex_enter(&mi->mi_lock);
1162 
1163 				if (curtime >= mi->mi_grace_wait)
1164 					mi->mi_grace_wait = 0;
1165 			} else {
1166 				mi->mi_grace_wait = 0;
1167 			}
1168 		}
1169 		mutex_exit(&mi->mi_lock);
1170 	}
1171 
1172 	return (error);
1173 }
1174 
1175 /*
1176  * If the client received NFS4ERR_DELAY for an operation on a vnode,
1177  * the client blocks here until it is time to try again.
1178  *
1179  * Return value:
1180  * - 0 if wait was successful
1181  * - EINTR if the call was interrupted
1182  */
1183 
1184 int
1185 nfs4_wait_for_delay(vnode_t *vp, nfs4_recov_state_t *rsp)
1186 {
1187 	int error = 0;
1188 	time_t curtime, time_to_wait;
1189 	rnode4_t *rp;
1190 
1191 	ASSERT(vp != NULL);
1192 
1193 	rp = VTOR4(vp);
1194 
1195 	/* do a unprotected check to reduce r_statelock contention */
1196 	if (rp->r_delay_wait != 0) {
1197 		mutex_enter(&rp->r_statelock);
1198 
1199 		if (rp->r_delay_wait != 0) {
1200 
1201 			if (!(rsp->rs_flags & NFS4_RS_DELAY_MSG)) {
1202 				rsp->rs_flags |= NFS4_RS_DELAY_MSG;
1203 				nfs4_mi_kstat_inc_delay(VTOMI4(vp));
1204 			}
1205 
1206 			curtime = gethrestime_sec();
1207 
1208 			if (curtime < rp->r_delay_wait) {
1209 
1210 				time_to_wait = rp->r_delay_wait - curtime;
1211 
1212 				mutex_exit(&rp->r_statelock);
1213 
1214 				delay(SEC_TO_TICK(time_to_wait));
1215 
1216 				curtime = gethrestime_sec();
1217 
1218 				mutex_enter(&rp->r_statelock);
1219 
1220 				if (curtime >= rp->r_delay_wait)
1221 					rp->r_delay_wait = 0;
1222 			} else {
1223 				rp->r_delay_wait = 0;
1224 			}
1225 		}
1226 		mutex_exit(&rp->r_statelock);
1227 	}
1228 
1229 	return (error);
1230 }
1231 
1232 /*
1233  * The recovery thread.
1234  */
1235 
1236 static void
1237 nfs4_recov_thread(recov_info_t *recovp)
1238 {
1239 	mntinfo4_t *mi = recovp->rc_mi;
1240 	nfs4_server_t *sp;
1241 	int done = 0, error = 0;
1242 	bool_t recov_fail = FALSE;
1243 	callb_cpr_t cpr_info;
1244 	kmutex_t cpr_lock;
1245 
1246 	nfs4_queue_event(RE_START, mi, NULL, mi->mi_recovflags,
1247 	    recovp->rc_vp1, recovp->rc_vp2, 0, NULL, 0, TAG_NONE, TAG_NONE,
1248 	    0, 0);
1249 
1250 	mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL);
1251 	CALLB_CPR_INIT(&cpr_info, &cpr_lock, callb_generic_cpr, "nfsv4Recov");
1252 
1253 	mutex_enter(&mi->mi_lock);
1254 	mi->mi_recovthread = curthread;
1255 	mutex_exit(&mi->mi_lock);
1256 
1257 	/*
1258 	 * We don't really need protection here against failover or
1259 	 * migration, since the current thread is the one that would make
1260 	 * any changes, but hold mi_recovlock anyway for completeness (and
1261 	 * to satisfy any ASSERTs).
1262 	 */
1263 	(void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_READER, 0);
1264 	sp = find_nfs4_server(mi);
1265 	if (sp != NULL)
1266 		mutex_exit(&sp->s_lock);
1267 	nfs_rw_exit(&mi->mi_recovlock);
1268 
1269 	/*
1270 	 * Do any necessary recovery, based on the information in recovp
1271 	 * and any recovery flags.
1272 	 */
1273 
1274 	do {
1275 		mutex_enter(&mi->mi_lock);
1276 		if (FS_OR_ZONE_GONE4(mi->mi_vfsp)) {
1277 			bool_t activesrv;
1278 
1279 			NFS4_DEBUG(nfs4_client_recov_debug &&
1280 			    mi->mi_vfsp->vfs_flag & VFS_UNMOUNTED, (CE_NOTE,
1281 				"nfs4_recov_thread: file system has been "
1282 				"unmounted"));
1283 			NFS4_DEBUG(nfs4_client_recov_debug &&
1284 			    zone_status_get(curproc->p_zone) >=
1285 			    ZONE_IS_SHUTTING_DOWN, (CE_NOTE,
1286 				"nfs4_recov_thread: zone shutting down"));
1287 			/*
1288 			 * If the server has lost its state for us and
1289 			 * the filesystem is unmounted, then the filesystem
1290 			 * can be tossed, even if there are lost lock or
1291 			 * lost state calls in the recovery queue.
1292 			 */
1293 			if (mi->mi_recovflags &
1294 			    (MI4R_NEED_CLIENTID | MI4R_REOPEN_FILES)) {
1295 				NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
1296 				"nfs4_recov_thread: bailing out"));
1297 				mi->mi_flags |= MI4_RECOV_FAIL;
1298 				mi->mi_error = recovp->rc_error;
1299 				recov_fail = TRUE;
1300 			}
1301 			/*
1302 			 * We don't know if the server has any state for
1303 			 * us, and the filesystem has been unmounted.  If
1304 			 * there are "lost state" recovery items, keep
1305 			 * trying to process them until there are no more
1306 			 * mounted filesystems for the server.  Otherwise,
1307 			 * bail out.  The reason we don't mark the
1308 			 * filesystem as failing recovery is in case we
1309 			 * have to do "lost state" recovery later (e.g., a
1310 			 * user process exits).
1311 			 */
1312 			if (!(mi->mi_recovflags & MI4R_LOST_STATE)) {
1313 				recov_done(mi, recovp);
1314 				mutex_exit(&mi->mi_lock);
1315 				break;
1316 			}
1317 			mutex_exit(&mi->mi_lock);
1318 
1319 			if (sp == NULL)
1320 				activesrv = FALSE;
1321 			else {
1322 				mutex_enter(&sp->s_lock);
1323 				activesrv = nfs4_fs_active(sp);
1324 			}
1325 			if (!activesrv) {
1326 				NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
1327 					"no active fs for server %p",
1328 					(void *)sp));
1329 				mutex_enter(&mi->mi_lock);
1330 				mi->mi_flags |= MI4_RECOV_FAIL;
1331 				mi->mi_error = recovp->rc_error;
1332 				mutex_exit(&mi->mi_lock);
1333 				recov_fail = TRUE;
1334 				if (sp != NULL) {
1335 					/*
1336 					 * Mark the server instance as
1337 					 * dead, so that nobody will attach
1338 					 * a new filesystem.
1339 					 */
1340 					nfs4_mark_srv_dead(sp);
1341 				}
1342 			}
1343 			if (sp != NULL)
1344 				mutex_exit(&sp->s_lock);
1345 		} else {
1346 			mutex_exit(&mi->mi_lock);
1347 		}
1348 
1349 		/*
1350 		 * Check if we need to select a new server for a
1351 		 * failover.  Choosing a new server will force at
1352 		 * least a check of the clientid.
1353 		 */
1354 		mutex_enter(&mi->mi_lock);
1355 		if (!recov_fail &&
1356 		    (mi->mi_recovflags & MI4R_NEED_NEW_SERVER)) {
1357 			mutex_exit(&mi->mi_lock);
1358 			recov_newserver(recovp, &sp, &recov_fail);
1359 		} else
1360 			mutex_exit(&mi->mi_lock);
1361 
1362 		/*
1363 		 * Check if we need to recover the clientid.  This
1364 		 * must be done before file and lock recovery, and it
1365 		 * potentially affects the recovery threads for other
1366 		 * filesystems, so it gets special treatment.
1367 		 */
1368 		if (sp != NULL && recov_fail == FALSE) {
1369 			mutex_enter(&sp->s_lock);
1370 			if (!(sp->s_flags & N4S_CLIENTID_SET)) {
1371 				mutex_exit(&sp->s_lock);
1372 				recov_clientid(recovp, sp);
1373 			} else {
1374 				/*
1375 				 * Unset this flag in case another recovery
1376 				 * thread successfully recovered the clientid
1377 				 * for us already.
1378 				 */
1379 				mutex_enter(&mi->mi_lock);
1380 				mi->mi_recovflags &= ~MI4R_NEED_CLIENTID;
1381 				mutex_exit(&mi->mi_lock);
1382 				mutex_exit(&sp->s_lock);
1383 			}
1384 		}
1385 
1386 		/*
1387 		 * Check if we need to get the security information.
1388 		 */
1389 		mutex_enter(&mi->mi_lock);
1390 		if ((mi->mi_recovflags & MI4R_NEED_SECINFO) &&
1391 		    !(mi->mi_flags & MI4_RECOV_FAIL)) {
1392 			mutex_exit(&mi->mi_lock);
1393 			(void) nfs_rw_enter_sig(&mi->mi_recovlock,
1394 							RW_WRITER, 0);
1395 			error = nfs4_secinfo_recov(recovp->rc_mi,
1396 					recovp->rc_vp1, recovp->rc_vp2);
1397 			/*
1398 			 * If error, nothing more can be done, stop
1399 			 * the recovery.
1400 			 */
1401 			if (error) {
1402 				mutex_enter(&mi->mi_lock);
1403 				mi->mi_flags |= MI4_RECOV_FAIL;
1404 				mi->mi_error = recovp->rc_error;
1405 				mutex_exit(&mi->mi_lock);
1406 				nfs4_queue_event(RE_WRONGSEC, mi, NULL,
1407 				    error, recovp->rc_vp1, recovp->rc_vp2,
1408 				    0, NULL, 0, TAG_NONE, TAG_NONE, 0, 0);
1409 			}
1410 			nfs_rw_exit(&mi->mi_recovlock);
1411 		} else
1412 			mutex_exit(&mi->mi_lock);
1413 
1414 		/*
1415 		 * Check if there's a bad seqid to recover.
1416 		 */
1417 		mutex_enter(&mi->mi_lock);
1418 		if ((mi->mi_recovflags & MI4R_BAD_SEQID) &&
1419 		    !(mi->mi_flags & MI4_RECOV_FAIL)) {
1420 			mutex_exit(&mi->mi_lock);
1421 			(void) nfs_rw_enter_sig(&mi->mi_recovlock,
1422 					RW_WRITER, 0);
1423 			recov_bad_seqid(recovp);
1424 			nfs_rw_exit(&mi->mi_recovlock);
1425 		} else
1426 			mutex_exit(&mi->mi_lock);
1427 
1428 		/*
1429 		 * Next check for recovery that affects the entire
1430 		 * filesystem.
1431 		 */
1432 		if (sp != NULL) {
1433 			mutex_enter(&mi->mi_lock);
1434 			if ((mi->mi_recovflags & MI4R_REOPEN_FILES) &&
1435 			    !(mi->mi_flags & MI4_RECOV_FAIL)) {
1436 				mutex_exit(&mi->mi_lock);
1437 				recov_openfiles(recovp, sp);
1438 			} else
1439 				mutex_exit(&mi->mi_lock);
1440 		}
1441 
1442 		/*
1443 		 * Send any queued state recovery requests.
1444 		 */
1445 		mutex_enter(&mi->mi_lock);
1446 		if (sp != NULL &&
1447 		    (mi->mi_recovflags & MI4R_LOST_STATE) &&
1448 		    !(mi->mi_flags & MI4_RECOV_FAIL)) {
1449 			mutex_exit(&mi->mi_lock);
1450 			(void) nfs_rw_enter_sig(&mi->mi_recovlock,
1451 				    RW_WRITER, 0);
1452 			nfs4_resend_lost_rqsts(recovp, sp);
1453 			if (list_head(&mi->mi_lost_state) == NULL) {
1454 				/* done */
1455 				mutex_enter(&mi->mi_lock);
1456 				mi->mi_recovflags &= ~MI4R_LOST_STATE;
1457 				mutex_exit(&mi->mi_lock);
1458 			}
1459 			nfs_rw_exit(&mi->mi_recovlock);
1460 		} else {
1461 			mutex_exit(&mi->mi_lock);
1462 		}
1463 
1464 		/*
1465 		 * See if there is anything more to do.  If not, announce
1466 		 * that we are done and exit.
1467 		 *
1468 		 * Need mi_recovlock to keep 'sp' valid.  Must grab
1469 		 * mi_recovlock before mi_lock to preserve lock ordering.
1470 		 */
1471 		(void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_READER, 0);
1472 		mutex_enter(&mi->mi_lock);
1473 		if ((mi->mi_recovflags & ~MI4R_SRV_REBOOT) == 0 ||
1474 		    (mi->mi_flags & MI4_RECOV_FAIL)) {
1475 			list_t local_lost_state;
1476 			nfs4_lost_rqst_t *lrp;
1477 
1478 			/*
1479 			 * We need to remove the lost requests before we
1480 			 * unmark the mi as no longer doing recovery to
1481 			 * avoid a race with a new thread putting new lost
1482 			 * requests on the same mi (and the going away
1483 			 * thread would remove the new lost requests).
1484 			 *
1485 			 * Move the lost requests to a local list since
1486 			 * nfs4_remove_lost_rqst() drops mi_lock, and
1487 			 * dropping the mi_lock would make our check to
1488 			 * see if recovery is done no longer valid.
1489 			 */
1490 			list_create(&local_lost_state,
1491 			    sizeof (nfs4_lost_rqst_t),
1492 			    offsetof(nfs4_lost_rqst_t, lr_node));
1493 			list_move_tail(&local_lost_state, &mi->mi_lost_state);
1494 
1495 			done = 1;
1496 			recov_done(mi, recovp);
1497 			mutex_exit(&mi->mi_lock);
1498 			/*
1499 			 * Now officially free the "moved"
1500 			 * lost requests.
1501 			 */
1502 			while ((lrp = list_head(&local_lost_state)) != NULL) {
1503 				list_remove(&local_lost_state, lrp);
1504 				nfs4_free_lost_rqst(lrp, sp);
1505 			}
1506 			list_destroy(&local_lost_state);
1507 		} else
1508 			mutex_exit(&mi->mi_lock);
1509 		nfs_rw_exit(&mi->mi_recovlock);
1510 
1511 		/*
1512 		 * If the filesystem has been forcibly unmounted, there is
1513 		 * probably no point in retrying immediately.  Furthermore,
1514 		 * there might be user processes waiting for a chance to
1515 		 * queue up "lost state" requests, so that they can exit.
1516 		 * So pause here for a moment.  Same logic for zone shutdown.
1517 		 */
1518 		if (!done && FS_OR_ZONE_GONE4(mi->mi_vfsp)) {
1519 			mutex_enter(&mi->mi_lock);
1520 			cv_broadcast(&mi->mi_failover_cv);
1521 			mutex_exit(&mi->mi_lock);
1522 			delay(SEC_TO_TICK(nfs4_unmount_delay));
1523 		}
1524 
1525 	} while (!done);
1526 
1527 	mutex_enter(&mi->mi_lock);
1528 	mi->mi_in_recovery--;
1529 	cv_broadcast(&mi->mi_cv_in_recov);
1530 	mutex_exit(&mi->mi_lock);
1531 
1532 	if (sp != NULL)
1533 		nfs4_server_rele(sp);
1534 
1535 	/*
1536 	 * Return all recalled delegations
1537 	 */
1538 	nfs4_dlistclean();
1539 
1540 	/*
1541 	 * Free up resources that were allocated for us.
1542 	 */
1543 	if (recovp->rc_vp1 != NULL)
1544 		VN_RELE(recovp->rc_vp1);
1545 	if (recovp->rc_vp2 != NULL)
1546 		VN_RELE(recovp->rc_vp2);
1547 	VFS_RELE(mi->mi_vfsp);
1548 	kmem_free(recovp, sizeof (recov_info_t));
1549 	mutex_enter(&cpr_lock);
1550 	CALLB_CPR_EXIT(&cpr_info);
1551 	mutex_destroy(&cpr_lock);
1552 	zthread_exit();
1553 }
1554 
1555 /*
1556  * Log the end of recovery and notify any waiting threads.
1557  */
1558 
1559 static void
1560 recov_done(mntinfo4_t *mi, recov_info_t *recovp)
1561 {
1562 
1563 	ASSERT(MUTEX_HELD(&mi->mi_lock));
1564 
1565 	nfs4_queue_event(RE_END, mi, NULL, 0, recovp->rc_vp1,
1566 		recovp->rc_vp2, 0, NULL, 0, TAG_NONE, TAG_NONE, 0, 0);
1567 	mi->mi_recovthread = NULL;
1568 	mi->mi_flags &= ~MI4_RECOV_ACTIV;
1569 	mi->mi_recovflags &= ~MI4R_SRV_REBOOT;
1570 	cv_broadcast(&mi->mi_failover_cv);
1571 }
1572 
1573 /*
1574  * State-specific recovery routines, by state.
1575  */
1576 
1577 /*
1578  * Failover.
1579  *
1580  * Replaces *spp with a reference to the new server, which must
1581  * eventually be freed.
1582  */
1583 
1584 static void
1585 recov_newserver(recov_info_t *recovp, nfs4_server_t **spp, bool_t *recov_fail)
1586 {
1587 	mntinfo4_t *mi = recovp->rc_mi;
1588 	servinfo4_t *svp = NULL;
1589 	nfs4_server_t *osp = *spp;
1590 	CLIENT *cl;
1591 	enum clnt_stat status;
1592 	struct timeval tv;
1593 	int error;
1594 	int oncethru = 0;
1595 	rnode4_t *rp;
1596 	int index;
1597 	nfs_fh4 fh;
1598 	char *snames;
1599 	size_t len;
1600 
1601 	(void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_WRITER, 0);
1602 
1603 	tv.tv_sec = 2;
1604 	tv.tv_usec = 0;
1605 
1606 #ifdef lint
1607 	/*
1608 	 * Lint can't follow the logic, so thinks that snames and len
1609 	 * can be used before being set.  They can't, but lint can't
1610 	 * figure it out.  To address the lint warning, initialize
1611 	 * snames and len for lint.
1612 	 */
1613 	snames = NULL;
1614 	len = 0;
1615 #endif
1616 
1617 	/*
1618 	 * Ping the null NFS procedure of every server in
1619 	 * the list until one responds.  We always start
1620 	 * at the head of the list and always skip the one
1621 	 * that is current, since it's caused us a problem.
1622 	 */
1623 	while (svp == NULL) {
1624 		for (svp = mi->mi_servers; svp; svp = svp->sv_next) {
1625 
1626 			mutex_enter(&mi->mi_lock);
1627 			if (FS_OR_ZONE_GONE4(mi->mi_vfsp)) {
1628 				mi->mi_flags |= MI4_RECOV_FAIL;
1629 				mutex_exit(&mi->mi_lock);
1630 				(void) nfs_rw_exit(&mi->mi_recovlock);
1631 				*recov_fail = TRUE;
1632 				if (oncethru)
1633 					kmem_free(snames, len);
1634 				return;
1635 			}
1636 			mutex_exit(&mi->mi_lock);
1637 
1638 			(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
1639 			if (svp->sv_flags & SV4_NOTINUSE) {
1640 				nfs_rw_exit(&svp->sv_lock);
1641 				continue;
1642 			}
1643 			nfs_rw_exit(&svp->sv_lock);
1644 
1645 			if (!oncethru && svp == mi->mi_curr_serv)
1646 				continue;
1647 
1648 			error = clnt_tli_kcreate(svp->sv_knconf, &svp->sv_addr,
1649 			    NFS_PROGRAM, NFS_V4, 0, 1, CRED(), &cl);
1650 			if (error)
1651 				continue;
1652 
1653 			if (!(mi->mi_flags & MI4_INT))
1654 				cl->cl_nosignal = TRUE;
1655 			status = CLNT_CALL(cl, RFS_NULL, xdr_void, NULL,
1656 			    xdr_void, NULL, tv);
1657 			if (!(mi->mi_flags & MI4_INT))
1658 				cl->cl_nosignal = FALSE;
1659 			AUTH_DESTROY(cl->cl_auth);
1660 			CLNT_DESTROY(cl);
1661 			if (status == RPC_SUCCESS) {
1662 				nfs4_queue_event(RE_FAILOVER, mi,
1663 				    svp == mi->mi_curr_serv ? NULL :
1664 				    svp->sv_hostname, 0, NULL, NULL, 0,
1665 				    NULL, 0, TAG_NONE, TAG_NONE, 0, 0);
1666 				break;
1667 			}
1668 		}
1669 
1670 		if (svp == NULL) {
1671 			if (!oncethru) {
1672 				snames = nfs4_getsrvnames(mi, &len);
1673 				nfs4_queue_fact(RF_SRVS_NOT_RESPOND, mi,
1674 				    0, 0, 0, FALSE, snames, 0, NULL);
1675 				oncethru = 1;
1676 			}
1677 			delay(hz);
1678 		}
1679 	}
1680 
1681 	if (oncethru) {
1682 		nfs4_queue_fact(RF_SRVS_OK, mi, 0, 0, 0, FALSE, snames,
1683 		    0, NULL);
1684 		kmem_free(snames, len);
1685 	}
1686 
1687 #if DEBUG
1688 	(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
1689 	ASSERT((svp->sv_flags & SV4_NOTINUSE) == 0);
1690 	nfs_rw_exit(&svp->sv_lock);
1691 #endif
1692 
1693 	mutex_enter(&mi->mi_lock);
1694 	mi->mi_recovflags &= ~MI4R_NEED_NEW_SERVER;
1695 	if (svp != mi->mi_curr_serv) {
1696 		servinfo4_t *osvp = mi->mi_curr_serv;
1697 
1698 		mutex_exit(&mi->mi_lock);
1699 
1700 		/*
1701 		 * Update server-dependent fields in the root vnode.
1702 		 */
1703 		index = rtable4hash(mi->mi_rootfh);
1704 		rw_enter(&rtable4[index].r_lock, RW_WRITER);
1705 
1706 		rp = r4find(&rtable4[index], mi->mi_rootfh, mi->mi_vfsp);
1707 		if (rp != NULL) {
1708 			NFS4_DEBUG(nfs4_client_failover_debug, (CE_NOTE,
1709 			    "recov_newserver: remapping %s", rnode4info(rp)));
1710 			mutex_enter(&rp->r_statelock);
1711 			rp->r_server = svp;
1712 			PURGE_ATTRCACHE4_LOCKED(rp);
1713 			mutex_exit(&rp->r_statelock);
1714 			(void) nfs4_free_data_reclaim(rp);
1715 			nfs4_purge_rddir_cache(RTOV4(rp));
1716 			rw_exit(&rtable4[index].r_lock);
1717 			NFS4_DEBUG(nfs4_client_failover_debug, (CE_NOTE,
1718 			    "recov_newserver: done with %s",
1719 			    rnode4info(rp)));
1720 			VN_RELE(RTOV4(rp));
1721 		} else
1722 			rw_exit(&rtable4[index].r_lock);
1723 		(void) dnlc_purge_vfsp(mi->mi_vfsp, 0);
1724 
1725 		mutex_enter(&mi->mi_lock);
1726 		mi->mi_recovflags |= MI4R_REOPEN_FILES | MI4R_REMAP_FILES;
1727 		if (recovp->rc_srv_reboot)
1728 			mi->mi_recovflags |= MI4R_SRV_REBOOT;
1729 		mi->mi_curr_serv = svp;
1730 		mi->mi_failover++;
1731 		mi->mi_flags &= ~MI4_BADOWNER_DEBUG;
1732 		mutex_exit(&mi->mi_lock);
1733 
1734 		(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
1735 		fh.nfs_fh4_len = svp->sv_fhandle.fh_len;
1736 		fh.nfs_fh4_val = svp->sv_fhandle.fh_buf;
1737 		sfh4_update(mi->mi_rootfh, &fh);
1738 		fh.nfs_fh4_len = svp->sv_pfhandle.fh_len;
1739 		fh.nfs_fh4_val = svp->sv_pfhandle.fh_buf;
1740 		sfh4_update(mi->mi_srvparentfh, &fh);
1741 		nfs_rw_exit(&svp->sv_lock);
1742 
1743 		*spp = nfs4_move_mi(mi, osvp, svp);
1744 		if (osp != NULL)
1745 			nfs4_server_rele(osp);
1746 	} else
1747 		mutex_exit(&mi->mi_lock);
1748 	(void) nfs_rw_exit(&mi->mi_recovlock);
1749 }
1750 
1751 /*
1752  * Clientid.
1753  */
1754 
1755 static void
1756 recov_clientid(recov_info_t *recovp, nfs4_server_t *sp)
1757 {
1758 	mntinfo4_t *mi = recovp->rc_mi;
1759 	int error = 0;
1760 	int still_stale;
1761 	int need_new_s;
1762 
1763 	ASSERT(sp != NULL);
1764 
1765 	/*
1766 	 * Acquire the recovery lock and then verify that the clientid
1767 	 * still needs to be recovered.  (Note that s_recovlock is supposed
1768 	 * to be acquired before s_lock.)  Since the thread holds the
1769 	 * recovery lock, no other thread will recover the clientid.
1770 	 */
1771 	(void) nfs_rw_enter_sig(&sp->s_recovlock, RW_WRITER, 0);
1772 	(void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_WRITER, 0);
1773 	mutex_enter(&sp->s_lock);
1774 	still_stale = ((sp->s_flags & N4S_CLIENTID_SET) == 0);
1775 	mutex_exit(&sp->s_lock);
1776 
1777 	if (still_stale) {
1778 		nfs4_error_t n4e;
1779 
1780 		nfs4_error_zinit(&n4e);
1781 		nfs4setclientid(mi, kcred, TRUE, &n4e);
1782 		error = n4e.error;
1783 		if (error != 0) {
1784 
1785 			/*
1786 			 * nfs4setclientid may have set MI4R_NEED_NEW_SERVER,
1787 			 * if so, just return and let recov_thread drive
1788 			 * failover.
1789 			 */
1790 			mutex_enter(&mi->mi_lock);
1791 			need_new_s = mi->mi_recovflags & MI4R_NEED_NEW_SERVER;
1792 			mutex_exit(&mi->mi_lock);
1793 
1794 			if (need_new_s) {
1795 				nfs_rw_exit(&mi->mi_recovlock);
1796 				nfs_rw_exit(&sp->s_recovlock);
1797 				return;
1798 			}
1799 
1800 			nfs4_queue_event(RE_CLIENTID, mi, NULL, n4e.error, NULL,
1801 			    NULL, n4e.stat, NULL, 0, TAG_NONE, TAG_NONE, 0, 0);
1802 			mutex_enter(&mi->mi_lock);
1803 			mi->mi_flags |= MI4_RECOV_FAIL;
1804 			mi->mi_error = recovp->rc_error;
1805 			mutex_exit(&mi->mi_lock);
1806 			/* don't destroy the nfs4_server, let umount do it */
1807 		}
1808 	}
1809 
1810 	if (error == 0) {
1811 		mutex_enter(&mi->mi_lock);
1812 		mi->mi_recovflags &= ~MI4R_NEED_CLIENTID;
1813 		/*
1814 		 * If still_stale isn't true, then another thread already
1815 		 * recovered the clientid.  And that thread that set the
1816 		 * clientid will have initiated reopening files on all the
1817 		 * filesystems for the server, so we should not initiate
1818 		 * reopening for this filesystem here.
1819 		 */
1820 		if (still_stale) {
1821 			mi->mi_recovflags |= MI4R_REOPEN_FILES;
1822 			if (recovp->rc_srv_reboot)
1823 				mi->mi_recovflags |= MI4R_SRV_REBOOT;
1824 		}
1825 		mutex_exit(&mi->mi_lock);
1826 	}
1827 
1828 	nfs_rw_exit(&mi->mi_recovlock);
1829 
1830 	if (error != 0) {
1831 		nfs_rw_exit(&sp->s_recovlock);
1832 		mutex_enter(&mi->mi_lock);
1833 		if ((mi->mi_flags & MI4_RECOV_FAIL) == 0)
1834 			delay(SEC_TO_TICK(recov_err_delay));
1835 		mutex_exit(&mi->mi_lock);
1836 	} else {
1837 		mntinfo4_t **milist;
1838 		mntinfo4_t *tmi;
1839 		int nummi, i;
1840 
1841 		/*
1842 		 * Initiate recovery of open files for other filesystems.
1843 		 * We create an array of filesystems, rather than just
1844 		 * walking the filesystem list, to avoid deadlock issues
1845 		 * with s_lock and mi_recovlock.
1846 		 */
1847 		milist = make_milist(sp, &nummi);
1848 		for (i = 0; i < nummi; i++) {
1849 			tmi = milist[i];
1850 			if (tmi != mi) {
1851 				(void) nfs_rw_enter_sig(&tmi->mi_recovlock,
1852 							RW_READER, 0);
1853 				start_recovery_action(NR_OPENFILES, TRUE, tmi,
1854 					NULL, NULL);
1855 				nfs_rw_exit(&tmi->mi_recovlock);
1856 			}
1857 		}
1858 		free_milist(milist, nummi);
1859 
1860 		nfs_rw_exit(&sp->s_recovlock);
1861 	}
1862 }
1863 
1864 /*
1865  * Return an array of filesystems associated with the given server.  The
1866  * caller should call free_milist() to free the references and memory.
1867  */
1868 
1869 static mntinfo4_t **
1870 make_milist(nfs4_server_t *sp, int *nummip)
1871 {
1872 	int nummi, i;
1873 	mntinfo4_t **milist;
1874 	mntinfo4_t *tmi;
1875 
1876 	mutex_enter(&sp->s_lock);
1877 	nummi = 0;
1878 	for (tmi = sp->mntinfo4_list; tmi != NULL; tmi = tmi->mi_clientid_next)
1879 		nummi++;
1880 
1881 	milist = kmem_alloc(nummi * sizeof (mntinfo4_t *), KM_NOSLEEP);
1882 
1883 	for (i = 0, tmi = sp->mntinfo4_list; tmi != NULL; i++,
1884 	    tmi = tmi->mi_clientid_next) {
1885 		milist[i] = tmi;
1886 		VFS_HOLD(tmi->mi_vfsp);
1887 	}
1888 	mutex_exit(&sp->s_lock);
1889 
1890 	*nummip = nummi;
1891 	return (milist);
1892 }
1893 
1894 /*
1895  * Free the filesystem list created by make_milist().
1896  */
1897 
1898 static void
1899 free_milist(mntinfo4_t **milist, int nummi)
1900 {
1901 	mntinfo4_t *tmi;
1902 	int i;
1903 
1904 	for (i = 0; i < nummi; i++) {
1905 		tmi = milist[i];
1906 		VFS_RELE(tmi->mi_vfsp);
1907 	}
1908 	kmem_free(milist, nummi * sizeof (mntinfo4_t *));
1909 }
1910 
1911 /*
1912  * Filehandle
1913  */
1914 
1915 /*
1916  * Lookup the filehandle for the given vnode and update the rnode if it has
1917  * changed.
1918  *
1919  * Errors:
1920  * - if the filehandle could not be updated because of an error that
1921  *   requires further recovery, initiate that recovery and return.
1922  * - if the filehandle could not be updated because of a signal, pretend we
1923  *   succeeded and let someone else deal with it.
1924  * - if the filehandle could not be updated and the filesystem has been
1925  *   forcibly unmounted, pretend we succeeded, and let the caller deal with
1926  *   the forced unmount (to retry or not to retry, that is the question).
1927  * - if the filehandle could not be updated because of some other error,
1928  *   mark the rnode bad and return.
1929  */
1930 static void
1931 recov_filehandle(nfs4_recov_t action, mntinfo4_t *mi, vnode_t *vp)
1932 {
1933 	rnode4_t *rp = VTOR4(vp);
1934 	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
1935 	bool_t needrecov;
1936 
1937 	mutex_enter(&rp->r_statelock);
1938 
1939 	if (rp->r_flags & R4RECOVERR) {
1940 		mutex_exit(&rp->r_statelock);
1941 		return;
1942 	}
1943 
1944 	/*
1945 	 * If someone else is updating the filehandle, wait for them to
1946 	 * finish and then let our caller retry.
1947 	 */
1948 	if (rp->r_flags & R4RECEXPFH) {
1949 		while (rp->r_flags & R4RECEXPFH) {
1950 			cv_wait(&rp->r_cv, &rp->r_statelock);
1951 		}
1952 		mutex_exit(&rp->r_statelock);
1953 		return;
1954 	}
1955 	rp->r_flags |= R4RECEXPFH;
1956 	mutex_exit(&rp->r_statelock);
1957 
1958 	if (action == NR_BADHANDLE) {
1959 		/* shouldn't happen */
1960 		nfs4_queue_event(RE_BADHANDLE, mi, NULL, 0,
1961 		    vp, NULL, 0, NULL, 0, TAG_NONE, TAG_NONE, 0, 0);
1962 	}
1963 
1964 	nfs4_remap_file(mi, vp, 0, &e);
1965 	needrecov = nfs4_needs_recovery(&e, FALSE, mi->mi_vfsp);
1966 
1967 	/*
1968 	 * If we get BADHANDLE or FHEXPIRED in their handler, something is
1969 	 * broken.  Don't try to recover, just mark the file dead.
1970 	 */
1971 	if (needrecov && e.error == 0 &&
1972 	    (e.stat == NFS4ERR_BADHANDLE || e.stat == NFS4ERR_FHEXPIRED))
1973 		needrecov = FALSE;
1974 	if (needrecov) {
1975 		(void) nfs4_start_recovery(&e, mi, vp,
1976 				NULL, NULL, NULL, OP_LOOKUP, NULL);
1977 	} else if (e.error != EINTR &&
1978 	    !NFS4_FRC_UNMT_ERR(e.error, mi->mi_vfsp) &&
1979 	    (e.error != 0 || e.stat != NFS4_OK)) {
1980 		nfs4_recov_fh_fail(vp, e.error, e.stat);
1981 		/*
1982 		 * Don't set r_error to ESTALE.  Higher-level code (e.g.,
1983 		 * cstatat_getvp()) retries on ESTALE, which would cause
1984 		 * an infinite loop.
1985 		 */
1986 	}
1987 
1988 	mutex_enter(&rp->r_statelock);
1989 	rp->r_flags &= ~R4RECEXPFH;
1990 	cv_broadcast(&rp->r_cv);
1991 	mutex_exit(&rp->r_statelock);
1992 }
1993 
1994 /*
1995  * Stale Filehandle
1996  */
1997 
1998 /*
1999  * A stale filehandle can happen when an individual file has
2000  * been removed, or when an entire filesystem has been taken
2001  * offline.  To distinguish these cases, we do this:
2002  * - if a GETATTR with the current filehandle is okay, we do
2003  *   nothing (this can happen with two-filehandle ops)
2004  * - if the GETATTR fails, but a GETATTR of the root filehandle
2005  *   succeeds, mark the rnode with R4STALE, which will stop use
2006  * - if the GETATTR fails, and a GETATTR of the root filehandle
2007  *   also fails, we consider the problem filesystem-wide, so:
2008  *   - if we can failover, we should
2009  *   - if we can't failover, we should mark both the original
2010  *     vnode and the root bad
2011  */
2012 static void
2013 recov_stale(mntinfo4_t *mi, vnode_t *vp)
2014 {
2015 	rnode4_t *rp = VTOR4(vp);
2016 	vnode_t *rootvp = NULL;
2017 	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
2018 	nfs4_ga_res_t gar;
2019 	char *fail_msg = "failed to recover from NFS4ERR_STALE";
2020 	bool_t needrecov;
2021 
2022 	mutex_enter(&rp->r_statelock);
2023 
2024 	if (rp->r_flags & R4RECOVERR) {
2025 		mutex_exit(&rp->r_statelock);
2026 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2027 		    "recov_stale: already marked dead, rp %s",
2028 		    rnode4info(rp)));
2029 		return;
2030 	}
2031 
2032 	if (rp->r_flags & R4STALE) {
2033 		mutex_exit(&rp->r_statelock);
2034 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2035 		    "recov_stale: already marked stale, rp %s",
2036 		    rnode4info(rp)));
2037 		return;
2038 	}
2039 
2040 	mutex_exit(&rp->r_statelock);
2041 
2042 	/* Try a GETATTR on this vnode */
2043 	nfs4_getattr_otw_norecovery(vp, &gar, &e, CRED(), 0);
2044 
2045 	/*
2046 	 * Handle non-STALE recoverable errors
2047 	 */
2048 	needrecov = nfs4_needs_recovery(&e, FALSE, vp->v_vfsp);
2049 	if (needrecov && (e.error != 0 || e.stat != NFS4ERR_STALE)) {
2050 		(void) nfs4_start_recovery(&e, mi, vp,
2051 				NULL, NULL, NULL, OP_GETATTR, NULL);
2052 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2053 		    "recov_stale: error=%d, stat=%d seen on rp %s",
2054 		    e.error, e.stat, rnode4info(rp)));
2055 		goto out;
2056 	}
2057 
2058 	/* Are things OK for this vnode? */
2059 	if (!e.error && e.stat == NFS4_OK) {
2060 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2061 		    "recov_stale: file appears fine, rp %s",
2062 		    rnode4info(rp)));
2063 		goto out;
2064 	}
2065 
2066 	/* Did we get an unrelated non-recoverable error? */
2067 	if (e.error || e.stat != NFS4ERR_STALE) {
2068 		nfs4_fail_recov(vp, fail_msg, e.error, e.stat);
2069 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2070 		    "recov_stale: unrelated fatal error, rp %s",
2071 		    rnode4info(rp)));
2072 		goto out;
2073 	}
2074 
2075 	/*
2076 	 * If we don't appear to be dealing with the root node, find it.
2077 	 */
2078 	if ((vp->v_flag & VROOT) == 0) {
2079 		nfs4_error_zinit(&e);
2080 		e.error = VFS_ROOT(vp->v_vfsp, &rootvp);
2081 		if (e.error) {
2082 			nfs4_fail_recov(vp, fail_msg, 0, NFS4ERR_STALE);
2083 			NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2084 			    "recov_stale: can't find root node for rp %s",
2085 			    rnode4info(rp)));
2086 			goto out;
2087 		}
2088 	}
2089 
2090 	/* Try a GETATTR on the root vnode */
2091 	if (rootvp != NULL) {
2092 		nfs4_error_zinit(&e);
2093 		nfs4_getattr_otw_norecovery(rootvp, &gar, &e, CRED(), 0);
2094 
2095 		/* Try recovery? */
2096 		if (e.error != 0 || e.stat != NFS4ERR_STALE) {
2097 			needrecov = nfs4_needs_recovery(&e, FALSE, vp->v_vfsp);
2098 			if (needrecov) {
2099 				(void) nfs4_start_recovery(&e,
2100 					mi, rootvp, NULL, NULL, NULL,
2101 					OP_GETATTR, NULL);
2102 				NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2103 				    "recov_stale: error=%d, stat=%d seen "
2104 				    "on rp %s", e.error, e.stat,
2105 				    rnode4info(rp)));
2106 			}
2107 		}
2108 
2109 		/*
2110 		 * Check to see if a failover attempt is warranted
2111 		 * NB: nfs4_try_failover doesn't check for STALE
2112 		 * because recov_stale gets a shot first.  Now that
2113 		 * recov_stale has failed, go ahead and try failover.
2114 		 *
2115 		 * If the getattr on the root filehandle was successful,
2116 		 * then mark recovery as failed for 'vp' and exit.
2117 		 */
2118 		if (nfs4_try_failover(&e) == 0 && e.stat != NFS4ERR_STALE) {
2119 			/*
2120 			 * pass the original error to fail_recov, not
2121 			 * the one from trying the root vnode.
2122 			 */
2123 			nfs4_fail_recov(vp, fail_msg, 0, NFS4ERR_STALE);
2124 			NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2125 			    "recov_stale: root node OK, marking "
2126 			    "dead rp %s", rnode4info(rp)));
2127 			goto out;
2128 		}
2129 	}
2130 
2131 	/*
2132 	 * Here, we know that both the original file and the
2133 	 * root filehandle (which may be the same) are stale.
2134 	 * We want to fail over if we can, and if we can't, we
2135 	 * want to mark everything in sight bad.
2136 	 */
2137 	if (FAILOVER_MOUNT4(mi)) {
2138 		mutex_enter(&mi->mi_lock);
2139 		mi->mi_recovflags |= MI4R_NEED_NEW_SERVER;
2140 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2141 		    "recov_stale: failing over due to rp %s",
2142 		    rnode4info(rp)));
2143 		mutex_exit(&mi->mi_lock);
2144 	} else {
2145 		rnode4_t *rootrp;
2146 		servinfo4_t *svp;
2147 
2148 		/*
2149 		 * Can't fail over, so mark things dead.
2150 		 *
2151 		 * If rootvp is set, we know we have a distinct
2152 		 * non-root vnode which can be marked dead in
2153 		 * the usual way.
2154 		 *
2155 		 * Then we want to mark the root vnode dead.
2156 		 * Note that if rootvp wasn't set, our vp is
2157 		 * actually the root vnode.
2158 		 */
2159 		if (rootvp != NULL) {
2160 			NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
2161 			    "recov_stale: can't fail over, marking dead rp %s",
2162 			    rnode4info(rp)));
2163 			nfs4_fail_recov(vp, fail_msg, 0, NFS4ERR_STALE);
2164 		} else {
2165 			rootvp = vp;
2166 			VN_HOLD(rootvp);
2167 		}
2168 
2169 		/*
2170 		 * Mark root dead, but quietly - since
2171 		 * the root rnode is frequently recreated,
2172 		 * we can encounter this at every access.
2173 		 * Also mark recovery as failed on this VFS.
2174 		 */
2175 		rootrp = VTOR4(rootvp);
2176 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_CONT,
2177 		    "recov_stale: marking dead root rp %s",
2178 		    rnode4info(rootrp)));
2179 		mutex_enter(&rootrp->r_statelock);
2180 		rootrp->r_flags |= (R4RECOVERR | R4STALE);
2181 		rootrp->r_error = ESTALE;
2182 		mutex_exit(&rootrp->r_statelock);
2183 		mutex_enter(&mi->mi_lock);
2184 		mi->mi_error = ESTALE;
2185 		mutex_exit(&mi->mi_lock);
2186 
2187 		svp = mi->mi_curr_serv;
2188 		(void) nfs_rw_enter_sig(&svp->sv_lock, RW_WRITER, 0);
2189 		svp->sv_flags |= SV4_ROOT_STALE;
2190 		nfs_rw_exit(&svp->sv_lock);
2191 	}
2192 
2193 out:
2194 	if (rootvp)
2195 		VN_RELE(rootvp);
2196 }
2197 
2198 /*
2199  * Locks.
2200  */
2201 
2202 /*
2203  * Reclaim all the active (acquired) locks for the given file.
2204  * If a process lost a lock, the process is sent a SIGLOST.  This is not
2205  * considered an error.
2206  *
2207  * Return values:
2208  * Errors and status are returned via the nfs4_error_t parameter
2209  * If an error indicates that recovery is needed, the caller is responsible
2210  * for dealing with it.
2211  */
2212 
2213 static void
2214 relock_file(vnode_t *vp, mntinfo4_t *mi, nfs4_error_t *ep,
2215     fattr4_change pre_change)
2216 {
2217 	locklist_t *locks, *llp;
2218 	rnode4_t *rp;
2219 
2220 	ASSERT(ep != NULL);
2221 	nfs4_error_zinit(ep);
2222 
2223 	if (VTOMI4(vp)->mi_flags & MI4_LLOCK)
2224 		return;
2225 
2226 	nfs4_flush_lock_owners(VTOR4(vp));
2227 
2228 	/*
2229 	 * If we get an error that requires recovery actions, just bail out
2230 	 * and let the top-level recovery code handle it.
2231 	 *
2232 	 * If we get some other error, kill the process that owned the lock
2233 	 * and mark its remaining locks (if any) as belonging to NOPID, so
2234 	 * that we don't make any more reclaim requests for that process.
2235 	 */
2236 
2237 	rp = VTOR4(vp);
2238 	locks = flk_active_locks_for_vp(vp);
2239 	for (llp = locks; llp != NULL; llp = llp->ll_next) {
2240 		int did_reclaim = 1;
2241 
2242 		ASSERT(llp->ll_vp == vp);
2243 		if (llp->ll_flock.l_pid == NOPID)
2244 			continue;
2245 		reclaim_one_lock(vp, &llp->ll_flock, ep, &did_reclaim);
2246 		/*
2247 		 * If we need to restart recovery, stop processing the
2248 		 * list.  Some errors would be recoverable under other
2249 		 * circumstances, but if they happen here we just give up
2250 		 * on the lock.
2251 		 */
2252 		if (nfs4_needs_recovery(ep, TRUE, vp->v_vfsp)) {
2253 			if (ep->error != 0)
2254 				break;
2255 			if (!nfs4_recov_marks_dead(ep->stat))
2256 				break;
2257 		}
2258 		/*
2259 		 *   In case the server isn't offering us a grace period, or
2260 		 * if we missed it, we might have opened & locked from scratch,
2261 		 * rather than reopened/reclaimed.
2262 		 *   We need to ensure that the object hadn't been otherwise
2263 		 * changed during this time, by comparing the changeinfo.
2264 		 *   We get passed the changeinfo from before the reopen by our
2265 		 * caller, in pre_change.
2266 		 *   The changeinfo from after the reopen is in rp->r_change,
2267 		 * courtesy of the GETATTR in the reopen.
2268 		 *   If they're different, then the file has changed, and we
2269 		 * have to SIGLOST the app.
2270 		 */
2271 		if (ep->error == 0 && ep->stat == NFS4_OK && !did_reclaim) {
2272 			mutex_enter(&rp->r_statelock);
2273 			if (pre_change != rp->r_change)
2274 				ep->stat = NFS4ERR_NO_GRACE;
2275 			mutex_exit(&rp->r_statelock);
2276 		}
2277 		if (ep->error != 0 || ep->stat != NFS4_OK) {
2278 			if (ep->error != 0)
2279 				nfs4_queue_event(RE_FAIL_RELOCK, mi,
2280 				    NULL, ep->error, vp, NULL, 0, NULL,
2281 				    llp->ll_flock.l_pid, TAG_NONE, TAG_NONE,
2282 				    0, 0);
2283 			else
2284 				nfs4_queue_event(RE_FAIL_RELOCK, mi,
2285 				    NULL, 0, vp, NULL, ep->stat, NULL,
2286 				    llp->ll_flock.l_pid, TAG_NONE, TAG_NONE,
2287 				    0, 0);
2288 			nfs4_send_siglost(llp->ll_flock.l_pid, mi, vp, TRUE,
2289 			    ep->error, ep->stat);
2290 			relock_skip_pid(llp, llp->ll_flock.l_pid);
2291 
2292 			/* Reinitialize the nfs4_error and continue */
2293 			nfs4_error_zinit(ep);
2294 		}
2295 	}
2296 
2297 	if (locks != NULL)
2298 		flk_free_locklist(locks);
2299 }
2300 
2301 /*
2302  * Reclaim the given lock.
2303  * If the lock can't be reclaimed, the process is sent SIGLOST, but this is
2304  * not considered an error.
2305  *
2306  * Errors are returned via the nfs4_error_t parameter.
2307  */
2308 static void
2309 reclaim_one_lock(vnode_t *vp, flock64_t *flk, nfs4_error_t *ep,
2310 	int *did_reclaimp)
2311 {
2312 	cred_t *cr;
2313 	rnode4_t *rp = VTOR4(vp);
2314 
2315 	cr = pid_to_cr(flk->l_pid);
2316 	if (cr == NULL) {
2317 		nfs4_error_zinit(ep);
2318 		ep->error = ESRCH;
2319 		return;
2320 	}
2321 
2322 	do {
2323 		mutex_enter(&rp->r_statelock);
2324 		if (rp->r_flags & R4RECOVERR) {
2325 			/*
2326 			 * This shouldn't affect other reclaims, so don't
2327 			 * return an error.
2328 			 */
2329 			mutex_exit(&rp->r_statelock);
2330 			break;
2331 		}
2332 		mutex_exit(&rp->r_statelock);
2333 
2334 		nfs4frlock(NFS4_LCK_CTYPE_RECLAIM, vp, F_SETLK, flk,
2335 				FREAD|FWRITE, 0, cr, ep, NULL, did_reclaimp);
2336 		if (ep->error == 0 && ep->stat == NFS4ERR_FHEXPIRED)
2337 			start_recovery_action(NR_FHEXPIRED, TRUE, VTOMI4(vp),
2338 					    vp, NULL);
2339 	} while (ep->error == 0 && ep->stat == NFS4ERR_FHEXPIRED);
2340 
2341 	crfree(cr);
2342 }
2343 
2344 /*
2345  * Open files.
2346  */
2347 
2348 /*
2349  * Verifies if the nfsstat4 is a valid error for marking this vnode dead.
2350  * Returns 1 if the error is valid; 0 otherwise.
2351  */
2352 static int
2353 nfs4_valid_recov_err_for_vp(vnode_t *vp, nfsstat4 stat)
2354 {
2355 	/*
2356 	 * We should not be marking non-regular files as dead,
2357 	 * except in very rare cases (eg: BADHANDLE or NFS4ERR_BADNAME).
2358 	 */
2359 	if (vp->v_type != VREG && stat != NFS4ERR_BADHANDLE &&
2360 	    stat != NFS4ERR_BADNAME)
2361 		return (0);
2362 
2363 	return (1);
2364 }
2365 
2366 /*
2367  * Failed attempting to recover a filehandle.  If 'stat' is valid for 'vp',
2368  * then mark the object dead.  Since we've had to do a lookup for
2369  * filehandle recovery, we will mark the object dead if we got NOENT.
2370  */
2371 static void
2372 nfs4_recov_fh_fail(vnode_t *vp, int error, nfsstat4 stat)
2373 {
2374 	ASSERT(vp != NULL);
2375 
2376 	if ((error == 0) && (stat != NFS4ERR_NOENT) &&
2377 	    (!nfs4_valid_recov_err_for_vp(vp, stat)))
2378 		return;
2379 
2380 	nfs4_fail_recov(vp, "can't recover filehandle", error, stat);
2381 }
2382 
2383 /*
2384  * Recovery from a "shouldn't happen" error.  In the long term, we'd like
2385  * to mark only the data structure(s) that provided the bad value as being
2386  * bad.  But for now we'll just mark the entire file.
2387  */
2388 
2389 static void
2390 recov_badstate(recov_info_t *recovp, vnode_t *vp, nfsstat4 stat)
2391 {
2392 	ASSERT(vp != NULL);
2393 	recov_throttle(recovp, vp);
2394 
2395 	if (!nfs4_valid_recov_err_for_vp(vp, stat))
2396 		return;
2397 
2398 	nfs4_fail_recov(vp, "", 0, stat);
2399 }
2400 
2401 /*
2402  * Free up the information saved for a lost state request.
2403  */
2404 static void
2405 nfs4_free_lost_rqst(nfs4_lost_rqst_t *lrp, nfs4_server_t *sp)
2406 {
2407 	component4 *filep;
2408 	nfs4_open_stream_t *osp;
2409 	int have_sync_lock;
2410 
2411 	NFS4_DEBUG(nfs4_lost_rqst_debug,
2412 		(CE_NOTE, "nfs4_free_lost_rqst:"));
2413 
2414 	switch (lrp->lr_op) {
2415 	case OP_OPEN:
2416 		filep = &lrp->lr_ofile;
2417 		if (filep->utf8string_val) {
2418 			kmem_free(filep->utf8string_val, filep->utf8string_len);
2419 			filep->utf8string_val = NULL;
2420 		}
2421 		break;
2422 	case OP_DELEGRETURN:
2423 		nfs4delegreturn_cleanup(VTOR4(lrp->lr_vp), sp);
2424 		break;
2425 	case OP_CLOSE:
2426 		osp = lrp->lr_osp;
2427 		ASSERT(osp != NULL);
2428 		mutex_enter(&osp->os_sync_lock);
2429 		have_sync_lock = 1;
2430 		if (osp->os_pending_close) {
2431 			/* clean up the open file state. */
2432 			osp->os_pending_close = 0;
2433 			nfs4close_notw(lrp->lr_vp, osp, &have_sync_lock);
2434 		}
2435 		if (have_sync_lock)
2436 			mutex_exit(&osp->os_sync_lock);
2437 		break;
2438 	}
2439 
2440 	lrp->lr_op = 0;
2441 	if (lrp->lr_oop != NULL) {
2442 		open_owner_rele(lrp->lr_oop);
2443 		lrp->lr_oop = NULL;
2444 	}
2445 	if (lrp->lr_osp != NULL) {
2446 		open_stream_rele(lrp->lr_osp, VTOR4(lrp->lr_vp));
2447 		lrp->lr_osp = NULL;
2448 	}
2449 	if (lrp->lr_lop != NULL) {
2450 		lock_owner_rele(lrp->lr_lop);
2451 		lrp->lr_lop = NULL;
2452 	}
2453 	if (lrp->lr_flk != NULL) {
2454 		kmem_free(lrp->lr_flk, sizeof (flock64_t));
2455 		lrp->lr_flk = NULL;
2456 	}
2457 	if (lrp->lr_vp != NULL) {
2458 		VN_RELE(lrp->lr_vp);
2459 		lrp->lr_vp = NULL;
2460 	}
2461 	if (lrp->lr_dvp != NULL) {
2462 		VN_RELE(lrp->lr_dvp);
2463 		lrp->lr_dvp = NULL;
2464 	}
2465 	if (lrp->lr_cr != NULL) {
2466 		crfree(lrp->lr_cr);
2467 		lrp->lr_cr = NULL;
2468 	}
2469 
2470 	kmem_free(lrp, sizeof (nfs4_lost_rqst_t));
2471 }
2472 
2473 /*
2474  * Remove any lost state requests and free them.
2475  */
2476 static void
2477 nfs4_remove_lost_rqsts(mntinfo4_t *mi, nfs4_server_t *sp)
2478 {
2479 	nfs4_lost_rqst_t *lrp;
2480 
2481 	mutex_enter(&mi->mi_lock);
2482 	while ((lrp = list_head(&mi->mi_lost_state)) != NULL) {
2483 		list_remove(&mi->mi_lost_state, lrp);
2484 		mutex_exit(&mi->mi_lock);
2485 		nfs4_free_lost_rqst(lrp, sp);
2486 		mutex_enter(&mi->mi_lock);
2487 	}
2488 	mutex_exit(&mi->mi_lock);
2489 }
2490 
2491 /*
2492  * Reopen all the files for the given filesystem and reclaim any locks.
2493  */
2494 
2495 static void
2496 recov_openfiles(recov_info_t *recovp, nfs4_server_t *sp)
2497 {
2498 	mntinfo4_t *mi = recovp->rc_mi;
2499 	nfs4_opinst_t *reopenlist = NULL, *rep;
2500 	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
2501 	open_claim_type4 claim;
2502 	int remap;
2503 	char *fail_msg = "No such file or directory on replica";
2504 	rnode4_t *rp;
2505 	fattr4_change pre_change;
2506 
2507 	ASSERT(sp != NULL);
2508 
2509 	/*
2510 	 * This check is to allow a 10ms pause before we reopen files
2511 	 * it should allow the server time to have received the CB_NULL
2512 	 * reply and update its internal structures such that (if
2513 	 * applicable) we are granted a delegation on reopened files.
2514 	 */
2515 	mutex_enter(&sp->s_lock);
2516 	if ((sp->s_flags & (N4S_CB_PINGED | N4S_CB_WAITER)) == 0) {
2517 		sp->s_flags |= N4S_CB_WAITER;
2518 		(void) cv_timedwait(&sp->wait_cb_null, &sp->s_lock,
2519 			(lbolt+drv_usectohz(N4S_CB_PAUSE_TIME)));
2520 	}
2521 	mutex_exit(&sp->s_lock);
2522 
2523 	(void) nfs_rw_enter_sig(&sp->s_recovlock, RW_READER, 0);
2524 	(void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_WRITER, 0);
2525 
2526 	if (NFS4_VOLATILE_FH(mi)) {
2527 		nfs4_remap_root(mi, &e, 0);
2528 		if (nfs4_needs_recovery(&e, FALSE, mi->mi_vfsp)) {
2529 			(void) nfs4_start_recovery(&e, mi, NULL,
2530 					NULL, NULL, NULL, OP_LOOKUP, NULL);
2531 		}
2532 	}
2533 
2534 	mutex_enter(&mi->mi_lock);
2535 	if (recovp->rc_srv_reboot || (mi->mi_recovflags & MI4R_SRV_REBOOT))
2536 		claim = CLAIM_PREVIOUS;
2537 	else
2538 		claim = CLAIM_NULL;
2539 	mutex_exit(&mi->mi_lock);
2540 
2541 	if (e.error == 0 && e.stat == NFS4_OK) {
2542 		/*
2543 		 * Get a snapshot of open files in the filesystem.  Note
2544 		 * that new opens will stall until the server's grace
2545 		 * period is done.
2546 		 */
2547 		reopenlist = r4mkopenlist(mi);
2548 
2549 		mutex_enter(&mi->mi_lock);
2550 		remap = mi->mi_recovflags & MI4R_REMAP_FILES;
2551 		mutex_exit(&mi->mi_lock);
2552 		/*
2553 		 * Since we are re-establishing state on the
2554 		 * server, its ok to blow away the saved lost
2555 		 * requests since we don't need to reissue it.
2556 		 */
2557 		nfs4_remove_lost_rqsts(mi, sp);
2558 
2559 		for (rep = reopenlist; rep; rep = rep->re_next) {
2560 
2561 			if (remap) {
2562 				nfs4_remap_file(mi, rep->re_vp,
2563 					NFS4_REMAP_CKATTRS, &e);
2564 			}
2565 			if (e.error == ENOENT || e.stat == NFS4ERR_NOENT) {
2566 				/*
2567 				 * The current server does not have the file
2568 				 * that is to be remapped.  This is most
2569 				 * likely due to an improperly maintained
2570 				 * replica.   The files that are missing from
2571 				 * the server will be marked dead and logged
2572 				 * in order to make sys admins aware of the
2573 				 * problem.
2574 				 */
2575 				nfs4_fail_recov(rep->re_vp,
2576 					fail_msg, e.error, e.stat);
2577 				/*
2578 				 * We've already handled the error so clear it.
2579 				 */
2580 				nfs4_error_zinit(&e);
2581 				continue;
2582 			} else if (e.error == 0 && e.stat == NFS4_OK) {
2583 				int j;
2584 
2585 				rp = VTOR4(rep->re_vp);
2586 				mutex_enter(&rp->r_statelock);
2587 				pre_change = rp->r_change;
2588 				mutex_exit(&rp->r_statelock);
2589 
2590 				for (j = 0; j < rep->re_numosp; j++) {
2591 					nfs4_reopen(rep->re_vp, rep->re_osp[j],
2592 						&e, claim, FALSE, TRUE);
2593 					if (e.error != 0 || e.stat != NFS4_OK)
2594 						break;
2595 				}
2596 				if (nfs4_needs_recovery(&e, TRUE,
2597 				    mi->mi_vfsp)) {
2598 					(void) nfs4_start_recovery(&e, mi,
2599 						rep->re_vp, NULL, NULL, NULL,
2600 						OP_OPEN, NULL);
2601 					break;
2602 				}
2603 			}
2604 #ifdef DEBUG
2605 			if (nfs4_recovdelay > 0)
2606 				delay(MSEC_TO_TICK(nfs4_recovdelay * 1000));
2607 #endif
2608 			if (e.error == 0 && e.stat == NFS4_OK)
2609 				relock_file(rep->re_vp, mi, &e, pre_change);
2610 
2611 			if (nfs4_needs_recovery(&e, TRUE, mi->mi_vfsp))
2612 				(void) nfs4_start_recovery(&e, mi,
2613 					rep->re_vp, NULL, NULL, NULL, OP_LOCK,
2614 					NULL);
2615 			if (e.error != 0 || e.stat != NFS4_OK)
2616 				break;
2617 		}
2618 
2619 		/*
2620 		 * Check to see if we need to remap files passed in
2621 		 * via the recovery arguments; this will have been
2622 		 * done for open files.  A failure here is not fatal.
2623 		 */
2624 		if (remap) {
2625 			nfs4_error_t ignore;
2626 			nfs4_check_remap(mi, recovp->rc_vp1, NFS4_REMAP_CKATTRS,
2627 				&ignore);
2628 			nfs4_check_remap(mi, recovp->rc_vp2, NFS4_REMAP_CKATTRS,
2629 				&ignore);
2630 		}
2631 	}
2632 
2633 	if (e.error == 0 && e.stat == NFS4_OK) {
2634 		mutex_enter(&mi->mi_lock);
2635 		mi->mi_recovflags &= ~(MI4R_REOPEN_FILES | MI4R_REMAP_FILES);
2636 		mutex_exit(&mi->mi_lock);
2637 	}
2638 
2639 	nfs_rw_exit(&mi->mi_recovlock);
2640 	nfs_rw_exit(&sp->s_recovlock);
2641 
2642 	if (reopenlist != NULL)
2643 		r4releopenlist(reopenlist);
2644 }
2645 
2646 /*
2647  * Resend the queued state recovery requests in "rqsts".
2648  */
2649 
2650 static void
2651 nfs4_resend_lost_rqsts(recov_info_t *recovp, nfs4_server_t *sp)
2652 {
2653 	nfs4_lost_rqst_t	*lrp, *tlrp;
2654 	mntinfo4_t		*mi = recovp->rc_mi;
2655 	nfs4_error_t		n4e;
2656 #ifdef NOTYET
2657 	uint32_t		deny_bits = 0;
2658 #endif
2659 
2660 	NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE, "nfs4_resend_lost_rqsts"));
2661 
2662 	ASSERT(mi != NULL);
2663 	ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
2664 
2665 	mutex_enter(&mi->mi_lock);
2666 	lrp = list_head(&mi->mi_lost_state);
2667 	mutex_exit(&mi->mi_lock);
2668 	while (lrp != NULL) {
2669 		nfs4_error_zinit(&n4e);
2670 		resend_one_op(lrp, &n4e, mi, sp);
2671 		NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE,
2672 		    "nfs4_resend_lost_rqsts: resend request: for vp %p got "
2673 		    "error %d stat %d", (void *)lrp->lr_vp, n4e.error,
2674 		    n4e.stat));
2675 
2676 		/*
2677 		 * If we get a recovery error that we can actually
2678 		 * recover from (such as ETIMEDOUT, FHEXPIRED), we
2679 		 * return and let the recovery thread redrive the call.
2680 		 * Don't requeue unless the zone is still healthy.
2681 		 */
2682 		if (zone_status_get(curproc->p_zone) < ZONE_IS_SHUTTING_DOWN &&
2683 		    nfs4_needs_recovery(&n4e, TRUE, mi->mi_vfsp) &&
2684 		    (nfs4_try_failover(&n4e) ||
2685 		    NFS4_FRC_UNMT_ERR(n4e.error, mi->mi_vfsp) ||
2686 		    (n4e.error == 0 && n4e.stat != NFS4ERR_BADHANDLE &&
2687 		    !nfs4_recov_marks_dead(n4e.stat)))) {
2688 			/*
2689 			 * For these three errors, we want to delay a bit
2690 			 * instead of pounding the server into submission.
2691 			 * We have to do this manually; the normal
2692 			 * processing for these errors only works for
2693 			 * non-recovery requests.
2694 			 */
2695 			if ((n4e.error == 0 && n4e.stat == NFS4ERR_DELAY) ||
2696 			    (n4e.error == 0 && n4e.stat == NFS4ERR_GRACE) ||
2697 			    (n4e.error == 0 && n4e.stat == NFS4ERR_RESOURCE) ||
2698 			    NFS4_FRC_UNMT_ERR(n4e.error, mi->mi_vfsp)) {
2699 				delay(SEC_TO_TICK(nfs4err_delay_time));
2700 			} else {
2701 				(void) nfs4_start_recovery(&n4e,
2702 					mi, lrp->lr_dvp, lrp->lr_vp, NULL, NULL,
2703 					lrp->lr_op, NULL);
2704 			}
2705 			return;
2706 		}
2707 
2708 		mutex_enter(&mi->mi_lock);
2709 		list_remove(&mi->mi_lost_state, lrp);
2710 		tlrp = lrp;
2711 		lrp = list_head(&mi->mi_lost_state);
2712 		mutex_exit(&mi->mi_lock);
2713 		nfs4_free_lost_rqst(tlrp, sp);
2714 	}
2715 }
2716 
2717 /*
2718  * Resend the given op, and issue any necessary undo call.
2719  * errors are returned via the nfs4_error_t parameter.
2720  */
2721 
2722 static void
2723 resend_one_op(nfs4_lost_rqst_t *lrp, nfs4_error_t *ep,
2724 	mntinfo4_t *mi, nfs4_server_t *sp)
2725 {
2726 	vnode_t *vp;
2727 	nfs4_open_stream_t *osp;
2728 	cred_t *cr;
2729 	uint32_t acc_bits;
2730 
2731 	vp = lrp->lr_vp;
2732 	NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE, "resend_one_op: "
2733 	    "have a lost open/close request for vp %p", (void *)vp));
2734 
2735 	switch (lrp->lr_op) {
2736 	case OP_OPEN:
2737 		nfs4_resend_open_otw(&vp, lrp, ep);
2738 		break;
2739 	case OP_OPEN_DOWNGRADE:
2740 		ASSERT(lrp->lr_oop != NULL);
2741 		ep->error = nfs4_start_open_seqid_sync(lrp->lr_oop, mi);
2742 		ASSERT(!ep->error);	/* recov thread always succeeds */
2743 		ASSERT(lrp->lr_osp != NULL);
2744 		mutex_enter(&lrp->lr_osp->os_sync_lock);
2745 		nfs4_open_downgrade(lrp->lr_dg_acc, lrp->lr_dg_deny,
2746 			    lrp->lr_oop, lrp->lr_osp, vp, lrp->lr_cr, lrp,
2747 			    ep, NULL, NULL);
2748 		mutex_exit(&lrp->lr_osp->os_sync_lock);
2749 		nfs4_end_open_seqid_sync(lrp->lr_oop);
2750 		break;
2751 	case OP_CLOSE:
2752 		osp = lrp->lr_osp;
2753 		cr = lrp->lr_cr;
2754 		acc_bits = 0;
2755 		mutex_enter(&osp->os_sync_lock);
2756 		if (osp->os_share_acc_read)
2757 			acc_bits |= OPEN4_SHARE_ACCESS_READ;
2758 		if (osp->os_share_acc_write)
2759 			acc_bits |= OPEN4_SHARE_ACCESS_WRITE;
2760 		mutex_exit(&osp->os_sync_lock);
2761 		nfs4close_one(vp, osp, cr, acc_bits, lrp, ep,
2762 				CLOSE_RESEND, 0, 0, 0);
2763 		break;
2764 	case OP_LOCK:
2765 	case OP_LOCKU:
2766 		resend_lock(lrp, ep);
2767 		goto done;
2768 	case OP_DELEGRETURN:
2769 		nfs4_resend_delegreturn(lrp, ep, sp);
2770 		goto done;
2771 	default:
2772 #ifdef DEBUG
2773 		cmn_err(CE_PANIC, "resend_one_op: unexpected op: %d",
2774 			lrp->lr_op);
2775 #endif
2776 		nfs4_queue_event(RE_LOST_STATE_BAD_OP, mi, NULL,
2777 		    lrp->lr_op, lrp->lr_vp, lrp->lr_dvp, NFS4_OK, NULL, 0,
2778 		    TAG_NONE, TAG_NONE, 0, 0);
2779 		nfs4_error_init(ep, EINVAL);
2780 		return;
2781 	}
2782 
2783 	/*
2784 	 * No need to retry nor send an "undo" CLOSE in the
2785 	 * event the server rebooted.
2786 	 */
2787 	if (ep->error == 0 && (ep->stat == NFS4ERR_STALE_CLIENTID ||
2788 	    ep->stat == NFS4ERR_STALE_STATEID || ep->stat == NFS4ERR_EXPIRED))
2789 		goto done;
2790 
2791 	/*
2792 	 * If we resent a CLOSE or OPEN_DOWNGRADE, there's nothing
2793 	 * to undo.  Undoing locking operations was handled by
2794 	 * resend_lock().
2795 	 */
2796 	if (lrp->lr_op == OP_OPEN_DOWNGRADE || lrp->lr_op == OP_CLOSE)
2797 		goto done;
2798 
2799 	/*
2800 	 * If we get any other error for OPEN, then don't attempt
2801 	 * to undo the resend of the open (since it was never
2802 	 * successful!).
2803 	 */
2804 	ASSERT(lrp->lr_op == OP_OPEN);
2805 	if (ep->error || ep->stat != NFS4_OK)
2806 		goto done;
2807 
2808 	/*
2809 	 * Now let's undo our OPEN.
2810 	 */
2811 	nfs4_error_zinit(ep);
2812 	close_after_open_resend(vp, lrp->lr_cr, lrp->lr_oacc, ep);
2813 	NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE, "resend_one_op: "
2814 	    "nfs4close_one: for vp %p got error %d stat %d",
2815 	    (void *)vp, ep->error, ep->stat));
2816 
2817 done:
2818 	if (vp != lrp->lr_vp)
2819 		VN_RELE(vp);
2820 }
2821 
2822 /*
2823  * Close a file that was opened via a resent OPEN.
2824  * Most errors are passed back to the caller (via the return value and
2825  * *statp), except for FHEXPIRED, which is retried.
2826  *
2827  * It might be conceptually cleaner to push the CLOSE request onto the
2828  * front of the resend queue, rather than sending it here.  That would
2829  * match the way we undo lost lock requests.  On the other
2830  * hand, we've already got something that works, and there's no reason to
2831  * change it at this time.
2832  */
2833 
2834 static void
2835 close_after_open_resend(vnode_t *vp, cred_t *cr, uint32_t acc_bits,
2836 			nfs4_error_t *ep)
2837 {
2838 
2839 	for (;;) {
2840 		nfs4close_one(vp, NULL, cr, acc_bits, NULL, ep,
2841 				CLOSE_AFTER_RESEND, 0, 0, 0);
2842 		if (ep->error == 0 && ep->stat == NFS4_OK)
2843 			break;		/* success; done */
2844 		if (ep->error != 0 || ep->stat != NFS4ERR_FHEXPIRED)
2845 			break;
2846 		/* else retry FHEXPIRED */
2847 	}
2848 
2849 }
2850 
2851 /*
2852  * Resend the given lost lock request.  Return an errno value.  If zero,
2853  * *statp is set to the NFS status code for the call.
2854  *
2855  * Issue a SIGLOST and mark the rnode dead if we get a non-recovery error or
2856  * a recovery error that we don't actually recover from yet (eg: BAD_SEQID).
2857  * Let the recovery thread redrive the call if we get a recovery error that
2858  * we can actually recover from.
2859  */
2860 static void
2861 resend_lock(nfs4_lost_rqst_t *lrp, nfs4_error_t *ep)
2862 {
2863 	bool_t		send_siglost = FALSE;
2864 	vnode_t		*vp = lrp->lr_vp;
2865 
2866 	NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE, "resend_lock:"));
2867 	ASSERT(lrp->lr_ctype == NFS4_LCK_CTYPE_REINSTATE ||
2868 	    lrp->lr_ctype == NFS4_LCK_CTYPE_RESEND);
2869 
2870 	nfs4frlock(lrp->lr_ctype, vp, F_SETLK,
2871 		    lrp->lr_flk, FREAD|FWRITE, 0, lrp->lr_cr, ep, lrp, NULL);
2872 
2873 	NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE, "resend_lock: "
2874 	    "nfs4frlock for vp %p returned error %d, stat %d",
2875 	    (void *)vp, ep->error, ep->stat));
2876 
2877 	if (ep->error == 0 && ep->stat == 0)
2878 		goto done;
2879 	if (ep->error == 0 && ep->stat == NFS4ERR_DENIED &&
2880 	    lrp->lr_ctype == NFS4_LCK_CTYPE_RESEND)
2881 		goto done;
2882 
2883 	/*
2884 	 * If we failed with a non-recovery error, send SIGLOST and
2885 	 * mark the file dead.
2886 	 */
2887 	if (!nfs4_needs_recovery(ep, TRUE, vp->v_vfsp))
2888 		send_siglost = TRUE;
2889 	else {
2890 		/*
2891 		 * Done with recovering LOST LOCK in the event the
2892 		 * server rebooted or we've lost the lease.
2893 		 */
2894 		if (ep->error == 0 && (ep->stat == NFS4ERR_STALE_CLIENTID ||
2895 		    ep->stat == NFS4ERR_STALE_STATEID ||
2896 		    ep->stat == NFS4ERR_EXPIRED)) {
2897 			goto done;
2898 		}
2899 
2900 		/*
2901 		 * BAD_STATEID on an unlock indicates that the server has
2902 		 * forgotten about the lock anyway, so act like the call
2903 		 * was successful.
2904 		 */
2905 		if (ep->error == 0 && ep->stat == NFS4ERR_BAD_STATEID &&
2906 		    lrp->lr_op == OP_LOCKU)
2907 			goto done;
2908 
2909 		/*
2910 		 * If we got a recovery error that we don't actually
2911 		 * recover from, send SIGLOST.  If the filesystem was
2912 		 * forcibly unmounted, we skip the SIGLOST because (a) it's
2913 		 * unnecessary noise, and (b) there could be a new process
2914 		 * with the same pid as the one that had generated the lost
2915 		 * state request.
2916 		 */
2917 		if (ep->error == 0 && (ep->stat == NFS4ERR_BADHANDLE ||
2918 		    nfs4_recov_marks_dead(ep->stat))) {
2919 			if (!(vp->v_vfsp->vfs_flag & VFS_UNMOUNTED))
2920 				send_siglost = TRUE;
2921 			goto done;
2922 		}
2923 
2924 		/*
2925 		 * If the filesystem was forcibly unmounted, we
2926 		 * still need to synchronize with the server and
2927 		 * release state.  Try again later.
2928 		 */
2929 		if (NFS4_FRC_UNMT_ERR(ep->error, vp->v_vfsp))
2930 			goto done;
2931 
2932 		/*
2933 		 * If we get a recovery error that we can actually
2934 		 * recover from (such as ETIMEDOUT, FHEXPIRED),
2935 		 * return and let the recovery thread redrive the call.
2936 		 *
2937 		 * For the three errors below, we want to delay a bit
2938 		 * instead of pounding the server into submission.
2939 		 */
2940 		if ((ep->error == 0 && ep->stat == NFS4ERR_DELAY) ||
2941 		    (ep->error == 0 && ep->stat == NFS4ERR_GRACE) ||
2942 		    (ep->error == 0 && ep->stat == NFS4ERR_RESOURCE))
2943 			delay(SEC_TO_TICK(recov_err_delay));
2944 		goto done;
2945 	}
2946 
2947 done:
2948 	if (send_siglost) {
2949 		cred_t *sv_cred;
2950 
2951 		/*
2952 		 * Must be root or the actual thread being issued the
2953 		 * SIGLOST for this to work, so just become root.
2954 		 */
2955 		sv_cred = curthread->t_cred;
2956 		curthread->t_cred = kcred;
2957 		nfs4_send_siglost(lrp->lr_flk->l_pid, VTOMI4(vp), vp, FALSE,
2958 		    ep->error, ep->stat);
2959 		curthread->t_cred = sv_cred;
2960 
2961 		/*
2962 		 * Flush any additional reinstantiation requests for
2963 		 * this operation.  Sending multiple SIGLOSTs to the user
2964 		 * process is unlikely to help and may cause trouble.
2965 		 */
2966 		if (lrp->lr_ctype == NFS4_LCK_CTYPE_REINSTATE)
2967 			flush_reinstate(lrp);
2968 	}
2969 }
2970 
2971 /*
2972  * Remove any lock reinstantiation requests that correspond to the given
2973  * lost request.  We only remove items that follow lrp in the queue,
2974  * assuming that lrp will be removed by the generic lost state code.
2975  */
2976 
2977 static void
2978 flush_reinstate(nfs4_lost_rqst_t *lrp)
2979 {
2980 	vnode_t *vp;
2981 	pid_t pid;
2982 	mntinfo4_t *mi;
2983 	nfs4_lost_rqst_t *nlrp;
2984 
2985 	vp = lrp->lr_vp;
2986 	mi = VTOMI4(vp);
2987 	pid = lrp->lr_flk->l_pid;
2988 
2989 	/*
2990 	 * If there are any more reinstantation requests to get rid of,
2991 	 * they should all be clustered at the front of the lost state
2992 	 * queue.
2993 	 */
2994 	mutex_enter(&mi->mi_lock);
2995 	for (lrp = list_next(&mi->mi_lost_state, lrp); lrp != NULL;
2996 	    lrp = nlrp) {
2997 		nlrp = list_next(&mi->mi_lost_state, lrp);
2998 		if (lrp->lr_op != OP_LOCK && lrp->lr_op != OP_LOCKU)
2999 			break;
3000 		if (lrp->lr_ctype != NFS4_LCK_CTYPE_REINSTATE)
3001 			break;
3002 		ASSERT(lrp->lr_vp == vp);
3003 		ASSERT(lrp->lr_flk->l_pid == pid);
3004 		NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE,
3005 				"remove reinstantiation %p", (void *)lrp));
3006 		list_remove(&mi->mi_lost_state, lrp);
3007 		nfs4_free_lost_rqst(lrp, NULL);
3008 	}
3009 	mutex_exit(&mi->mi_lock);
3010 }
3011 
3012 /*
3013  * End of state-specific recovery routines.
3014  */
3015 
3016 /*
3017  * Allocate a lost request struct, initialize it from lost_rqstp (including
3018  * bumping the reference counts for the referenced vnode, etc.), and hang
3019  * it off of recovp.
3020  */
3021 
3022 static void
3023 nfs4_save_lost_rqst(nfs4_lost_rqst_t *lost_rqstp, recov_info_t *recovp,
3024 	nfs4_recov_t *action, mntinfo4_t *mi)
3025 {
3026 	nfs4_lost_rqst_t *destp;
3027 
3028 	ASSERT(recovp->rc_lost_rqst == NULL);
3029 
3030 	destp = kmem_alloc(sizeof (nfs4_lost_rqst_t), KM_SLEEP);
3031 	recovp->rc_lost_rqst = destp;
3032 
3033 	if (lost_rqstp->lr_op == OP_LOCK ||
3034 	    lost_rqstp->lr_op == OP_LOCKU) {
3035 		ASSERT(lost_rqstp->lr_lop);
3036 		*action = NR_LOST_LOCK;
3037 		destp->lr_ctype = lost_rqstp->lr_ctype;
3038 		destp->lr_locktype = lost_rqstp->lr_locktype;
3039 	} else if (lost_rqstp->lr_op == OP_OPEN) {
3040 		component4 *srcfp, *destfp;
3041 
3042 		destp->lr_oacc = lost_rqstp->lr_oacc;
3043 		destp->lr_odeny = lost_rqstp->lr_odeny;
3044 		destp->lr_oclaim = lost_rqstp->lr_oclaim;
3045 		if (lost_rqstp->lr_oclaim == CLAIM_DELEGATE_CUR)
3046 			destp->lr_ostateid = lost_rqstp->lr_ostateid;
3047 
3048 		srcfp = &lost_rqstp->lr_ofile;
3049 		destfp = &destp->lr_ofile;
3050 		/*
3051 		 * Consume caller's utf8string
3052 		 */
3053 		destfp->utf8string_len = srcfp->utf8string_len;
3054 		destfp->utf8string_val = srcfp->utf8string_val;
3055 		srcfp->utf8string_len = 0;
3056 		srcfp->utf8string_val = NULL;	/* make sure not reused */
3057 
3058 		*action = NR_LOST_STATE_RQST;
3059 	} else if (lost_rqstp->lr_op == OP_OPEN_DOWNGRADE) {
3060 		destp->lr_dg_acc = lost_rqstp->lr_dg_acc;
3061 		destp->lr_dg_deny = lost_rqstp->lr_dg_deny;
3062 
3063 		*action = NR_LOST_STATE_RQST;
3064 	} else if (lost_rqstp->lr_op == OP_CLOSE) {
3065 		ASSERT(lost_rqstp->lr_oop);
3066 		*action = NR_LOST_STATE_RQST;
3067 	} else if (lost_rqstp->lr_op == OP_DELEGRETURN) {
3068 		*action = NR_LOST_STATE_RQST;
3069 	} else {
3070 #ifdef DEBUG
3071 		cmn_err(CE_PANIC, "nfs4_save_lost_rqst: bad op %d",
3072 			lost_rqstp->lr_op);
3073 #endif
3074 		nfs4_queue_event(RE_LOST_STATE_BAD_OP, mi, NULL,
3075 		    lost_rqstp->lr_op, lost_rqstp->lr_vp, lost_rqstp->lr_dvp,
3076 		    NFS4_OK, NULL, curproc->p_pid, TAG_NONE, TAG_NONE, 0, 0);
3077 		*action = NR_UNUSED;
3078 		recovp->rc_lost_rqst = NULL;
3079 		kmem_free(destp, sizeof (nfs4_lost_rqst_t));
3080 		return;
3081 	}
3082 
3083 	destp->lr_op = lost_rqstp->lr_op;
3084 	destp->lr_vp = lost_rqstp->lr_vp;
3085 	if (destp->lr_vp)
3086 		VN_HOLD(destp->lr_vp);
3087 	destp->lr_dvp = lost_rqstp->lr_dvp;
3088 	if (destp->lr_dvp)
3089 		VN_HOLD(destp->lr_dvp);
3090 	destp->lr_oop = lost_rqstp->lr_oop;
3091 	if (destp->lr_oop)
3092 		open_owner_hold(destp->lr_oop);
3093 	destp->lr_osp = lost_rqstp->lr_osp;
3094 	if (destp->lr_osp)
3095 		open_stream_hold(destp->lr_osp);
3096 	destp->lr_lop = lost_rqstp->lr_lop;
3097 	if (destp->lr_lop)
3098 		lock_owner_hold(destp->lr_lop);
3099 	destp->lr_cr = lost_rqstp->lr_cr;
3100 	if (destp->lr_cr)
3101 		crhold(destp->lr_cr);
3102 	if (lost_rqstp->lr_flk == NULL)
3103 		destp->lr_flk = NULL;
3104 	else {
3105 		destp->lr_flk = kmem_alloc(sizeof (flock64_t), KM_SLEEP);
3106 		*destp->lr_flk = *lost_rqstp->lr_flk;
3107 	}
3108 	destp->lr_putfirst = lost_rqstp->lr_putfirst;
3109 }
3110 
3111 /*
3112  * Map the given return values (errno and nfs4 status code) to a recovery
3113  * action and fill in the following fields of recovp: rc_action,
3114  * rc_srv_reboot, rc_stateid, rc_lost_rqst.
3115  */
3116 
3117 void
3118 errs_to_action(recov_info_t *recovp,
3119 	nfs4_server_t *sp, mntinfo4_t *mi, stateid4 *sidp,
3120 	nfs4_lost_rqst_t *lost_rqstp, int unmounted, nfs_opnum4 op,
3121 	nfs4_bseqid_entry_t *bsep)
3122 {
3123 	nfs4_recov_t action = NR_UNUSED;
3124 	bool_t reboot = FALSE;
3125 	int try_f;
3126 	int error = recovp->rc_orig_errors.error;
3127 	nfsstat4 stat = recovp->rc_orig_errors.stat;
3128 
3129 	bzero(&recovp->rc_stateid, sizeof (stateid4));
3130 	recovp->rc_lost_rqst = NULL;
3131 	recovp->rc_bseqid_rqst = NULL;
3132 
3133 	try_f = nfs4_try_failover(&recovp->rc_orig_errors) &&
3134 			FAILOVER_MOUNT4(mi);
3135 
3136 	/*
3137 	 * We start recovery for EINTR only in the lost lock
3138 	 * or lost open/close case.
3139 	 */
3140 
3141 	if (try_f || error == EINTR || (error == EIO && unmounted)) {
3142 		recovp->rc_error = (error != 0 ? error : geterrno4(stat));
3143 		if (lost_rqstp) {
3144 			ASSERT(lost_rqstp->lr_op != 0);
3145 			nfs4_save_lost_rqst(lost_rqstp, recovp, &action, mi);
3146 		}
3147 		if (try_f)
3148 			action = NR_FAILOVER;
3149 	} else if (error != 0) {
3150 		recovp->rc_error = error;
3151 		nfs4_queue_event(RE_UNEXPECTED_ERRNO, mi, NULL, error, NULL,
3152 		    NULL, 0, NULL, 0, TAG_NONE, TAG_NONE, 0, 0);
3153 		action = NR_CLIENTID;
3154 	} else {
3155 		recovp->rc_error = geterrno4(stat);
3156 		switch (stat) {
3157 #ifdef notyet
3158 		case NFS4ERR_LEASE_MOVED:
3159 			action = xxx;
3160 			break;
3161 		case NFS4ERR_MOVED:
3162 			action = xxx;
3163 			break;
3164 #endif
3165 		case NFS4ERR_BADHANDLE:
3166 			action = NR_BADHANDLE;
3167 			break;
3168 		case NFS4ERR_BAD_SEQID:
3169 			if (bsep)
3170 				save_bseqid_rqst(bsep, recovp);
3171 			action = NR_BAD_SEQID;
3172 			break;
3173 		case NFS4ERR_OLD_STATEID:
3174 			action = NR_OLDSTATEID;
3175 			break;
3176 		case NFS4ERR_WRONGSEC:
3177 			action = NR_WRONGSEC;
3178 			break;
3179 		case NFS4ERR_FHEXPIRED:
3180 			action = NR_FHEXPIRED;
3181 			break;
3182 		case NFS4ERR_BAD_STATEID:
3183 			if (sp == NULL || (sp != NULL && inlease(sp))) {
3184 
3185 				action = NR_BAD_STATEID;
3186 				if (sidp)
3187 					recovp->rc_stateid = *sidp;
3188 			} else
3189 				action = NR_CLIENTID;
3190 			break;
3191 		case NFS4ERR_EXPIRED:
3192 			/*
3193 			 * The client's lease has expired, either due
3194 			 * to a network partition or perhaps a client
3195 			 * error.  In either case, try an NR_CLIENTID
3196 			 * style recovery.  reboot remains false, since
3197 			 * there is no evidence the server has rebooted.
3198 			 * This will cause CLAIM_NULL opens and lock
3199 			 * requests without the reclaim bit.
3200 			 */
3201 			action = NR_CLIENTID;
3202 
3203 			DTRACE_PROBE4(nfs4__expired,
3204 					nfs4_server_t *, sp,
3205 					mntinfo4_t *, mi,
3206 					stateid4 *, sidp, int, op);
3207 
3208 			break;
3209 		case NFS4ERR_STALE_CLIENTID:
3210 		case NFS4ERR_STALE_STATEID:
3211 			action = NR_CLIENTID;
3212 			reboot = TRUE;
3213 			break;
3214 		case NFS4ERR_RESOURCE:
3215 			/*
3216 			 * If this had been a FAILOVER mount, then
3217 			 * we'd have tried failover.  Since it's not,
3218 			 * just delay a while and retry.
3219 			 */
3220 			action = NR_DELAY;
3221 			break;
3222 		case NFS4ERR_GRACE:
3223 			action = NR_GRACE;
3224 			break;
3225 		case NFS4ERR_DELAY:
3226 			action = NR_DELAY;
3227 			break;
3228 		case NFS4ERR_STALE:
3229 			action = NR_STALE;
3230 			break;
3231 		default:
3232 			nfs4_queue_event(RE_UNEXPECTED_STATUS, mi, NULL, 0,
3233 			    NULL, NULL, stat, NULL, 0, TAG_NONE, TAG_NONE,
3234 			    0, 0);
3235 			action = NR_CLIENTID;
3236 			break;
3237 		}
3238 	}
3239 
3240 	/* make sure action got set */
3241 	ASSERT(action != NR_UNUSED);
3242 	recovp->rc_srv_reboot = reboot;
3243 	recovp->rc_action = action;
3244 	nfs4_queue_fact(RF_ERR, mi, stat, action, op, reboot, NULL, error,
3245 		NULL);
3246 }
3247 
3248 /*
3249  * Return the (held) credential for the process with the given pid.
3250  * May return NULL (e.g., process not found).
3251  */
3252 
3253 static cred_t *
3254 pid_to_cr(pid_t pid)
3255 {
3256 	proc_t *p;
3257 	cred_t *cr;
3258 
3259 	mutex_enter(&pidlock);
3260 	if ((p = prfind(pid)) == NULL) {
3261 		mutex_exit(&pidlock);
3262 		return (NULL);
3263 	}
3264 
3265 	mutex_enter(&p->p_crlock);
3266 	crhold(cr = p->p_cred);
3267 	mutex_exit(&p->p_crlock);
3268 	mutex_exit(&pidlock);
3269 
3270 	return (cr);
3271 }
3272 
3273 /*
3274  * Send SIGLOST to the given process and queue the event.
3275  *
3276  * The 'dump' boolean tells us whether this action should dump the
3277  * in-kernel queue of recovery messages or not.
3278  */
3279 
3280 void
3281 nfs4_send_siglost(pid_t pid, mntinfo4_t *mi, vnode_t *vp, bool_t dump,
3282     int error, nfsstat4 stat)
3283 {
3284 	proc_t *p;
3285 
3286 	mutex_enter(&pidlock);
3287 	p = prfind(pid);
3288 	if (p)
3289 		psignal(p, SIGLOST);
3290 	mutex_exit(&pidlock);
3291 	nfs4_queue_event(dump ? RE_SIGLOST : RE_SIGLOST_NO_DUMP, mi,
3292 	    NULL, error, vp, NULL, stat, NULL, pid, TAG_NONE, TAG_NONE, 0, 0);
3293 }
3294 
3295 /*
3296  * Scan the lock list for entries that match the given pid.  Change the
3297  * pid in those that do to NOPID.
3298  */
3299 
3300 static void
3301 relock_skip_pid(locklist_t *llp, pid_t pid)
3302 {
3303 	for (; llp != NULL; llp = llp->ll_next) {
3304 		if (llp->ll_flock.l_pid == pid)
3305 			llp->ll_flock.l_pid = NOPID;
3306 	}
3307 }
3308 
3309 /*
3310  * Mark a file as having failed recovery, after making a last-ditch effort
3311  * to return any delegation.
3312  *
3313  * Sets r_error to EIO or ESTALE for the given vnode.
3314  */
3315 void
3316 nfs4_fail_recov(vnode_t *vp, char *why, int error, nfsstat4 stat)
3317 {
3318 	rnode4_t *rp = VTOR4(vp);
3319 
3320 #ifdef DEBUG
3321 	if (nfs4_fail_recov_stop)
3322 		debug_enter("nfs4_fail_recov");
3323 #endif
3324 
3325 	mutex_enter(&rp->r_statelock);
3326 	if (rp->r_flags & (R4RECOVERR|R4RECOVERRP)) {
3327 		mutex_exit(&rp->r_statelock);
3328 		return;
3329 	}
3330 
3331 	/*
3332 	 * Set R4RECOVERRP to indicate that a recovery error is in
3333 	 * progress.  This will shut down reads and writes at the top
3334 	 * half.  Don't set R4RECOVERR until after we've returned the
3335 	 * delegation, otherwise it will fail.
3336 	 */
3337 
3338 	rp->r_flags |= R4RECOVERRP;
3339 	mutex_exit(&rp->r_statelock);
3340 
3341 	nfs4delegabandon(rp);
3342 
3343 	mutex_enter(&rp->r_statelock);
3344 	rp->r_flags |= (R4RECOVERR | R4STALE);
3345 	rp->r_error = (error == 0 && stat == NFS4ERR_STALE) ? ESTALE : EIO;
3346 	PURGE_ATTRCACHE4_LOCKED(rp);
3347 	if (!(vp->v_vfsp->vfs_flag & VFS_UNMOUNTED))
3348 		nfs4_queue_event(RE_DEAD_FILE, VTOMI4(vp), NULL, error,
3349 		    vp, NULL, stat, why, 0, TAG_NONE, TAG_NONE, 0, 0);
3350 	mutex_exit(&rp->r_statelock);
3351 
3352 	dnlc_purge_vp(vp);
3353 }
3354 
3355 /*
3356  * recov_throttle: if the file had the same recovery action within the
3357  * throttle interval, wait for the throttle interval to finish before
3358  * proceeding.
3359  *
3360  * Side effects: updates the rnode with the current recovery information.
3361  */
3362 
3363 static void
3364 recov_throttle(recov_info_t *recovp, vnode_t *vp)
3365 {
3366 	time_t curtime, time_to_wait;
3367 	rnode4_t *rp = VTOR4(vp);
3368 
3369 	curtime = gethrestime_sec();
3370 
3371 	mutex_enter(&rp->r_statelock);
3372 	NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
3373 		"recov_throttle: now: (%d, %ld), last: (%d, %ld)",
3374 		recovp->rc_action, curtime,
3375 		rp->r_recov_act, rp->r_last_recov));
3376 	if (recovp->rc_action == rp->r_recov_act &&
3377 	    rp->r_last_recov + recov_err_delay > curtime) {
3378 		time_to_wait = rp->r_last_recov + recov_err_delay - curtime;
3379 		mutex_exit(&rp->r_statelock);
3380 		delay(SEC_TO_TICK(time_to_wait));
3381 		curtime = gethrestime_sec();
3382 		mutex_enter(&rp->r_statelock);
3383 	}
3384 
3385 	rp->r_last_recov = curtime;
3386 	rp->r_recov_act = recovp->rc_action;
3387 	mutex_exit(&rp->r_statelock);
3388 }
3389 
3390 /*
3391  * React to NFS4ERR_GRACE by setting the time we'll permit
3392  * the next call to this filesystem.
3393  */
3394 void
3395 nfs4_set_grace_wait(mntinfo4_t *mi)
3396 {
3397 	mutex_enter(&mi->mi_lock);
3398 	/* Mark the time for the future */
3399 	mi->mi_grace_wait = gethrestime_sec() + nfs4err_delay_time;
3400 	mutex_exit(&mi->mi_lock);
3401 }
3402 
3403 /*
3404  * React to MFS4ERR_DELAY by setting the time we'll permit
3405  * the next call to this vnode.
3406  */
3407 void
3408 nfs4_set_delay_wait(vnode_t *vp)
3409 {
3410 	rnode4_t *rp = VTOR4(vp);
3411 
3412 	mutex_enter(&rp->r_statelock);
3413 	/*
3414 	 * Calculate amount we should delay, initial
3415 	 * delay will be short and then we will back off.
3416 	 */
3417 	if (rp->r_delay_interval == 0)
3418 		rp->r_delay_interval = NFS4_INITIAL_DELAY_INTERVAL;
3419 	else
3420 		/* calculate next interval value */
3421 		rp->r_delay_interval =
3422 		    MIN(NFS4_MAX_DELAY_INTERVAL, (rp->r_delay_interval << 1));
3423 	rp->r_delay_wait = gethrestime_sec() + rp->r_delay_interval;
3424 	mutex_exit(&rp->r_statelock);
3425 }
3426 
3427 /*
3428  * The caller is responsible for freeing the returned string.
3429  */
3430 static char *
3431 nfs4_getsrvnames(mntinfo4_t *mi, size_t *len)
3432 {
3433 	servinfo4_t *svp;
3434 	char *srvnames;
3435 	char *namep;
3436 	size_t length;
3437 
3438 	/*
3439 	 * Calculate the length of the string required to hold all
3440 	 * of the server names plus either a comma or a null
3441 	 * character following each individual one.
3442 	 */
3443 	length = 0;
3444 	for (svp = mi->mi_servers; svp != NULL; svp = svp->sv_next) {
3445 		(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
3446 		if (svp->sv_flags & SV4_NOTINUSE) {
3447 			nfs_rw_exit(&svp->sv_lock);
3448 			continue;
3449 		}
3450 		nfs_rw_exit(&svp->sv_lock);
3451 		length += svp->sv_hostnamelen;
3452 	}
3453 
3454 	srvnames = kmem_alloc(length, KM_SLEEP);
3455 
3456 	namep = srvnames;
3457 	for (svp = mi->mi_servers; svp != NULL; svp = svp->sv_next) {
3458 		(void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
3459 		if (svp->sv_flags & SV4_NOTINUSE) {
3460 			nfs_rw_exit(&svp->sv_lock);
3461 			continue;
3462 		}
3463 		nfs_rw_exit(&svp->sv_lock);
3464 		(void) strcpy(namep, svp->sv_hostname);
3465 		namep += svp->sv_hostnamelen - 1;
3466 		*namep++ = ',';
3467 	}
3468 	*--namep = '\0';
3469 
3470 	*len = length;
3471 
3472 	return (srvnames);
3473 }
3474 
3475 static void
3476 save_bseqid_rqst(nfs4_bseqid_entry_t *bsep, recov_info_t *recovp)
3477 {
3478 	nfs4_bseqid_entry_t *destp;
3479 
3480 	destp = kmem_alloc(sizeof (nfs4_bseqid_entry_t), KM_SLEEP);
3481 	recovp->rc_bseqid_rqst = destp;
3482 
3483 	if (bsep->bs_oop)
3484 		open_owner_hold(bsep->bs_oop);
3485 	destp->bs_oop = bsep->bs_oop;
3486 	if (bsep->bs_lop)
3487 		lock_owner_hold(bsep->bs_lop);
3488 	destp->bs_lop = bsep->bs_lop;
3489 	if (bsep->bs_vp)
3490 		VN_HOLD(bsep->bs_vp);
3491 	destp->bs_vp = bsep->bs_vp;
3492 	destp->bs_pid = bsep->bs_pid;
3493 	destp->bs_tag = bsep->bs_tag;
3494 	destp->bs_seqid = bsep->bs_seqid;
3495 }
3496 
3497 static void
3498 free_bseqid_rqst(nfs4_bseqid_entry_t *bsep)
3499 {
3500 	if (bsep->bs_oop)
3501 		open_owner_rele(bsep->bs_oop);
3502 	if (bsep->bs_lop)
3503 		lock_owner_rele(bsep->bs_lop);
3504 	if (bsep->bs_vp)
3505 		VN_RELE(bsep->bs_vp);
3506 	kmem_free(bsep, sizeof (nfs4_bseqid_entry_t));
3507 }
3508 
3509 /*
3510  * We don't actually fully recover from NFS4ERR_BAD_SEQID.  We
3511  * simply mark the open owner and open stream (if provided) as "bad".
3512  * Then future uses of these data structures will be limited to basically
3513  * just cleaning up the internal client state (no going OTW).
3514  *
3515  * The result of this is to return errors back to the app/usr when
3516  * we receive NFS4ERR_BAD_SEQID, but also allow future/new calls to
3517  * succeed so progress can be made.
3518  */
3519 void
3520 recov_bad_seqid(recov_info_t *recovp)
3521 {
3522 	mntinfo4_t		*mi = recovp->rc_mi;
3523 	nfs4_open_owner_t	*bad_oop;
3524 	nfs4_lock_owner_t	*bad_lop;
3525 	vnode_t			*vp;
3526 	rnode4_t		*rp = NULL;
3527 	pid_t			pid;
3528 	nfs4_bseqid_entry_t	*bsep, *tbsep;
3529 	int			error;
3530 
3531 	ASSERT(mi != NULL);
3532 	ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
3533 
3534 	mutex_enter(&mi->mi_lock);
3535 	bsep = list_head(&mi->mi_bseqid_list);
3536 	mutex_exit(&mi->mi_lock);
3537 
3538 	/*
3539 	 * Handle all the bad seqid entries on mi's list.
3540 	 */
3541 	while (bsep != NULL) {
3542 		bad_oop = bsep->bs_oop;
3543 		bad_lop = bsep->bs_lop;
3544 		vp = bsep->bs_vp;
3545 		pid = bsep->bs_pid;
3546 
3547 		NFS4_DEBUG(nfs4_client_recov_debug, (CE_NOTE,
3548 		    "recov_bad_seqid: mark oop %p lop %p as bad for "
3549 		    "vp %p tag %s pid %d: last good seqid %d for tag %s",
3550 		    (void *)bad_oop, (void *)bad_lop, (void *)vp,
3551 		    nfs4_ctags[bsep->bs_tag].ct_str, pid,
3552 		    bad_oop ?  bad_oop->oo_last_good_seqid : 0,
3553 		    bad_oop ? nfs4_ctags[bad_oop->oo_last_good_op].ct_str :
3554 		    nfs4_ctags[TAG_NONE].ct_str));
3555 
3556 		nfs4_queue_event(RE_BAD_SEQID, mi, NULL,
3557 		    0, vp, NULL, NFS4ERR_BAD_SEQID, NULL, pid, bsep->bs_tag,
3558 		    bad_oop ? bad_oop->oo_last_good_op : TAG_NONE,
3559 		    bsep->bs_seqid, bad_oop ? bad_oop->oo_last_good_seqid : 0);
3560 
3561 		if (bad_oop) {
3562 			/* essentially reset the open owner */
3563 			error = nfs4_start_open_seqid_sync(bad_oop, mi);
3564 			ASSERT(!error);	/* recov thread always succeeds */
3565 			bad_oop->oo_name = nfs4_get_new_oo_name();
3566 			bad_oop->oo_seqid = 0;
3567 			nfs4_end_open_seqid_sync(bad_oop);
3568 		}
3569 
3570 		if (bad_lop) {
3571 			mutex_enter(&bad_lop->lo_lock);
3572 			bad_lop->lo_flags |= NFS4_BAD_SEQID_LOCK;
3573 			mutex_exit(&bad_lop->lo_lock);
3574 
3575 			ASSERT(vp != NULL);
3576 			rp = VTOR4(vp);
3577 			mutex_enter(&rp->r_statelock);
3578 			rp->r_flags |= R4LODANGLERS;
3579 			mutex_exit(&rp->r_statelock);
3580 
3581 			nfs4_send_siglost(pid, mi, vp, TRUE,
3582 			    0, NFS4ERR_BAD_SEQID);
3583 		}
3584 
3585 		mutex_enter(&mi->mi_lock);
3586 		list_remove(&mi->mi_bseqid_list, bsep);
3587 		tbsep = bsep;
3588 		bsep = list_head(&mi->mi_bseqid_list);
3589 		mutex_exit(&mi->mi_lock);
3590 		free_bseqid_rqst(tbsep);
3591 	}
3592 
3593 	mutex_enter(&mi->mi_lock);
3594 	mi->mi_recovflags &= ~MI4R_BAD_SEQID;
3595 	mutex_exit(&mi->mi_lock);
3596 }
3597