Print this page
NEX-3705 Need to update libses with LID/USN code from sesctld
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/scsi/libses/common/ses_node.c
+++ new/usr/src/lib/scsi/libses/common/ses_node.c
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
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
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 /*
23 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 25 */
25 26
26 27 #include <scsi/libses.h>
27 28 #include "ses_impl.h"
28 29
29 30 #define NEXT_ED(eip) \
30 - ((ses2_ed_impl_t *)((uint8_t *)(eip) + \
31 + ((ses2_ed_impl_t *)((uint8_t *)(eip) + \
31 32 ((eip)->st_hdr.sehi_ed_len + sizeof (ses2_ed_hdr_impl_t))))
32 33
33 34 static ses_node_t *
34 35 ses_find_enclosure(ses_snap_t *sp, uint64_t number)
35 36 {
36 37 ses_node_t *np;
37 38
38 39 for (np = sp->ss_root->sn_first_child; np != NULL;
39 40 np = np->sn_next_sibling) {
40 41 ASSERT(np->sn_type == SES_NODE_ENCLOSURE);
41 42 if (np->sn_enc_num == number)
42 43 return ((ses_node_t *)np);
43 44 }
44 45
45 46 return (NULL);
46 47 }
47 48
48 49 /*
49 50 * ses_snap_primary_enclosure() finds the primary enclosure for
50 51 * the supplied ses_snap_t.
51 52 */
52 53 ses_node_t *
53 54 ses_snap_primary_enclosure(ses_snap_t *sp)
54 55 {
55 56 return (ses_find_enclosure(sp, 0));
56 57 }
57 58
58 59 void
59 60 ses_node_teardown(ses_node_t *np)
60 61 {
61 62 ses_node_t *rp;
62 63
63 64 if (np == NULL)
64 65 return;
65 66
66 67 for (; np != NULL; np = rp) {
67 68 ses_node_teardown(np->sn_first_child);
68 69 rp = np->sn_next_sibling;
69 70 nvlist_free(np->sn_props);
70 71 ses_free(np);
71 72 }
72 73 }
73 74
74 75 static ses_node_t *
75 76 ses_node_alloc(ses_snap_t *sp, ses_node_t *pnp)
76 77 {
77 78 ses_node_t *np;
78 79
79 80 np = ses_zalloc(sizeof (ses_node_t));
80 81 if (np == NULL)
81 82 goto fail;
82 83 if (nvlist_alloc(&np->sn_props, NV_UNIQUE_NAME, 0) != 0)
83 84 goto fail;
84 85
85 86 np->sn_snapshot = sp;
86 87 np->sn_id = sp->ss_n_nodes++;
87 88
88 89 if (pnp == NULL) {
89 90 ASSERT(sp->ss_root == NULL);
90 91 sp->ss_root = np;
91 92 } else {
92 93 np->sn_parent = pnp;
93 94 np->sn_prev_sibling = pnp->sn_last_child;
94 95
95 96 if (pnp->sn_first_child == NULL)
96 97 pnp->sn_first_child = np;
97 98 else
98 99 pnp->sn_last_child->sn_next_sibling = np;
99 100
100 101 pnp->sn_last_child = np;
101 102 }
102 103
103 104 return (np);
104 105
105 106 fail:
106 107 ses_free(np);
107 108 ses_node_teardown(sp->ss_root);
108 109 sp->ss_root = NULL;
109 110 return (NULL);
110 111 }
111 112
112 113 /*
113 114 * Parse element type descriptor.
114 115 */
115 116 static int
116 117 elem_parse_td(ses2_td_hdr_impl_t *tip, const char *tp, nvlist_t *nvl)
117 118 {
118 119 int nverr;
119 120
120 121 if (tp != NULL)
121 122 SES_NV_ADD(fixed_string, nverr, nvl, SES_PROP_CLASS_DESCRIPTION,
122 123 tp, tip->sthi_text_len);
123 124
124 125 return (0);
125 126 }
126 127
127 128
128 129 /*
129 130 * Build a skeleton tree of nodes in the given snapshot. This is the heart of
130 131 * libses, and is responsible for parsing the config page into a tree and
131 132 * populating nodes with data from the config page.
132 133 */
133 134 static int
134 135 ses_build_snap_skel(ses_snap_t *sp)
135 136 {
136 137 ses2_ed_impl_t *eip;
137 138 ses2_td_hdr_impl_t *tip, *ftip;
138 139 ses_node_t *np, *pnp, *cnp, *root;
139 140 ses_snap_page_t *pp;
140 141 ses2_config_page_impl_t *pip;
141 142 int i, j, n_etds = 0;
142 143 off_t toff;
143 144 char *tp, *text;
144 145 int err;
145 146 uint64_t idx, eidx;
146 147
147 148 pp = ses_snap_find_page(sp, SES2_DIAGPAGE_CONFIG, B_FALSE);
148 149 if (pp == NULL)
149 150 return (ses_error(ESES_BAD_RESPONSE, "target does not support "
150 151 "configuration diagnostic page"));
151 152 pip = (ses2_config_page_impl_t *)pp->ssp_page;
152 153
153 154 if (pp->ssp_len < offsetof(ses2_config_page_impl_t, scpi_data))
154 155 return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
155 156 "descriptors found"));
156 157
157 158 /*
158 159 * Start with the root of the tree, which is a target node, containing
159 160 * just the SCSI inquiry properties.
160 161 */
|
↓ open down ↓ |
120 lines elided |
↑ open up ↑ |
161 162 if ((root = ses_node_alloc(sp, sp->ss_root)) == NULL)
162 163 return (-1);
163 164
164 165 root->sn_type = SES_NODE_TARGET;
165 166 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_VENDOR,
166 167 libscsi_vendor(sp->ss_target->st_target));
167 168 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_PRODUCT,
168 169 libscsi_product(sp->ss_target->st_target));
169 170 SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_REVISION,
170 171 libscsi_revision(sp->ss_target->st_target));
172 + if (libscsi_usn(sp->ss_target->st_target) != NULL)
173 + SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_USN,
174 + libscsi_usn(sp->ss_target->st_target));
175 + if (libscsi_lid(sp->ss_target->st_target) != NULL)
176 + SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_LID,
177 + libscsi_lid(sp->ss_target->st_target));
171 178
172 179 for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
173 180 i < pip->scpi_n_subenclosures + 1;
174 181 i++, eip = NEXT_ED(eip)) {
175 182 if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
176 183 break;
177 184
178 185 n_etds += eip->st_hdr.sehi_n_etd_hdrs;
179 186 }
180 187 ftip = (ses2_td_hdr_impl_t *)eip;
181 188
182 189 /*
183 190 * There should really be only one Enclosure element possible for a
184 191 * give subenclosure ID. The standard never comes out and says this,
185 192 * but it does describe this element as "managing the enclosure itself"
186 193 * which implies rather strongly that the subenclosure ID field is that
187 194 * of, well, the enclosure itself. Since an enclosure can't contain
188 195 * itself, it follows logically that each subenclosure has at most one
189 196 * Enclosure type descriptor elements matching its ID. Of course, some
190 197 * enclosure firmware is buggy, so this may not always work out; in
191 198 * this case we just ignore all but the first Enclosure-type element
192 199 * with our subenclosure ID.
193 200 */
194 201 for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
195 202 i < pip->scpi_n_subenclosures + 1;
196 203 i++, eip = NEXT_ED(eip)) {
197 204 if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
198 205 break;
199 206
200 207 if ((np = ses_node_alloc(sp, root)) == NULL)
201 208 return (-1);
202 209
|
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
203 210 np->sn_type = SES_NODE_ENCLOSURE;
204 211 np->sn_enc_num = eip->st_hdr.sehi_subenclosure_id;
205 212
206 213 if (!SES_WITHIN_PAGE(eip, eip->st_hdr.sehi_ed_len +
207 214 sizeof (ses2_ed_hdr_impl_t),
208 215 pp->ssp_page, pp->ssp_len))
209 216 break;
210 217
211 218 if (enc_parse_ed(eip, np->sn_props) != 0)
212 219 return (-1);
220 +
221 + if (libscsi_usn(sp->ss_target->st_target) != NULL)
222 + SES_NV_ADD(string, err, np->sn_props, SCSI_PROP_USN,
223 + libscsi_usn(sp->ss_target->st_target));
224 +
225 + if (libscsi_lid(sp->ss_target->st_target) != NULL)
226 + SES_NV_ADD(string, err, np->sn_props, SCSI_PROP_LID,
227 + libscsi_lid(sp->ss_target->st_target));
213 228 }
214 229
215 230 if (root->sn_first_child == NULL)
216 231 return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
217 232 "descriptors found"));
218 233
219 234 tp = (char *)(ftip + n_etds);
220 235
221 236 for (i = 0, toff = 0, idx = eidx = 0; i < n_etds; i++) {
222 237 tip = ftip + i;
223 238
224 239 if (!SES_WITHIN_PAGE_STRUCT(tip, pp->ssp_page, pp->ssp_len))
225 240 break;
226 241
227 242 pnp = ses_find_enclosure(sp,
228 243 tip->sthi_subenclosure_id);
229 244 if (pnp == NULL) {
230 245 idx += tip->sthi_max_elements + 1;
231 246 eidx += tip->sthi_max_elements;
232 247 toff += tip->sthi_text_len;
233 248 continue;
234 249 }
235 250
236 251 if (tip->sthi_element_type == SES_ET_ENCLOSURE) {
237 252 if (tip->sthi_max_elements == 0) {
238 253 SES_NV_ADD(uint64, err, pnp->sn_props,
239 254 SES_PROP_ELEMENT_INDEX, idx);
240 255 pnp->sn_rootidx = idx;
241 256 } else {
242 257 SES_NV_ADD(uint64, err, pnp->sn_props,
243 258 SES_PROP_ELEMENT_INDEX, idx + 1);
244 259 SES_NV_ADD(uint64, err, pnp->sn_props,
245 260 SES_PROP_ELEMENT_ONLY_INDEX, eidx);
246 261 pnp->sn_rootidx = idx + 1;
247 262 }
248 263
249 264 if (tip->sthi_text_len > 0 &&
250 265 SES_WITHIN_PAGE(tp + toff, tip->sthi_text_len,
251 266 pp->ssp_page, pp->ssp_len)) {
252 267 text = tp + toff;
253 268 toff += tip->sthi_text_len;
254 269 } else {
255 270 text = NULL;
256 271 }
257 272
258 273 SES_NV_ADD(uint64, err, pnp->sn_props,
259 274 SES_PROP_ELEMENT_TYPE, SES_ET_ENCLOSURE);
260 275 if (enc_parse_td(tip, text, pnp->sn_props) != 0)
261 276 return (-1);
262 277
263 278 idx += tip->sthi_max_elements + 1;
264 279 eidx += tip->sthi_max_elements;
265 280 continue;
266 281 }
267 282
268 283 if ((np = ses_node_alloc(sp, pnp)) == NULL)
269 284 return (-1);
270 285
271 286 np->sn_type = SES_NODE_AGGREGATE;
272 287 np->sn_enc_num = tip->sthi_subenclosure_id;
273 288 np->sn_parent = pnp;
274 289 np->sn_rootidx = idx;
275 290
276 291 SES_NV_ADD(uint64, err, np->sn_props,
277 292 SES_PROP_ELEMENT_INDEX, idx);
278 293 SES_NV_ADD(uint64, err, np->sn_props,
279 294 SES_PROP_ELEMENT_TYPE, tip->sthi_element_type);
280 295
281 296 if (tip->sthi_text_len > 0 &&
282 297 SES_WITHIN_PAGE(tp + toff, tip->sthi_text_len,
283 298 pp->ssp_page, pp->ssp_len)) {
284 299 text = tp + toff;
285 300 toff += tip->sthi_text_len;
286 301 } else {
287 302 text = NULL;
288 303 }
289 304
290 305 if (elem_parse_td(tip, text, np->sn_props) != 0)
291 306 return (-1);
292 307
293 308 idx += tip->sthi_max_elements + 1;
294 309
295 310 if (tip->sthi_max_elements == 0)
296 311 continue;
297 312
298 313 for (j = 0; j < tip->sthi_max_elements; j++) {
299 314 cnp = ses_node_alloc(sp, np);
300 315 if (cnp == NULL)
301 316 return (-1);
302 317
303 318 cnp->sn_type = SES_NODE_ELEMENT;
304 319 SES_NV_ADD(uint64, err, cnp->sn_props,
305 320 SES_PROP_ELEMENT_INDEX, np->sn_rootidx + j + 1);
306 321 SES_NV_ADD(uint64, err, cnp->sn_props,
307 322 SES_PROP_ELEMENT_ONLY_INDEX, eidx + j);
308 323 SES_NV_ADD(uint64, err, cnp->sn_props,
309 324 SES_PROP_ELEMENT_CLASS_INDEX, j);
310 325 SES_NV_ADD(uint64, err, cnp->sn_props,
311 326 SES_PROP_ELEMENT_TYPE, tip->sthi_element_type);
312 327 }
313 328
314 329 eidx += tip->sthi_max_elements;
315 330 }
316 331
317 332 np->sn_snapshot->ss_n_elem = idx;
318 333
319 334 return (0);
320 335 }
321 336
322 337 static int
323 338 ses_fill_tree(ses_node_t *np)
324 339 {
325 340 if (np == NULL)
326 341 return (0);
327 342
328 343 for (; np != NULL; np = np->sn_next_sibling) {
329 344 if (ses_fill_node(np) != 0)
330 345 return (-1);
331 346 if (ses_fill_tree(np->sn_first_child) != 0)
332 347 return (-1);
333 348 }
334 349
335 350 return (0);
336 351 }
337 352
338 353 int
339 354 ses_fill_snap(ses_snap_t *sp)
340 355 {
341 356 if (ses_build_snap_skel(sp) != 0)
342 357 return (-1);
343 358
344 359 if (ses_fill_tree(sp->ss_root) != 0)
345 360 return (-1);
346 361
347 362 return (0);
348 363 }
349 364
350 365 ses_node_t *
351 366 ses_root_node(ses_snap_t *sp)
352 367 {
353 368 return (sp->ss_root);
354 369 }
355 370
356 371 ses_node_t *
357 372 ses_node_sibling(ses_node_t *np)
358 373 {
359 374 return (np->sn_next_sibling);
360 375 }
361 376
362 377 ses_node_t *
363 378 ses_node_prev_sibling(ses_node_t *np)
364 379 {
365 380 return (np->sn_prev_sibling);
366 381 }
367 382
368 383 ses_node_t *
369 384 ses_node_parent(ses_node_t *np)
370 385 {
371 386 return (np->sn_parent);
372 387 }
373 388
374 389 ses_node_t *
375 390 ses_node_child(ses_node_t *np)
376 391 {
377 392 return (np->sn_first_child);
378 393 }
379 394
380 395 ses_node_type_t
381 396 ses_node_type(ses_node_t *np)
382 397 {
383 398 return (np->sn_type);
384 399 }
385 400
386 401 ses_snap_t *
387 402 ses_node_snapshot(ses_node_t *np)
388 403 {
389 404 return ((ses_snap_t *)np->sn_snapshot);
390 405 }
391 406
392 407 ses_target_t *
393 408 ses_node_target(ses_node_t *np)
394 409 {
395 410 return (np->sn_snapshot->ss_target);
396 411 }
397 412
398 413 nvlist_t *
399 414 ses_node_props(ses_node_t *np)
400 415 {
401 416 return (np->sn_props);
402 417 }
403 418
404 419 /*
405 420 * A node identifier is a (generation, index) tuple that can be used to lookup a
406 421 * node within this target at a later point. This will be valid across
407 422 * snapshots, though it will return failure if the generation count has changed.
408 423 */
409 424 uint64_t
410 425 ses_node_id(ses_node_t *np)
411 426 {
412 427 return (((uint64_t)np->sn_snapshot->ss_generation << 32) |
413 428 np->sn_id);
414 429 }
|
↓ open down ↓ |
192 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX