Print this page
3217 cfgadm should spell "adaptors" correctly
Reviewed by: Alexander Eremin <alexander.r.eremin@gmail.com>
Reviewed by: David Hoeppner <0xffea@gmail.com>
Reviewed by: Gary Mills <gary_mills@fastmail.fm>
Reviewed by: Eric Schrock <Eric.Schrock@delphix.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/cfgadm_plugins/fp/common/cfga_utils.c
+++ new/usr/src/lib/cfgadm_plugins/fp/common/cfga_utils.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
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 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 #include "cfga_fp.h"
28 28
29 29 /*
30 30 * This file contains helper routines for the FP plugin
31 31 */
32 32
33 33 #if !defined(TEXT_DOMAIN)
34 34 #define TEXT_DOMAIN "SYS_TEST"
35 35 #endif
36 36
37 37 typedef struct strlist {
38 38 const char *str;
39 39 struct strlist *next;
40 40 } strlist_t;
41 41
42 42 typedef struct {
43 43 fpcfga_ret_t fp_err;
44 44 cfga_err_t cfga_err;
45 45 } errcvt_t;
46 46
47 47 typedef struct {
48 48 fpcfga_cmd_t cmd;
49 49 int type;
50 50 int (*fcn)(const devctl_hdl_t);
51 51 } set_state_cmd_t;
52 52
53 53 typedef struct {
54 54 fpcfga_cmd_t cmd;
55 55 int type;
56 56 int (*state_fcn)(const devctl_hdl_t, uint_t *);
57 57 } get_state_cmd_t;
58 58
59 59 /* defines for nftw() */
60 60 #define NFTW_DEPTH 1
61 61 #define NFTW_CONTINUE 0
62 62 #define NFTW_TERMINATE 1
63 63 #define NFTW_ERROR -1
64 64 #define MAX_RETRIES 10
65 65
66 66 /* Function prototypes */
67 67 static int do_recurse_dev(const char *path, const struct stat *sbuf,
68 68 int type, struct FTW *ftwp);
69 69 static fpcfga_recur_t lookup_dev(const char *lpath, void *arg);
70 70 static void msg_common(char **err_msgpp, int append_newline, int l_errno,
71 71 va_list ap);
72 72 static void lunlist_free(struct luninfo_list *lunlist);
73 73
74 74 /* Globals */
75 75 struct {
76 76 mutex_t mp;
77 77 void *arg;
78 78 fpcfga_recur_t (*fcn)(const char *lpath, void *arg);
79 79 } nftw_arg = {DEFAULTMUTEX};
80 80
81 81 /*
82 82 * The string table contains most of the strings used by the fp cfgadm plugin.
83 83 * All strings which are to be internationalized must be in this table.
84 84 * Some strings which are not internationalized are also included here.
85 85 * Arguments to messages are NOT internationalized.
86 86 */
87 87 msgcvt_t str_tbl[] = {
88 88
89 89 /*
90 90 * The first element (ERR_UNKNOWN) MUST always be present in the array.
91 91 */
92 92 #define UNKNOWN_ERR_IDX 0 /* Keep the index in sync */
93 93
94 94
95 95 /* msg_code num_args, I18N msg_string */
96 96
97 97 /* ERRORS */
98 98 {ERR_UNKNOWN, 0, 1, "unknown error"},
99 99 {ERR_OP_FAILED, 0, 1, "operation failed"},
100 100 {ERR_CMD_INVAL, 0, 1, "invalid command"},
101 101 {ERR_NOT_BUSAPID, 0, 1, "not a FP bus apid"},
102 102 {ERR_APID_INVAL, 0, 1, "invalid FP ap_id"},
103 103 {ERR_NOT_BUSOP, 0, 1, "operation not supported for FC bus"},
104 104 {ERR_NOT_DEVOP, 0, 1, "operation not supported for FC device"},
105 105 {ERR_UNAVAILABLE, 0, 1, "unavailable"},
106 106 {ERR_CTRLR_CRIT, 0, 1, "critical partition controlled by FC HBA"},
107 107 {ERR_BUS_GETSTATE, 0, 1, "failed to get state for FC bus"},
108 108 {ERR_BUS_NOTCONNECTED, 0, 1, "FC bus not connected"},
109 109 {ERR_BUS_CONNECTED, 0, 1, "FC bus not disconnected"},
110 110 {ERR_BUS_QUIESCE, 0, 1, "FC bus quiesce failed"},
111 111 {ERR_BUS_UNQUIESCE, 0, 1, "FC bus unquiesce failed"},
112 112 {ERR_BUS_CONFIGURE, 0, 1, "failed to configure devices on FC bus"},
113 113 {ERR_BUS_UNCONFIGURE, 0, 1, "failed to unconfigure FC bus"},
114 114 {ERR_DEV_CONFIGURE, 0, 1, "failed to configure FC device"},
115 115 {ERR_DEV_UNCONFIGURE, 0, 1, "failed to unconfigure FC device"},
116 116 {ERR_FCA_CONFIGURE, 0, 1, "failed to configure ANY device on FCA port"},
117 117 {ERR_FCA_UNCONFIGURE, 0, 1, "failed to unconfigure ANY device on FCA port"},
118 118 {ERR_DEV_REPLACE, 0, 1, "replace operation failed"},
119 119 {ERR_DEV_INSERT, 0, 1, "insert operation failed"},
120 120 {ERR_DEV_GETSTATE, 0, 1, "failed to get state for FC device"},
121 121 {ERR_RESET, 0, 1, "reset failed"},
122 122 {ERR_LIST, 0, 1, "list operation failed"},
123 123 {ERR_SIG_STATE, 0, 1, "could not restore signal disposition"},
124 124 {ERR_MAYBE_BUSY, 0, 1, "device may be busy"},
125 125 {ERR_BUS_DEV_MISMATCH, 0, 1, "mismatched FC bus and device"},
126 126 {ERR_MEM_ALLOC, 0, 1, "Failed to allocated memory"},
127 127 {ERR_DEVCTL_OFFLINE, 0, 1, "failed to offline device"},
128 128 {ERR_UPD_REP, 0, 1, "Repository update failed"},
129 129 {ERR_CONF_OK_UPD_REP, 0, 1,
↓ open down ↓ |
129 lines elided |
↑ open up ↑ |
130 130 "Configuration successful, but Repository update failed"},
131 131 {ERR_UNCONF_OK_UPD_REP, 0, 1,
132 132 "Unconfiguration successful, but Repository update failed"},
133 133 {ERR_PARTIAL_SUCCESS, 0, 1,
134 134 "Operation partially successful. Some failures seen"},
135 135 {ERR_HBA_LOAD_LIBRARY, 0, 1,
136 136 "HBA load library failed"},
137 137 {ERR_MATCHING_HBA_PORT, 0, 1,
138 138 "No match HBA port found"},
139 139 {ERR_NO_ADAPTER_FOUND, 0, 1,
140 - "No Fibre Channel adpaters found"},
140 + "No Fibre Channel adapters found"},
141 141
142 142 /* Errors with arguments */
143 143 {ERRARG_OPT_INVAL, 1, 1, "invalid option: "},
144 144 {ERRARG_HWCMD_INVAL, 1, 1, "invalid command: "},
145 145 {ERRARG_DEVINFO, 1, 1, "libdevinfo failed on path: "},
146 146 {ERRARG_NOT_IN_DEVLIST, 1, 1, "Device not found in fabric device list: "},
147 147 {ERRARG_NOT_IN_DEVINFO, 1, 1, "Could not find entry in devinfo tree: "},
148 148 {ERRARG_DI_GET_PROP, 1, 1, "Could not get libdevinfo property: "},
149 149 {ERRARG_DC_DDEF_ALLOC, 1, 1, "failed to alloc ddef space: "},
150 150 {ERRARG_DC_BYTE_ARRAY, 1, 1, "failed to add property: "},
151 151 {ERRARG_DC_BUS_ACQUIRE, 1, 1, "failed to acquire bus handle: "},
152 152 {ERRARG_BUS_DEV_CREATE, 1, 1, "failed to create device node: "},
153 153 {ERRARG_BUS_DEV_CREATE_UNKNOWN, 1, 1,
154 154 "failed to create device node... Device may be unconfigurable: "},
155 155 {ERRARG_DEV_ACQUIRE, 1, 1, "device acquire operation failed: "},
156 156 {ERRARG_DEV_REMOVE, 1, 1, "remove operation failed: "},
157 157
158 158 /* Fibre Channel operation Errors */
159 159 {ERR_FC, 0, 1, "FC error"},
160 160 {ERR_FC_GET_DEVLIST, 0, 1, "Failed to get fabric device list"},
161 161 {ERR_FC_GET_NEXT_DEV, 0, 1, "Failed to get next device on device map"},
162 162 {ERR_FC_GET_FIRST_DEV, 0, 1, "Failed to get first device on device map"},
163 163 {ERRARG_FC_DEV_MAP_INIT, 1, 1,
164 164 "Failed to initialize device map for: "},
165 165 {ERRARG_FC_PROP_LOOKUP_BYTES, 1, 1, "Failed to get property of "},
166 166 {ERRARG_FC_INQUIRY, 1, 1, "inquiry failed: "},
167 167 {ERRARG_FC_REP_LUNS, 1, 1, "report LUNs failed: "},
168 168 {ERRARG_FC_TOPOLOGY, 1, 1, "failed to get port topology: "},
169 169 {ERRARG_PATH_TOO_LONG, 1, 1, "Path length exceeds max possible: "},
170 170 {ERRARG_INVALID_PATH, 1, 1, "Invalid path: "},
171 171 {ERRARG_OPENDIR, 1, 1, "failure opening directory: "},
172 172
173 173 /* MPXIO Errors */
174 174 {ERRARG_VHCI_GET_PATHLIST, 1, 1, "failed to get path list from vHCI: "},
175 175 {ERRARG_XPORT_NOT_IN_PHCI_LIST, 1, 1, "Transport not in pHCI list: "},
176 176
177 177 /* RCM Errors */
178 178 {ERR_RCM_HANDLE, 0, 1, "cannot get RCM handle"},
179 179 {ERRARG_RCM_SUSPEND, 1, 1, "failed to suspend: "},
180 180 {ERRARG_RCM_RESUME, 1, 1, "failed to resume: "},
181 181 {ERRARG_RCM_OFFLINE, 1, 1, "failed to offline: "},
182 182 {ERRARG_RCM_ONLINE, 1, 1, "failed to online: "},
183 183 {ERRARG_RCM_REMOVE, 1, 1, "failed to remove: "},
184 184 {ERRARG_RCM_INFO, 1, 1, "failed to query: "},
185 185
186 186 /* Commands */
187 187 {CMD_INSERT_DEV, 0, 0, "insert_device"},
188 188 {CMD_REMOVE_DEV, 0, 0, "remove_device"},
189 189 {CMD_REPLACE_DEV, 0, 0, "replace_device"},
190 190 {CMD_RESET_DEV, 0, 0, "reset_device"},
191 191 {CMD_RESET_BUS, 0, 0, "reset_bus"},
192 192 {CMD_RESET_ALL, 0, 0, "reset_all"},
193 193
194 194 /* help messages */
195 195 {MSG_HELP_HDR, 0, 1, "\nfp attachment point specific options:\n"},
196 196 {MSG_HELP_USAGE, 0, 0,
197 197 "\t-c configure -o force_update ap_id [ap_id..]\n"
198 198 "\t-c configure -o no_update ap_id [ap_id...]\n"
199 199 "\t-c unconfigure -o force_update ap_id [ap_id... ]\n"
200 200 "\t-c unconfigure -o no_update ap_id [ap_id... ]\n"},
201 201
202 202 /* hotplug messages */
203 203 {MSG_INSDEV, 1, 1, "Adding device to FC HBA: "},
204 204 {MSG_RMDEV, 1, 1, "Removing FC device: "},
205 205 {MSG_REPLDEV, 1, 1, "Replacing FC device: "},
206 206
207 207 /* Hotplugging confirmation prompts */
208 208 {CONF_QUIESCE_1, 1, 1,
209 209 "This operation will suspend activity on FC bus: "},
210 210
211 211 {CONF_QUIESCE_2, 0, 1, "\nContinue"},
212 212
213 213 {CONF_UNQUIESCE, 0, 1,
214 214 "FC bus quiesced successfully.\n"
215 215 "It is now safe to proceed with hotplug operation."
216 216 "\nEnter y if operation is complete or n to abort"},
217 217
218 218 /* Misc. */
219 219 {WARN_DISCONNECT, 0, 1,
220 220 "WARNING: Disconnecting critical partitions may cause system hang."
221 221 "\nContinue"}
222 222 };
223 223
224 224
225 225 #define N_STRS (sizeof (str_tbl) / sizeof (str_tbl[0]))
226 226
227 227 #define GET_MSG_NARGS(i) (str_tbl[msg_idx(i)].nargs)
228 228 #define GET_MSG_INTL(i) (str_tbl[msg_idx(i)].intl)
229 229
230 230 static errcvt_t err_cvt_tbl[] = {
231 231 { FPCFGA_OK, CFGA_OK },
232 232 { FPCFGA_LIB_ERR, CFGA_LIB_ERROR },
233 233 { FPCFGA_APID_NOEXIST, CFGA_APID_NOEXIST },
234 234 { FPCFGA_NACK, CFGA_NACK },
235 235 { FPCFGA_BUSY, CFGA_BUSY },
236 236 { FPCFGA_SYSTEM_BUSY, CFGA_SYSTEM_BUSY },
237 237 { FPCFGA_OPNOTSUPP, CFGA_OPNOTSUPP },
238 238 { FPCFGA_PRIV, CFGA_PRIV },
239 239 { FPCFGA_UNKNOWN_ERR, CFGA_ERROR },
240 240 { FPCFGA_ERR, CFGA_ERROR }
241 241 };
242 242
243 243 #define N_ERR_CVT_TBL (sizeof (err_cvt_tbl)/sizeof (err_cvt_tbl[0]))
244 244
245 245 #define DEV_OP 0
246 246 #define BUS_OP 1
247 247 static set_state_cmd_t set_state_cmds[] = {
248 248
249 249 { FPCFGA_BUS_QUIESCE, BUS_OP, devctl_bus_quiesce },
250 250 { FPCFGA_BUS_UNQUIESCE, BUS_OP, devctl_bus_unquiesce },
251 251 { FPCFGA_BUS_CONFIGURE, BUS_OP, devctl_bus_configure },
252 252 { FPCFGA_BUS_UNCONFIGURE, BUS_OP, devctl_bus_unconfigure },
253 253 { FPCFGA_RESET_BUS, BUS_OP, devctl_bus_reset },
254 254 { FPCFGA_RESET_ALL, BUS_OP, devctl_bus_resetall },
255 255 { FPCFGA_DEV_CONFIGURE, DEV_OP, devctl_device_online },
256 256 { FPCFGA_DEV_UNCONFIGURE, DEV_OP, devctl_device_offline },
257 257 { FPCFGA_DEV_REMOVE, DEV_OP, devctl_device_remove },
258 258 { FPCFGA_RESET_DEV, DEV_OP, devctl_device_reset }
259 259
260 260 };
261 261
262 262 #define N_SET_STATE_CMDS (sizeof (set_state_cmds)/sizeof (set_state_cmds[0]))
263 263
264 264 static get_state_cmd_t get_state_cmds[] = {
265 265 { FPCFGA_BUS_GETSTATE, BUS_OP, devctl_bus_getstate },
266 266 { FPCFGA_DEV_GETSTATE, DEV_OP, devctl_device_getstate }
267 267 };
268 268
269 269 #define N_GET_STATE_CMDS (sizeof (get_state_cmds)/sizeof (get_state_cmds[0]))
270 270
271 271 /* Order is important. Earlier directories are searched first */
272 272 static const char *dev_dir_hints[] = {
273 273 CFGA_DEV_DIR,
274 274 DEV_RMT,
275 275 DEV_DSK,
276 276 DEV_RDSK,
277 277 DEV_DIR
278 278 };
279 279
280 280 #define N_DEV_DIR_HINTS (sizeof (dev_dir_hints) / sizeof (dev_dir_hints[0]))
281 281
282 282
283 283 /*
284 284 * Routine to search the /dev directory or a subtree of /dev.
285 285 * If the entire /dev hierarchy is to be searched, the most likely directories
286 286 * are searched first.
287 287 */
288 288 fpcfga_ret_t
289 289 recurse_dev(
290 290 const char *basedir,
291 291 void *arg,
292 292 fpcfga_recur_t (*fcn)(const char *lpath, void *arg))
293 293 {
294 294 int i, rv = NFTW_ERROR;
295 295
296 296 (void) mutex_lock(&nftw_arg.mp);
297 297
298 298 nftw_arg.arg = arg;
299 299 nftw_arg.fcn = fcn;
300 300
301 301 if (strcmp(basedir, DEV_DIR)) {
302 302 errno = 0;
303 303 rv = nftw(basedir, do_recurse_dev, NFTW_DEPTH, FTW_PHYS);
304 304 goto out;
305 305 }
306 306
307 307 /*
308 308 * Search certain selected subdirectories first if basedir == "/dev".
309 309 * Ignore errors as some of these directories may not exist.
310 310 */
311 311 for (i = 0; i < N_DEV_DIR_HINTS; i++) {
312 312 errno = 0;
313 313 if ((rv = nftw(dev_dir_hints[i], do_recurse_dev, NFTW_DEPTH,
314 314 FTW_PHYS)) == NFTW_TERMINATE) {
315 315 break;
316 316 }
317 317 }
318 318
319 319 /*FALLTHRU*/
320 320 out:
321 321 (void) mutex_unlock(&nftw_arg.mp);
322 322 return (rv == NFTW_ERROR ? FPCFGA_ERR : FPCFGA_OK);
323 323 }
324 324
325 325 /*ARGSUSED*/
326 326 static int
327 327 do_recurse_dev(
328 328 const char *path,
329 329 const struct stat *sbuf,
330 330 int type,
331 331 struct FTW *ftwp)
332 332 {
333 333 /* We want only VALID symlinks */
334 334 if (type != FTW_SL) {
335 335 return (NFTW_CONTINUE);
336 336 }
337 337
338 338 assert(nftw_arg.fcn != NULL);
339 339
340 340 if (nftw_arg.fcn(path, nftw_arg.arg) == FPCFGA_TERMINATE) {
341 341 /* terminate prematurely, but may not be error */
342 342 errno = 0;
343 343 return (NFTW_TERMINATE);
344 344 } else {
345 345 return (NFTW_CONTINUE);
346 346 }
347 347 }
348 348
349 349 cfga_err_t
350 350 err_cvt(fpcfga_ret_t fp_err)
351 351 {
352 352 int i;
353 353
354 354 for (i = 0; i < N_ERR_CVT_TBL; i++) {
355 355 if (err_cvt_tbl[i].fp_err == fp_err) {
356 356 return (err_cvt_tbl[i].cfga_err);
357 357 }
358 358 }
359 359
360 360 return (CFGA_ERROR);
361 361 }
362 362
363 363 /*
364 364 * Removes duplicate slashes from a pathname and any trailing slashes.
365 365 * Returns "/" if input is "/"
366 366 */
367 367 char *
368 368 pathdup(const char *path, int *l_errnop)
369 369 {
370 370 int prev_was_slash = 0;
371 371 char c, *dp = NULL, *dup = NULL;
372 372 const char *sp = NULL;
373 373
374 374 *l_errnop = 0;
375 375
376 376 if (path == NULL) {
377 377 return (NULL);
378 378 }
379 379
380 380 if ((dup = calloc(1, strlen(path) + 1)) == NULL) {
381 381 *l_errnop = errno;
382 382 return (NULL);
383 383 }
384 384
385 385 prev_was_slash = 0;
386 386 for (sp = path, dp = dup; (c = *sp) != '\0'; sp++) {
387 387 if (!prev_was_slash || c != '/') {
388 388 *dp++ = c;
389 389 }
390 390 if (c == '/') {
391 391 prev_was_slash = 1;
392 392 } else {
393 393 prev_was_slash = 0;
394 394 }
395 395 }
396 396
397 397 /* Remove trailing slash except if it is the first char */
398 398 if (prev_was_slash && dp != dup && dp - 1 != dup) {
399 399 *(--dp) = '\0';
400 400 } else {
401 401 *dp = '\0';
402 402 }
403 403
404 404 return (dup);
405 405 }
406 406
407 407 fpcfga_ret_t
408 408 apidt_create(const char *ap_id, apid_t *apidp, char **errstring)
409 409 {
410 410 char *xport_phys = NULL, *dyn = NULL;
411 411 char *dyncomp = NULL;
412 412 struct luninfo_list *lunlistp = NULL;
413 413 int l_errno = 0;
414 414 size_t len = 0;
415 415 fpcfga_ret_t ret;
416 416
417 417 if ((xport_phys = pathdup(ap_id, &l_errno)) == NULL) {
418 418 cfga_err(errstring, l_errno, ERR_OP_FAILED, 0);
419 419 return (FPCFGA_LIB_ERR);
420 420 }
421 421
422 422 /* Extract the base(hba) and dynamic(device) component if any */
423 423 dyncomp = NULL;
424 424 if ((dyn = GET_DYN(xport_phys)) != NULL) {
425 425 len = strlen(DYN_TO_DYNCOMP(dyn)) + 1;
426 426 dyncomp = calloc(1, len);
427 427 if (dyncomp == NULL) {
428 428 cfga_err(errstring, errno, ERR_OP_FAILED, 0);
429 429 ret = FPCFGA_LIB_ERR;
430 430 goto err;
431 431 }
432 432 (void) strcpy(dyncomp, DYN_TO_DYNCOMP(dyn));
433 433 if (GET_LUN_DYN(dyncomp)) {
434 434 ret = FPCFGA_APID_NOEXIST;
↓ open down ↓ |
284 lines elided |
↑ open up ↑ |
435 435 goto err;
436 436 }
437 437
438 438 /* Remove the dynamic component from the base. */
439 439 *dyn = '\0';
440 440 }
441 441
442 442 /* Get the path of dynamic attachment point if already configured. */
443 443 if (dyncomp != NULL) {
444 444 ret = dyn_apid_to_path(xport_phys, dyncomp,
445 - &lunlistp, &l_errno);
445 + &lunlistp, &l_errno);
446 446 if ((ret != FPCFGA_OK) && (ret != FPCFGA_APID_NOCONFIGURE)) {
447 447 cfga_err(errstring, l_errno, ERR_OP_FAILED, 0);
448 448 goto err;
449 449 }
450 450 }
451 451
452 452 assert(xport_phys != NULL);
453 453
454 454 apidp->xport_phys = xport_phys;
455 455 apidp->dyncomp = dyncomp;
456 456 apidp->lunlist = lunlistp;
457 457 apidp->flags = 0;
458 458
459 459 return (FPCFGA_OK);
460 460
461 461 err:
462 462 S_FREE(xport_phys);
463 463 S_FREE(dyncomp);
464 464 lunlist_free(lunlistp);
465 465 return (ret);
466 466 }
467 467
468 468 static void
469 469 lunlist_free(struct luninfo_list *lunlist)
470 470 {
471 471 struct luninfo_list *lunp;
472 472
473 473 while (lunlist != NULL) {
474 474 lunp = lunlist->next;
475 475 S_FREE(lunlist->path);
476 476 S_FREE(lunlist);
477 477 lunlist = lunp;
478 478 }
479 479 }
480 480
481 481 void
482 482 apidt_free(apid_t *apidp)
483 483 {
484 484 if (apidp == NULL)
485 485 return;
486 486
487 487 S_FREE(apidp->xport_phys);
488 488 S_FREE(apidp->dyncomp);
489 489 lunlist_free(apidp->lunlist);
490 490 }
491 491
492 492 fpcfga_ret_t
493 493 walk_tree(
494 494 const char *physpath,
495 495 void *arg,
496 496 uint_t init_flags,
497 497 walkarg_t *up,
498 498 fpcfga_cmd_t cmd,
499 499 int *l_errnop)
500 500 {
501 501 int rv;
502 502 di_node_t root, tree_root, fpnode;
503 503 char *root_path, *cp = NULL;
504 504 char *devfs_fp_path;
505 505 size_t len;
506 506 fpcfga_ret_t ret;
507 507 int found = 0;
508 508
509 509 *l_errnop = 0;
510 510
511 511 if ((root_path = strdup(physpath)) == NULL) {
512 512 *l_errnop = errno;
513 513 return (FPCFGA_LIB_ERR);
514 514 }
515 515
516 516 /* Fix up path for di_init() */
517 517 len = strlen(DEVICES_DIR);
518 518 if (strncmp(root_path, DEVICES_DIR SLASH,
519 519 len + strlen(SLASH)) == 0) {
520 520 cp = root_path + len;
521 521 (void) memmove(root_path, cp, strlen(cp) + 1);
522 522 } else if (*root_path != '/') {
523 523 *l_errnop = 0;
524 524 ret = FPCFGA_ERR;
525 525 goto out;
526 526 }
527 527
528 528 /* Remove dynamic component if any */
529 529 if ((cp = GET_DYN(root_path)) != NULL) {
530 530 *cp = '\0';
531 531 }
532 532
533 533 /* Remove minor name if any */
534 534 if ((cp = strrchr(root_path, ':')) != NULL) {
535 535 *cp = '\0';
536 536 }
537 537
538 538 /*
539 539 * If force_flag is set
540 540 * do di_init with DINFOFORCE flag and get to the input fp node
541 541 * from the device tree.
542 542 *
543 543 * In order to get the link between path_info node and scsi_vhci node
544 544 * it is required to take the snapshot of the whole device tree.
545 545 * this behavior of libdevinfo is inefficient. For a specific
546 546 * fca port DINFOPROP was sufficient on the fca path prior to
547 547 * scsi_vhci node support.
548 548 *
549 549 */
550 550 if ((up->flags & FLAG_DEVINFO_FORCE) == FLAG_DEVINFO_FORCE) {
551 551 tree_root = di_init("/", init_flags | DINFOFORCE);
552 552 } else {
553 553 tree_root = di_init("/", init_flags);
554 554 }
555 555
556 556 if (tree_root == DI_NODE_NIL) {
↓ open down ↓ |
101 lines elided |
↑ open up ↑ |
557 557 *l_errnop = errno;
558 558 ret = FPCFGA_LIB_ERR;
559 559 goto out;
560 560 }
561 561
562 562 fpnode = di_drv_first_node("fp", tree_root);
563 563
564 564 while (fpnode) {
565 565 devfs_fp_path = di_devfs_path(fpnode);
566 566 if ((devfs_fp_path) && !(strncmp(devfs_fp_path,
567 - root_path, strlen(root_path)))) {
567 + root_path, strlen(root_path)))) {
568 568 found = 1;
569 569 di_devfs_path_free(devfs_fp_path);
570 570 break;
571 571 }
572 572 di_devfs_path_free(devfs_fp_path);
573 573 fpnode = di_drv_next_node(fpnode);
574 574 }
575 575 if (!(found)) {
576 576 ret = FPCFGA_LIB_ERR;
577 577 goto out;
578 578 } else {
579 579 root = fpnode;
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
580 580 }
581 581
582 582 /* Walk the tree */
583 583 errno = 0;
584 584 if (cmd == FPCFGA_WALK_NODE) {
585 585 rv = di_walk_node(root, up->walkmode.node_args.flags, arg,
586 586 up->walkmode.node_args.fcn);
587 587 } else {
588 588 assert(cmd == FPCFGA_WALK_MINOR);
589 589 rv = di_walk_minor(root, up->walkmode.minor_args.nodetype, 0,
590 - arg, up->walkmode.minor_args.fcn);
590 + arg, up->walkmode.minor_args.fcn);
591 591 }
592 592
593 593 if (rv != 0) {
594 594 *l_errnop = errno;
595 595 ret = FPCFGA_LIB_ERR;
596 596 } else {
597 597 if ((up->flags & FLAG_PATH_INFO_WALK) == FLAG_PATH_INFO_WALK) {
598 598 ret = stat_path_info_node(root, arg, l_errnop);
599 599 } else {
600 600 *l_errnop = 0;
601 601 ret = FPCFGA_OK;
602 602 }
603 603 }
604 604
605 605 di_fini(tree_root);
606 606
607 607 /*FALLTHRU*/
608 608 out:
609 609 S_FREE(root_path);
610 610 return (ret);
611 611 }
612 612
613 613
614 614 int
615 615 msg_idx(msgid_t msgid)
616 616 {
617 617 int idx = 0;
618 618
619 619 /* The string table index and the error id may or may not be same */
620 620 if (msgid >= 0 && msgid <= N_STRS - 1 &&
621 621 str_tbl[msgid].msgid == msgid) {
622 622 idx = msgid;
623 623 } else {
624 624 for (idx = 0; idx < N_STRS; idx++) {
625 625 if (str_tbl[idx].msgid == msgid)
626 626 break;
627 627 }
628 628 if (idx >= N_STRS) {
629 629 idx = UNKNOWN_ERR_IDX;
630 630 }
631 631 }
632 632
633 633 return (idx);
634 634 }
635 635
636 636 /*
637 637 * cfga_err() accepts a variable number of message IDs and constructs
638 638 * a corresponding error string which is returned via the errstring argument.
639 639 * cfga_err() calls dgettext() to internationalize proper messages.
640 640 * May be called with a NULL argument.
641 641 */
642 642 void
643 643 cfga_err(char **errstring, int l_errno, ...)
644 644 {
645 645 va_list ap;
646 646 int append_newline = 0;
647 647 char *tmp_str, *tmp_err_str = NULL;
648 648
649 649 if (errstring == NULL) {
650 650 return;
651 651 }
652 652
653 653 /*
654 654 * Don't append a newline, the application (for example cfgadm)
655 655 * should do that.
656 656 */
657 657 append_newline = 0;
658 658
659 659 va_start(ap, l_errno);
660 660 msg_common(&tmp_err_str, append_newline, l_errno, ap);
661 661 va_end(ap);
662 662
663 663 if (*errstring == NULL) {
↓ open down ↓ |
63 lines elided |
↑ open up ↑ |
664 664 *errstring = tmp_err_str;
665 665 return;
666 666 }
667 667
668 668 /*
669 669 * *errstring != NULL
670 670 * There was something in errstring prior to this call.
671 671 * So, concatenate the old and new strings
672 672 */
673 673 if ((tmp_str = calloc(1,
674 - strlen(*errstring) + strlen(tmp_err_str) + 2)) == NULL) {
674 + strlen(*errstring) + strlen(tmp_err_str) + 2)) == NULL) {
675 675 /* In case of error, retain only the earlier message */
676 676 free(tmp_err_str);
677 677 return;
678 678 }
679 679
680 680 sprintf(tmp_str, "%s\n%s", *errstring, tmp_err_str);
681 681 free(tmp_err_str);
682 682 free(*errstring);
683 683 *errstring = tmp_str;
684 684 }
685 685
686 686 /*
687 687 * This routine accepts a variable number of message IDs and constructs
688 688 * a corresponding message string which is printed via the message print
689 689 * routine argument.
690 690 */
691 691 void
692 692 cfga_msg(struct cfga_msg *msgp, ...)
693 693 {
694 694 char *p = NULL;
695 695 int append_newline = 0, l_errno = 0;
696 696 va_list ap;
697 697
698 698 if (msgp == NULL || msgp->message_routine == NULL) {
699 699 return;
700 700 }
701 701
702 702 /* Append a newline after message */
703 703 append_newline = 1;
704 704 l_errno = 0;
705 705
706 706 va_start(ap, msgp);
707 707 msg_common(&p, append_newline, l_errno, ap);
708 708 va_end(ap);
709 709
710 710 (void) (*msgp->message_routine)(msgp->appdata_ptr, p);
711 711
712 712 S_FREE(p);
713 713 }
714 714
715 715 /*
716 716 * Get internationalized string corresponding to message id
717 717 * Caller must free the memory allocated.
718 718 */
719 719 char *
720 720 cfga_str(int append_newline, ...)
721 721 {
722 722 char *p = NULL;
723 723 int l_errno = 0;
724 724 va_list ap;
725 725
726 726 va_start(ap, append_newline);
727 727 msg_common(&p, append_newline, l_errno, ap);
728 728 va_end(ap);
729 729
730 730 return (p);
731 731 }
732 732
733 733 static void
734 734 msg_common(char **msgpp, int append_newline, int l_errno, va_list ap)
735 735 {
736 736 int a = 0;
737 737 size_t len = 0;
738 738 int i = 0, n = 0;
739 739 char *s = NULL, *t = NULL;
740 740 strlist_t dummy;
741 741 strlist_t *savep = NULL, *sp = NULL, *tailp = NULL;
742 742
743 743 if (*msgpp != NULL) {
744 744 return;
745 745 }
746 746
747 747 dummy.next = NULL;
748 748 tailp = &dummy;
749 749 for (len = 0; (a = va_arg(ap, int)) != 0; ) {
750 750 n = GET_MSG_NARGS(a); /* 0 implies no additional args */
751 751 for (i = 0; i <= n; i++) {
752 752 sp = calloc(1, sizeof (*sp));
753 753 if (sp == NULL) {
754 754 goto out;
755 755 }
756 756 if (i == 0 && GET_MSG_INTL(a)) {
757 757 sp->str = dgettext(TEXT_DOMAIN, GET_MSG_STR(a));
758 758 } else if (i == 0) {
759 759 sp->str = GET_MSG_STR(a);
760 760 } else {
761 761 sp->str = va_arg(ap, char *);
762 762 }
763 763 len += (strlen(sp->str));
764 764 sp->next = NULL;
765 765 tailp->next = sp;
766 766 tailp = sp;
767 767 }
768 768 }
769 769
770 770 len += 1; /* terminating NULL */
771 771
772 772 s = t = NULL;
773 773 if (l_errno) {
774 774 s = dgettext(TEXT_DOMAIN, ": ");
775 775 t = S_STR(strerror(l_errno));
776 776 if (s != NULL && t != NULL) {
777 777 len += strlen(s) + strlen(t);
778 778 }
779 779 }
780 780
781 781 if (append_newline) {
782 782 len++;
783 783 }
784 784
785 785 if ((*msgpp = calloc(1, len)) == NULL) {
786 786 goto out;
787 787 }
788 788
789 789 **msgpp = '\0';
790 790 for (sp = dummy.next; sp != NULL; sp = sp->next) {
791 791 (void) strcat(*msgpp, sp->str);
792 792 }
793 793
794 794 if (s != NULL && t != NULL) {
795 795 (void) strcat(*msgpp, s);
796 796 (void) strcat(*msgpp, t);
797 797 }
798 798
799 799 if (append_newline) {
800 800 (void) strcat(*msgpp, dgettext(TEXT_DOMAIN, "\n"));
801 801 }
802 802
803 803 /* FALLTHROUGH */
804 804 out:
805 805 sp = dummy.next;
806 806 while (sp != NULL) {
807 807 savep = sp->next;
808 808 S_FREE(sp);
809 809 sp = savep;
810 810 }
811 811 }
812 812
813 813 fpcfga_ret_t
814 814 devctl_cmd(
815 815 const char *physpath,
816 816 fpcfga_cmd_t cmd,
817 817 uint_t *statep,
818 818 int *l_errnop)
819 819 {
820 820 int rv = -1, i, type;
821 821 devctl_hdl_t hdl = NULL;
822 822 char *cp = NULL, *path = NULL;
823 823 int (*func)(const devctl_hdl_t);
824 824 int (*state_func)(const devctl_hdl_t, uint_t *);
825 825
826 826 *l_errnop = 0;
827 827
828 828 if (statep != NULL) *statep = 0;
829 829
830 830 func = NULL;
831 831 state_func = NULL;
832 832 type = 0;
833 833
834 834 for (i = 0; i < N_GET_STATE_CMDS; i++) {
835 835 if (get_state_cmds[i].cmd == cmd) {
836 836 state_func = get_state_cmds[i].state_fcn;
837 837 type = get_state_cmds[i].type;
838 838 assert(statep != NULL);
839 839 break;
840 840 }
841 841 }
842 842
843 843 if (state_func == NULL) {
844 844 for (i = 0; i < N_SET_STATE_CMDS; i++) {
845 845 if (set_state_cmds[i].cmd == cmd) {
846 846 func = set_state_cmds[i].fcn;
847 847 type = set_state_cmds[i].type;
848 848 assert(statep == NULL);
849 849 break;
850 850 }
851 851 }
852 852 }
853 853
854 854 assert(type == BUS_OP || type == DEV_OP);
855 855
856 856 if (func == NULL && state_func == NULL) {
857 857 return (FPCFGA_ERR);
858 858 }
859 859
860 860 /*
861 861 * Fix up path for calling devctl.
862 862 */
863 863 if ((path = strdup(physpath)) == NULL) {
864 864 *l_errnop = errno;
865 865 return (FPCFGA_LIB_ERR);
866 866 }
867 867
868 868 /* Remove dynamic component if any */
869 869 if ((cp = GET_DYN(path)) != NULL) {
870 870 *cp = '\0';
871 871 }
872 872
873 873 /* Remove minor name */
874 874 if ((cp = strrchr(path, ':')) != NULL) {
875 875 *cp = '\0';
876 876 }
877 877
878 878 errno = 0;
879 879
880 880 if (type == BUS_OP) {
881 881 hdl = devctl_bus_acquire(path, 0);
882 882 } else {
883 883 hdl = devctl_device_acquire(path, 0);
884 884 }
885 885 *l_errnop = errno;
886 886
887 887 S_FREE(path);
888 888
889 889 if (hdl == NULL) {
890 890 return (FPCFGA_ERR);
891 891 }
892 892
893 893 errno = 0;
894 894 /* Only getstate functions require a second argument */
895 895 if (func != NULL && statep == NULL) {
896 896 rv = func(hdl);
897 897 *l_errnop = errno;
898 898 } else if (state_func != NULL && statep != NULL) {
899 899 rv = state_func(hdl, statep);
900 900 *l_errnop = errno;
901 901 } else {
902 902 rv = -1;
903 903 *l_errnop = 0;
904 904 }
905 905
906 906 devctl_release(hdl);
907 907
908 908 return ((rv == -1) ? FPCFGA_ERR : FPCFGA_OK);
909 909 }
910 910
911 911 /*
912 912 * Is device in a known state ? (One of BUSY, ONLINE, OFFLINE)
913 913 * BUSY --> One or more device special files are open. Implies online
914 914 * ONLINE --> driver attached
915 915 * OFFLINE --> CF1 with offline flag set.
916 916 * UNKNOWN --> None of the above
917 917 */
918 918 int
919 919 known_state(di_node_t node)
920 920 {
↓ open down ↓ |
236 lines elided |
↑ open up ↑ |
921 921 uint_t state;
922 922
923 923 state = di_state(node);
924 924
925 925 /*
926 926 * CF1 without offline flag set is considered unknown state.
927 927 * We are in a known state if either CF2 (driver attached) or
928 928 * offline.
929 929 */
930 930 if ((state & DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE ||
931 - (state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) {
931 + (state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) {
932 932 return (1);
933 933 }
934 934
935 935 return (0);
936 936 }
937 937
938 938 void
939 939 list_free(ldata_list_t **llpp)
940 940 {
941 941 ldata_list_t *lp, *olp;
942 942
943 943 lp = *llpp;
944 944 while (lp != NULL) {
945 945 olp = lp;
946 946 lp = olp->next;
947 947 S_FREE(olp);
948 948 }
949 949
950 950 *llpp = NULL;
951 951 }
952 952
953 953 /*
954 954 * Obtain the devlink from a /devices path
955 955 */
956 956 fpcfga_ret_t
957 957 physpath_to_devlink(
958 958 const char *basedir,
959 959 char *xport_phys,
960 960 char **xport_logpp,
961 961 int *l_errnop,
962 962 int match_minor)
963 963 {
964 964 pathm_t pmt = {NULL};
965 965 fpcfga_ret_t ret;
966 966
967 967 pmt.phys = xport_phys;
968 968 pmt.ret = FPCFGA_NO_REC;
969 969 pmt.match_minor = match_minor;
970 970
971 971 /*
972 972 * Search the /dev hierarchy starting at basedir.
973 973 */
974 974 ret = recurse_dev(basedir, &pmt, lookup_dev);
975 975 if (ret == FPCFGA_OK && (ret = pmt.ret) == FPCFGA_OK) {
976 976 assert(pmt.log != NULL);
977 977 *xport_logpp = pmt.log;
978 978 } else {
979 979 if (pmt.log != NULL) {
980 980 S_FREE(pmt.log);
981 981 }
982 982
983 983 *xport_logpp = NULL;
984 984 *l_errnop = pmt.l_errno;
985 985 }
986 986
987 987 return (ret);
988 988 }
989 989
990 990 static fpcfga_recur_t
991 991 lookup_dev(const char *lpath, void *arg)
992 992 {
993 993 char ppath[PATH_MAX];
994 994 pathm_t *pmtp = (pathm_t *)arg;
995 995
996 996 if (realpath(lpath, ppath) == NULL) {
997 997 return (FPCFGA_CONTINUE);
998 998 }
999 999
1000 1000 ppath[sizeof (ppath) - 1] = '\0';
1001 1001
1002 1002 /* Is this the physical path we are looking for */
1003 1003 if (dev_cmp(ppath, pmtp->phys, pmtp->match_minor)) {
1004 1004 return (FPCFGA_CONTINUE);
1005 1005 }
1006 1006
1007 1007 if ((pmtp->log = strdup(lpath)) == NULL) {
1008 1008 pmtp->l_errno = errno;
1009 1009 pmtp->ret = FPCFGA_LIB_ERR;
1010 1010 } else {
1011 1011 pmtp->ret = FPCFGA_OK;
1012 1012 }
1013 1013
1014 1014 return (FPCFGA_TERMINATE);
1015 1015 }
1016 1016
1017 1017 /* Compare HBA physical ap_id and device path */
1018 1018 int
1019 1019 hba_dev_cmp(const char *hba, const char *devpath)
1020 1020 {
1021 1021 char *cp = NULL;
1022 1022 int rv;
1023 1023 size_t hba_len, dev_len;
1024 1024 char l_hba[MAXPATHLEN], l_dev[MAXPATHLEN];
1025 1025
1026 1026 (void) snprintf(l_hba, sizeof (l_hba), "%s", hba);
1027 1027 (void) snprintf(l_dev, sizeof (l_dev), "%s", devpath);
1028 1028
1029 1029 /* Remove dynamic component if any */
1030 1030 if ((cp = GET_DYN(l_hba)) != NULL) {
1031 1031 *cp = '\0';
1032 1032 }
1033 1033
1034 1034 if ((cp = GET_DYN(l_dev)) != NULL) {
1035 1035 *cp = '\0';
1036 1036 }
1037 1037
1038 1038
1039 1039 /* Remove minor names */
1040 1040 if ((cp = strrchr(l_hba, ':')) != NULL) {
1041 1041 *cp = '\0';
1042 1042 }
1043 1043
1044 1044 if ((cp = strrchr(l_dev, ':')) != NULL) {
1045 1045 *cp = '\0';
1046 1046 }
1047 1047
1048 1048 hba_len = strlen(l_hba);
1049 1049 dev_len = strlen(l_dev);
1050 1050
1051 1051 /* Check if HBA path is component of device path */
1052 1052 if (rv = strncmp(l_hba, l_dev, hba_len)) {
1053 1053 return (rv);
1054 1054 }
1055 1055
1056 1056 /* devpath must have '/' and 1 char in addition to hba path */
1057 1057 if (dev_len >= hba_len + 2 && l_dev[hba_len] == '/') {
1058 1058 return (0);
1059 1059 } else {
1060 1060 return (-1);
1061 1061 }
1062 1062 }
1063 1063
1064 1064 int
1065 1065 dev_cmp(const char *dev1, const char *dev2, int match_minor)
1066 1066 {
1067 1067 char l_dev1[MAXPATHLEN], l_dev2[MAXPATHLEN];
1068 1068 char *mn1, *mn2;
1069 1069 int rv;
1070 1070
1071 1071 (void) snprintf(l_dev1, sizeof (l_dev1), "%s", dev1);
1072 1072 (void) snprintf(l_dev2, sizeof (l_dev2), "%s", dev2);
1073 1073
1074 1074 if ((mn1 = GET_DYN(l_dev1)) != NULL) {
1075 1075 *mn1 = '\0';
1076 1076 }
1077 1077
1078 1078 if ((mn2 = GET_DYN(l_dev2)) != NULL) {
1079 1079 *mn2 = '\0';
1080 1080 }
1081 1081
1082 1082 /* Separate out the minor names */
1083 1083 if ((mn1 = strrchr(l_dev1, ':')) != NULL) {
1084 1084 *mn1++ = '\0';
1085 1085 }
1086 1086
1087 1087 if ((mn2 = strrchr(l_dev2, ':')) != NULL) {
1088 1088 *mn2++ = '\0';
1089 1089 }
1090 1090
1091 1091 if ((rv = strcmp(l_dev1, l_dev2)) != 0 || !match_minor) {
1092 1092 return (rv);
1093 1093 }
1094 1094
1095 1095 /*
1096 1096 * Compare minor names
1097 1097 */
1098 1098 if (mn1 == NULL && mn2 == NULL) {
1099 1099 return (0);
1100 1100 } else if (mn1 == NULL) {
1101 1101 return (-1);
1102 1102 } else if (mn2 == NULL) {
1103 1103 return (1);
1104 1104 } else {
1105 1105 return (strcmp(mn1, mn2));
1106 1106 }
1107 1107 }
1108 1108
1109 1109 /*
1110 1110 * Returns non-zero on failure (aka, HBA_STATUS_ERROR_*
↓ open down ↓ |
169 lines elided |
↑ open up ↑ |
1111 1111 * Will handle retries if applicable.
1112 1112 */
1113 1113 int
1114 1114 getAdapterAttrs(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES *attrs)
1115 1115 {
1116 1116 int count = 0;
1117 1117 HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */
1118 1118
1119 1119 /* Loop as long as we have a retryable error */
1120 1120 while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
1121 - status == HBA_STATUS_ERROR_BUSY) &&
1122 - count++ < HBA_MAX_RETRIES) {
1121 + status == HBA_STATUS_ERROR_BUSY) &&
1122 + count++ < HBA_MAX_RETRIES) {
1123 1123 status = HBA_GetAdapterAttributes(handle, attrs);
1124 1124 if (status == HBA_STATUS_OK) {
1125 1125 break;
1126 1126 }
1127 1127 sleep(1);
1128 1128 }
1129 1129 return (status);
1130 1130 }
1131 1131
1132 1132 /*
1133 1133 * Returns non-zero on failure (aka, HBA_STATUS_ERROR_*
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
1134 1134 * Will handle retries if applicable.
1135 1135 */
1136 1136 int
1137 1137 getPortAttrsByWWN(HBA_HANDLE handle, HBA_WWN wwn, HBA_PORTATTRIBUTES *attrs)
1138 1138 {
1139 1139 int count = 0;
1140 1140 HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */
1141 1141
1142 1142 /* Loop as long as we have a retryable error */
1143 1143 while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
1144 - status == HBA_STATUS_ERROR_BUSY) &&
1145 - count++ < HBA_MAX_RETRIES) {
1144 + status == HBA_STATUS_ERROR_BUSY) &&
1145 + count++ < HBA_MAX_RETRIES) {
1146 1146 status = HBA_GetPortAttributesByWWN(handle, wwn, attrs);
1147 1147 if (status == HBA_STATUS_OK) {
1148 - break;
1148 + break;
1149 1149 }
1150 1150
1151 1151 /* The odds of this occuring are very slim, but possible. */
1152 1152 if (status == HBA_STATUS_ERROR_STALE_DATA) {
1153 1153 /*
1154 1154 * If we hit a stale data scenario,
1155 1155 * we'll just tell the user to try again.
1156 1156 */
1157 1157 status = HBA_STATUS_ERROR_TRY_AGAIN;
1158 1158 break;
1159 1159 }
1160 1160 sleep(1);
1161 1161 }
1162 1162 return (status);
1163 1163 }
1164 1164
1165 1165 /*
1166 1166 * Returns non-zero on failure (aka, HBA_STATUS_ERROR_*
1167 1167 * Will handle retries if applicable.
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
1168 1168 */
1169 1169 int
1170 1170 getAdapterPortAttrs(HBA_HANDLE handle, int portIndex,
1171 1171 HBA_PORTATTRIBUTES *attrs)
1172 1172 {
1173 1173 int count = 0;
1174 1174 HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */
1175 1175
1176 1176 /* Loop as long as we have a retryable error */
1177 1177 while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
1178 - status == HBA_STATUS_ERROR_BUSY) &&
1179 - count++ < HBA_MAX_RETRIES) {
1178 + status == HBA_STATUS_ERROR_BUSY) &&
1179 + count++ < HBA_MAX_RETRIES) {
1180 1180 status = HBA_GetAdapterPortAttributes(handle, portIndex, attrs);
1181 1181 if (status == HBA_STATUS_OK) {
1182 1182 break;
1183 1183 }
1184 1184
1185 1185 /* The odds of this occuring are very slim, but possible. */
1186 1186 if (status == HBA_STATUS_ERROR_STALE_DATA) {
1187 1187 /*
1188 1188 * If we hit a stale data scenario,
1189 1189 * we'll just tell the user to try again.
1190 1190 */
1191 1191 status = HBA_STATUS_ERROR_TRY_AGAIN;
1192 1192 break;
1193 1193 }
1194 1194 sleep(1);
1195 1195 }
1196 1196 return (status);
1197 1197 }
1198 1198
1199 1199 /*
1200 1200 * Returns non-zero on failure (aka, HBA_STATUS_ERROR_*
1201 1201 * Will handle retries if applicable.
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
1202 1202 */
1203 1203 int
1204 1204 getDiscPortAttrs(HBA_HANDLE handle, int portIndex, int discIndex,
1205 1205 HBA_PORTATTRIBUTES *attrs)
1206 1206 {
1207 1207 int count = 0;
1208 1208 HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */
1209 1209
1210 1210 /* Loop as long as we have a retryable error */
1211 1211 while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
1212 - status == HBA_STATUS_ERROR_BUSY) &&
1213 - count++ < HBA_MAX_RETRIES) {
1212 + status == HBA_STATUS_ERROR_BUSY) &&
1213 + count++ < HBA_MAX_RETRIES) {
1214 1214 status = HBA_GetDiscoveredPortAttributes(handle, portIndex,
1215 - discIndex, attrs);
1215 + discIndex, attrs);
1216 1216 if (status == HBA_STATUS_OK) {
1217 1217 break;
1218 1218 }
1219 1219
1220 1220 /* The odds of this occuring are very slim, but possible. */
1221 1221 if (status == HBA_STATUS_ERROR_STALE_DATA) {
1222 1222 /*
1223 1223 * If we hit a stale data scenario, we'll just tell the
1224 1224 * user to try again.
1225 1225 */
1226 1226 status = HBA_STATUS_ERROR_TRY_AGAIN;
1227 1227 break;
1228 1228 }
1229 1229 sleep(1);
1230 1230 }
1231 1231 return (status);
1232 1232 }
1233 1233
1234 1234 /*
1235 1235 * Find the Adapter port that matches the portPath.
1236 1236 * When the matching port is found the caller have to close handle
1237 1237 * and free library.
1238 1238 */
1239 1239 fpcfga_ret_t
1240 1240 findMatchingAdapterPort(char *portPath, HBA_HANDLE *matchingHandle,
1241 1241 int *matchingPortIndex, HBA_PORTATTRIBUTES *matchingPortAttrs,
1242 1242 char **errstring)
1243 1243 {
1244 1244 HBA_HANDLE handle;
1245 1245 HBA_ADAPTERATTRIBUTES hbaAttrs;
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
1246 1246 HBA_PORTATTRIBUTES portAttrs;
1247 1247 HBA_STATUS status = HBA_STATUS_OK;
1248 1248 int count, retry = 0, l_errno = 0;
1249 1249 int adapterIndex, portIndex;
1250 1250 char adapterName[256];
1251 1251 char *cfg_ptr, *tmpPtr;
1252 1252 char *logical_apid = NULL;
1253 1253
1254 1254 status = HBA_LoadLibrary();
1255 1255 if (status != HBA_STATUS_OK) {
1256 - cfga_err(errstring, 0, ERR_HBA_LOAD_LIBRARY, 0);
1257 - return (FPCFGA_LIB_ERR);
1256 + cfga_err(errstring, 0, ERR_HBA_LOAD_LIBRARY, 0);
1257 + return (FPCFGA_LIB_ERR);
1258 1258 }
1259 1259 count = HBA_GetNumberOfAdapters();
1260 1260 if (count == 0) {
1261 - cfga_err(errstring, 0, ERR_NO_ADAPTER_FOUND, 0);
1262 - HBA_FreeLibrary();
1263 - return (FPCFGA_LIB_ERR);
1261 + cfga_err(errstring, 0, ERR_NO_ADAPTER_FOUND, 0);
1262 + HBA_FreeLibrary();
1263 + return (FPCFGA_LIB_ERR);
1264 1264 }
1265 1265
1266 1266 /* Loop over all HBAs */
1267 1267 for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) {
1268 - status = HBA_GetAdapterName(adapterIndex, (char *)&adapterName);
1269 - if (status != HBA_STATUS_OK) {
1270 - /* May have been DR'd */
1271 - continue;
1272 - }
1273 - handle = HBA_OpenAdapter(adapterName);
1274 - if (handle == 0) {
1275 - /* May have been DR'd */
1276 - continue;
1277 - }
1278 -
1279 - do {
1280 - if (getAdapterAttrs(handle, &hbaAttrs)) {
1281 - /* Should never happen */
1282 - HBA_CloseAdapter(handle);
1283 - continue;
1268 + status = HBA_GetAdapterName(adapterIndex, (char *)&adapterName);
1269 + if (status != HBA_STATUS_OK) {
1270 + /* May have been DR'd */
1271 + continue;
1284 1272 }
1273 + handle = HBA_OpenAdapter(adapterName);
1274 + if (handle == 0) {
1275 + /* May have been DR'd */
1276 + continue;
1277 + }
1285 1278
1286 - /* Loop over all HBA Ports */
1287 - for (portIndex = 0;
1288 - portIndex < hbaAttrs.NumberOfPorts; portIndex++) {
1289 - if ((status = getAdapterPortAttrs(handle, portIndex,
1290 - &portAttrs)) != HBA_STATUS_OK) {
1291 - /* Need to refresh adapter */
1292 - if (status == HBA_STATUS_ERROR_STALE_DATA) {
1293 - HBA_RefreshInformation(handle);
1294 - break;
1295 - } else {
1296 - continue;
1279 + do {
1280 + if (getAdapterAttrs(handle, &hbaAttrs)) {
1281 + /* Should never happen */
1282 + HBA_CloseAdapter(handle);
1283 + continue;
1297 1284 }
1298 - }
1299 1285
1300 - /*
1301 - * check to see if OSDeviceName is a /dev/cfg link
1302 - * or the physical path
1303 - */
1304 - if (strncmp(portAttrs.OSDeviceName, CFGA_DEV_DIR,
1305 - strlen(CFGA_DEV_DIR)) != 0) {
1306 - tmpPtr = strstr(portAttrs.OSDeviceName, MINOR_SEP);
1307 - if (tmpPtr != NULL) {
1308 - if (strncmp(portPath,
1286 + /* Loop over all HBA Ports */
1287 + for (portIndex = 0;
1288 + portIndex < hbaAttrs.NumberOfPorts; portIndex++) {
1289 + if ((status = getAdapterPortAttrs(handle,
1290 + portIndex,
1291 + &portAttrs)) != HBA_STATUS_OK) {
1292 + /* Need to refresh adapter */
1293 + if (status ==
1294 + HBA_STATUS_ERROR_STALE_DATA) {
1295 + HBA_RefreshInformation(handle);
1296 + break;
1297 + } else {
1298 + continue;
1299 + }
1300 + }
1301 +
1302 + /*
1303 + * check to see if OSDeviceName is a /dev/cfg
1304 + * link or the physical path
1305 + */
1306 + if (strncmp(portAttrs.OSDeviceName,
1307 + CFGA_DEV_DIR,
1308 + strlen(CFGA_DEV_DIR)) != 0) {
1309 + tmpPtr = strstr(portAttrs.OSDeviceName,
1310 + MINOR_SEP);
1311 + if ((tmpPtr != NULL) &&
1312 + strncmp(portPath,
1309 1313 portAttrs.OSDeviceName,
1310 1314 strlen(portAttrs.OSDeviceName) -
1311 1315 strlen(tmpPtr)) == 0) {
1312 - if (matchingHandle)
1313 - *matchingHandle = handle;
1314 - if (matchingPortIndex)
1315 - *matchingPortIndex = portIndex;
1316 - if (matchingPortAttrs)
1317 - *matchingPortAttrs = portAttrs;
1318 - return (FPCFGA_OK);
1316 + if (matchingHandle)
1317 + *matchingHandle =
1318 + handle;
1319 + if (matchingPortIndex)
1320 + *matchingPortIndex =
1321 + portIndex;
1322 + if (matchingPortAttrs)
1323 + *matchingPortAttrs =
1324 + portAttrs;
1325 + return (FPCFGA_OK);
1326 + }
1327 + } else {
1328 + /*
1329 + * strip off the /dev/cfg/ portion of
1330 + * the OSDeviceName make sure that the
1331 + * OSDeviceName is at least
1332 + * strlen("/dev/cfg") + 1 + 1 long.
1333 + * first 1 is for the / after /dev/cfg
1334 + * second 1 is to make sure there is
1335 + * somthing after
1336 + */
1337 + if (strlen(portAttrs.OSDeviceName) <
1338 + (strlen(CFGA_DEV_DIR) + 1 + 1))
1339 + continue;
1340 + cfg_ptr = portAttrs.OSDeviceName +
1341 + strlen(CFGA_DEV_DIR) + 1;
1342 + if (logical_apid == NULL) {
1343 + /*
1344 + * get the /dev/cfg link from
1345 + * the portPath
1346 + */
1347 + if (make_xport_logid(portPath,
1348 + &logical_apid,
1349 + &l_errno) != FPCFGA_OK) {
1350 + cfga_err(errstring,
1351 + l_errno,
1352 + ERR_LIST, 0);
1353 + HBA_FreeLibrary();
1354 + return
1355 + (FPCFGA_LIB_ERR);
1356 + }
1357 + }
1358 + /* compare logical ap_id */
1359 + if (strcmp(logical_apid,
1360 + cfg_ptr) == 0) {
1361 + if (matchingHandle)
1362 + *matchingHandle =
1363 + handle;
1364 + if (matchingPortIndex)
1365 + *matchingPortIndex =
1366 + portIndex;
1367 + if (matchingPortAttrs)
1368 + *matchingPortAttrs =
1369 + portAttrs;
1370 + S_FREE(logical_apid);
1371 + return (FPCFGA_OK);
1372 + }
1319 1373 }
1320 1374 }
1321 - } else {
1322 - /*
1323 - * strip off the /dev/cfg/ portion of the
1324 - * OSDeviceName
1325 - * make sure that the OSDeviceName is at least
1326 - * strlen("/dev/cfg") + 1 + 1 long.
1327 - * first 1 is for the / after /dev/cfg
1328 - * second 1 is to make sure there is somthing
1329 - * after
1330 - */
1331 - if (strlen(portAttrs.OSDeviceName) <
1332 - (strlen(CFGA_DEV_DIR) + 1 + 1))
1333 - continue;
1334 - cfg_ptr = portAttrs.OSDeviceName +
1335 - strlen(CFGA_DEV_DIR) + 1;
1336 - if (logical_apid == NULL) {
1337 - /* get the /dev/cfg link from the portPath */
1338 - if (make_xport_logid(portPath, &logical_apid,
1339 - &l_errno) != FPCFGA_OK) {
1340 - cfga_err(errstring, l_errno,
1341 - ERR_LIST, 0);
1342 - HBA_FreeLibrary();
1343 - return (FPCFGA_LIB_ERR);
1344 - }
1345 - }
1346 - /* compare logical ap_id */
1347 - if (strcmp(logical_apid, cfg_ptr) == 0) {
1348 - if (matchingHandle)
1349 - *matchingHandle = handle;
1350 - if (matchingPortIndex)
1351 - *matchingPortIndex = portIndex;
1352 - if (matchingPortAttrs)
1353 - *matchingPortAttrs = portAttrs;
1375 + if (logical_apid != NULL)
1354 1376 S_FREE(logical_apid);
1355 - return (FPCFGA_OK);
1356 - }
1357 - }
1358 - }
1359 - if (logical_apid != NULL)
1360 - S_FREE(logical_apid);
1361 - } while ((status == HBA_STATUS_ERROR_STALE_DATA) &&
1362 - (retry++ < HBA_MAX_RETRIES));
1377 + } while ((status == HBA_STATUS_ERROR_STALE_DATA) &&
1378 + (retry++ < HBA_MAX_RETRIES));
1363 1379
1364 - HBA_CloseAdapter(handle);
1380 + HBA_CloseAdapter(handle);
1365 1381 }
1366 1382 free(logical_apid);
1367 1383
1368 - /* Got here. No mathcing adatper port found. */
1384 + /* Got here. No matching adapter port found. */
1369 1385 cfga_err(errstring, 0, ERR_MATCHING_HBA_PORT, 0);
1370 1386 HBA_FreeLibrary();
1371 1387 return (FPCFGA_LIB_ERR);
1372 1388 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX