Print this page
NEX-14898 Null message (cfga_msg: NULL msgp) printed for sata devices with cfgadm
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/cfgadm_plugins/sata/common/cfga_sata.c
+++ new/usr/src/lib/cfgadm_plugins/sata/common/cfga_sata.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 2009 Sun Microsystems, Inc. All rights reserved.
24 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 25 * Use is subject to license terms.
25 26 */
26 27
27 28 #include <sys/param.h>
28 29 #include <sys/stat.h>
29 30 #include <errno.h>
30 31 #include <string.h>
31 32 #include <dirent.h>
32 33 #include "cfga_sata.h"
33 34
34 35 /*
35 36 * This file contains the entry points to the plug-in as defined in the
36 37 * config_admin(3X) man page.
37 38 */
38 39
39 40 /*
40 41 * Set the version number for the cfgadm library's use.
41 42 */
42 43 int cfga_version = CFGA_HSL_V2;
43 44
44 45 enum {
45 46 HELP_HEADER = 1,
46 47 HELP_CONFIG,
47 48 HELP_RESET_PORT,
48 49 HELP_RESET_DEVICE,
49 50 HELP_RESET_ALL,
50 51 HELP_PORT_DEACTIVATE,
51 52 HELP_PORT_ACTIVATE,
52 53 HELP_PORT_SELF_TEST,
53 54 HELP_CNTRL_SELF_TEST,
54 55 HELP_UNKNOWN
55 56 };
56 57
57 58 /* SATA specific help messages */
58 59 static char *sata_help[] = {
59 60 NULL,
60 61 "SATA specific commands:\n",
61 62 " cfgadm -c [configure|unconfigure|disconnect|connect] ap_id "
62 63 "[ap_id...]\n",
63 64 " cfgadm -x sata_reset_port ap_id [ap_id...]\n",
64 65 " cfgadm -x sata_reset_device ap_id [ap_id...]\n",
65 66 " cfgadm -x sata_reset_all ap_id\n",
66 67 " cfgadm -x sata_port_deactivate ap_id [ap_id...]\n",
67 68 " cfgadm -x sata_port_activate ap_id [ap_id...]\n",
68 69 " cfgadm -x sata_port_self_test ap_id [ap_id...]\n",
69 70 " cfgadm -t ap_id\n",
70 71 "\tunknown command or option:\n",
71 72 NULL
72 73 }; /* End help messages */
73 74
74 75
75 76 /*
76 77 * Messages.
77 78 */
78 79 static msgcvt_t sata_msgs[] = {
79 80 /* CFGA_SATA_OK */
80 81 { CVT, CFGA_OK, "" },
81 82
82 83 /* CFGA_SATA_NACK */
83 84 { CVT, CFGA_NACK, "" },
84 85
85 86 /* CFGA_SATA_DEVICE_UNCONFIGURED */
86 87 { CVT, CFGA_OK, "Device unconfigured prior to disconnect" },
87 88
88 89 /* CFGA_SATA_UNKNOWN / CFGA_LIB_ERROR -> "Library error" */
89 90 { CVT, CFGA_LIB_ERROR, "Unknown message; internal error" },
90 91
91 92 /* CFGA_SATA_INTERNAL_ERROR / CFGA_LIB_ERROR -> "Library error" */
92 93 { CVT, CFGA_LIB_ERROR, "Internal error" },
93 94
94 95 /* CFGA_SATA_DATA_ERROR / CFGA_DATA_ERROR -> "Data error" */
95 96 { CVT, CFGA_DATA_ERROR, "cfgadm data error" },
96 97
97 98 /* CFGA_SATA_OPTIONS / CFGA_ERROR -> "Hardware specific failure" */
98 99 { CVT, CFGA_ERROR, "Hardware specific option not supported" },
99 100
100 101 /* CFGA_SATA_HWOPNOTSUPP / CFGA_ERROR -> "Hardware specific failure" */
101 102 { CVT, CFGA_ERROR, "Hardware specific operation not supported" },
102 103
103 104 /*
104 105 * CFGA_SATA_DYNAMIC_AP /
105 106 * CFGA_LIB_ERROR -> "Configuration operation invalid"
106 107 */
107 108 { CVT, CFGA_INVAL, "Cannot identify attached device" },
108 109
109 110 /* CFGA_SATA_AP / CFGA_APID_NOEXIST -> "Attachment point not found" */
110 111 { CVT, CFGA_APID_NOEXIST, "" },
111 112
112 113 /* CFGA_SATA_PORT / CFGA_LIB_ERROR -> "Library error" */
113 114 { CVT, CFGA_LIB_ERROR, "Cannot determine sata port number for " },
114 115
115 116 /* CFGA_SATA_DEVCTL / CFGA_LIB_ERROR -> "Library error" */
116 117 { CVT, CFGA_LIB_ERROR, "Internal error: "
117 118 "Cannot allocate devctl handle " },
118 119
119 120 /*
120 121 * CFGA_SATA_DEV_CONFIGURE /
121 122 * CFGA_ERROR -> "Hardware specific failure"
122 123 */
123 124 { CVT, CFGA_ERROR, "Failed to config device at " },
124 125
125 126 /*
126 127 * CFGA_SATA_DEV_UNCONFIGURE /
127 128 * CFGA_ERROR -> "Hardware specific failure"
128 129 */
129 130 { CVT, CFGA_ERROR, "Failed to unconfig device at " },
130 131
131 132 /*
132 133 * CFGA_SATA_DISCONNECTED
133 134 * CFGA_INVAL -> "Configuration operation invalid"
134 135 */
135 136 { CVT, CFGA_INVAL, "Port already disconnected " },
136 137
137 138 /*
138 139 * CFGA_SATA_NOT_CONNECTED
139 140 * CFGA_INVAL -> "Configuration operation invalid"
140 141 */
141 142 { CVT, CFGA_INVAL, "No device connected to " },
142 143
143 144 /*
144 145 * CFGA_SATA_NOT_CONFIGURED /
145 146 * CFGA_INVAL -> "Configuration operation invalid"
146 147 */
147 148 { CVT, CFGA_INVAL, "No device configured at " },
148 149
149 150 /*
150 151 * CFGA_SATA_ALREADY_CONNECTED /
151 152 * CFGA_INVAL -> "Configuration operation invalid"
152 153 */
153 154 { CVT, CFGA_INVAL, "Device already connected to " },
154 155
155 156 /*
156 157 * CFGA_SATA_ALREADY_CONFIGURED /
157 158 * CFGA_INVAL -> "Configuration operation invalid"
158 159 */
159 160 { CVT, CFGA_INVAL, "Device already configured at " },
160 161
161 162 /*
162 163 * CFGA_SATA_INVALID_DEVNAME /
163 164 * CFGA_INVAL -> "Configuration operation invalid"
164 165 */
165 166 { CVT, CFGA_INVAL, "Cannot specify device name" },
166 167
167 168 /* CFGA_SATA_OPEN / CFGA_LIB_ERROR -> "Library error" */
168 169 { CVT, CFGA_LIB_ERROR, "Cannot open " },
169 170
170 171 /* CFGA_SATA_IOCTL / CFGA_ERROR -> "Hardware specific failure" */
171 172 { CVT, CFGA_ERROR, "Driver ioctl failed " },
172 173
173 174 /*
174 175 * CFGA_SATA_BUSY /
175 176 * CFGA_SYSTEM_BUSY -> "System is busy, try again"
176 177 */
177 178 { CVT, CFGA_SYSTEM_BUSY, "" },
178 179
179 180 /* CFGA_SATA_ALLOC_FAIL / CFGA_LIB_ERROR -> "Library error" */
180 181 { CVT, CFGA_LIB_ERROR, "Memory allocation failure" },
181 182
182 183 /*
183 184 * CFGA_SATA_OPNOTSUPP /
184 185 * CFGA_OPNOTSUPP -> "Configuration operation not supported"
185 186 */
186 187 { CVT, CFGA_OPNOTSUPP, "Operation not supported" },
187 188
188 189 /* CFGA_SATA_DEVLINK / CFGA_LIB_ERROR -> "Library error" */
189 190 { CVT, CFGA_LIB_ERROR, "Could not find /dev/cfg link for " },
190 191
191 192 /* CFGA_SATA_STATE / CFGA_LIB_ERROR -> "Library error" */
192 193 { CVT, CFGA_LIB_ERROR, "Internal error: Unrecognized ap state" },
193 194
194 195 /* CFGA_SATA_PRIV / CFGA_PRIV -> "Insufficient privileges" */
195 196 { CVT, CFGA_PRIV, "" },
196 197
197 198 /* CFGA_SATA_NVLIST / CFGA_ERROR -> "Hardware specific failure" */
198 199 { CVT, CFGA_ERROR, "Internal error (nvlist)" },
199 200
200 201 /* CFGA_SATA_ZEROLEN / CFGA_ERROR -> "Hardware specific failure" */
201 202 { CVT, CFGA_ERROR, "Internal error (zerolength string)" },
202 203
203 204 /* CFGA_SATA_RCM_HANDLE / CFGA_ERROR -> "Hardware specific failure" */
204 205 { CVT, CFGA_ERROR, "cannot get RCM handle"},
205 206
206 207 /*
207 208 * CFGA_SATA_RCM_ONLINE /
208 209 * CFGA_SYSTEM_BUSY -> "System is busy, try again"
209 210 */
210 211 { CVT, CFGA_SYSTEM_BUSY, "failed to online: "},
211 212
212 213 /*
213 214 * CFGA_SATA_RCM_OFFLINE /
214 215 * CFGA_SYSTEM_BUSY -> "System is busy, try again"
215 216 */
216 217 { CVT, CFGA_SYSTEM_BUSY, "failed to offline: "},
217 218
218 219 /* CFGA_SATA_RCM_INFO / CFGA_ERROR -> "Hardware specific failure" */
219 220 { CVT, CFGA_ERROR, "failed to query: "}
220 221
221 222 }; /* End error messages */
222 223
223 224 static cfga_sata_ret_t
224 225 verify_params(const char *ap_id, const char *options, char **errstring);
225 226
226 227
227 228 static cfga_sata_ret_t
228 229 setup_for_devctl_cmd(const char *ap_id, devctl_hdl_t *devctl_hdl,
229 230 nvlist_t **user_nvlistp, uint_t oflag);
230 231
231 232 static cfga_sata_ret_t
232 233 port_state(devctl_hdl_t hdl, nvlist_t *list,
233 234 ap_rstate_t *rstate, ap_ostate_t *ostate);
234 235
235 236 static cfga_sata_ret_t
236 237 do_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
237 238 void **descrp, size_t *sizep);
238 239
239 240 static void
240 241 cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist);
241 242
242 243 static char *
243 244 sata_get_devicepath(const char *ap_id);
244 245
245 246 static int
246 247 sata_confirm(struct cfga_confirm *confp, char *msg);
247 248
248 249 static cfga_sata_ret_t
249 250 get_port_num(const char *ap_id, uint32_t *port);
250 251
251 252 /* Utilities */
252 253
253 254 static cfga_sata_ret_t
254 255 physpath_to_devlink(const char *basedir, const char *node_path,
255 256 char **logpp, int *l_errnop)
256 257 {
257 258 char *linkpath;
258 259 char *buf;
259 260 char *real_path;
260 261 DIR *dp;
261 262 struct dirent *dep, *newdep;
262 263 int deplen;
263 264 boolean_t found = B_FALSE;
264 265 int err = 0;
265 266 struct stat sb;
266 267 char *p;
267 268 cfga_sata_ret_t rv = CFGA_SATA_INTERNAL_ERROR;
268 269
269 270 /*
270 271 * Using libdevinfo for this is overkill and kills performance
271 272 * when multiple consumers of libcfgadm are executing
272 273 * concurrently.
273 274 */
274 275 if ((dp = opendir(basedir)) == NULL) {
275 276 *l_errnop = errno;
276 277 return (CFGA_SATA_INTERNAL_ERROR);
277 278 }
278 279
279 280 linkpath = malloc(PATH_MAX);
280 281 buf = malloc(PATH_MAX);
281 282 real_path = malloc(PATH_MAX);
282 283
283 284 deplen = pathconf(basedir, _PC_NAME_MAX);
284 285 deplen = (deplen <= 0 ? MAXNAMELEN : deplen) +
285 286 sizeof (struct dirent);
286 287 dep = (struct dirent *)malloc(deplen);
287 288
288 289 if (dep == NULL || linkpath == NULL || buf == NULL ||
289 290 real_path == NULL) {
290 291 *l_errnop = ENOMEM;
291 292 rv = CFGA_SATA_ALLOC_FAIL;
292 293 goto pp_cleanup;
293 294 }
294 295
295 296 *logpp = NULL;
296 297
297 298 while (!found && (err = readdir_r(dp, dep, &newdep)) == 0 &&
298 299 newdep != NULL) {
299 300
300 301 assert(newdep == dep);
301 302
302 303 if (strcmp(dep->d_name, ".") == 0 ||
303 304 strcmp(dep->d_name, "..") == 0)
304 305 continue;
305 306
306 307 (void) snprintf(linkpath, MAXPATHLEN,
307 308 "%s/%s", basedir, dep->d_name);
308 309
309 310 if (lstat(linkpath, &sb) < 0)
310 311 continue;
311 312
312 313 if (S_ISDIR(sb.st_mode)) {
313 314
314 315 if ((rv = physpath_to_devlink(linkpath, node_path,
315 316 logpp, l_errnop)) != CFGA_SATA_OK) {
316 317
317 318 goto pp_cleanup;
318 319 }
319 320
320 321 if (*logpp != NULL)
321 322 found = B_TRUE;
322 323
323 324 } else if (S_ISLNK(sb.st_mode)) {
324 325
325 326 bzero(buf, PATH_MAX);
326 327 if (readlink(linkpath, buf, PATH_MAX) < 0)
327 328 continue;
328 329
329 330
330 331 /*
331 332 * realpath() is too darn slow, so fake
332 333 * it, by using what we know about /dev
333 334 * links: they are always of the form:
334 335 * <"../">+/devices/<path>
335 336 */
336 337 p = buf;
337 338 while (strncmp(p, "../", 3) == 0)
338 339 p += 3;
339 340
340 341 if (p != buf)
341 342 p--; /* back up to get a slash */
342 343
343 344 assert (*p == '/');
344 345
345 346 if (strcmp(p, node_path) == 0) {
346 347 *logpp = strdup(linkpath);
347 348 if (*logpp == NULL) {
348 349
349 350 rv = CFGA_SATA_ALLOC_FAIL;
350 351 goto pp_cleanup;
351 352 }
352 353
353 354 found = B_TRUE;
354 355 }
355 356 }
356 357 }
357 358
358 359 free(linkpath);
359 360 free(buf);
360 361 free(real_path);
361 362 free(dep);
362 363 (void) closedir(dp);
363 364
364 365 if (err != 0) {
365 366 *l_errnop = err;
366 367 return (CFGA_SATA_INTERNAL_ERROR);
367 368 }
368 369
369 370 return (CFGA_SATA_OK);
370 371
371 372 pp_cleanup:
372 373
373 374 if (dp)
374 375 (void) closedir(dp);
375 376 if (dep)
376 377 free(dep);
377 378 if (linkpath)
378 379 free(linkpath);
379 380 if (buf)
380 381 free(buf);
381 382 if (real_path)
382 383 free(real_path);
383 384 if (*logpp) {
384 385 free(*logpp);
385 386 *logpp = NULL;
386 387 }
387 388 return (rv);
388 389 }
389 390
390 391
391 392 /*
392 393 * Given the index into a table (msgcvt_t) of messages, get the message
393 394 * string, converting it to the proper locale if necessary.
394 395 * NOTE: Indexes are defined in cfga_sata.h
395 396 */
396 397 static const char *
397 398 get_msg(uint_t msg_index, msgcvt_t *msg_tbl, uint_t tbl_size)
398 399 {
399 400 if (msg_index >= tbl_size) {
400 401 msg_index = CFGA_SATA_UNKNOWN;
401 402 }
402 403
403 404 return ((msg_tbl[msg_index].intl) ?
404 405 dgettext(TEXT_DOMAIN, msg_tbl[msg_index].msgstr) :
405 406 msg_tbl[msg_index].msgstr);
406 407 }
407 408
408 409 /*
409 410 * Allocates and creates a message string (in *ret_str),
410 411 * by concatenating all the (char *) args together, in order.
411 412 * Last arg MUST be NULL.
412 413 */
413 414 static void
414 415 set_msg(char **ret_str, ...)
415 416 {
416 417 char *str;
417 418 size_t total_len;
418 419 va_list valist;
419 420
420 421 va_start(valist, ret_str);
421 422
422 423 total_len = (*ret_str == NULL) ? 0 : strlen(*ret_str);
423 424
424 425 while ((str = va_arg(valist, char *)) != NULL) {
425 426 size_t len = strlen(str);
426 427 char *old_str = *ret_str;
427 428
428 429 *ret_str = (char *)realloc(*ret_str, total_len + len + 1);
429 430 if (*ret_str == NULL) {
430 431 /* We're screwed */
431 432 free(old_str);
432 433 va_end(valist);
433 434 return;
434 435 }
435 436
436 437 (void) strcpy(*ret_str + total_len, str);
437 438 total_len += len;
438 439 }
439 440
440 441 va_end(valist);
441 442 }
442 443
443 444 /*
444 445 * Error message handling.
445 446 * For the rv passed in, looks up the corresponding error message string(s),
446 447 * internationalized if necessary, and concatenates it into a new
447 448 * memory buffer, and points *errstring to it.
448 449 * Note not all rvs will result in an error message return, as not all
449 450 * error conditions warrant a SATA-specific error message - for those
450 451 * conditions the cfgadm generic messages are sufficient.
451 452 *
452 453 * Some messages may display ap_id or errno, which is why they are passed
453 454 * in.
454 455 */
455 456
456 457 cfga_err_t
457 458 sata_err_msg(
458 459 char **errstring,
459 460 cfga_sata_ret_t rv,
460 461 const char *ap_id,
461 462 int l_errno)
462 463 {
463 464 if (errstring == NULL) {
464 465 return (sata_msgs[rv].cfga_err);
465 466 }
466 467
467 468 /*
468 469 * Generate the appropriate SATA-specific error message(s) (if any).
469 470 */
470 471 switch (rv) {
471 472 case CFGA_SATA_OK:
472 473 case CFGA_NACK:
473 474 /* Special case - do nothing. */
474 475 break;
475 476
476 477 case CFGA_SATA_UNKNOWN:
477 478 case CFGA_SATA_DYNAMIC_AP:
478 479 case CFGA_SATA_INTERNAL_ERROR:
479 480 case CFGA_SATA_OPTIONS:
480 481 case CFGA_SATA_ALLOC_FAIL:
481 482 case CFGA_SATA_STATE:
482 483 case CFGA_SATA_PRIV:
483 484 case CFGA_SATA_OPNOTSUPP:
484 485 case CFGA_SATA_DATA_ERROR:
485 486 /* These messages require no additional strings passed. */
486 487 set_msg(errstring, ERR_STR(rv), NULL);
487 488 break;
488 489
489 490 case CFGA_SATA_HWOPNOTSUPP:
490 491 /* hardware-specific help needed */
491 492 set_msg(errstring, ERR_STR(rv), NULL);
492 493 set_msg(errstring, "\n",
493 494 dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]), NULL);
494 495 set_msg(errstring, sata_help[HELP_RESET_PORT], NULL);
495 496 set_msg(errstring, sata_help[HELP_RESET_DEVICE], NULL);
496 497 set_msg(errstring, sata_help[HELP_RESET_ALL], NULL);
497 498 set_msg(errstring, sata_help[HELP_PORT_ACTIVATE], NULL);
498 499 set_msg(errstring, sata_help[HELP_PORT_DEACTIVATE], NULL);
499 500 set_msg(errstring, sata_help[HELP_PORT_SELF_TEST], NULL);
500 501 set_msg(errstring, sata_help[HELP_CNTRL_SELF_TEST], NULL);
501 502 break;
502 503
503 504 case CFGA_SATA_AP:
504 505 case CFGA_SATA_PORT:
505 506 case CFGA_SATA_NOT_CONNECTED:
506 507 case CFGA_SATA_NOT_CONFIGURED:
507 508 case CFGA_SATA_ALREADY_CONNECTED:
508 509 case CFGA_SATA_ALREADY_CONFIGURED:
509 510 case CFGA_SATA_BUSY:
510 511 case CFGA_SATA_DEVLINK:
511 512 case CFGA_SATA_RCM_HANDLE:
512 513 case CFGA_SATA_RCM_ONLINE:
513 514 case CFGA_SATA_RCM_OFFLINE:
514 515 case CFGA_SATA_RCM_INFO:
515 516 case CFGA_SATA_DEV_CONFIGURE:
516 517 case CFGA_SATA_DEV_UNCONFIGURE:
517 518 case CFGA_SATA_DISCONNECTED:
518 519 /* These messages also print ap_id. */
519 520 set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "", NULL);
520 521 break;
521 522
522 523
523 524 case CFGA_SATA_IOCTL:
524 525 case CFGA_SATA_NVLIST:
525 526 /* These messages also print errno. */
526 527 {
527 528 char *errno_str = l_errno ? strerror(l_errno) : "";
528 529
529 530 set_msg(errstring, ERR_STR(rv), errno_str,
530 531 l_errno ? "\n" : "", NULL);
531 532 break;
532 533 }
533 534
534 535 case CFGA_SATA_OPEN:
535 536 /* These messages also apid and errno. */
536 537 {
537 538 char *errno_str = l_errno ? strerror(l_errno) : "";
538 539
539 540 set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "\n",
540 541 errno_str, l_errno ? "\n" : "", NULL);
541 542 break;
542 543 }
543 544
544 545 default:
545 546 set_msg(errstring, ERR_STR(CFGA_SATA_INTERNAL_ERROR), NULL);
546 547
547 548 } /* end switch */
548 549
549 550
550 551 /*
551 552 * Determine the proper error code to send back to the cfgadm library.
552 553 */
553 554 return (sata_msgs[rv].cfga_err);
554 555 }
555 556
556 557
557 558 /*
558 559 * Entry points
559 560 */
560 561 /* cfgadm entry point */
561 562 /*ARGSUSED*/
562 563 cfga_err_t
563 564 cfga_change_state(
564 565 cfga_cmd_t state_change_cmd,
565 566 const char *ap_id,
566 567 const char *options,
567 568 struct cfga_confirm *confp,
568 569 struct cfga_msg *msgp,
569 570 char **errstring,
570 571 cfga_flags_t flags)
571 572 {
572 573 int ret;
573 574 int len;
574 575 char *msg;
575 576 char *devpath;
576 577 nvlist_t *nvl = NULL;
577 578 ap_rstate_t rstate;
578 579 ap_ostate_t ostate;
579 580 devctl_hdl_t hdl = NULL;
580 581 cfga_sata_ret_t rv = CFGA_SATA_OK;
581 582 char *pdyn;
582 583 char *str_type;
583 584 size_t size;
584 585 boolean_t pmult = B_FALSE;
585 586
586 587 /*
587 588 * All sub-commands which can change state of device require
588 589 * root privileges.
589 590 */
590 591 if (geteuid() != 0) {
591 592 rv = CFGA_SATA_PRIV;
592 593 goto bailout;
593 594 }
594 595
595 596 if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SATA_OK) {
596 597 (void) cfga_help(msgp, options, flags);
597 598 goto bailout;
598 599 }
599 600
600 601 if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &nvl,
601 602 DC_RDONLY)) != CFGA_SATA_OK) {
602 603 goto bailout;
603 604 }
604 605
605 606 /*
606 607 * Checking device type. A port multiplier is not configurable - it is
607 608 * already configured as soon as it is connected.
608 609 */
609 610 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
610 611 (void **)&str_type, &size)) != CFGA_SATA_OK) {
611 612 /* no such deivce */
612 613 goto bailout;
613 614 }
614 615 if (strncmp(str_type, "sata-pmult", sizeof ("sata-pmult")) == 0) {
615 616 pmult = B_TRUE;
616 617 }
617 618
618 619 switch (state_change_cmd) {
619 620 case CFGA_CMD_CONFIGURE:
620 621 if (pmult == B_TRUE) {
621 622 rv = CFGA_SATA_HWOPNOTSUPP;
622 623 goto bailout;
623 624 }
624 625
625 626 if ((rv = port_state(hdl, nvl, &rstate, &ostate)) !=
626 627 CFGA_SATA_OK)
627 628 goto bailout;
628 629
629 630 if (ostate == AP_OSTATE_CONFIGURED) {
630 631 rv = CFGA_SATA_ALREADY_CONFIGURED;
631 632 goto bailout;
632 633 }
633 634 /* Disallow dynamic AP name component */
634 635 if (GET_DYN(ap_id) != NULL) {
635 636 rv = CFGA_SATA_INVALID_DEVNAME;
636 637 goto bailout;
637 638 }
638 639
639 640 if (rstate == AP_RSTATE_EMPTY) {
640 641 rv = CFGA_SATA_NOT_CONNECTED;
641 642 goto bailout;
642 643 }
643 644 rv = CFGA_SATA_OK;
644 645
645 646 if (devctl_ap_configure(hdl, nvl) != 0) {
646 647 rv = CFGA_SATA_DEV_CONFIGURE;
647 648 goto bailout;
648 649 }
649 650
650 651 devpath = sata_get_devicepath(ap_id);
651 652 if (devpath == NULL) {
652 653 int i;
653 654 /*
654 655 * Try for some time as SATA hotplug thread
655 656 * takes a while to create the path then
656 657 * eventually give up.
657 658 */
658 659 for (i = 0; i < 12 && (devpath == NULL); i++) {
659 660 (void) sleep(6);
660 661 devpath = sata_get_devicepath(ap_id);
661 662 }
662 663
663 664 if (devpath == NULL) {
664 665 rv = CFGA_SATA_DEV_CONFIGURE;
665 666 break;
666 667 }
667 668 }
668 669
669 670 S_FREE(devpath);
670 671 break;
671 672
672 673 case CFGA_CMD_UNCONFIGURE:
673 674 if (pmult == B_TRUE) {
674 675 rv = CFGA_SATA_HWOPNOTSUPP;
675 676 goto bailout;
676 677 }
677 678
678 679 if ((rv = port_state(hdl, nvl, &rstate, &ostate)) !=
679 680 CFGA_SATA_OK)
680 681 goto bailout;
681 682
682 683 if (rstate != AP_RSTATE_CONNECTED) {
683 684 rv = CFGA_SATA_NOT_CONNECTED;
684 685 goto bailout;
685 686 }
686 687
687 688 if (ostate != AP_OSTATE_CONFIGURED) {
688 689 rv = CFGA_SATA_NOT_CONFIGURED;
689 690 goto bailout;
690 691 }
691 692 /* Strip off AP name dynamic component, if present */
692 693 if ((pdyn = GET_DYN(ap_id)) != NULL) {
693 694 *pdyn = '\0';
694 695 }
695 696
696 697 rv = CFGA_SATA_OK;
697 698
698 699 len = strlen(SATA_CONFIRM_DEVICE) +
699 700 strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
700 701 strlen("Unconfigure") + strlen(ap_id);
701 702 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
702 703 (void) snprintf(msg, len + 3, "Unconfigure"
703 704 " %s%s\n%s",
704 705 SATA_CONFIRM_DEVICE, ap_id,
705 706 SATA_CONFIRM_DEVICE_SUSPEND);
706 707 }
|
↓ open down ↓ |
673 lines elided |
↑ open up ↑ |
707 708
708 709 if (!sata_confirm(confp, msg)) {
709 710 free(msg);
710 711 rv = CFGA_SATA_NACK;
711 712 break;
712 713 }
713 714 free(msg);
714 715
715 716 devpath = sata_get_devicepath(ap_id);
716 717 if (devpath == NULL) {
717 - (void) printf(
718 + DPRINTF(
718 719 "cfga_change_state: get device path failed\n");
719 720 rv = CFGA_SATA_DEV_UNCONFIGURE;
720 721 break;
721 722 }
722 723
723 724 if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags))
724 725 != CFGA_SATA_OK) {
725 726 break;
726 727 }
727 728
728 729 ret = devctl_ap_unconfigure(hdl, nvl);
729 730
730 731 if (ret != 0) {
731 732 rv = CFGA_SATA_DEV_UNCONFIGURE;
732 733 if (errno == EBUSY) {
733 734 rv = CFGA_SATA_BUSY;
734 735 }
735 736 (void) sata_rcm_online(ap_id, errstring, devpath,
736 737 flags);
737 738 } else {
738 739 (void) sata_rcm_remove(ap_id, errstring, devpath,
739 740 flags);
740 741
741 742 }
742 743 S_FREE(devpath);
743 744
744 745 break;
745 746
746 747 case CFGA_CMD_DISCONNECT:
747 748 if ((rv = port_state(hdl, nvl, &rstate, &ostate)) !=
748 749 CFGA_SATA_OK)
749 750 goto bailout;
750 751
751 752 if (rstate == AP_RSTATE_DISCONNECTED) {
752 753 rv = CFGA_SATA_DISCONNECTED;
753 754 goto bailout;
754 755 }
755 756
756 757 /* Strip off AP name dynamic component, if present */
757 758 if ((pdyn = GET_DYN(ap_id)) != NULL) {
758 759 *pdyn = '\0';
759 760 }
760 761
761 762
762 763 rv = CFGA_SATA_OK; /* other statuses don't matter */
763 764
|
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
764 765 /*
765 766 * If the port originally with device attached and was
766 767 * unconfigured already, the devicepath for the sd will be
767 768 * removed. sata_get_devicepath in this case is not necessary.
768 769 */
769 770 /* only call rcm_offline if the state was CONFIGURED */
770 771 if (ostate == AP_OSTATE_CONFIGURED &&
771 772 pmult == B_FALSE) {
772 773 devpath = sata_get_devicepath(ap_id);
773 774 if (devpath == NULL) {
774 - (void) printf(
775 + DPRINTF(
775 776 "cfga_change_state: get path failed\n");
776 777 rv = CFGA_SATA_DEV_UNCONFIGURE;
777 778 break;
778 779 }
779 780
780 781 len = strlen(SATA_CONFIRM_DEVICE) +
781 782 strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
782 783 strlen("Disconnect") + strlen(ap_id);
783 784 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
784 785 (void) snprintf(msg, len + 3,
785 786 "Disconnect"
786 787 " %s%s\n%s",
787 788 SATA_CONFIRM_DEVICE, ap_id,
788 789 SATA_CONFIRM_DEVICE_SUSPEND);
789 790 }
790 791 if (!sata_confirm(confp, msg)) {
791 792 free(msg);
792 793 rv = CFGA_SATA_NACK;
793 794 break;
794 795 }
795 796 free(msg);
796 797
797 798 if ((rv = sata_rcm_offline(ap_id, errstring,
798 799 devpath, flags)) != CFGA_SATA_OK) {
799 800 break;
800 801 }
801 802
802 803 ret = devctl_ap_unconfigure(hdl, nvl);
803 804 if (ret != 0) {
804 805 (void) printf(
805 806 "devctl_ap_unconfigure failed\n");
806 807 rv = CFGA_SATA_DEV_UNCONFIGURE;
807 808 if (errno == EBUSY)
808 809 rv = CFGA_SATA_BUSY;
809 810 (void) sata_rcm_online(ap_id, errstring,
810 811 devpath, flags);
811 812 S_FREE(devpath);
812 813
813 814 /*
814 815 * The current policy is that if unconfigure
815 816 * failed, do not continue with disconnect.
816 817 * If the port needs to be forced into the
817 818 * disconnect (shutdown) state,
818 819 * the -x sata_port_poweroff command should be
819 820 * used instead of -c disconnect
820 821 */
821 822 break;
822 823 } else {
823 824 (void) printf("%s\n",
824 825 ERR_STR(CFGA_SATA_DEVICE_UNCONFIGURED));
825 826 (void) sata_rcm_remove(ap_id, errstring,
826 827 devpath, flags);
827 828 }
828 829 S_FREE(devpath);
829 830 } else if (rstate == AP_RSTATE_CONNECTED ||
830 831 rstate == AP_RSTATE_EMPTY) {
831 832 len = strlen(SATA_CONFIRM_PORT) +
832 833 strlen(SATA_CONFIRM_PORT_DISABLE) +
833 834 strlen("Deactivate Port") + strlen(ap_id);
834 835 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
835 836 (void) snprintf(msg, len +3,
836 837 "Disconnect"
837 838 " %s%s\n%s",
838 839 SATA_CONFIRM_PORT, ap_id,
839 840 SATA_CONFIRM_PORT_DISABLE);
840 841 }
841 842 if (!sata_confirm(confp, msg)) {
842 843 free(msg);
843 844 rv = CFGA_SATA_NACK;
844 845 break;
845 846 }
846 847 }
847 848 ret = devctl_ap_disconnect(hdl, nvl);
848 849 if (ret != 0) {
849 850 rv = CFGA_SATA_IOCTL;
850 851 if (errno == EBUSY) {
851 852 rv = CFGA_SATA_BUSY;
852 853 }
853 854 }
854 855 break;
855 856
856 857 case CFGA_CMD_CONNECT:
857 858 if ((rv = port_state(hdl, nvl, &rstate, &ostate)) !=
858 859 CFGA_SATA_OK)
859 860 goto bailout;
860 861
861 862 if (rstate == AP_RSTATE_CONNECTED) {
862 863 rv = CFGA_SATA_ALREADY_CONNECTED;
863 864 goto bailout;
864 865 }
865 866
866 867 len = strlen(SATA_CONFIRM_PORT) +
867 868 strlen(SATA_CONFIRM_PORT_ENABLE) +
868 869 strlen("Activate Port") + strlen(ap_id);
869 870 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
870 871 (void) snprintf(msg, len +3, "Activate"
871 872 " %s%s\n%s",
872 873 SATA_CONFIRM_PORT, ap_id,
873 874 SATA_CONFIRM_PORT_ENABLE);
874 875 }
875 876 if (!sata_confirm(confp, msg)) {
876 877 rv = CFGA_SATA_NACK;
877 878 break;
878 879 }
879 880
880 881 /* Disallow dynamic AP name component */
881 882 if (GET_DYN(ap_id) != NULL) {
882 883 rv = CFGA_SATA_INVALID_DEVNAME;
883 884 goto bailout;
884 885 }
885 886
886 887 ret = devctl_ap_connect(hdl, nvl);
887 888 if (ret != 0) {
888 889 rv = CFGA_SATA_IOCTL;
889 890 } else {
890 891 rv = CFGA_SATA_OK;
891 892 }
892 893
893 894 break;
894 895
895 896 case CFGA_CMD_LOAD:
896 897 case CFGA_CMD_UNLOAD:
897 898 (void) cfga_help(msgp, options, flags);
898 899 rv = CFGA_SATA_OPNOTSUPP;
899 900 break;
900 901
901 902 case CFGA_CMD_NONE:
902 903 default:
903 904 (void) cfga_help(msgp, options, flags);
904 905 rv = CFGA_SATA_INTERNAL_ERROR;
905 906 }
906 907
907 908 bailout:
908 909 cleanup_after_devctl_cmd(hdl, nvl);
909 910
910 911 return (sata_err_msg(errstring, rv, ap_id, errno));
911 912 }
912 913
913 914 /* cfgadm entry point */
914 915 cfga_err_t
915 916 cfga_private_func(
916 917 const char *func,
917 918 const char *ap_id,
918 919 const char *options,
919 920 struct cfga_confirm *confp,
920 921 struct cfga_msg *msgp,
921 922 char **errstring,
922 923 cfga_flags_t flags)
923 924 {
924 925 int len;
925 926 char *msg;
926 927 nvlist_t *list = NULL;
927 928 ap_ostate_t ostate;
928 929 ap_rstate_t rstate;
929 930 devctl_hdl_t hdl = NULL;
930 931 cfga_sata_ret_t rv;
931 932 char *str_p;
932 933 size_t size;
933 934
934 935 if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SATA_OK) {
935 936 (void) cfga_help(msgp, options, flags);
936 937 return (sata_err_msg(errstring, rv, ap_id, errno));
937 938 }
938 939
|
↓ open down ↓ |
154 lines elided |
↑ open up ↑ |
939 940 /*
940 941 * All subcommands which can change state of device require
941 942 * root privileges.
942 943 */
943 944 if (geteuid() != 0) {
944 945 rv = CFGA_SATA_PRIV;
945 946 goto bailout;
946 947 }
947 948
948 949 if (func == NULL) {
949 - (void) printf("No valid option specified\n");
950 + DPRINTF("No valid option specified\n");
950 951 rv = CFGA_SATA_OPTIONS;
951 952 goto bailout;
952 953 }
953 954
954 955 if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) !=
955 956 CFGA_SATA_OK) {
956 957 goto bailout;
957 958 }
958 959
959 960 /* We do not care here about dynamic AP name component */
960 961 if ((str_p = GET_DYN(ap_id)) != NULL) {
961 962 *str_p = '\0';
962 963 }
963 964
964 965 rv = CFGA_SATA_OK;
965 966
966 967 if (strcmp(func, SATA_RESET_PORT) == 0) {
967 968 len = strlen(SATA_CONFIRM_PORT) +
968 969 strlen(SATA_CONFIRM_DEVICE_ABORT) +
969 970 strlen("Reset Port") + strlen(ap_id);
970 971
971 972 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
972 973 (void) snprintf(msg, len +3, "Reset"
973 974 " %s%s\n%s",
974 975 SATA_CONFIRM_PORT, ap_id,
975 976 SATA_CONFIRM_DEVICE_ABORT);
976 977 } else {
977 978 rv = CFGA_SATA_NACK;
978 979 goto bailout;
979 980 }
980 981
981 982 if (!sata_confirm(confp, msg)) {
982 983 rv = CFGA_SATA_NACK;
983 984 goto bailout;
984 985 }
985 986
986 987 rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_PORT, NULL,
987 988 (void **)&str_p, &size);
988 989
989 990 } else if (strcmp(func, SATA_RESET_DEVICE) == 0) {
990 991 if ((rv = port_state(hdl, list, &rstate, &ostate)) !=
991 992 CFGA_SATA_OK)
992 993 goto bailout;
993 994 /*
994 995 * Reset device function requires device to be connected
995 996 */
996 997 if (rstate != AP_RSTATE_CONNECTED) {
997 998 rv = CFGA_SATA_NOT_CONNECTED;
998 999 goto bailout;
999 1000 }
1000 1001
1001 1002 len = strlen(SATA_CONFIRM_DEVICE) +
1002 1003 strlen(SATA_CONFIRM_DEVICE_ABORT) +
1003 1004 strlen("Reset Device") + strlen(ap_id);
1004 1005
1005 1006 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1006 1007 (void) snprintf(msg, len +3, "Reset"
1007 1008 " %s%s\n%s",
1008 1009 SATA_CONFIRM_DEVICE, ap_id,
1009 1010 SATA_CONFIRM_DEVICE_ABORT);
1010 1011 } else {
1011 1012 rv = CFGA_SATA_NACK;
1012 1013 goto bailout;
1013 1014 }
1014 1015
1015 1016 if (!sata_confirm(confp, msg)) {
1016 1017 rv = CFGA_SATA_NACK;
1017 1018 goto bailout;
1018 1019 }
1019 1020
1020 1021 rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_DEVICE, NULL,
1021 1022 (void **)&str_p, &size);
1022 1023
1023 1024 } else if (strcmp(func, SATA_RESET_ALL) == 0) {
1024 1025 len = strlen(SATA_CONFIRM_CONTROLLER) +
1025 1026 strlen(SATA_CONFIRM_CONTROLLER_ABORT) +
1026 1027 strlen("Reset All") + strlen(ap_id);
1027 1028
1028 1029 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1029 1030 (void) snprintf(msg, len +3, "Reset"
1030 1031 " %s%s\n%s",
1031 1032 SATA_CONFIRM_CONTROLLER, ap_id,
1032 1033 SATA_CONFIRM_CONTROLLER_ABORT);
1033 1034 } else {
1034 1035 rv = CFGA_SATA_NACK;
1035 1036 goto bailout;
1036 1037 }
1037 1038
1038 1039 if (!sata_confirm(confp, msg)) {
1039 1040 rv = CFGA_SATA_NACK;
1040 1041 goto bailout;
1041 1042 }
1042 1043 rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_ALL, NULL,
1043 1044 (void **)&str_p, &size);
1044 1045
1045 1046 } else if (strcmp(func, SATA_PORT_DEACTIVATE) == 0) {
1046 1047 len = strlen(SATA_CONFIRM_PORT) +
1047 1048 strlen(SATA_CONFIRM_PORT_DISABLE) +
1048 1049 strlen("Deactivate Port") + strlen(ap_id);
1049 1050
1050 1051 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1051 1052 (void) snprintf(msg, len +3, "Deactivate"
1052 1053 " %s%s\n%s",
1053 1054 SATA_CONFIRM_PORT, ap_id,
1054 1055 SATA_CONFIRM_PORT_DISABLE);
1055 1056 } else {
1056 1057 rv = CFGA_SATA_NACK;
1057 1058 goto bailout;
1058 1059 }
1059 1060 if (!sata_confirm(confp, msg)) {
1060 1061 rv = CFGA_SATA_NACK;
1061 1062 goto bailout;
1062 1063 }
1063 1064
1064 1065 rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_DEACTIVATE, NULL,
1065 1066 (void **)&str_p, &size);
1066 1067
1067 1068 } else if (strcmp(func, SATA_PORT_ACTIVATE) == 0) {
1068 1069 len = strlen(SATA_CONFIRM_PORT) +
1069 1070 strlen(SATA_CONFIRM_PORT_ENABLE) +
1070 1071 strlen("Activate Port") + strlen(ap_id);
1071 1072
1072 1073 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1073 1074 (void) snprintf(msg, len +3, "Activate"
1074 1075 " %s%s\n%s",
1075 1076 SATA_CONFIRM_PORT, ap_id,
1076 1077 SATA_CONFIRM_PORT_ENABLE);
1077 1078 } else {
1078 1079 rv = CFGA_SATA_NACK;
1079 1080 goto bailout;
1080 1081 }
1081 1082 if (!sata_confirm(confp, msg)) {
1082 1083 rv = CFGA_SATA_NACK;
1083 1084 goto bailout;
1084 1085 }
1085 1086
1086 1087 rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_ACTIVATE,
1087 1088 NULL, (void **)&str_p, &size);
1088 1089 goto bailout;
1089 1090
1090 1091 } else if (strcmp(func, SATA_PORT_SELF_TEST) == 0) {
1091 1092 len = strlen(SATA_CONFIRM_PORT) +
1092 1093 strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
1093 1094 strlen("Self Test Port") + strlen(ap_id);
1094 1095
1095 1096 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1096 1097 (void) snprintf(msg, len +3, "Self Test"
1097 1098 " %s%s\n%s",
1098 1099 SATA_CONFIRM_PORT, ap_id,
1099 1100 SATA_CONFIRM_DEVICE_SUSPEND);
1100 1101 } else {
1101 1102 rv = CFGA_SATA_NACK;
1102 1103 goto bailout;
1103 1104 }
1104 1105 if (!sata_confirm(confp, msg)) {
1105 1106 rv = CFGA_SATA_NACK;
1106 1107 goto bailout;
1107 1108 }
1108 1109
1109 1110 rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_SELF_TEST,
1110 1111 NULL, (void **)&str_p, &size);
1111 1112 } else {
1112 1113 /* Unrecognized operation request */
1113 1114 rv = CFGA_SATA_HWOPNOTSUPP;
1114 1115 }
1115 1116
1116 1117 bailout:
1117 1118 cleanup_after_devctl_cmd(hdl, list);
1118 1119
1119 1120 return (sata_err_msg(errstring, rv, ap_id, errno));
1120 1121
1121 1122 }
1122 1123
1123 1124 /* cfgadm entry point */
1124 1125 /*ARGSUSED*/
1125 1126 cfga_err_t
1126 1127 cfga_test(
1127 1128 const char *ap_id,
1128 1129 const char *options,
1129 1130 struct cfga_msg *msgp,
1130 1131 char **errstring,
1131 1132 cfga_flags_t flags)
1132 1133 {
1133 1134 /* Should call ioctl for self test - phase 2 */
1134 1135 return (CFGA_OPNOTSUPP);
1135 1136 }
1136 1137
1137 1138
1138 1139 int
1139 1140 sata_check_target_node(di_node_t node, void *arg)
1140 1141 {
1141 1142 char *minorpath;
1142 1143 char *cp;
1143 1144
1144 1145 minorpath = di_devfs_minor_path(di_minor_next(node, DI_MINOR_NIL));
1145 1146 if (minorpath != NULL) {
1146 1147 if (strstr(minorpath, arg) != NULL) {
1147 1148 cp = strrchr(minorpath, (int)*MINOR_SEP);
1148 1149 if (cp != NULL) {
1149 1150 (void) strcpy(arg, cp);
1150 1151 }
1151 1152 free(minorpath);
1152 1153 return (DI_WALK_TERMINATE);
1153 1154 }
1154 1155 free(minorpath);
1155 1156 }
1156 1157 return (DI_WALK_CONTINUE);
1157 1158 }
1158 1159
1159 1160 struct chk_dev {
1160 1161 int c_isblk;
1161 1162 char *c_minor;
1162 1163 };
1163 1164
1164 1165 /*ARGSUSED*/
1165 1166 static int
1166 1167 chk_dev_fcn(di_node_t node, di_minor_t minor, void *arg)
1167 1168 {
1168 1169 char *mn;
1169 1170 struct chk_dev *chkp = (struct chk_dev *)arg;
1170 1171
1171 1172 mn = di_minor_name(minor);
1172 1173 if (mn == NULL)
1173 1174 return (DI_WALK_CONTINUE);
1174 1175
1175 1176 if (strcmp(mn, chkp->c_minor) != 0)
1176 1177 return (DI_WALK_CONTINUE);
1177 1178
1178 1179 chkp->c_isblk = di_minor_spectype(minor) == S_IFBLK ? 1 : 0;
1179 1180
1180 1181 return (DI_WALK_TERMINATE);
1181 1182 }
1182 1183
1183 1184 /*
1184 1185 * Don't use devfs if stat() in /devices fails. Use libdevinfo instead.
1185 1186 * Retired devices don't show up in devfs.
1186 1187 *
1187 1188 * Returns:
1188 1189 * 1 - minor exists and is of type BLK
1189 1190 * 0 - minor does not exist or is not of type BLK.
1190 1191 */
1191 1192 static int
1192 1193 is_devinfo_blk(char *minor_path)
1193 1194 {
1194 1195 char *minor_portion;
1195 1196 struct chk_dev chk_dev;
1196 1197 di_node_t node;
1197 1198 int rv;
1198 1199
1199 1200 /*
1200 1201 * prune minor path for di_init() - no /devices prefix and no minor name
1201 1202 */
1202 1203 if (strncmp(minor_path, "/devices/", strlen("/devices/")) != 0)
1203 1204 return (0);
1204 1205
1205 1206 minor_portion = strrchr(minor_path, *MINOR_SEP);
1206 1207 if (minor_portion == NULL)
1207 1208 return (0);
1208 1209
1209 1210 *minor_portion = 0;
1210 1211
1211 1212 node = di_init(minor_path + strlen("/devices"), DINFOMINOR);
1212 1213
1213 1214 *minor_portion = *MINOR_SEP;
1214 1215
1215 1216 if (node == DI_NODE_NIL)
1216 1217 return (0);
1217 1218
1218 1219 chk_dev.c_isblk = 0;
1219 1220 chk_dev.c_minor = minor_portion + 1;
1220 1221
1221 1222 rv = di_walk_minor(node, NULL, 0, &chk_dev, chk_dev_fcn);
1222 1223
1223 1224 di_fini(node);
1224 1225
1225 1226 if (rv == 0 && chk_dev.c_isblk)
1226 1227 return (1);
1227 1228 else
1228 1229 return (0);
1229 1230 }
1230 1231
1231 1232 /*
1232 1233 * The dynamic component buffer returned by this function has to be freed!
1233 1234 */
1234 1235 int
1235 1236 sata_make_dyncomp(const char *ap_id, char **dyncomp, const char *type)
1236 1237 {
1237 1238 char *devpath = NULL;
1238 1239 char *cp = NULL;
1239 1240 int l_errno;
1240 1241 char minor_path[MAXPATHLEN];
1241 1242 char name_part[MAXNAMELEN];
1242 1243 char *devlink = NULL;
1243 1244 char *minor_portion = NULL;
1244 1245 int deplen;
1245 1246 int err;
1246 1247 DIR *dp = NULL;
1247 1248 struct stat sb;
1248 1249 struct dirent *dep = NULL;
1249 1250 struct dirent *newdep = NULL;
|
↓ open down ↓ |
290 lines elided |
↑ open up ↑ |
1250 1251 char *p;
1251 1252
1252 1253 assert(dyncomp != NULL);
1253 1254
1254 1255 /*
1255 1256 * Get target node path
1256 1257 */
1257 1258 devpath = sata_get_devicepath(ap_id);
1258 1259 if (devpath == NULL) {
1259 1260
1260 - (void) printf("cfga_list_ext: cannot locate target device\n");
1261 + DPRINTF("cfga_list_ext: cannot locate target device\n");
1261 1262 return (CFGA_SATA_DYNAMIC_AP);
1262 1263
1263 1264 } else {
1264 1265
1265 1266 cp = strrchr(devpath, *PATH_SEP);
1266 1267 assert(cp != NULL);
1267 1268 *cp = 0; /* terminate path for opendir() */
1268 1269
1269 1270 (void) strncpy(name_part, cp + 1, MAXNAMELEN);
1270 1271
1271 1272 /*
1272 1273 * Using libdevinfo for this is overkill and kills
1273 1274 * performance when many consumers are using libcfgadm
1274 1275 * concurrently.
1275 1276 */
1276 1277 if ((dp = opendir(devpath)) == NULL) {
1277 1278 goto bailout;
1278 1279 }
1279 1280
1280 1281 /*
1281 1282 * deplen is large enough to fit the largest path-
1282 1283 * struct dirent includes one byte (the terminator)
1283 1284 * so we don't add 1 to the calculation here.
1284 1285 */
1285 1286 deplen = pathconf(devpath, _PC_NAME_MAX);
1286 1287 deplen = ((deplen <= 0) ? MAXNAMELEN : deplen) +
1287 1288 sizeof (struct dirent);
1288 1289 dep = (struct dirent *)malloc(deplen);
1289 1290 if (dep == NULL)
1290 1291 goto bailout;
1291 1292
1292 1293 while ((err = readdir_r(dp, dep, &newdep)) == 0 &&
1293 1294 newdep != NULL) {
1294 1295
1295 1296 assert(newdep == dep);
1296 1297
1297 1298 if (strcmp(dep->d_name, ".") == 0 ||
1298 1299 strcmp(dep->d_name, "..") == 0 ||
1299 1300 (minor_portion = strchr(dep->d_name,
1300 1301 *MINOR_SEP)) == NULL)
1301 1302 continue;
1302 1303
1303 1304 *minor_portion = 0;
1304 1305 if (strcmp(dep->d_name, name_part) != 0)
1305 1306 continue;
1306 1307 *minor_portion = *MINOR_SEP;
1307 1308
1308 1309 (void) snprintf(minor_path, MAXPATHLEN,
1309 1310 "%s/%s", devpath, dep->d_name);
1310 1311
1311 1312 /*
1312 1313 * Break directly for tape device
1313 1314 */
1314 1315 if (strcmp(type, "tape") == 0)
1315 1316 break;
1316 1317
1317 1318 /*
1318 1319 * If stat() fails, the device *may* be retired.
1319 1320 * Check via libdevinfo if the device has a BLK minor.
1320 1321 * We don't use libdevinfo all the time, since taking
1321 1322 * a snapshot is slower than a stat().
1322 1323 */
1323 1324 if (stat(minor_path, &sb) < 0) {
1324 1325 if (is_devinfo_blk(minor_path)) {
1325 1326 break;
1326 1327 } else {
1327 1328 continue;
1328 1329 }
1329 1330 }
1330 1331
1331 1332 if (S_ISBLK(sb.st_mode))
1332 1333 break;
1333 1334
1334 1335 }
1335 1336
1336 1337 (void) closedir(dp);
1337 1338 free(dep);
1338 1339 free(devpath);
1339 1340
1340 1341 dp = NULL;
1341 1342 dep = NULL;
1342 1343 devpath = NULL;
1343 1344
1344 1345 /*
1345 1346 * If there was an error, or we didn't exit the loop
1346 1347 * by finding a block or character device, bail out.
1347 1348 */
1348 1349 if (err != 0 || newdep == NULL)
1349 1350 goto bailout;
1350 1351
1351 1352 /*
1352 1353 * Look for links to the physical path in /dev/dsk
1353 1354 * and /dev/rmt. So far, sata modue supports disk,
1354 1355 * dvd and tape devices, so we will first look for
1355 1356 * BLOCK devices, and then look for tape devices.
1356 1357 */
1357 1358 (void) physpath_to_devlink("/dev/dsk",
1358 1359 minor_path, &devlink, &l_errno);
1359 1360
1360 1361 /* postprocess and copy logical name here */
1361 1362 if (devlink != NULL) {
1362 1363 /*
1363 1364 * For disks, remove partition/slice info
1364 1365 */
1365 1366 if ((cp = strstr(devlink, "dsk/")) != NULL) {
1366 1367 /* cXtYdZ[(s[0..15])|(p[0..X])] */
1367 1368 if ((p = strchr(cp + 4, 'd')) != NULL) {
1368 1369 p++; /* Skip the 'd' */
1369 1370 while (*p != 0 && isdigit(*p))
1370 1371 p++;
1371 1372 *p = 0;
1372 1373 }
1373 1374 *dyncomp = strdup(cp);
1374 1375 }
1375 1376
1376 1377 free(devlink);
1377 1378 } else if (strcmp(type, "tape") == 0) {
1378 1379
1379 1380 /*
1380 1381 * For tape device, logical name looks like
1381 1382 * rmt/X
1382 1383 */
1383 1384 (void) physpath_to_devlink("/dev/rmt",
1384 1385 minor_path, &devlink, &l_errno);
1385 1386
1386 1387 if (devlink != NULL) {
1387 1388 if ((cp = strstr(devlink, "rmt/")) != NULL) {
1388 1389 *dyncomp = strdup(cp);
1389 1390 }
1390 1391
1391 1392 free(devlink);
1392 1393 }
1393 1394 }
1394 1395
1395 1396 return (SATA_CFGA_OK);
1396 1397 }
1397 1398
1398 1399 bailout:
1399 1400 if (dp)
1400 1401 (void) closedir(dp);
1401 1402 if (devpath)
1402 1403 free(devpath);
1403 1404 if (dep)
1404 1405 free(dep);
1405 1406 return (CFGA_SATA_DYNAMIC_AP);
1406 1407 }
1407 1408
1408 1409 /* cfgadm entry point */
1409 1410 /*ARGSUSED*/
1410 1411 cfga_err_t
1411 1412 cfga_list_ext(
1412 1413 const char *ap_id,
1413 1414 cfga_list_data_t **ap_id_list,
1414 1415 int *nlistp,
1415 1416 const char *options,
1416 1417 const char *listopts,
1417 1418 char **errstring,
1418 1419 cfga_flags_t flags)
1419 1420 {
1420 1421 int l_errno;
1421 1422 char *ap_id_log = NULL;
1422 1423 size_t size;
1423 1424 nvlist_t *user_nvlist = NULL;
1424 1425 devctl_hdl_t devctl_hdl = NULL;
1425 1426 cfga_sata_ret_t rv = CFGA_SATA_OK;
1426 1427 devctl_ap_state_t devctl_ap_state;
1427 1428 char *pdyn;
1428 1429 boolean_t pmult = B_FALSE;
1429 1430 uint32_t port;
1430 1431
1431 1432
1432 1433 if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SATA_OK) {
1433 1434 (void) cfga_help(NULL, options, flags);
1434 1435 goto bailout;
1435 1436 }
1436 1437 /* We do not care here about dynamic AP name component */
1437 1438 if ((pdyn = GET_DYN(ap_id)) != NULL) {
1438 1439 *pdyn = '\0';
1439 1440 }
1440 1441
1441 1442 if (ap_id_list == NULL || nlistp == NULL) {
1442 1443 rv = CFGA_SATA_DATA_ERROR;
1443 1444 (void) cfga_help(NULL, options, flags);
1444 1445 goto bailout;
1445 1446 }
1446 1447
1447 1448 /* Get ap status */
1448 1449 if ((rv = setup_for_devctl_cmd(ap_id, &devctl_hdl, &user_nvlist,
1449 1450 DC_RDONLY)) != CFGA_SATA_OK) {
1450 1451 goto bailout;
1451 1452 }
1452 1453
1453 1454 /* will call dc_cmd to send IOCTL to kernel */
1454 1455 if (devctl_ap_getstate(devctl_hdl, user_nvlist,
1455 1456 &devctl_ap_state) == -1) {
1456 1457 cleanup_after_devctl_cmd(devctl_hdl, user_nvlist);
1457 1458 rv = CFGA_SATA_IOCTL;
1458 1459 goto bailout;
1459 1460 }
1460 1461
1461 1462 cleanup_after_devctl_cmd(devctl_hdl, user_nvlist);
1462 1463
1463 1464 /*
1464 1465 * Create cfga_list_data_t struct.
1465 1466 */
1466 1467 if ((*ap_id_list =
1467 1468 (cfga_list_data_t *)malloc(sizeof (**ap_id_list))) == NULL) {
1468 1469 rv = CFGA_SATA_ALLOC_FAIL;
1469 1470 goto bailout;
1470 1471 }
1471 1472 *nlistp = 1;
1472 1473
1473 1474 /*
1474 1475 * Rest of the code fills in the cfga_list_data_t struct.
1475 1476 */
1476 1477
1477 1478 /* Get /dev/cfg path to corresponding to the physical ap_id */
1478 1479 /* Remember ap_id_log must be freed */
1479 1480 rv = physpath_to_devlink(CFGA_DEV_DIR, (char *)ap_id,
1480 1481 &ap_id_log, &l_errno);
1481 1482
1482 1483 if (rv != 0) {
1483 1484 rv = CFGA_SATA_DEVLINK;
1484 1485 goto bailout;
1485 1486 }
1486 1487
1487 1488 /* Get logical ap_id corresponding to the physical */
1488 1489 if (ap_id_log == NULL || strstr(ap_id_log, CFGA_DEV_DIR) == NULL) {
1489 1490 rv = CFGA_SATA_DEVLINK;
1490 1491 goto bailout;
1491 1492 }
1492 1493
1493 1494 (void) strlcpy((*ap_id_list)->ap_log_id,
1494 1495 /* Strip off /dev/cfg/ */ ap_id_log + strlen(CFGA_DEV_DIR)+ 1,
1495 1496 sizeof ((*ap_id_list)->ap_log_id));
1496 1497
1497 1498 free(ap_id_log);
1498 1499 ap_id_log = NULL;
1499 1500
1500 1501 (void) strlcpy((*ap_id_list)->ap_phys_id, ap_id,
1501 1502 sizeof ((*ap_id_list)->ap_phys_id));
1502 1503
1503 1504 switch (devctl_ap_state.ap_rstate) {
1504 1505 case AP_RSTATE_EMPTY:
1505 1506 (*ap_id_list)->ap_r_state = CFGA_STAT_EMPTY;
1506 1507 break;
1507 1508
1508 1509 case AP_RSTATE_DISCONNECTED:
1509 1510 (*ap_id_list)->ap_r_state = CFGA_STAT_DISCONNECTED;
1510 1511 break;
1511 1512
1512 1513 case AP_RSTATE_CONNECTED:
1513 1514 (*ap_id_list)->ap_r_state = CFGA_STAT_CONNECTED;
1514 1515 break;
1515 1516
1516 1517 default:
1517 1518 rv = CFGA_SATA_STATE;
1518 1519 goto bailout;
1519 1520 }
1520 1521
1521 1522 switch (devctl_ap_state.ap_ostate) {
1522 1523 case AP_OSTATE_CONFIGURED:
1523 1524 (*ap_id_list)->ap_o_state = CFGA_STAT_CONFIGURED;
1524 1525 break;
1525 1526
1526 1527 case AP_OSTATE_UNCONFIGURED:
1527 1528 (*ap_id_list)->ap_o_state = CFGA_STAT_UNCONFIGURED;
1528 1529 break;
1529 1530
1530 1531 default:
1531 1532 rv = CFGA_SATA_STATE;
1532 1533 goto bailout;
1533 1534 }
1534 1535
1535 1536 switch (devctl_ap_state.ap_condition) {
1536 1537 case AP_COND_OK:
1537 1538 (*ap_id_list)->ap_cond = CFGA_COND_OK;
1538 1539 break;
1539 1540
1540 1541 case AP_COND_FAILING:
1541 1542 (*ap_id_list)->ap_cond = CFGA_COND_FAILING;
1542 1543 break;
1543 1544
1544 1545 case AP_COND_FAILED:
1545 1546 (*ap_id_list)->ap_cond = CFGA_COND_FAILED;
1546 1547 break;
1547 1548
1548 1549 case AP_COND_UNUSABLE:
1549 1550 (*ap_id_list)->ap_cond = CFGA_COND_UNUSABLE;
1550 1551 break;
1551 1552
1552 1553 case AP_COND_UNKNOWN:
1553 1554 (*ap_id_list)->ap_cond = CFGA_COND_UNKNOWN;
1554 1555 break;
1555 1556
1556 1557 default:
1557 1558 rv = CFGA_SATA_STATE;
1558 1559 goto bailout;
1559 1560 }
1560 1561
1561 1562 (*ap_id_list)->ap_class[0] = '\0'; /* Filled by libcfgadm */
1562 1563 (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition;
1563 1564 (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change;
1564 1565 (*ap_id_list)->ap_info[0] = NULL;
1565 1566
|
↓ open down ↓ |
295 lines elided |
↑ open up ↑ |
1566 1567 if ((*ap_id_list)->ap_r_state == CFGA_STAT_CONNECTED) {
1567 1568 char *str_p;
1568 1569 int skip, i;
1569 1570
1570 1571 /*
1571 1572 * Fill in the 'Information' field for the -v option
1572 1573 * Model (MOD:)
1573 1574 */
1574 1575 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_MODEL_INFO,
1575 1576 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1576 - (void) printf(
1577 + DPRINTF(
1577 1578 "SATA_CFGA_GET_MODULE_INFO ioctl failed\n");
1578 1579 goto bailout;
1579 1580 }
1580 1581 /* drop leading and trailing spaces */
1581 1582 skip = strspn(str_p, " ");
1582 1583 for (i = size - 1; i >= 0; i--) {
1583 1584 if (str_p[i] == '\040')
1584 1585 str_p[i] = '\0';
1585 1586 else if (str_p[i] != '\0')
1586 1587 break;
1587 1588 }
1588 1589
1589 1590 (void) strlcpy((*ap_id_list)->ap_info, "Mod: ",
1590 1591 sizeof ((*ap_id_list)->ap_info));
1591 1592 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1592 1593 sizeof ((*ap_id_list)->ap_info));
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1593 1594
1594 1595 free(str_p);
1595 1596
1596 1597 /*
1597 1598 * Fill in the 'Information' field for the -v option
1598 1599 * Firmware revision (FREV:)
1599 1600 */
1600 1601 if ((rv = do_control_ioctl(ap_id,
1601 1602 SATA_CFGA_GET_REVFIRMWARE_INFO,
1602 1603 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1603 - (void) printf(
1604 + DPRINTF(
1604 1605 "SATA_CFGA_GET_REVFIRMWARE_INFO ioctl failed\n");
1605 1606 goto bailout;
1606 1607 }
1607 1608 /* drop leading and trailing spaces */
1608 1609 skip = strspn(str_p, " ");
1609 1610 for (i = size - 1; i >= 0; i--) {
1610 1611 if (str_p[i] == '\040')
1611 1612 str_p[i] = '\0';
1612 1613 else if (str_p[i] != '\0')
1613 1614 break;
1614 1615 }
1615 1616 (void) strlcat((*ap_id_list)->ap_info, " FRev: ",
1616 1617 sizeof ((*ap_id_list)->ap_info));
1617 1618 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1618 1619 sizeof ((*ap_id_list)->ap_info));
1619 1620
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1620 1621 free(str_p);
1621 1622
1622 1623
1623 1624 /*
1624 1625 * Fill in the 'Information' field for the -v option
1625 1626 * Serial Number (SN:)
1626 1627 */
1627 1628 if ((rv = do_control_ioctl(ap_id,
1628 1629 SATA_CFGA_GET_SERIALNUMBER_INFO,
1629 1630 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1630 - (void) printf(
1631 + DPRINTF(
1631 1632 "SATA_CFGA_GET_SERIALNUMBER_INFO ioctl failed\n");
1632 1633 goto bailout;
1633 1634 }
1634 1635 /* drop leading and trailing spaces */
1635 1636 skip = strspn(str_p, " ");
1636 1637 for (i = size - 1; i >= 0; i--) {
1637 1638 if (str_p[i] == '\040')
1638 1639 str_p[i] = '\0';
1639 1640 else if (str_p[i] != '\0')
1640 1641 break;
1641 1642 }
1642 1643 (void) strlcat((*ap_id_list)->ap_info, " SN: ",
1643 1644 sizeof ((*ap_id_list)->ap_info));
1644 1645 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
1645 1646 sizeof ((*ap_id_list)->ap_info));
1646 1647
1647 1648 free(str_p);
1648 1649
1649 1650
1650 1651
1651 1652 /* Fill in ap_type which is collected from HBA driver */
1652 1653 /* call do_control_ioctl TBD */
1653 1654 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
1654 1655 (void **)&str_p, &size)) != CFGA_SATA_OK) {
1655 - (void) printf(
1656 + DPRINTF(
1656 1657 "SATA_CFGA_GET_AP_TYPE ioctl failed\n");
1657 1658 goto bailout;
1658 1659 }
1659 1660
1660 1661 (void) strlcpy((*ap_id_list)->ap_type, str_p,
1661 1662 sizeof ((*ap_id_list)->ap_type));
1662 1663
1663 1664 free(str_p);
1664 1665
1665 1666 /*
1666 1667 * Checking device type. Port multiplier has no dynamic
1667 1668 * suffix.
1668 1669 */
1669 1670 if (strncmp((*ap_id_list)->ap_type, "sata-pmult",
1670 1671 sizeof ("sata-pmult")) == 0)
1671 1672 pmult = B_TRUE;
1672 1673
1673 1674 if ((*ap_id_list)->ap_o_state == CFGA_STAT_CONFIGURED &&
1674 1675 pmult == B_FALSE) {
1675 1676
1676 1677 char *dyncomp = NULL;
1677 1678
1678 1679 /*
1679 1680 * This is the case where we need to generate
1680 1681 * a dynamic component of the ap_id, i.e. device.
1681 1682 */
1682 1683 rv = sata_make_dyncomp(ap_id, &dyncomp,
1683 1684 (*ap_id_list)->ap_type);
1684 1685 if (rv != CFGA_SATA_OK)
1685 1686 goto bailout;
1686 1687 if (dyncomp != NULL) {
1687 1688 (void) strcat((*ap_id_list)->ap_log_id,
1688 1689 DYN_SEP);
1689 1690 (void) strlcat((*ap_id_list)->ap_log_id,
1690 1691 dyncomp,
1691 1692 sizeof ((*ap_id_list)->ap_log_id));
1692 1693 free(dyncomp);
1693 1694 }
1694 1695 }
1695 1696
1696 1697 } else {
1697 1698 /* This is an empty port */
1698 1699 if (get_port_num(ap_id, &port) != CFGA_SATA_OK) {
1699 1700 goto bailout;
1700 1701 }
1701 1702
1702 1703 if (port & SATA_CFGA_PMPORT_QUAL) {
1703 1704 (void) strlcpy((*ap_id_list)->ap_type, "pmult-port",
1704 1705 sizeof ((*ap_id_list)->ap_type));
1705 1706 } else {
1706 1707 (void) strlcpy((*ap_id_list)->ap_type, "sata-port",
1707 1708 sizeof ((*ap_id_list)->ap_type));
1708 1709 }
1709 1710 }
1710 1711
1711 1712 return (sata_err_msg(errstring, rv, ap_id, errno));
1712 1713
1713 1714 bailout:
1714 1715 if (*ap_id_list != NULL) {
1715 1716 free(*ap_id_list);
1716 1717 }
1717 1718 if (ap_id_log != NULL) {
1718 1719 free(ap_id_log);
1719 1720 }
1720 1721
1721 1722 return (sata_err_msg(errstring, rv, ap_id, errno));
1722 1723 }
1723 1724 /*
|
↓ open down ↓ |
58 lines elided |
↑ open up ↑ |
1724 1725 * This routine accepts a string adn prints it using
1725 1726 * the message print routine argument.
1726 1727 */
1727 1728 static void
1728 1729 cfga_msg(struct cfga_msg *msgp, const char *str)
1729 1730 {
1730 1731 int len;
1731 1732 char *q;
1732 1733
1733 1734 if (msgp == NULL || msgp->message_routine == NULL) {
1734 - (void) printf("cfga_msg: NULL msgp\n");
1735 + DPRINTF("cfga_msg: msg\n");
1735 1736 return;
1736 1737 }
1737 1738
1738 1739 if ((len = strlen(str)) == 0) {
1739 - (void) printf("cfga_msg: null str\n");
1740 + DPRINTF("cfga_msg: null str\n");
1740 1741 return;
1741 1742 }
1742 1743
1743 1744 if ((q = (char *)calloc(len + 1, 1)) == NULL) {
1744 - perror("cfga_msg");
1745 + DPRINTF("cfga_msg: null q\n");
1745 1746 return;
1746 1747 }
1747 1748
1748 1749 (void) strcpy(q, str);
1749 1750 (*msgp->message_routine)(msgp->appdata_ptr, q);
1750 1751
1751 1752 free(q);
1752 1753 }
1753 1754
1754 1755 /* cfgadm entry point */
1755 1756 /* ARGSUSED */
1756 1757 cfga_err_t
1757 1758 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
1758 1759 {
1759 1760 if (options != NULL) {
1760 1761 cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_UNKNOWN]));
1761 1762 cfga_msg(msgp, options);
1762 1763 }
1763 1764 cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]));
1764 1765 cfga_msg(msgp, sata_help[HELP_CONFIG]);
1765 1766 cfga_msg(msgp, sata_help[HELP_RESET_PORT]);
1766 1767 cfga_msg(msgp, sata_help[HELP_RESET_DEVICE]);
1767 1768 cfga_msg(msgp, sata_help[HELP_RESET_ALL]);
1768 1769 cfga_msg(msgp, sata_help[HELP_PORT_ACTIVATE]);
1769 1770 cfga_msg(msgp, sata_help[HELP_PORT_DEACTIVATE]);
1770 1771 cfga_msg(msgp, sata_help[HELP_PORT_SELF_TEST]);
1771 1772 cfga_msg(msgp, sata_help[HELP_CNTRL_SELF_TEST]);
1772 1773
1773 1774 return (CFGA_OK);
1774 1775 }
1775 1776
1776 1777
1777 1778 /*
1778 1779 * Ensure the ap_id passed is in the correct (physical ap_id) form:
1779 1780 * path/device:xx[.xx]
1780 1781 * where xx is a one or two-digit number.
1781 1782 *
1782 1783 * Note the library always calls the plugin with a physical ap_id.
1783 1784 */
1784 1785 static int
1785 1786 verify_valid_apid(const char *ap_id)
1786 1787 {
1787 1788 char *l_ap_id;
1788 1789
1789 1790 if (ap_id == NULL)
1790 1791 return (-1);
1791 1792
1792 1793 l_ap_id = strrchr(ap_id, (int)*MINOR_SEP);
1793 1794 l_ap_id++;
1794 1795
1795 1796 if (strspn(l_ap_id, "0123456789.") != strlen(l_ap_id)) {
1796 1797 /* Bad characters in the ap_id */
1797 1798 return (-1);
1798 1799 }
1799 1800
1800 1801 if (strstr(l_ap_id, "..") != NULL) {
1801 1802 /* ap_id has 1..2 or more than 2 dots */
1802 1803 return (-1);
1803 1804 }
1804 1805
1805 1806 return (0);
1806 1807 }
1807 1808
1808 1809
1809 1810
1810 1811 /*
1811 1812 * Verify the params passed in are valid.
1812 1813 */
1813 1814 static cfga_sata_ret_t
1814 1815 verify_params(
1815 1816 const char *ap_id,
1816 1817 const char *options,
|
↓ open down ↓ |
62 lines elided |
↑ open up ↑ |
1817 1818 char **errstring)
1818 1819 {
1819 1820 char *pdyn, *lap_id;
1820 1821 int rv;
1821 1822
1822 1823 if (errstring != NULL) {
1823 1824 *errstring = NULL;
1824 1825 }
1825 1826
1826 1827 if (options != NULL) {
1828 + DPRINTF("verify_params: hardware-specific options not "
1829 + "supported.\n");
1827 1830 return (CFGA_SATA_OPTIONS);
1828 1831 }
1829 1832
1830 1833 /* Strip dynamic AP name component if it is present. */
1831 1834 lap_id = strdup(ap_id);
1832 1835 if (lap_id == NULL) {
1833 1836 return (CFGA_SATA_ALLOC_FAIL);
1834 1837 }
1835 1838 if ((pdyn = GET_DYN(lap_id)) != NULL) {
1836 1839 *pdyn = '\0';
1837 1840 }
1838 1841
1839 1842 if (verify_valid_apid(lap_id) != 0) {
1843 + DPRINTF("verify_params: not a SATA ap_id.\n");
1840 1844 rv = CFGA_SATA_AP;
1841 1845 } else {
1842 1846 rv = CFGA_SATA_OK;
1843 1847 }
1844 1848 free(lap_id);
1845 1849
1846 1850 return (rv);
1847 1851 }
1848 1852
1849 1853 /*
1850 1854 * Takes a validated ap_id and extracts the port number.
1851 1855 * Port multiplier is supported now.
1852 1856 */
1853 1857 static cfga_sata_ret_t
1854 1858 get_port_num(const char *ap_id, uint32_t *port)
1855 1859 {
1856 1860 uint32_t cport, pmport = 0, qual = 0;
1857 1861 char *cport_str, *pmport_str;
1858 1862
1859 1863 /* Get the cport number */
1860 1864 cport_str = strrchr(ap_id, (int)*MINOR_SEP) + strlen(MINOR_SEP);
1861 1865
1862 1866 errno = 0;
1863 1867 cport = strtol(cport_str, NULL, 10);
1864 1868 if ((cport & ~SATA_CFGA_CPORT_MASK) != 0 || errno != 0) {
1865 1869 return (CFGA_SATA_PORT);
1866 1870 }
1867 1871
1868 1872 /* Get pmport number if there is a PORT_SEPARATOR */
1869 1873 errno = 0;
1870 1874 if ((pmport_str = strrchr(ap_id, (int)*PORT_SEPARATOR)) != 0) {
1871 1875 pmport_str += strlen(PORT_SEPARATOR);
1872 1876 pmport = strtol(pmport_str, NULL, 10);
1873 1877 qual = SATA_CFGA_PMPORT_QUAL;
1874 1878 if ((pmport & ~SATA_CFGA_PMPORT_MASK) != 0 || errno != 0) {
1875 1879 return (CFGA_SATA_PORT);
1876 1880 }
1877 1881 }
1878 1882
1879 1883 *port = cport | (pmport << SATA_CFGA_PMPORT_SHIFT) | qual;
1880 1884 return (CFGA_SATA_OK);
1881 1885 }
1882 1886
1883 1887 /*
1884 1888 * Pair of routines to set up for/clean up after a devctl_ap_* lib call.
1885 1889 */
1886 1890 static void
1887 1891 cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist)
1888 1892 {
1889 1893 if (user_nvlist != NULL) {
1890 1894 nvlist_free(user_nvlist);
1891 1895 }
1892 1896 if (devctl_hdl != NULL) {
1893 1897 devctl_release(devctl_hdl);
1894 1898 }
1895 1899 }
1896 1900
1897 1901 static cfga_sata_ret_t
1898 1902 setup_for_devctl_cmd(
1899 1903 const char *ap_id,
1900 1904 devctl_hdl_t *devctl_hdl,
1901 1905 nvlist_t **user_nvlistp,
1902 1906 uint_t oflag)
1903 1907 {
1904 1908
1905 1909 uint_t port;
1906 1910 cfga_sata_ret_t rv = CFGA_SATA_OK;
1907 1911 char *lap_id, *pdyn;
1908 1912
1909 1913 lap_id = strdup(ap_id);
1910 1914 if (lap_id == NULL)
1911 1915 return (CFGA_SATA_ALLOC_FAIL);
1912 1916 if ((pdyn = GET_DYN(lap_id)) != NULL) {
1913 1917 *pdyn = '\0';
1914 1918 }
1915 1919
1916 1920 /* Get a devctl handle to pass to the devctl_ap_XXX functions */
1917 1921 if ((*devctl_hdl = devctl_ap_acquire((char *)lap_id, oflag)) == NULL) {
1918 1922 (void) fprintf(stderr, "[libcfgadm:sata] "
|
↓ open down ↓ |
69 lines elided |
↑ open up ↑ |
1919 1923 "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n",
1920 1924 strerror(errno));
1921 1925 rv = CFGA_SATA_DEVCTL;
1922 1926 goto bailout;
1923 1927 }
1924 1928
1925 1929 /* Set up nvlist to pass the port number down to the driver */
1926 1930 if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) {
1927 1931 *user_nvlistp = NULL;
1928 1932 rv = CFGA_SATA_NVLIST;
1929 - (void) printf("nvlist_alloc failed\n");
1933 + DPRINTF("nvlist_alloc failed\n");
1930 1934 goto bailout;
1931 1935 }
1932 1936
1933 1937 /*
1934 1938 * Get port id, for Port Multiplier port, things could be a little bit
1935 1939 * complicated because of "port.port" format in ap_id, thus for
1936 1940 * port multiplier port, port number should be coded as 32bit int
1937 1941 * with the sig 16 bit as sata channel number, least 16 bit as
1938 1942 * the port number of sata port multiplier port.
1939 1943 */
1940 1944 if ((rv = get_port_num(lap_id, &port)) != CFGA_SATA_OK) {
1941 - (void) printf(
1945 + DPRINTF(
1942 1946 "setup_for_devctl_cmd: get_port_num, errno: %d\n",
1943 1947 errno);
1944 1948 goto bailout;
1945 1949 }
1946 1950
1947 1951 /* Creates an int32_t entry */
1948 1952 if (nvlist_add_int32(*user_nvlistp, PORT, port) == -1) {
1949 - (void) printf("nvlist_add_int32 failed\n");
1953 + DPRINTF("nvlist_add_int32 failed\n");
1950 1954 rv = CFGA_SATA_NVLIST;
1951 1955 goto bailout;
1952 1956 }
1953 1957
1954 1958 free(lap_id);
1955 1959 return (rv);
1956 1960
1957 1961 bailout:
1958 1962 free(lap_id);
1959 1963 (void) cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
1960 1964
1961 1965 return (rv);
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
1962 1966 }
1963 1967
1964 1968
1965 1969 static cfga_sata_ret_t
1966 1970 port_state(devctl_hdl_t hdl, nvlist_t *list,
1967 1971 ap_rstate_t *rstate, ap_ostate_t *ostate)
1968 1972 {
1969 1973 devctl_ap_state_t devctl_ap_state;
1970 1974
1971 1975 if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) {
1972 - (void) printf("devctl_ap_getstate failed, errno: %d\n", errno);
1976 + DPRINTF("devctl_ap_getstate failed, errno: %d\n", errno);
1973 1977 return (CFGA_SATA_IOCTL);
1974 1978 }
1975 1979 *rstate = devctl_ap_state.ap_rstate;
1976 1980 *ostate = devctl_ap_state.ap_ostate;
1977 1981 return (CFGA_SATA_OK);
1978 1982 }
1979 1983
1980 1984
1981 1985 /*
1982 1986 * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
1983 1987 * the data to be returned, allocate a buffer, then get the data.
1984 1988 * Returns *descrp (which must be freed) and size.
1985 1989 *
1986 1990 * Note SATA_DESCR_TYPE_STRING returns an ASCII NULL-terminated string,
1987 1991 * not a string descr.
1988 1992 */
1989 1993 cfga_sata_ret_t
1990 1994 do_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
1991 1995 void **descrp, size_t *sizep)
1992 1996 {
1993 1997 int fd = -1;
1994 1998 uint_t port;
1995 1999 uint32_t local_size;
1996 2000 cfga_sata_ret_t rv = CFGA_SATA_OK;
1997 2001 struct sata_ioctl_data ioctl_data;
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
1998 2002
1999 2003 assert(descrp != NULL);
2000 2004 *descrp = NULL;
2001 2005 assert(sizep != NULL);
2002 2006
2003 2007 if ((rv = get_port_num(ap_id, &port)) != CFGA_SATA_OK) {
2004 2008 goto bailout;
2005 2009 }
2006 2010
2007 2011 if ((fd = open(ap_id, O_RDONLY)) == -1) {
2008 - (void) printf("do_control_ioctl: open failed: errno:%d\n",
2012 + DPRINTF("do_control_ioctl: open failed: errno:%d\n",
2009 2013 errno);
2010 2014 rv = CFGA_SATA_OPEN;
2011 2015 if (errno == EBUSY) {
2012 2016 rv = CFGA_SATA_BUSY;
2013 2017 }
2014 2018 goto bailout;
2015 2019 }
2016 2020
2017 2021 ioctl_data.cmd = subcommand;
2018 2022 ioctl_data.port = port;
2019 2023 ioctl_data.misc_arg = (uint_t)arg;
2020 2024
2021 2025 /*
2022 2026 * Find out how large a buf we need to get the data.
2023 2027 * Note the ioctls only accept/return a 32-bit int for a get_size
2024 2028 * to avoid 32/64 and BE/LE issues.
2025 2029 */
2026 2030 if ((subcommand == SATA_CFGA_GET_AP_TYPE) ||
2027 2031 (subcommand == SATA_CFGA_GET_DEVICE_PATH) ||
2028 2032 (subcommand == SATA_CFGA_GET_MODEL_INFO) ||
2029 2033 (subcommand == SATA_CFGA_GET_REVFIRMWARE_INFO) ||
2030 2034 (subcommand == SATA_CFGA_GET_SERIALNUMBER_INFO)) {
2031 2035 ioctl_data.get_size = B_TRUE;
2032 2036 ioctl_data.buf = (caddr_t)&local_size;
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
2033 2037 ioctl_data.bufsiz = sizeof (local_size);
2034 2038
2035 2039 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2036 2040 perror("ioctl failed (size)");
2037 2041 rv = CFGA_SATA_IOCTL;
2038 2042 goto bailout;
2039 2043 }
2040 2044 *sizep = local_size;
2041 2045
2042 2046 if (local_size == 0) {
2043 - (void) printf("zero length data\n");
2047 + DPRINTF("zero length data\n");
2044 2048 rv = CFGA_SATA_ZEROLEN;
2045 2049 goto bailout;
2046 2050 }
2047 2051 if ((*descrp = malloc(*sizep)) == NULL) {
2048 - (void) printf("do_control_ioctl: malloc failed\n");
2052 + DPRINTF("do_control_ioctl: malloc failed\n");
2049 2053 rv = CFGA_SATA_ALLOC_FAIL;
2050 2054 goto bailout;
2051 2055 }
2052 2056 } else {
2053 2057 *sizep = 0;
2054 2058 }
2055 2059 ioctl_data.get_size = B_FALSE;
2056 2060 ioctl_data.buf = *descrp;
2057 2061 ioctl_data.bufsiz = *sizep;
2058 2062
2059 2063 /* Execute IOCTL */
2060 2064
2061 2065 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2062 2066 rv = CFGA_SATA_IOCTL;
2063 2067 goto bailout;
2064 2068 }
2065 2069
2066 2070 (void) close(fd);
2067 2071
2068 2072 return (rv);
2069 2073
2070 2074 bailout:
2071 2075 if (fd != -1) {
2072 2076 (void) close(fd);
2073 2077 }
2074 2078 if (*descrp != NULL) {
2075 2079 free(*descrp);
2076 2080 *descrp = NULL;
2077 2081 }
2078 2082
2079 2083 if (rv == CFGA_SATA_IOCTL && errno == EBUSY) {
2080 2084 rv = CFGA_SATA_BUSY;
2081 2085 }
2082 2086
2083 2087 return (rv);
2084 2088 }
2085 2089
2086 2090
2087 2091 static int
2088 2092 sata_confirm(struct cfga_confirm *confp, char *msg)
2089 2093 {
2090 2094 int rval;
2091 2095
2092 2096 if (confp == NULL || confp->confirm == NULL) {
2093 2097 return (0);
2094 2098 }
2095 2099 rval = (*confp->confirm)(confp->appdata_ptr, msg);
2096 2100
2097 2101 return (rval);
2098 2102 }
2099 2103
2100 2104
2101 2105 static char *
2102 2106 sata_get_devicepath(const char *ap_id)
2103 2107 {
2104 2108 char *devpath = NULL;
2105 2109 size_t size;
2106 2110 cfga_sata_ret_t rv;
2107 2111
2108 2112 rv = do_control_ioctl(ap_id, SATA_CFGA_GET_DEVICE_PATH, NULL,
2109 2113 (void **)&devpath, &size);
2110 2114
2111 2115 if (rv == CFGA_SATA_OK) {
2112 2116 return (devpath);
2113 2117 } else {
2114 2118 return ((char *)NULL);
2115 2119 }
2116 2120
2117 2121 }
|
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX