4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include <sys/kstat.h>
29 #include <sys/systm.h>
31 #include <sys/vnode.h>
32 #include <sys/cmn_err.h>
34 #include <nfs/nfs4_clnt.h>
35 #include <nfs/rnode4.h>
40 typedef struct rkstat
{
41 kstat_named_t badhandle
;
42 kstat_named_t badowner
;
43 kstat_named_t clientid
;
44 kstat_named_t dead_file
;
46 kstat_named_t fail_relock
;
47 kstat_named_t file_diff
;
48 kstat_named_t no_grace
;
49 kstat_named_t not_responding
;
50 kstat_named_t opens_changed
;
51 kstat_named_t siglost
;
52 kstat_named_t unexp_action
;
53 kstat_named_t unexp_errno
;
54 kstat_named_t unexp_status
;
55 kstat_named_t wrongsec
;
56 kstat_named_t lost_state_bad_op
;
59 static rkstat_t rkstat_template
= {
60 { "badhandle", KSTAT_DATA_ULONG
},
61 { "badowner", KSTAT_DATA_ULONG
},
62 { "clientid", KSTAT_DATA_ULONG
},
63 { "dead_file", KSTAT_DATA_ULONG
},
64 { "delay", KSTAT_DATA_ULONG
},
65 { "fail_relock", KSTAT_DATA_ULONG
},
66 { "file_diff", KSTAT_DATA_ULONG
},
67 { "no_grace", KSTAT_DATA_ULONG
},
68 { "not_responding", KSTAT_DATA_ULONG
},
69 { "opens_changed", KSTAT_DATA_ULONG
},
70 { "siglost", KSTAT_DATA_ULONG
},
71 { "unexp_action", KSTAT_DATA_ULONG
},
72 { "unexp_errno", KSTAT_DATA_ULONG
},
73 { "unexp_status", KSTAT_DATA_ULONG
},
74 { "wrongsec", KSTAT_DATA_ULONG
},
75 { "bad_op", KSTAT_DATA_ULONG
},
78 /* maximum number of messages allowed on the mi's mi_msg_list */
79 int nfs4_msg_max
= NFS4_MSG_MAX
;
80 #define DEFAULT_LEASE 180
83 * Sets the appropiate fields of "ep", given "id" and various parameters.
84 * Assumes that ep's fields have been initialized to zero/null, except for
85 * re_type and mount point info, which are already set.
88 set_event(nfs4_event_type_t id
, nfs4_revent_t
*ep
, mntinfo4_t
*mi
,
89 rnode4_t
*rp1
, rnode4_t
*rp2
, uint_t count
, pid_t pid
, nfsstat4 nfs4_error
,
90 char *server1
, char *why
, nfs4_tag_type_t tag1
, nfs4_tag_type_t tag2
,
91 seqid4 seqid1
, seqid4 seqid2
)
99 /* bad seqid'd file <path/component name> */
100 if (rp1
&& rp1
->r_svnode
.sv_name
)
101 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
109 ep
->re_stat4
= nfs4_error
;
112 ep
->re_seqid1
= seqid1
;
113 ep
->re_seqid2
= seqid2
;
118 /* dead file <path/component name> */
119 if (rp1
->r_svnode
.sv_name
)
120 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
128 /* the error we failed with */
130 ep
->re_stat4
= nfs4_error
;
135 /* dead file <path/component name> */
136 if (rp1
->r_svnode
.sv_name
)
137 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
142 /* why the file got killed */
145 ep
->re_char2
= kmem_alloc(len
+ 1, KM_SLEEP
);
146 bcopy(why
, ep
->re_char2
, len
);
147 ep
->re_char2
[len
] = '\0';
151 ep
->re_stat4
= nfs4_error
;
155 if (rp1
&& rp1
->r_svnode
.sv_name
)
156 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
162 if (rp2
&& rp2
->r_svnode
.sv_name
)
163 ep
->re_char2
= fn_path(rp2
->r_svnode
.sv_name
);
173 /* error on fail relock */
176 /* process that failed */
180 ep
->re_stat4
= nfs4_error
;
182 /* file <path/component name> */
183 if (rp1
->r_svnode
.sv_name
)
184 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
189 case RE_FAIL_REMAP_LEN
:
190 /* length of returned filehandle */
193 case RE_FAIL_REMAP_OP
:
196 /* server we're failing over to (if not picking original) */
197 if (server1
!= NULL
) {
198 len
= strlen(server1
);
199 ep
->re_char1
= kmem_alloc(len
+ 1, KM_SLEEP
);
200 bcopy(server1
, ep
->re_char1
, len
);
201 ep
->re_char1
[len
] = '\0';
209 /* dead file <path/component name> */
210 if (rp1
->r_svnode
.sv_name
)
211 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
217 ep
->re_uint
= count
; /* op number */
218 if (rp1
&& rp1
->r_svnode
.sv_name
)
219 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
223 if (rp2
&& rp2
->r_svnode
.sv_name
)
224 ep
->re_char2
= fn_path(rp2
->r_svnode
.sv_name
);
229 case RE_OPENS_CHANGED
:
232 /* original number of open files */
234 /* new number of open files */
238 case RE_SIGLOST_NO_DUMP
:
241 /* file <path/component name> */
242 if (rp1
->r_svnode
.sv_name
)
243 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
249 ep
->re_stat4
= nfs4_error
;
252 /* file <path/component name> */
253 if (rp1
&& rp1
->r_svnode
.sv_name
)
254 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
259 /* file <path/component name> */
260 if (rp2
&& rp2
->r_svnode
.sv_name
)
261 ep
->re_char2
= fn_path(rp2
->r_svnode
.sv_name
);
269 case RE_UNEXPECTED_ACTION
:
270 case RE_UNEXPECTED_ERRNO
:
271 /* the error that is unexpected */
274 case RE_UNEXPECTED_STATUS
:
276 ep
->re_stat4
= nfs4_error
;
279 /* the error we failed with */
282 /* file <path/component name> */
283 if (rp1
&& rp1
->r_svnode
.sv_name
)
284 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
289 /* file <path/component name> */
290 if (rp2
&& rp2
->r_svnode
.sv_name
)
291 ep
->re_char2
= fn_path(rp2
->r_svnode
.sv_name
);
296 case RE_LOST_STATE_BAD_OP
:
297 ep
->re_uint
= count
; /* the unexpected op */
300 if (rp1
!= NULL
&& rp1
->r_svnode
.sv_name
!= NULL
)
301 ep
->re_char1
= fn_path(rp1
->r_svnode
.sv_name
);
303 if (rp2
!= NULL
&& rp2
->r_svnode
.sv_name
!= NULL
)
304 ep
->re_char2
= fn_path(rp2
->r_svnode
.sv_name
);
307 /* server we're being referred to */
308 if (server1
!= NULL
) {
309 len
= strlen(server1
);
310 ep
->re_char1
= kmem_alloc(len
+ 1, KM_SLEEP
);
311 bcopy(server1
, ep
->re_char1
, len
);
312 ep
->re_char1
[len
] = '\0';
323 * Sets the appropiate fields of the 'fact' for this 'id'.
326 set_fact(nfs4_fact_type_t id
, nfs4_rfact_t
*fp
, nfsstat4 stat4
,
327 nfs4_recov_t raction
, nfs_opnum4 op
, bool_t reboot
, int error
,
335 fp
->rf_reboot
= reboot
;
336 fp
->rf_stat4
= stat4
;
338 case RF_RENEW_EXPIRED
:
342 fp
->rf_reboot
= reboot
;
343 fp
->rf_stat4
= stat4
;
344 fp
->rf_action
= raction
;
345 fp
->rf_error
= error
;
349 case RF_SRV_NOT_RESPOND
:
353 case RF_SRVS_NOT_RESPOND
:
354 gethrestime(&fp
->rf_time
);
356 case RF_DELMAP_CB_ERR
:
358 fp
->rf_stat4
= stat4
;
362 if (rp1
&& rp1
->r_svnode
.sv_name
)
363 fp
->rf_char1
= fn_path(rp1
->r_svnode
.sv_name
);
370 zcmn_err(getzoneid(), CE_NOTE
, "illegal fact %d", id
);
376 * Returns 1 if the event/fact is of a successful communication
377 * from the server; 0 otherwise.
380 successful_comm(nfs4_debug_msg_t
*msgp
)
382 if (msgp
->msg_type
== RM_EVENT
) {
383 switch (msgp
->rmsg_u
.msg_event
.re_type
) {
386 case RE_FAIL_REMAP_LEN
:
387 case RE_FAIL_REMAP_OP
:
390 case RE_UNEXPECTED_ACTION
:
391 case RE_UNEXPECTED_ERRNO
:
392 case RE_UNEXPECTED_STATUS
:
401 case RE_OPENS_CHANGED
:
403 case RE_SIGLOST_NO_DUMP
:
404 case RE_LOST_STATE_BAD_OP
:
412 switch (msgp
->rmsg_u
.msg_fact
.rf_type
) {
415 case RF_RENEW_EXPIRED
:
418 case RF_DELMAP_CB_ERR
:
420 case RF_SRV_NOT_RESPOND
:
421 case RF_SRVS_NOT_RESPOND
:
431 * Iterate backwards through the mi's mi_msg_list to find the earliest
432 * message that we should find relevant facts to investigate.
434 static nfs4_debug_msg_t
*
435 find_beginning(nfs4_debug_msg_t
*first_msg
, mntinfo4_t
*mi
)
437 nfs4_debug_msg_t
*oldest_msg
, *cur_msg
;
440 ASSERT(mutex_owned(&mi
->mi_msg_list_lock
));
441 if (mi
->mi_lease_period
> 0)
442 lease
= 2 * mi
->mi_lease_period
;
444 lease
= DEFAULT_LEASE
;
446 oldest_msg
= first_msg
;
447 cur_msg
= list_prev(&mi
->mi_msg_list
, first_msg
);
449 first_msg
->msg_time
.tv_sec
- cur_msg
->msg_time
.tv_sec
< lease
) {
450 oldest_msg
= cur_msg
;
451 if ((cur_msg
->msg_type
== RM_FACT
) &&
452 (cur_msg
->rmsg_u
.msg_fact
.rf_type
== RF_SRV_OK
)) {
453 /* find where we lost contact with the server */
455 if ((cur_msg
->msg_type
== RM_FACT
) &&
456 (cur_msg
->rmsg_u
.msg_fact
.rf_type
==
459 oldest_msg
= cur_msg
;
460 cur_msg
= list_prev(&mi
->mi_msg_list
, cur_msg
);
463 * Find the first successful message before
464 * we lost contact with the server.
467 cur_msg
= list_prev(&mi
->mi_msg_list
, cur_msg
);
468 while (cur_msg
&& !successful_comm(cur_msg
)) {
469 oldest_msg
= cur_msg
;
470 cur_msg
= list_prev(&mi
->mi_msg_list
,
475 * If we're not at the dummy head pointer,
476 * set the oldest and current message.
480 oldest_msg
= cur_msg
;
481 cur_msg
= list_prev(&mi
->mi_msg_list
, cur_msg
);
484 cur_msg
= list_prev(&mi
->mi_msg_list
, cur_msg
);
491 * Returns 1 if facts have been found; 0 otherwise.
494 get_facts(nfs4_debug_msg_t
*msgp
, nfs4_rfact_t
*ret_fp
, char **mnt_pt
,
497 nfs4_debug_msg_t
*cur_msg
, *oldest_msg
;
498 nfs4_rfact_t
*cur_fp
;
499 int found_a_fact
= 0;
504 /* find the oldest msg to search backwards to */
505 oldest_msg
= find_beginning(cur_msg
, mi
);
506 ASSERT(oldest_msg
!= NULL
);
509 * Create a fact sheet by searching from our current message
510 * backwards to the 'oldest_msg', recording facts along the way
511 * until we found facts that have been inspected by another time.
513 while (cur_msg
&& cur_msg
!= list_prev(&mi
->mi_msg_list
, oldest_msg
)) {
514 if (cur_msg
->msg_type
!= RM_FACT
) {
515 cur_msg
= list_prev(&mi
->mi_msg_list
, cur_msg
);
519 cur_fp
= &cur_msg
->rmsg_u
.msg_fact
;
521 * If this fact has already been looked at, then so
522 * have all preceding facts. Return Now.
524 if (cur_fp
->rf_status
== RFS_INSPECT
)
525 return (found_a_fact
);
527 cur_fp
->rf_status
= RFS_INSPECT
;
529 switch (cur_fp
->rf_type
) {
534 * Don't want to overwrite a fact that was
535 * previously found during our current search.
537 if (!ret_fp
->rf_reboot
)
538 ret_fp
->rf_reboot
= cur_fp
->rf_reboot
;
539 if (!ret_fp
->rf_stat4
)
540 ret_fp
->rf_stat4
= cur_fp
->rf_stat4
;
541 if (!ret_fp
->rf_action
)
542 ret_fp
->rf_action
= cur_fp
->rf_action
;
544 case RF_RENEW_EXPIRED
:
545 if (cur_msg
->msg_mntpt
&& !(*mnt_pt
)) {
546 len
= strlen(cur_msg
->msg_mntpt
) + 1;
547 *mnt_pt
= kmem_alloc(len
, KM_SLEEP
);
548 bcopy(cur_msg
->msg_mntpt
, *mnt_pt
, len
);
553 case RF_SRV_NOT_RESPOND
:
555 * Okay to overwrite this fact as
556 * we want the earliest time.
558 ret_fp
->rf_time
= cur_fp
->rf_time
;
562 case RF_SRVS_NOT_RESPOND
:
564 case RF_DELMAP_CB_ERR
:
569 zcmn_err(getzoneid(), CE_NOTE
,
570 "get facts: illegal fact %d", cur_fp
->rf_type
);
573 cur_msg
= list_prev(&mi
->mi_msg_list
, cur_msg
);
576 return (found_a_fact
);
580 * Returns 1 if this fact is identical to the last fact recorded
581 * (only checks for a match within the last 2 lease periods).
584 facts_same(nfs4_debug_msg_t
*cur_msg
, nfs4_debug_msg_t
*new_msg
,
587 nfs4_rfact_t
*fp1
, *fp2
;
590 ASSERT(mutex_owned(&mi
->mi_msg_list_lock
));
591 if (mi
->mi_lease_period
> 0)
592 lease
= 2 * mi
->mi_lease_period
;
594 lease
= DEFAULT_LEASE
;
596 fp2
= &new_msg
->rmsg_u
.msg_fact
;
599 new_msg
->msg_time
.tv_sec
- cur_msg
->msg_time
.tv_sec
< lease
) {
600 if (cur_msg
->msg_type
!= RM_FACT
) {
601 cur_msg
= list_prev(&mi
->mi_msg_list
, cur_msg
);
604 fp1
= &cur_msg
->rmsg_u
.msg_fact
;
605 if (fp1
->rf_type
!= fp2
->rf_type
)
608 /* now actually compare the facts */
609 if (fp1
->rf_action
!= fp2
->rf_action
)
611 if (fp1
->rf_stat4
!= fp2
->rf_stat4
)
613 if (fp1
->rf_reboot
!= fp2
->rf_reboot
)
615 if (fp1
->rf_op
!= fp2
->rf_op
)
617 if (fp1
->rf_time
.tv_sec
!= fp2
->rf_time
.tv_sec
)
619 if (fp1
->rf_error
!= fp2
->rf_error
)
621 if (fp1
->rf_rp1
!= fp2
->rf_rp1
)
623 if (cur_msg
->msg_srv
!= NULL
) {
624 if (new_msg
->msg_srv
== NULL
)
626 len
= strlen(cur_msg
->msg_srv
);
627 if (strncmp(cur_msg
->msg_srv
, new_msg
->msg_srv
,
630 } else if (new_msg
->msg_srv
!= NULL
) {
633 if (cur_msg
->msg_mntpt
!= NULL
) {
634 if (new_msg
->msg_mntpt
== NULL
)
636 len
= strlen(cur_msg
->msg_mntpt
);
637 if (strncmp(cur_msg
->msg_mntpt
, new_msg
->msg_mntpt
,
640 } else if (new_msg
->msg_mntpt
!= NULL
) {
643 if (fp1
->rf_char1
!= NULL
) {
644 if (fp2
->rf_char1
== NULL
)
646 len
= strlen(fp1
->rf_char1
);
647 if (strncmp(fp1
->rf_char1
, fp2
->rf_char1
, len
) != 0)
649 } else if (fp2
->rf_char1
!= NULL
) {
659 * Returns 1 if these two messages are identical; 0 otherwise.
662 events_same(nfs4_debug_msg_t
*cur_msg
, nfs4_debug_msg_t
*new_msg
,
665 nfs4_revent_t
*ep1
, *ep2
;
668 /* find the last event, bypassing all facts */
669 while (cur_msg
&& cur_msg
->msg_type
!= RM_EVENT
)
670 cur_msg
= list_prev(&mi
->mi_msg_list
, cur_msg
);
675 if (cur_msg
->msg_type
!= RM_EVENT
)
678 ep1
= &cur_msg
->rmsg_u
.msg_event
;
679 ep2
= &new_msg
->rmsg_u
.msg_event
;
680 if (ep1
->re_type
!= ep2
->re_type
)
684 * Since we zalloc the buffer, then the two nfs4_debug_msg's
685 * must match up even if all the fields weren't filled in
688 if (ep1
->re_mi
!= ep2
->re_mi
)
690 if (ep1
->re_uint
!= ep2
->re_uint
)
692 if (ep1
->re_stat4
!= ep2
->re_stat4
)
694 if (ep1
->re_pid
!= ep2
->re_pid
)
696 if (ep1
->re_rp1
!= ep2
->re_rp1
)
698 if (ep1
->re_rp2
!= ep2
->re_rp2
)
700 if (ep1
->re_tag1
!= ep2
->re_tag1
)
702 if (ep1
->re_tag2
!= ep2
->re_tag2
)
704 if (ep1
->re_seqid1
!= ep2
->re_seqid1
)
706 if (ep1
->re_seqid2
!= ep2
->re_seqid2
)
709 if (cur_msg
->msg_srv
!= NULL
) {
710 if (new_msg
->msg_srv
== NULL
)
712 len
= strlen(cur_msg
->msg_srv
);
713 if (strncmp(cur_msg
->msg_srv
, new_msg
->msg_srv
, len
) != 0)
715 } else if (new_msg
->msg_srv
!= NULL
) {
719 if (ep1
->re_char1
!= NULL
) {
720 if (ep2
->re_char1
== NULL
)
722 len
= strlen(ep1
->re_char1
);
723 if (strncmp(ep1
->re_char1
, ep2
->re_char1
, len
) != 0)
725 } else if (ep2
->re_char1
!= NULL
) {
729 if (ep1
->re_char2
!= NULL
) {
730 if (ep2
->re_char2
== NULL
)
732 len
= strlen(ep1
->re_char2
);
733 if (strncmp(ep1
->re_char2
, ep2
->re_char2
, len
) != 0)
735 } else if (ep2
->re_char2
!= NULL
) {
739 if (cur_msg
->msg_mntpt
!= NULL
) {
740 if (new_msg
->msg_mntpt
== NULL
)
742 len
= strlen(cur_msg
->msg_mntpt
);
743 if (strncmp(cur_msg
->msg_mntpt
, cur_msg
->msg_mntpt
, len
) != 0)
745 } else if (new_msg
->msg_mntpt
!= NULL
) {
753 * Free up a recovery event.
756 free_event(nfs4_revent_t
*ep
)
761 len
= strlen(ep
->re_char1
) + 1;
762 kmem_free(ep
->re_char1
, len
);
765 len
= strlen(ep
->re_char2
) + 1;
766 kmem_free(ep
->re_char2
, len
);
771 * Free up a recovery fact.
774 free_fact(nfs4_rfact_t
*fp
)
779 len
= strlen(fp
->rf_char1
) + 1;
780 kmem_free(fp
->rf_char1
, len
);
785 * Free up the message.
788 nfs4_free_msg(nfs4_debug_msg_t
*msg
)
792 if (msg
->msg_type
== RM_EVENT
)
793 free_event(&msg
->rmsg_u
.msg_event
);
795 free_fact(&msg
->rmsg_u
.msg_fact
);
798 len
= strlen(msg
->msg_srv
) + 1;
799 kmem_free(msg
->msg_srv
, len
);
802 if (msg
->msg_mntpt
) {
803 len
= strlen(msg
->msg_mntpt
) + 1;
804 kmem_free(msg
->msg_mntpt
, len
);
807 /* free up the data structure itself */
808 kmem_free(msg
, sizeof (*msg
));
812 * Prints out the interesting facts for recovery events:
817 print_facts(nfs4_debug_msg_t
*msg
, mntinfo4_t
*mi
)
823 if (msg
->rmsg_u
.msg_event
.re_type
!= RE_DEAD_FILE
&&
824 msg
->rmsg_u
.msg_event
.re_type
!= RE_SIGLOST
&&
825 msg
->rmsg_u
.msg_event
.re_type
!= RE_SIGLOST_NO_DUMP
)
828 fp
= kmem_zalloc(sizeof (*fp
), KM_SLEEP
);
831 if (get_facts(msg
, fp
, &mount_pt
, mi
)) {
835 if (fp
->rf_time
.tv_sec
)
836 (void) snprintf(time
, 256, "%ld",
837 (gethrestime_sec() - fp
->rf_time
.tv_sec
)/60);
838 zcmn_err(mi
->mi_zone
->zone_id
, CE_NOTE
,
839 "!NFS4 FACT SHEET: %s%s %s%s %s %s%s%s %s%s",
840 fp
->rf_action
? "\n Action: " : "",
841 fp
->rf_action
? nfs4_recov_action_to_str(fp
->rf_action
) :
843 fp
->rf_stat4
? "\n NFS4 error: " : "",
844 fp
->rf_stat4
? nfs4_stat_to_str(fp
->rf_stat4
) : "",
845 fp
->rf_reboot
? "\n Suspected server reboot. " : "",
846 fp
->rf_time
.tv_sec
? "\n Server was down for " : "",
847 fp
->rf_time
.tv_sec
? time
: "",
848 fp
->rf_time
.tv_sec
? " minutes." : "",
849 mount_pt
? " \n Client's lease expired on mount " : "",
850 mount_pt
? mount_pt
: "");
854 len
= strlen(mount_pt
) + 1;
855 kmem_free(mount_pt
, len
);
858 /* free the fact struct itself */
860 kmem_free(fp
, sizeof (*fp
));
864 * Print an event message to /var/adm/messages
865 * The last argument to this fuction dictates the repeat status
866 * of the event. If set to 1, it means that we are dumping this
867 * event and it will _never_ be printed after this time. Else if
868 * set to 0 it will be printed again.
871 queue_print_event(nfs4_debug_msg_t
*msg
, mntinfo4_t
*mi
, int dump
)
876 ep
= &msg
->rmsg_u
.msg_event
;
877 zoneid
= mi
->mi_zone
->zone_id
;
879 switch (ep
->re_type
) {
881 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
882 "Operation %s for file %s (rnode_pt 0x%p), pid %d using "
883 "seqid %d got %s. Last good seqid was %d for "
885 msg
->msg_srv
, msg
->msg_mntpt
,
886 nfs4_ctags
[ep
->re_tag1
].ct_str
, ep
->re_char1
,
887 (void *)ep
->re_rp1
, ep
->re_pid
, ep
->re_seqid1
,
888 nfs4_stat_to_str(ep
->re_stat4
), ep
->re_seqid2
,
889 nfs4_ctags
[ep
->re_tag2
].ct_str
);
892 ASSERT(ep
->re_rp1
!= NULL
);
893 if (ep
->re_char1
!= NULL
) {
894 zcmn_err(zoneid
, CE_NOTE
,
895 "![NFS4][Server: %s][Mntpt: %s]"
896 "server %s said filehandle was "
897 "invalid for file: %s (rnode_pt 0x%p) on mount %s",
898 msg
->msg_srv
, msg
->msg_mntpt
, msg
->msg_srv
,
899 ep
->re_char1
, (void *)ep
->re_rp1
, msg
->msg_mntpt
);
901 zcmn_err(zoneid
, CE_NOTE
,
902 "![NFS4][Server: %s][Mntpt: %s]"
903 "server %s said filehandle was "
904 "invalid for file: (rnode_pt 0x%p) on mount %s"
905 " for fh:", msg
->msg_srv
, msg
->msg_mntpt
,
906 msg
->msg_srv
, (void *)ep
->re_rp1
, msg
->msg_mntpt
);
907 sfh4_printfhandle(ep
->re_rp1
->r_fh
);
911 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
912 "Can't recover clientid on mount point %s "
913 "(mi 0x%p) due to error %d (%s), for server %s. Marking "
914 "file system as unusable.",
915 msg
->msg_srv
, msg
->msg_mntpt
, msg
->msg_mntpt
,
916 (void *)ep
->re_mi
, ep
->re_uint
,
917 nfs4_stat_to_str(ep
->re_stat4
),
921 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
922 "File %s (rnode_pt: %p) was closed due to NFS "
923 "recovery error on server %s(%s %s)", msg
->msg_srv
,
924 msg
->msg_mntpt
, ep
->re_char1
, (void *)ep
->re_rp1
,
925 msg
->msg_srv
, ep
->re_char2
? ep
->re_char2
: "",
926 ep
->re_stat4
? nfs4_stat_to_str(ep
->re_stat4
) : "");
929 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
930 "NFS Recovery done for mount %s (mi 0x%p) "
931 "on server %s, rnode_pt1 %s (0x%p), "
932 "rnode_pt2 %s (0x%p)", msg
->msg_srv
, msg
->msg_mntpt
,
933 msg
->msg_mntpt
, (void *)ep
->re_mi
, msg
->msg_srv
,
934 ep
->re_char1
, (void *)ep
->re_rp1
, ep
->re_char2
,
938 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
939 "Couldn't reclaim lock for pid %d for "
940 "file %s (rnode_pt 0x%p) on (server %s): error %d",
941 msg
->msg_srv
, msg
->msg_mntpt
, ep
->re_pid
, ep
->re_char1
,
942 (void *)ep
->re_rp1
, msg
->msg_srv
,
943 ep
->re_uint
? ep
->re_uint
: ep
->re_stat4
);
945 case RE_FAIL_REMAP_LEN
:
946 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
947 "remap_lookup: server %s returned bad "
948 "fhandle length (%d)", msg
->msg_srv
, msg
->msg_mntpt
,
949 msg
->msg_srv
, ep
->re_uint
);
951 case RE_FAIL_REMAP_OP
:
952 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
953 "remap_lookup: didn't get expected OP_GETFH"
954 " for server %s", msg
->msg_srv
, msg
->msg_mntpt
,
959 zcmn_err(zoneid
, CE_NOTE
,
960 "![NFS4][Server: %s][Mntpt: %s]"
961 "failing over from %s to %s", msg
->msg_srv
,
962 msg
->msg_mntpt
, msg
->msg_srv
, ep
->re_char1
);
964 zcmn_err(zoneid
, CE_NOTE
,
965 "![NFS4][Server: %s][Mntpt: %s]"
966 "NFS4: failing over: selecting "
967 "original server %s", msg
->msg_srv
, msg
->msg_mntpt
,
971 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
972 "File %s (rnode_pt: %p) on server %s was closed "
973 "and failed attempted failover since its is different than "
974 "the original file", msg
->msg_srv
, msg
->msg_mntpt
,
975 ep
->re_char1
, (void *)ep
->re_rp1
, msg
->msg_srv
);
978 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
979 "Lost %s request for fs %s, file %s (rnode_pt: 0x%p), "
980 "dir %s (0x%p) for server %s", msg
->msg_srv
, msg
->msg_mntpt
,
981 nfs4_op_to_str(ep
->re_uint
), msg
->msg_mntpt
,
982 ep
->re_char1
, (void *)ep
->re_rp1
, ep
->re_char2
,
983 (void *)ep
->re_rp2
, msg
->msg_srv
);
985 case RE_OPENS_CHANGED
:
986 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
987 "The number of open files to reopen changed "
988 "for mount %s mi 0x%p (old %d, new %d) on server %s",
989 msg
->msg_srv
, msg
->msg_mntpt
, msg
->msg_mntpt
,
990 (void *)ep
->re_mi
, ep
->re_uint
, ep
->re_pid
, msg
->msg_srv
);
993 case RE_SIGLOST_NO_DUMP
:
995 zcmn_err(zoneid
, CE_NOTE
,
996 "![NFS4][Server: %s][Mntpt: %s]"
997 "Process %d lost its locks on "
998 "file %s (rnode_pt: %p) due to NFS recovery error "
999 "(%d) on server %s.", msg
->msg_srv
, msg
->msg_mntpt
,
1000 ep
->re_pid
, ep
->re_char1
, (void *)ep
->re_rp1
,
1001 ep
->re_uint
, msg
->msg_srv
);
1003 zcmn_err(zoneid
, CE_NOTE
,
1004 "![NFS4][Server: %s][Mntpt: %s]"
1005 "Process %d lost its locks on "
1006 "file %s (rnode_pt: %p) due to NFS recovery error "
1007 "(%s) on server %s.", msg
->msg_srv
, msg
->msg_mntpt
,
1008 ep
->re_pid
, ep
->re_char1
, (void *)ep
->re_rp1
,
1009 nfs4_stat_to_str(ep
->re_stat4
), msg
->msg_srv
);
1012 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1013 "NFS Starting recovery for mount %s "
1014 "(mi 0x%p mi_recovflags [0x%x]) on server %s, "
1015 "rnode_pt1 %s (0x%p), rnode_pt2 %s (0x%p)", msg
->msg_srv
,
1016 msg
->msg_mntpt
, msg
->msg_mntpt
, (void *)ep
->re_mi
,
1017 ep
->re_uint
, msg
->msg_srv
, ep
->re_char1
, (void *)ep
->re_rp1
,
1018 ep
->re_char2
, (void *)ep
->re_rp2
);
1020 case RE_UNEXPECTED_ACTION
:
1021 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1022 "NFS recovery: unexpected action (%s) on server %s",
1023 msg
->msg_srv
, msg
->msg_mntpt
,
1024 nfs4_recov_action_to_str(ep
->re_uint
), msg
->msg_srv
);
1026 case RE_UNEXPECTED_ERRNO
:
1027 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1028 "NFS recovery: unexpected errno (%d) on server %s",
1029 msg
->msg_srv
, msg
->msg_mntpt
, ep
->re_uint
, msg
->msg_srv
);
1031 case RE_UNEXPECTED_STATUS
:
1032 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1033 "NFS recovery: unexpected NFS status code (%s) "
1034 "on server %s", msg
->msg_srv
, msg
->msg_mntpt
,
1035 nfs4_stat_to_str(ep
->re_stat4
),
1039 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1040 "NFS can't recover from NFS4ERR_WRONGSEC."
1041 " error %d for server %s: rnode_pt1 %s (0x%p)"
1042 " rnode_pt2 %s (0x%p)", msg
->msg_srv
, msg
->msg_mntpt
,
1043 ep
->re_uint
, msg
->msg_srv
, ep
->re_char1
, (void *)ep
->re_rp1
,
1044 ep
->re_char2
, (void *)ep
->re_rp2
);
1046 case RE_LOST_STATE_BAD_OP
:
1047 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1048 "NFS lost state with unrecognized op (%d)."
1049 " fs %s, server %s, pid %d, file %s (rnode_pt: 0x%p), "
1050 "dir %s (0x%p)", msg
->msg_srv
, msg
->msg_mntpt
,
1051 ep
->re_uint
, msg
->msg_mntpt
, msg
->msg_srv
, ep
->re_pid
,
1052 ep
->re_char1
, (void *)ep
->re_rp1
, ep
->re_char2
,
1053 (void *)ep
->re_rp2
);
1057 zcmn_err(zoneid
, CE_NOTE
,
1058 "![NFS4][Server: %s][Mntpt: %s]"
1059 "being referred from %s to %s", msg
->msg_srv
,
1060 msg
->msg_mntpt
, msg
->msg_srv
, ep
->re_char1
);
1062 zcmn_err(zoneid
, CE_NOTE
,
1063 "![NFS4][Server: %s][Mntpt: %s]"
1064 "NFS4: being referred from %s to unknown server",
1065 msg
->msg_srv
, msg
->msg_mntpt
, msg
->msg_srv
);
1068 zcmn_err(zoneid
, CE_WARN
,
1069 "!queue_print_event: illegal event %d", ep
->re_type
);
1073 print_facts(msg
, mi
);
1076 * If set this event will not be printed again and is considered
1080 msg
->msg_status
= NFS4_MS_NO_DUMP
;
1084 * Print a fact message to /var/adm/messages
1087 queue_print_fact(nfs4_debug_msg_t
*msg
, int dump
)
1092 fp
= &msg
->rmsg_u
.msg_fact
;
1093 zoneid
= getzoneid();
1095 switch (fp
->rf_type
) {
1097 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1098 "NFSMAPID_DOMAIN does not match the server: %s domain\n"
1099 "Please check configuration", msg
->msg_srv
, msg
->msg_mntpt
,
1104 zcmn_err(zoneid
, CE_NOTE
,
1105 "![NFS4][Server: %s][Mntpt: %s]NFS op %s got "
1106 "error %d causing recovery action %s.%s",
1107 msg
->msg_srv
, msg
->msg_mntpt
,
1108 nfs4_op_to_str(fp
->rf_op
), fp
->rf_error
,
1109 nfs4_recov_action_to_str(fp
->rf_action
),
1111 " Client also suspects that the server rebooted,"
1112 " or experienced a network partition." : "");
1114 zcmn_err(zoneid
, CE_NOTE
,
1115 "![NFS4][Server: %s][Mntpt: %s]NFS op %s got "
1116 "error %s causing recovery action %s.%s",
1117 msg
->msg_srv
, msg
->msg_mntpt
,
1118 nfs4_op_to_str(fp
->rf_op
),
1119 nfs4_stat_to_str(fp
->rf_stat4
),
1120 nfs4_recov_action_to_str(fp
->rf_action
),
1122 " Client also suspects that the server rebooted,"
1123 " or experienced a network partition." : "");
1125 case RF_RENEW_EXPIRED
:
1126 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1127 "NFS4 renew thread detected client's "
1128 "lease has expired. Current open files/locks/IO may fail",
1129 msg
->msg_srv
, msg
->msg_mntpt
);
1131 case RF_SRV_NOT_RESPOND
:
1132 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1133 "NFS server %s not responding; still trying\n",
1134 msg
->msg_srv
, msg
->msg_mntpt
, msg
->msg_srv
);
1137 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1138 "NFS server %s ok", msg
->msg_srv
, msg
->msg_mntpt
,
1141 case RF_SRVS_NOT_RESPOND
:
1142 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1143 "NFS servers %s not responding; still trying", msg
->msg_srv
,
1144 msg
->msg_mntpt
, msg
->msg_srv
);
1147 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1148 "NFS servers %s ok", msg
->msg_srv
, msg
->msg_mntpt
,
1151 case RF_DELMAP_CB_ERR
:
1152 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1153 "NFS op %s got error %s when executing delmap on file %s "
1155 msg
->msg_srv
, msg
->msg_mntpt
, nfs4_op_to_str(fp
->rf_op
),
1156 nfs4_stat_to_str(fp
->rf_stat4
), fp
->rf_char1
,
1157 (void *)fp
->rf_rp1
);
1160 zcmn_err(zoneid
, CE_NOTE
, "![NFS4][Server: %s][Mntpt: %s]"
1161 "send queue to NFS server %s is full; still trying\n",
1162 msg
->msg_srv
, msg
->msg_mntpt
, msg
->msg_srv
);
1166 zcmn_err(zoneid
, CE_WARN
, "!queue_print_fact: illegal fact %d",
1171 * If set this fact will not be printed again and is considered
1175 msg
->msg_status
= NFS4_MS_NO_DUMP
;
1179 * Returns 1 if the entire queue should be dumped, 0 otherwise.
1182 id_to_dump_queue(nfs4_event_type_t id
)
1196 * Returns 1 if the event (but not the entire queue) should be printed;
1200 id_to_dump_solo_event(nfs4_event_type_t id
)
1205 case RE_FAIL_REMAP_LEN
:
1206 case RE_FAIL_REMAP_OP
:
1208 case RE_OPENS_CHANGED
:
1209 case RE_SIGLOST_NO_DUMP
:
1210 case RE_UNEXPECTED_ACTION
:
1211 case RE_UNEXPECTED_ERRNO
:
1212 case RE_UNEXPECTED_STATUS
:
1213 case RE_LOST_STATE_BAD_OP
:
1222 * Returns 1 if the fact (but not the entire queue) should be printed;
1226 id_to_dump_solo_fact(nfs4_fact_type_t id
)
1229 case RF_SRV_NOT_RESPOND
:
1231 case RF_SRVS_NOT_RESPOND
:
1241 * Update a kernel stat
1244 update_recov_kstats(nfs4_debug_msg_t
*msg
, mntinfo4_t
*mi
)
1248 if (!mi
->mi_recov_ksp
)
1251 rsp
= (rkstat_t
*)mi
->mi_recov_ksp
->ks_data
;
1253 if (msg
->msg_type
== RM_EVENT
) {
1254 switch (msg
->rmsg_u
.msg_event
.re_type
) {
1256 rsp
->badhandle
.value
.ul
++;
1259 rsp
->clientid
.value
.ul
++;
1262 rsp
->dead_file
.value
.ul
++;
1264 case RE_FAIL_RELOCK
:
1265 rsp
->fail_relock
.value
.ul
++;
1268 rsp
->file_diff
.value
.ul
++;
1270 case RE_OPENS_CHANGED
:
1271 rsp
->opens_changed
.value
.ul
++;
1274 case RE_SIGLOST_NO_DUMP
:
1275 rsp
->siglost
.value
.ul
++;
1277 case RE_UNEXPECTED_ACTION
:
1278 rsp
->unexp_action
.value
.ul
++;
1280 case RE_UNEXPECTED_ERRNO
:
1281 rsp
->unexp_errno
.value
.ul
++;
1283 case RE_UNEXPECTED_STATUS
:
1284 rsp
->unexp_status
.value
.ul
++;
1287 rsp
->wrongsec
.value
.ul
++;
1289 case RE_LOST_STATE_BAD_OP
:
1290 rsp
->lost_state_bad_op
.value
.ul
++;
1295 } else if (msg
->msg_type
== RM_FACT
) {
1296 switch (msg
->rmsg_u
.msg_fact
.rf_type
) {
1298 rsp
->badowner
.value
.ul
++;
1300 case RF_SRV_NOT_RESPOND
:
1301 rsp
->not_responding
.value
.ul
++;
1310 * Dump the mi's mi_msg_list of recovery messages.
1313 dump_queue(mntinfo4_t
*mi
, nfs4_debug_msg_t
*msg
)
1315 nfs4_debug_msg_t
*tmp_msg
;
1317 ASSERT(mutex_owned(&mi
->mi_msg_list_lock
));
1320 update_recov_kstats(msg
, mi
);
1323 * If we aren't supposed to dump the queue then see if we
1324 * should just print this single message, then return.
1326 if (!id_to_dump_queue(msg
->rmsg_u
.msg_event
.re_type
)) {
1327 if (id_to_dump_solo_event(msg
->rmsg_u
.msg_event
.re_type
))
1328 queue_print_event(msg
, mi
, 0);
1333 * Write all events/facts in the queue that haven't been
1334 * previously written to disk.
1336 tmp_msg
= list_head(&mi
->mi_msg_list
);
1338 if (tmp_msg
->msg_status
== NFS4_MS_DUMP
) {
1339 if (tmp_msg
->msg_type
== RM_EVENT
)
1340 queue_print_event(tmp_msg
, mi
, 1);
1341 else if (tmp_msg
->msg_type
== RM_FACT
)
1342 queue_print_fact(tmp_msg
, 1);
1344 tmp_msg
= list_next(&mi
->mi_msg_list
, tmp_msg
);
1349 * Places the event into mi's debug recovery message queue. Some of the
1350 * fields can be overloaded to be a generic value, depending on the event
1351 * type. These include "count", "why".
1354 nfs4_queue_event(nfs4_event_type_t id
, mntinfo4_t
*mi
, char *server1
,
1355 uint_t count
, vnode_t
*vp1
, vnode_t
*vp2
, nfsstat4 nfs4_error
,
1356 char *why
, pid_t pid
, nfs4_tag_type_t tag1
, nfs4_tag_type_t tag2
,
1357 seqid4 seqid1
, seqid4 seqid2
)
1359 nfs4_debug_msg_t
*msg
;
1362 rnode4_t
*rp1
= NULL
, *rp2
= NULL
;
1372 * Initialize the message with the relevant server/mount_pt/time
1373 * information. Also place the relevent event related info.
1375 msg
= kmem_zalloc(sizeof (*msg
), KM_SLEEP
);
1376 msg
->msg_type
= RM_EVENT
;
1377 msg
->msg_status
= NFS4_MS_DUMP
;
1378 ep
= &msg
->rmsg_u
.msg_event
;
1380 gethrestime(&msg
->msg_time
);
1382 cur_srv
= mi
->mi_curr_serv
->sv_hostname
;
1383 msg
->msg_srv
= strdup(cur_srv
);
1384 mntpt
= vfs_getmntpoint(mi
->mi_vfsp
);
1385 msg
->msg_mntpt
= strdup(refstr_value(mntpt
));
1388 set_event(id
, ep
, mi
, rp1
, rp2
, count
, pid
, nfs4_error
, server1
,
1389 why
, tag1
, tag2
, seqid1
, seqid2
);
1391 mutex_enter(&mi
->mi_msg_list_lock
);
1393 /* if this event is the same as the last event, drop it */
1394 if (events_same(list_tail(&mi
->mi_msg_list
), msg
, mi
)) {
1395 mutex_exit(&mi
->mi_msg_list_lock
);
1400 /* queue the message at the end of the list */
1401 list_insert_tail(&mi
->mi_msg_list
, msg
);
1403 dump_queue(mi
, msg
);
1405 if (mi
->mi_msg_count
== nfs4_msg_max
) {
1406 nfs4_debug_msg_t
*rm_msg
;
1408 /* remove the queue'd message at the front of the list */
1409 rm_msg
= list_head(&mi
->mi_msg_list
);
1410 list_remove(&mi
->mi_msg_list
, rm_msg
);
1411 mutex_exit(&mi
->mi_msg_list_lock
);
1412 nfs4_free_msg(rm_msg
);
1415 mutex_exit(&mi
->mi_msg_list_lock
);
1420 * Places the fact into mi's debug recovery messages queue.
1423 nfs4_queue_fact(nfs4_fact_type_t fid
, mntinfo4_t
*mi
, nfsstat4 stat4
,
1424 nfs4_recov_t raction
, nfs_opnum4 op
, bool_t reboot
, char *srvname
,
1425 int error
, vnode_t
*vp
)
1427 nfs4_debug_msg_t
*msg
;
1433 * Initialize the message with the relevant server/mount_pt/time
1434 * information. Also place the relevant fact related info.
1436 msg
= kmem_zalloc(sizeof (*msg
), KM_SLEEP
);
1437 msg
->msg_type
= RM_FACT
;
1438 msg
->msg_status
= NFS4_MS_DUMP
;
1439 gethrestime(&msg
->msg_time
);
1444 cur_srv
= mi
->mi_curr_serv
->sv_hostname
;
1446 msg
->msg_srv
= strdup(cur_srv
);
1447 mntpt
= vfs_getmntpoint(mi
->mi_vfsp
);
1448 msg
->msg_mntpt
= strdup(refstr_value(mntpt
));
1451 fp
= &msg
->rmsg_u
.msg_fact
;
1453 fp
->rf_status
= RFS_NO_INSPECT
;
1454 set_fact(fid
, fp
, stat4
, raction
, op
, reboot
, error
, vp
);
1456 update_recov_kstats(msg
, mi
);
1458 mutex_enter(&mi
->mi_msg_list_lock
);
1460 /* if this fact is the same as the last fact, drop it */
1461 if (facts_same(list_tail(&mi
->mi_msg_list
), msg
, mi
)) {
1462 mutex_exit(&mi
->mi_msg_list_lock
);
1467 /* queue the message at the end of the list */
1468 list_insert_tail(&mi
->mi_msg_list
, msg
);
1470 if (id_to_dump_solo_fact(msg
->rmsg_u
.msg_fact
.rf_type
))
1471 queue_print_fact(msg
, 0);
1473 if (mi
->mi_msg_count
== nfs4_msg_max
) {
1474 nfs4_debug_msg_t
*rm_msg
;
1476 /* remove the queue'd message at the front of the list */
1477 rm_msg
= list_head(&mi
->mi_msg_list
);
1478 list_remove(&mi
->mi_msg_list
, rm_msg
);
1479 mutex_exit(&mi
->mi_msg_list_lock
);
1480 nfs4_free_msg(rm_msg
);
1483 mutex_exit(&mi
->mi_msg_list_lock
);
1488 * Initialize the 'mi_recov_kstat' kstat.
1491 nfs4_mnt_recov_kstat_init(vfs_t
*vfsp
)
1493 mntinfo4_t
*mi
= VFTOMI4(vfsp
);
1495 zoneid_t zoneid
= mi
->mi_zone
->zone_id
;
1498 * Create the version specific kstats.
1500 * PSARC 2001/697 Contract Private Interface
1501 * All nfs kstats are under SunMC contract
1502 * Please refer to the PSARC listed above and contact
1503 * SunMC before making any changes!
1505 * Changes must be reviewed by Solaris File Sharing
1506 * Changes must be communicated to contract-2001-697@sun.com
1510 if ((ksp
= kstat_create_zone("nfs", getminor(vfsp
->vfs_dev
),
1511 "mi_recov_kstat", "misc", KSTAT_TYPE_NAMED
,
1512 sizeof (rkstat_t
) / sizeof (kstat_named_t
),
1513 KSTAT_FLAG_WRITABLE
, zoneid
)) == NULL
) {
1514 mi
->mi_recov_ksp
= NULL
;
1515 zcmn_err(GLOBAL_ZONEID
, CE_NOTE
,
1516 "!mi_recov_kstat for mi %p failed\n",
1520 if (zoneid
!= GLOBAL_ZONEID
)
1521 kstat_zone_add(ksp
, GLOBAL_ZONEID
);
1522 mi
->mi_recov_ksp
= ksp
;
1523 bcopy(&rkstat_template
, ksp
->ks_data
, sizeof (rkstat_t
));
1528 * Increment the "delay" kstat.
1531 nfs4_mi_kstat_inc_delay(mntinfo4_t
*mi
)
1535 if (!mi
->mi_recov_ksp
)
1538 rsp
= (rkstat_t
*)mi
->mi_recov_ksp
->ks_data
;
1539 rsp
->delay
.value
.ul
++;
1543 * Increment the "no_grace" kstat.
1546 nfs4_mi_kstat_inc_no_grace(mntinfo4_t
*mi
)
1550 if (!mi
->mi_recov_ksp
)
1553 rsp
= (rkstat_t
*)mi
->mi_recov_ksp
->ks_data
;
1554 rsp
->no_grace
.value
.ul
++;