Print this page
NEX-4592 race condition allows FC initiator LUN offline hotplug handler deadlocks with FMA faulting leaf vdev between LDI and ZFS
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/sys/sunldi_impl.h
+++ new/usr/src/uts/common/sys/sunldi_impl.h
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25 /*
26 26 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
27 27 */
28 28
29 29 #ifndef _SYS_SUNLDI_IMPL_H
30 30 #define _SYS_SUNLDI_IMPL_H
31 31
32 32 #ifdef __cplusplus
33 33 extern "C" {
34 34 #endif
35 35
36 36 #include <sys/dditypes.h>
37 37 #include <sys/vnode.h>
38 38
39 39 /*
40 40 * NOTE
41 41 *
42 42 * The contents of this file are private to this implementation
43 43 * of Solaris and are subject to change at any time without notice.
44 44 *
45 45 * Applications and drivers using these interfaces will fail
46 46 * to run on future releases.
47 47 */
48 48
49 49 /*
50 50 * LDI hash definitions
51 51 */
52 52 #define LH_HASH_SZ 32
53 53 #define LI_HASH_SZ 32
54 54
|
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
55 55 /*
56 56 * Obsolete LDI event interfaces are available for now but are deprecated and a
57 57 * warning will be issued to consumers.
58 58 */
59 59 #define LDI_OBSOLETE_EVENT 1
60 60
61 61 /*
62 62 * Flag for LDI handle's lh_flags field
63 63 */
64 64 #define LH_FLAGS_NOTIFY 0x0001 /* invoked in context of a notify */
65 +#define LH_FLAGS_NOTIFY_NOTIFY 0x0002 /* processed once in notify loop */
66 +#define LH_FLAGS_NOTIFY_FINALIZE 0x0004 /* processed once in finalize loop */
65 67
66 68 /*
67 69 * LDI initialization function
68 70 */
69 71 void ldi_init(void);
70 72
71 73 /*
72 74 * LDI streams linking interfaces
73 75 */
74 76 extern int ldi_mlink_lh(vnode_t *, int, intptr_t, cred_t *, int *);
75 77 extern void ldi_mlink_fp(struct stdata *, struct file *, int, int);
76 78 extern void ldi_munlink_fp(struct stdata *, struct file *, int);
77 79
78 80 /*
79 81 * LDI module identifier
80 82 */
81 83 struct ldi_ident {
82 84 /* protected by ldi_ident_hash_lock */
83 85 struct ldi_ident *li_next;
84 86 uint_t li_ref;
85 87
86 88 /* unique/static fields in the ident */
87 89 char li_modname[MODMAXNAMELEN];
88 90 modid_t li_modid;
89 91 major_t li_major;
90 92 dev_info_t *li_dip;
91 93 dev_t li_dev;
92 94 };
93 95
94 96 /*
95 97 * LDI handle
96 98 */
97 99 struct ldi_handle {
98 100 /* protected by ldi_handle_hash_lock */
99 101 struct ldi_handle *lh_next;
100 102 uint_t lh_ref;
101 103 uint_t lh_flags;
102 104
103 105 /* unique/static fields in the handle */
104 106 uint_t lh_type;
105 107 struct ldi_ident *lh_ident;
106 108 vnode_t *lh_vp;
107 109
108 110 #ifdef LDI_OBSOLETE_EVENT
109 111 /* fields protected by lh_lock */
110 112 kmutex_t lh_lock[1];
111 113 struct ldi_event *lh_events;
112 114 #endif
113 115 };
114 116
115 117 /*
116 118 * LDI event information
117 119 */
118 120 #ifdef LDI_OBSOLETE_EVENT
119 121 typedef struct ldi_event {
120 122 /* fields protected by le_lhp->lh_lock */
121 123 struct ldi_event *le_next;
122 124 struct ldi_event *le_prev;
123 125
124 126 /* unique/static fields in the handle */
125 127 struct ldi_handle *le_lhp;
126 128 void (*le_handler)();
127 129 void *le_arg;
128 130 ddi_callback_id_t le_id;
129 131 } ldi_event_t;
130 132 #endif
131 133
132 134 typedef struct ldi_ev_callback_impl {
133 135 struct ldi_handle *lec_lhp;
134 136 dev_info_t *lec_dip;
135 137 dev_t lec_dev;
136 138 int lec_spec;
137 139 int (*lec_notify)();
138 140 void (*lec_finalize)();
139 141 void *lec_arg;
140 142 void *lec_cookie;
141 143 void *lec_id;
142 144 list_node_t lec_list;
143 145 } ldi_ev_callback_impl_t;
144 146
145 147 /*
146 148 * Members of "struct ldi_ev_callback_list" are protected by their le_lock
147 149 * member. The struct is currently only used once, as a file-level global,
148 150 * and the locking protocol is currently implemented in ldi_ev_lock() and
149 151 * ldi_ev_unlock().
150 152 *
151 153 * When delivering events to subscribers, ldi_invoke_notify() and
152 154 * ldi_invoke_finalize() will walk the list of callbacks: le_head. It is
153 155 * possible that an invoked callback function will need to unregister an
154 156 * arbitrary number of callbacks from this list.
155 157 *
156 158 * To enable ldi_ev_remove_callbacks() to remove elements from the list
157 159 * without breaking the walk-in-progress, we store the next element in the
158 160 * walk direction on the struct as le_walker_next and le_walker_prev.
159 161 */
160 162 struct ldi_ev_callback_list {
161 163 kmutex_t le_lock;
162 164 kcondvar_t le_cv;
163 165 int le_busy;
164 166 void *le_thread;
165 167 list_t le_head;
166 168 ldi_ev_callback_impl_t *le_walker_next;
167 169 ldi_ev_callback_impl_t *le_walker_prev;
168 170 };
169 171
170 172 int ldi_invoke_notify(dev_info_t *dip, dev_t dev, int spec_type, char *event,
171 173 void *ev_data);
172 174 void ldi_invoke_finalize(dev_info_t *dip, dev_t dev, int spec_type, char *event,
173 175 int ldi_result, void *ev_data);
174 176 int e_ddi_offline_notify(dev_info_t *dip);
175 177 void e_ddi_offline_finalize(dev_info_t *dip, int result);
176 178
177 179
178 180 /*
179 181 * LDI device usage interfaces
180 182 *
181 183 * ldi_usage_count(), ldi_usage_walker(), and ldi_usage_t
182 184 *
183 185 * These functions are used by the devinfo driver and fuser to get a
184 186 * device usage information from the LDI. These functions along with
185 187 * the ldi_usage_t data structure allow these other subsystems to have
186 188 * no knowledge of how the LDI stores it's internal state.
187 189 *
188 190 * ldi_usage_count() provides an count of how many kernel
189 191 * device clients currently exist.
190 192 *
191 193 * ldi_usage_walker() reports all kernel device usage information.
192 194 */
193 195 #define LDI_USAGE_CONTINUE 0
194 196 #define LDI_USAGE_TERMINATE 1
195 197
196 198 typedef struct ldi_usage {
197 199 /*
198 200 * information about the kernel subsystem that is accessing
199 201 * the target device
200 202 */
201 203 modid_t src_modid;
202 204 char *src_name;
203 205 dev_info_t *src_dip;
204 206 dev_t src_devt;
205 207
206 208 /*
207 209 * information about the target device that is open
208 210 */
209 211 modid_t tgt_modid;
210 212 char *tgt_name;
211 213 dev_info_t *tgt_dip;
212 214 dev_t tgt_devt;
213 215 int tgt_spec_type;
214 216 } ldi_usage_t;
215 217
216 218 int ldi_usage_count();
217 219 void ldi_usage_walker(void *arg,
218 220 int (*callback)(const ldi_usage_t *ldi_usage, void *arg));
219 221
220 222 #ifdef __cplusplus
221 223 }
222 224 #endif
223 225
224 226 #endif /* _SYS_SUNLDI_IMPL_H */
|
↓ open down ↓ |
150 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX