xref: /illumos-gate/usr/src/uts/common/io/overlay/overlay_fm.c (revision 36589d6bb0cdae89e166b57b0d64ae56d53247d9)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2016 Joyent, Inc.
14  */
15 
16 /*
17  * Overlay device FMA operations.
18  *
19  * For more information, see the big theory statement in
20  * uts/common/io/overlay/overlay.c
21  */
22 
23 #include <sys/ddifm.h>
24 #include <sys/overlay_impl.h>
25 
26 kmutex_t overlay_fm_lock;
27 uint_t overlay_fm_count;
28 
29 void
overlay_fm_init(void)30 overlay_fm_init(void)
31 {
32 	overlay_fm_count = 0;
33 	mutex_init(&overlay_fm_lock, NULL, MUTEX_DRIVER, NULL);
34 }
35 
36 void
overlay_fm_fini(void)37 overlay_fm_fini(void)
38 {
39 	VERIFY(overlay_fm_count == 0);
40 	mutex_destroy(&overlay_fm_lock);
41 }
42 
43 void
overlay_fm_degrade(overlay_dev_t * odd,const char * msg)44 overlay_fm_degrade(overlay_dev_t *odd, const char *msg)
45 {
46 	mutex_enter(&overlay_fm_lock);
47 	mutex_enter(&odd->odd_lock);
48 
49 	if (msg != NULL)
50 		(void) strlcpy(odd->odd_fmamsg, msg, OVERLAY_STATUS_BUFLEN);
51 
52 	if (odd->odd_flags & OVERLAY_F_DEGRADED)
53 		goto out;
54 
55 	odd->odd_flags |= OVERLAY_F_DEGRADED;
56 	overlay_fm_count++;
57 	if (overlay_fm_count == 1) {
58 		ddi_fm_service_impact(overlay_dip, DDI_SERVICE_DEGRADED);
59 	}
60 out:
61 	mutex_exit(&odd->odd_lock);
62 	mutex_exit(&overlay_fm_lock);
63 }
64 
65 void
overlay_fm_restore(overlay_dev_t * odd)66 overlay_fm_restore(overlay_dev_t *odd)
67 {
68 	mutex_enter(&overlay_fm_lock);
69 	mutex_enter(&odd->odd_lock);
70 	if (!(odd->odd_flags & OVERLAY_F_DEGRADED))
71 		goto out;
72 
73 	odd->odd_fmamsg[0] = '\0';
74 	odd->odd_flags &= ~OVERLAY_F_DEGRADED;
75 	overlay_fm_count--;
76 	if (overlay_fm_count == 0) {
77 		ddi_fm_service_impact(overlay_dip, DDI_SERVICE_RESTORED);
78 	}
79 out:
80 	mutex_exit(&odd->odd_lock);
81 	mutex_exit(&overlay_fm_lock);
82 }
83