dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / cfgadm_plugins / scsi / common / cfga_ctl.c
blob6b1139f00f2d9339233238e9066522c07c599d34
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include "cfga_scsi.h"
29 struct larg {
30 int ndevs;
31 int nelem;
32 char *dev;
33 char **dev_list;
36 #define ETC_VFSTAB "/etc/vfstab"
37 #define SCFGA_LOCK "/var/run/cfgadm_scsi"
39 /* Function prototypes */
41 static scfga_ret_t quiesce_confirm(apid_t *apidp,
42 msgid_t cmd_msg, prompt_t *pt, int *okp, int *quiesce, int *l_errnop);
43 static scfga_ret_t dev_hotplug(apid_t *apidp,
44 prompt_t *pt, cfga_flags_t flags, int quiesce, char **errstring);
45 static int disconnect(struct cfga_confirm *confp);
46 static int critical_ctrlr(const char *hba_phys);
47 static cfga_stat_t bus_devctl_to_recep_state(uint_t bus_dc_state);
48 static int get_hba_children(char *bus_path, char *dev_excl, char ***dev_list);
49 static char *get_node_path(char *minor_path);
50 static void free_dev_list_elements(char **dev_list);
51 static void free_dev_list(char **dev_list);
52 static int alloc_dev_list(struct larg *largp);
55 * Single thread all implicit quiesce operations
57 static mutex_t quiesce_mutex = DEFAULTMUTEX;
59 /*ARGSUSED*/
60 scfga_ret_t
61 bus_change_state(
62 cfga_cmd_t state_change_cmd,
63 apid_t *apidp,
64 struct cfga_confirm *confp,
65 cfga_flags_t flags,
66 char **errstring)
68 int l_errno = 0, force;
69 uint_t state = 0;
70 cfga_stat_t bus_state;
71 scfga_cmd_t cmd;
72 msgid_t errid;
73 cfga_stat_t prereq;
74 scfga_ret_t ret;
75 char **dev_list = NULL;
77 assert(apidp->path != NULL);
78 assert(apidp->hba_phys != NULL);
81 * No dynamic components allowed
83 if (apidp->dyncomp != NULL) {
84 cfga_err(errstring, 0, ERR_NOT_BUSAPID, 0);
85 return (SCFGA_ERR);
88 /* Get bus state */
89 if (devctl_cmd(apidp->path, SCFGA_BUS_GETSTATE, &state,
90 &l_errno) != SCFGA_OK) {
91 cfga_err(errstring, l_errno, ERR_BUS_GETSTATE, 0);
92 return (SCFGA_ERR);
95 bus_state = bus_devctl_to_recep_state(state);
96 force = ((flags & CFGA_FLAG_FORCE) == CFGA_FLAG_FORCE) ? 1 : 0;
97 assert(confp->confirm != NULL);
99 switch (state_change_cmd) {
100 case CFGA_CMD_DISCONNECT: /* quiesce bus */
102 * If force flag not specified, check if controller is
103 * critical.
105 if (!force) {
107 * This check is not foolproof, get user confirmation
108 * if test passes.
110 if (critical_ctrlr(apidp->path)) {
111 cfga_err(errstring, 0, ERR_CTRLR_CRIT, 0);
112 ret = SCFGA_ERR;
113 break;
114 } else if (!disconnect(confp)) {
115 ret = SCFGA_NACK;
116 break;
120 cmd = SCFGA_BUS_QUIESCE;
121 errid = ERR_BUS_QUIESCE;
122 prereq = CFGA_STAT_CONNECTED;
124 goto common;
126 case CFGA_CMD_CONNECT: /* unquiesce bus */
127 cmd = SCFGA_BUS_UNQUIESCE;
128 errid = ERR_BUS_UNQUIESCE;
129 prereq = CFGA_STAT_DISCONNECTED;
131 goto common;
133 case CFGA_CMD_CONFIGURE:
134 cmd = SCFGA_BUS_CONFIGURE;
135 errid = ERR_BUS_CONFIGURE;
136 prereq = CFGA_STAT_CONNECTED;
138 goto common;
140 case CFGA_CMD_UNCONFIGURE:
141 cmd = SCFGA_BUS_UNCONFIGURE;
142 errid = ERR_BUS_UNCONFIGURE;
143 prereq = CFGA_STAT_CONNECTED;
145 /* FALLTHROUGH */
146 common:
147 if (bus_state != prereq) {
148 cfga_err(errstring, 0,
149 (prereq == CFGA_STAT_CONNECTED)
150 ? ERR_BUS_NOTCONNECTED
151 : ERR_BUS_CONNECTED, 0);
152 ret = SCFGA_ERR;
153 break;
157 * When quiescing or unconfiguring a bus, first suspend or
158 * offline it through RCM.
159 * For unquiescing, we simple build the dev_list for
160 * resume notification.
162 if (((apidp->flags & FLAG_DISABLE_RCM) == 0) &&
163 ((cmd == SCFGA_BUS_QUIESCE) ||
164 (cmd == SCFGA_BUS_UNQUIESCE) ||
165 (cmd == SCFGA_BUS_UNCONFIGURE))) {
166 ret = get_hba_children(apidp->path, NULL, &dev_list);
167 if (ret != SCFGA_OK) {
168 break;
170 if (cmd == SCFGA_BUS_QUIESCE) {
171 if ((ret = scsi_rcm_suspend(dev_list,
172 errstring, flags, 1)) != SCFGA_OK) {
173 break;
175 } else if (cmd == SCFGA_BUS_UNCONFIGURE) {
176 if ((ret = scsi_rcm_offline(dev_list,
177 errstring, flags)) != SCFGA_OK) {
178 break;
183 ret = devctl_cmd(apidp->path, cmd, NULL, &l_errno);
184 if (ret != SCFGA_OK) {
186 * EIO when child devices are busy may confuse user.
187 * So explain it.
189 if (cmd == SCFGA_BUS_UNCONFIGURE && l_errno == EIO)
190 errid = ERR_MAYBE_BUSY;
192 cfga_err(errstring, l_errno, errid, 0);
195 * If the bus was suspended in RCM, then cancel the RCM
196 * operation. Discard RCM failures here because the
197 * devctl's failure is what is most relevant.
199 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) {
200 if (cmd == SCFGA_BUS_QUIESCE)
201 (void) scsi_rcm_resume(dev_list,
202 errstring,
203 (flags & (~CFGA_FLAG_FORCE)), 1);
204 else if (cmd == SCFGA_BUS_UNCONFIGURE) {
205 (void) devctl_cmd(apidp->path,
206 SCFGA_BUS_CONFIGURE, NULL,
207 &l_errno);
208 (void) scsi_rcm_online(dev_list,
209 errstring,
210 (flags & (~CFGA_FLAG_FORCE)));
214 break;
218 * When unquiescing or configuring a bus, resume or online it
219 * in RCM when the devctl command is complete.
220 * When unconfiguring a bus, notify removal of devices.
222 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) {
223 if (cmd == SCFGA_BUS_UNQUIESCE) {
224 ret = scsi_rcm_resume(dev_list, errstring,
225 (flags & (~CFGA_FLAG_FORCE)), 1);
226 } else if (cmd == SCFGA_BUS_UNCONFIGURE) {
227 ret = scsi_rcm_remove(dev_list, errstring,
228 (flags & (~CFGA_FLAG_FORCE)));
231 break;
233 case CFGA_CMD_LOAD:
234 case CFGA_CMD_UNLOAD:
235 ret = SCFGA_OPNOTSUPP;
236 break;
238 default:
239 cfga_err(errstring, 0, ERR_CMD_INVAL, 0);
240 ret = SCFGA_ERR;
241 break;
244 free_dev_list(dev_list);
245 return (ret);
248 scfga_ret_t
249 dev_change_state(
250 cfga_cmd_t state_change_cmd,
251 apid_t *apidp,
252 cfga_flags_t flags,
253 char **errstring)
255 uint_t state = 0;
256 int l_errno = 0;
257 cfga_stat_t bus_state;
258 scfga_cmd_t cmd;
259 msgid_t errid;
260 scfga_ret_t ret;
261 char *dev_list[2] = {NULL};
263 assert(apidp->path != NULL);
264 assert(apidp->hba_phys != NULL);
267 * For a device, dynamic component must be present
269 if (apidp->dyncomp == NULL) {
270 cfga_err(errstring, 0, ERR_APID_INVAL, 0);
271 return (SCFGA_ERR);
274 /* Get bus state */
275 if (devctl_cmd(apidp->hba_phys, SCFGA_BUS_GETSTATE, &state,
276 &l_errno) != SCFGA_OK) {
277 cfga_err(errstring, l_errno, ERR_BUS_GETSTATE, 0);
278 return (SCFGA_ERR);
281 bus_state = bus_devctl_to_recep_state(state);
283 switch (state_change_cmd) {
284 case CFGA_CMD_CONFIGURE: /* online device */
285 cmd = SCFGA_DEV_CONFIGURE;
286 errid = ERR_DEV_CONFIGURE;
287 goto common;
289 case CFGA_CMD_UNCONFIGURE: /* offline device */
290 cmd = SCFGA_DEV_UNCONFIGURE;
291 errid = ERR_DEV_UNCONFIGURE;
292 /* FALLTHROUGH */
293 common:
294 if (bus_state != CFGA_STAT_CONNECTED) {
295 cfga_err(errstring, 0, ERR_BUS_NOTCONNECTED, 0);
296 ret = SCFGA_ERR;
297 break;
300 if (apidp->dyntype == PATH_APID) {
301 /* call a scsi_vhci ioctl to do online/offline path. */
302 ret = path_apid_state_change(apidp, cmd,
303 flags, errstring, &l_errno, errid);
304 } else {
306 * When unconfiguring a device, first offline it
307 * through RCM.
309 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) {
310 if (cmd == SCFGA_DEV_UNCONFIGURE) {
311 dev_list[0] =
312 get_node_path(apidp->path);
313 if (dev_list[0] == NULL) {
314 ret = SCFGA_ERR;
315 break;
317 if ((ret = scsi_rcm_offline(dev_list,
318 errstring, flags)) != SCFGA_OK) {
319 break;
324 ret = devctl_cmd(apidp->path, cmd, NULL, &l_errno);
325 if (ret != SCFGA_OK) {
326 cfga_err(errstring, l_errno, errid, 0);
329 * If an unconfigure fails, cancel the RCM offline.
330 * Discard any RCM failures so that the devctl
331 * failure will still be reported.
333 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) {
334 if (cmd == SCFGA_DEV_UNCONFIGURE)
335 (void) scsi_rcm_online(dev_list,
336 errstring, flags);
338 break;
340 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) {
342 * Unconfigure succeeded, call the RCM notify_remove.
344 if (cmd == SCFGA_DEV_UNCONFIGURE)
345 (void) scsi_rcm_remove(dev_list,
346 errstring, flags);
349 break;
352 * Cannot disconnect/connect individual devices without affecting
353 * other devices on the bus. So we don't support these ops.
355 case CFGA_CMD_DISCONNECT:
356 case CFGA_CMD_CONNECT:
357 cfga_err(errstring, 0, ERR_NOT_DEVOP, 0);
358 ret = SCFGA_ERR;
359 break;
360 case CFGA_CMD_LOAD:
361 case CFGA_CMD_UNLOAD:
362 ret = SCFGA_OPNOTSUPP;
363 break;
364 default:
365 cfga_err(errstring, 0, ERR_CMD_INVAL, 0);
366 ret = SCFGA_ERR;
367 break;
370 free_dev_list_elements(dev_list);
371 return (ret);
374 /*ARGSUSED*/
375 scfga_ret_t
376 dev_remove(
377 const char *func,
378 scfga_cmd_t cmd,
379 apid_t *apidp,
380 prompt_t *prp,
381 cfga_flags_t flags,
382 char **errstring)
384 int proceed, l_errno = 0;
385 scfga_ret_t ret;
386 int do_quiesce;
387 char *dev_list[2] = {NULL};
389 assert(apidp->hba_phys != NULL);
390 assert(apidp->path != NULL);
392 /* device operation only */
393 if (apidp->dyncomp == NULL) {
394 cfga_err(errstring, 0, ERR_NOT_BUSOP, 0);
395 return (SCFGA_ERR);
398 proceed = 1;
399 ret = quiesce_confirm(apidp, MSG_RMDEV, prp, &proceed, &do_quiesce,
400 &l_errno);
401 if (ret != SCFGA_OK) {
402 cfga_err(errstring, l_errno, ERR_DEV_REMOVE, 0);
403 return (ret);
406 if (!proceed) {
407 return (SCFGA_NACK);
411 * Offline the device in RCM
413 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) {
414 dev_list[0] = get_node_path(apidp->path);
415 if (dev_list[0] == NULL)
416 return (SCFGA_ERR);
417 if ((ret = scsi_rcm_offline(dev_list, errstring, flags))
418 != SCFGA_OK) {
419 free_dev_list_elements(dev_list);
420 return (ret);
425 * Offline the device
427 ret = devctl_cmd(apidp->path, SCFGA_DEV_UNCONFIGURE, NULL, &l_errno);
428 if (ret != SCFGA_OK) {
430 cfga_err(errstring, l_errno, ERR_DEV_REMOVE, 0);
433 * Cancel the RCM offline. Discard the RCM failures so that
434 * the above devctl failure is still reported.
436 if ((apidp->flags & FLAG_DISABLE_RCM) == 0)
437 (void) scsi_rcm_online(dev_list, errstring, flags);
438 free_dev_list_elements(dev_list);
439 return (ret);
442 /* Do the physical removal */
443 ret = dev_hotplug(apidp, prp, flags, do_quiesce, errstring);
445 if (ret == SCFGA_OK) {
447 * Complete the remove.
448 * Since the device is already offlined, remove shouldn't
449 * fail. Even if remove fails, there is no side effect.
451 (void) devctl_cmd(apidp->path, SCFGA_DEV_REMOVE,
452 NULL, &l_errno);
453 if ((apidp->flags & FLAG_DISABLE_RCM) == 0)
454 ret = scsi_rcm_remove(dev_list, errstring, flags);
455 } else {
457 * Reconfigure the device and restore the device's RCM state.
458 * If reconfigure succeeds, restore the state to online.
459 * If reconfigure fails (e.g. a typo from user), we treat
460 * the device as removed.
462 if (devctl_cmd(apidp->path, SCFGA_DEV_CONFIGURE, NULL, &l_errno)
463 == SCFGA_OK) {
464 if ((apidp->flags & FLAG_DISABLE_RCM) == 0)
465 (void) scsi_rcm_online(dev_list, errstring,
466 flags);
467 } else {
468 char *cp = strrchr(apidp->path, ':');
469 if (cp)
470 *cp = '\0';
471 cfga_err(errstring, l_errno, ERR_DEV_RECONFIGURE,
472 apidp->path, 0);
473 if (cp)
474 *cp = ':';
475 if ((apidp->flags & FLAG_DISABLE_RCM) == 0)
476 (void) scsi_rcm_remove(dev_list, errstring,
477 flags);
481 free_dev_list_elements(dev_list);
482 return (ret);
485 /*ARGSUSED*/
486 scfga_ret_t
487 dev_insert(
488 const char *func,
489 scfga_cmd_t cmd,
490 apid_t *apidp,
491 prompt_t *prp,
492 cfga_flags_t flags,
493 char **errstring)
495 int proceed, l_errno = 0;
496 scfga_ret_t ret;
497 int do_quiesce;
499 assert(apidp->hba_phys != NULL);
500 assert(apidp->path != NULL);
502 /* Currently, insert operation only allowed for bus */
503 if (apidp->dyncomp != NULL) {
504 cfga_err(errstring, 0, ERR_NOT_DEVOP, 0);
505 return (SCFGA_ERR);
508 proceed = 1;
509 ret = quiesce_confirm(apidp, MSG_INSDEV, prp, &proceed, &do_quiesce,
510 &l_errno);
511 if (ret != SCFGA_OK) {
512 cfga_err(errstring, l_errno, ERR_DEV_INSERT, 0);
513 return (ret);
516 if (!proceed) {
517 return (SCFGA_NACK);
520 /* Do the physical addition */
521 ret = dev_hotplug(apidp, prp, flags, do_quiesce, errstring);
522 if (ret != SCFGA_OK) {
523 return (ret);
527 * Configure bus to online new device(s).
528 * Previously offlined devices will not be onlined.
530 ret = devctl_cmd(apidp->hba_phys, SCFGA_BUS_CONFIGURE, NULL, &l_errno);
531 if (ret != SCFGA_OK) {
532 cfga_err(errstring, l_errno, ERR_DEV_INSERT, 0);
533 return (SCFGA_ERR);
536 return (SCFGA_OK);
539 /*ARGSUSED*/
540 scfga_ret_t
541 dev_replace(
542 const char *func,
543 scfga_cmd_t cmd,
544 apid_t *apidp,
545 prompt_t *prp,
546 cfga_flags_t flags,
547 char **errstring)
549 int proceed, l_errno = 0;
550 scfga_ret_t ret, ret2;
551 int do_quiesce;
552 char *dev_list[2] = {NULL};
554 assert(apidp->hba_phys != NULL);
555 assert(apidp->path != NULL);
557 /* device operation only */
558 if (apidp->dyncomp == NULL) {
559 cfga_err(errstring, 0, ERR_NOT_BUSOP, 0);
560 return (SCFGA_ERR);
563 proceed = 1;
564 ret = quiesce_confirm(apidp, MSG_REPLDEV, prp, &proceed, &do_quiesce,
565 &l_errno);
566 if (ret != SCFGA_OK) {
567 cfga_err(errstring, l_errno, ERR_DEV_REPLACE, 0);
568 return (ret);
571 if (!proceed) {
572 return (SCFGA_NACK);
575 /* Offline the device in RCM */
576 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) {
577 dev_list[0] = get_node_path(apidp->path);
578 if (dev_list[0] == NULL)
579 return (SCFGA_ERR);
580 if ((ret = scsi_rcm_offline(dev_list, errstring, flags))
581 != SCFGA_OK) {
582 free_dev_list_elements(dev_list);
583 return (ret);
587 ret = devctl_cmd(apidp->path, SCFGA_DEV_REMOVE, NULL, &l_errno);
588 if (ret != SCFGA_OK) {
591 * Cancel the RCM offline. Discard any RCM failures so that
592 * the devctl failure can still be reported.
594 if ((apidp->flags & FLAG_DISABLE_RCM) == 0)
595 (void) scsi_rcm_online(dev_list, errstring, flags);
597 cfga_err(errstring, l_errno, ERR_DEV_REPLACE, 0);
598 free_dev_list_elements(dev_list);
599 return (ret);
602 /* do the physical replace */
603 ret = dev_hotplug(apidp, prp, flags, do_quiesce, errstring);
605 /* Online the replacement, or restore state on error */
606 ret2 = devctl_cmd(apidp->path, SCFGA_DEV_CONFIGURE, NULL, &l_errno);
608 if (ret2 != SCFGA_OK) {
609 cfga_err(errstring, l_errno, ERR_DEV_REPLACE, 0);
613 * Remove the replaced device in RCM, or online the device in RCM
614 * to recover.
616 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) {
617 if (ret == SCFGA_OK)
618 ret = scsi_rcm_remove(dev_list, errstring, flags);
619 else if (ret2 == SCFGA_OK)
620 ret2 = scsi_rcm_online(dev_list, errstring, flags);
622 free_dev_list_elements(dev_list);
624 return (ret == SCFGA_OK ? ret2 : ret);
627 #pragma weak plat_dev_led
628 /*ARGSUSED*/
629 scfga_ret_t
630 dev_led(
631 const char *func,
632 scfga_cmd_t cmd,
633 apid_t *apidp,
634 prompt_t *prp,
635 cfga_flags_t flags,
636 char **errstring)
640 * The implementation of the led command is platform-specific, so
641 * the default behavior is to say that the functionality is not
642 * available for this device.
644 if (plat_dev_led) {
645 return (plat_dev_led(func, cmd, apidp, prp, flags, errstring));
647 cfga_err(errstring, 0, ERR_UNAVAILABLE, 0);
648 return (SCFGA_ERR);
651 /*ARGSUSED*/
652 scfga_ret_t
653 reset_common(
654 const char *func,
655 scfga_cmd_t cmd,
656 apid_t *apidp,
657 prompt_t *prp,
658 cfga_flags_t flags,
659 char **errstring)
661 int l_errno = 0;
662 scfga_ret_t ret;
665 assert(apidp->path != NULL);
666 assert(apidp->hba_phys != NULL);
668 switch (cmd) {
669 case SCFGA_RESET_DEV:
670 if (apidp->dyncomp == NULL) {
671 cfga_err(errstring, 0, ERR_NOT_BUSOP, 0);
672 return (SCFGA_ERR);
674 break;
676 case SCFGA_RESET_BUS:
677 case SCFGA_RESET_ALL:
678 if (apidp->dyncomp != NULL) {
679 cfga_err(errstring, 0, ERR_NOT_DEVOP, 0);
680 return (SCFGA_ERR);
682 break;
683 default:
684 cfga_err(errstring, 0, ERR_CMD_INVAL, 0);
685 return (SCFGA_ERR);
688 ret = devctl_cmd(apidp->path, cmd, NULL, &l_errno);
689 if (ret != SCFGA_OK) {
690 cfga_err(errstring, l_errno, ERR_RESET, 0);
693 return (ret);
696 static int
697 disconnect(struct cfga_confirm *confp)
699 int ans, append_newline;
700 char *cq;
702 append_newline = 0;
703 cq = cfga_str(append_newline, WARN_DISCONNECT, 0);
705 ans = confp->confirm(confp->appdata_ptr, cq);
707 S_FREE(cq);
709 return (ans == 1);
713 * Check for "scsi-no-quiesce" property
714 * Return code: -1 error, 0 quiesce not required, 1 quiesce required
716 static int
717 quiesce_required(apid_t *apidp, int *l_errnop)
719 di_node_t bus_node, dev_node;
720 char *bus_path, *bus_end;
721 char *dev_path, *dev_end;
722 int *propval;
724 /* take libdevinfo snapshot of subtree at hba */
725 bus_path = apidp->hba_phys + strlen(DEVICES_DIR);
726 bus_end = strrchr(bus_path, ':');
727 if (bus_end)
728 *bus_end = '\0';
730 bus_node = di_init(bus_path, DINFOSUBTREE|DINFOPROP);
731 if (bus_end)
732 *bus_end = ':';
733 if (bus_node == DI_NODE_NIL) {
734 *l_errnop = errno;
735 return (-1); /* error */
738 /* check bus node for property */
739 if (di_prop_lookup_ints(DDI_DEV_T_ANY, bus_node, SCSI_NO_QUIESCE,
740 &propval) == 1) {
741 di_fini(bus_node);
742 return (0); /* quiesce not required */
745 /* if this ap is HBA, return with quiesce required */
746 if (apidp->dyncomp == NULL) {
747 di_fini(bus_node);
748 return (1);
751 /* check device node for property */
752 dev_path = apidp->path + strlen(DEVICES_DIR);
753 dev_end = strrchr(dev_path, ':');
754 if (dev_end)
755 *dev_end = '\0';
757 dev_node = di_child_node(bus_node);
758 while (dev_node != DI_NODE_NIL) {
759 char *child_path;
760 child_path = di_devfs_path(dev_node);
761 if (strcmp(child_path, dev_path) == 0) {
762 di_devfs_path_free(child_path);
763 break;
765 di_devfs_path_free(child_path);
766 dev_node = di_sibling_node(dev_node);
769 if (dev_end)
770 *dev_end = ':';
771 if (dev_node == DI_NODE_NIL) {
772 di_fini(bus_node);
773 return (1); /* dev not found (insert case) */
776 /* check child node for property */
777 if (di_prop_lookup_ints(DDI_DEV_T_ANY, dev_node, "scsi-no-quiesce",
778 &propval) == 1) {
779 di_fini(bus_node);
780 return (0); /* quiesce not required */
782 return (1); /* quiesce required */
785 static scfga_ret_t
786 quiesce_confirm(
787 apid_t *apidp,
788 msgid_t cmd_msg,
789 prompt_t *prp,
790 int *okp,
791 int *quiesce,
792 int *l_errnop)
794 char *buf = NULL, *hbap = NULL, *cq1 = NULL, *cq2 = NULL;
795 char *cp;
796 size_t len = 0;
797 int i = 0, append_newline;
798 scfga_ret_t ret;
800 assert(apidp->path != NULL);
801 assert(apidp->hba_phys != NULL);
803 *quiesce = quiesce_required(apidp, l_errnop);
804 if (*quiesce == -1)
805 return (SCFGA_ERR);
806 else if (*quiesce == 0)
807 return (SCFGA_OK);
810 * Try to create HBA logical ap_id.
811 * If that fails use physical path
813 ret = make_hba_logid(apidp->hba_phys, &hbap, &i);
814 if (ret != SCFGA_OK) {
815 if ((hbap = get_node_path(apidp->hba_phys)) == NULL) {
816 *l_errnop = errno;
817 return (SCFGA_LIB_ERR);
821 assert(hbap != NULL);
823 append_newline = 0;
824 cq1 = cfga_str(append_newline, CONF_QUIESCE_1, hbap, 0);
825 cq2 = cfga_str(append_newline, CONF_QUIESCE_2, 0);
826 len = strlen(cq1) + strlen(cq2) + 1; /* Includes term. NULL */
828 if ((buf = calloc(1, len)) == NULL) {
829 *l_errnop = errno;
830 ret = SCFGA_LIB_ERR;
831 S_FREE(cq1);
832 S_FREE(cq2);
833 goto out;
835 (void) strcpy(buf, cq1);
836 (void) strcat(buf, cq2);
838 S_FREE(cq1);
839 S_FREE(cq2);
842 /* Remove minor name (if any) from phys path */
843 if ((cp = strrchr(apidp->path, ':')) != NULL) {
844 *cp = '\0';
847 /* describe operation being attempted */
848 cfga_msg(prp->msgp, cmd_msg, apidp->path, 0);
850 /* Restore minor name */
851 if (cp != NULL) {
852 *cp = ':';
855 /* request permission to quiesce */
856 assert(prp->confp != NULL && prp->confp->confirm != NULL);
857 *okp = prp->confp->confirm(prp->confp->appdata_ptr, buf);
859 ret = SCFGA_OK;
860 /*FALLTHRU*/
861 out:
862 S_FREE(buf);
863 S_FREE(hbap);
864 return (ret);
867 static scfga_ret_t
868 suspend_in_rcm(
869 apid_t *apidp,
870 char ***suspend_list_ptr,
871 char **errstring,
872 cfga_flags_t flags)
874 scfga_ret_t ret;
875 char *bus_path = NULL;
876 char *dev_path = NULL;
877 char **suspend_list = NULL;
879 *suspend_list_ptr = NULL;
881 /* Suspend the bus through RCM */
882 if (apidp->flags & FLAG_DISABLE_RCM)
883 return (SCFGA_OK);
885 /* The bus_path is the HBA path without its minor */
886 if ((bus_path = get_node_path(apidp->hba_phys)) == NULL)
887 return (SCFGA_ERR);
890 * The dev_path is already initialized to NULL. If the AP Id
891 * path differs from the HBA path, then the dev_path should
892 * instead be set to the AP Id path without its minor.
894 if (strcmp(apidp->hba_phys, apidp->path) != 0) {
895 if ((dev_path = get_node_path(apidp->path)) == NULL) {
896 ret = SCFGA_ERR;
897 goto out;
901 if ((ret = get_hba_children(bus_path, dev_path, &suspend_list))
902 != SCFGA_OK) {
903 free_dev_list(suspend_list);
904 goto out;
907 if (scsi_rcm_suspend(suspend_list, errstring, flags, 0) != SCFGA_OK) {
908 ret = SCFGA_ERR;
909 free_dev_list(suspend_list);
910 } else {
911 ret = SCFGA_OK;
912 *suspend_list_ptr = suspend_list;
914 /*FALLTHROUGH*/
915 out:
916 S_FREE(bus_path);
917 S_FREE(dev_path);
918 return (ret);
922 * Resume the bus through RCM if it successfully
923 * unquiesced.
925 static void
926 resume_in_rcm(
927 apid_t *apidp,
928 char **suspend_list,
929 char **errstring,
930 cfga_flags_t flags)
932 if (apidp->flags & FLAG_DISABLE_RCM)
933 return;
935 (void) scsi_rcm_resume(suspend_list, errstring, flags, 0);
937 free_dev_list(suspend_list);
940 static scfga_ret_t
941 wait_for_hotplug(prompt_t *pt, int msg)
943 char *cu = NULL;
944 int append_newline = 0;
945 scfga_ret_t ret;
947 cu = cfga_str(append_newline, msg, 0);
948 if (pt->confp->confirm(pt->confp->appdata_ptr, cu) != 1) {
949 ret = SCFGA_NACK;
950 } else {
951 ret = SCFGA_OK;
953 S_FREE(cu);
954 return (ret);
957 static scfga_ret_t
958 bus_quiesce(apid_t *apidp, prompt_t *pt, char **errstring, cfga_flags_t flags)
960 int l_errno;
961 scfga_ret_t ret;
962 scfga_ret_t hpret;
963 char **suspend_list = NULL;
965 ret = suspend_in_rcm(apidp, &suspend_list, errstring, flags);
966 if (ret != SCFGA_OK) {
967 return (ret);
971 * If the quiesce fails, then cancel the RCM suspend.
972 * Discard any RCM failures so that the devctl failure
973 * can still be reported.
975 l_errno = 0;
976 ret = devctl_cmd(apidp->hba_phys, SCFGA_BUS_QUIESCE, NULL, &l_errno);
977 if (ret != SCFGA_OK) {
978 resume_in_rcm(apidp, suspend_list, errstring, flags);
979 cfga_err(errstring, l_errno, ERR_BUS_QUIESCE, 0);
980 return (ret);
984 * Prompt user to proceed with physical hotplug
985 * and wait until they are done.
987 hpret = wait_for_hotplug(pt, CONF_UNQUIESCE);
990 * The unquiesce may fail with EALREADY (which is ok)
991 * or some other error (which is not ok).
993 l_errno = 0;
994 ret = devctl_cmd(apidp->hba_phys, SCFGA_BUS_UNQUIESCE, NULL, &l_errno);
995 if (ret != SCFGA_OK && l_errno != EALREADY) {
996 free_dev_list(suspend_list);
997 cfga_err(errstring, l_errno, ERR_BUS_UNQUIESCE, 0);
998 return (SCFGA_ERR);
1001 resume_in_rcm(apidp, suspend_list, errstring, flags);
1003 return (hpret);
1006 #define MAX_LOCK_TRIES 20
1007 #define MAX_UNLINK_TRIES 60
1008 #define s_getpid (int)getpid /* else lint causes problems */
1010 static void
1011 s_unlink(char *file)
1013 int count = 0;
1015 retry:
1016 if (unlink(file) == -1) {
1017 if (errno != EINTR && errno != EAGAIN) {
1018 CFGA_TRACE1((stdout, "s_unlink[%d]: unlink failed: "
1019 "%s: %s\n", s_getpid(), file, strerror(errno)));
1020 return;
1023 if (++count < MAX_UNLINK_TRIES) {
1024 (void) sleep(1);
1025 goto retry;
1027 CFGA_TRACE1((stdout, "s_unlink[%d]: retry limit: %s\n",
1028 s_getpid(), file));
1029 } else {
1030 CFGA_TRACE3((stdout, "s_unlink[%d]: unlinked: %s\n",
1031 s_getpid(), file));
1035 static scfga_ret_t
1036 create_lock(int *fdp, struct cfga_msg *msgp, char **errstring)
1038 FILE *fp;
1039 int count;
1040 struct extmnttab ent;
1041 int mnted;
1044 *fdp = -1;
1047 * Check that /var/run is mounted. In the unlikely event
1048 * that the lock file is left behind, we want it
1049 * cleared on the next reboot.
1051 errno = 0;
1052 if ((fp = fopen(MNTTAB, "r")) == NULL) {
1053 cfga_err(errstring, errno, ERRARG_OPEN, MNTTAB, 0);
1054 return (SCFGA_LIB_ERR);
1057 resetmnttab(fp);
1059 mnted = 0;
1060 while (getextmntent(fp, &ent, sizeof (ent)) == 0) {
1061 if (strcmp(ent.mnt_mountp, "/var/run") == 0) {
1062 mnted = 1;
1063 break;
1067 (void) fclose(fp);
1069 if (!mnted) {
1070 cfga_err(errstring, 0, ERR_VAR_RUN, 0);
1071 return (SCFGA_LIB_ERR);
1075 * Wait for a short period of time if we cannot O_EXCL create
1076 * lock file. If some other cfgadm process is finishing up, we
1077 * can get in. If the wait required is long however, just
1078 * return SYSTEM_BUSY to the user - a hotplug operation is
1079 * probably in progress.
1081 count = 0;
1082 retry:
1083 *fdp = open(SCFGA_LOCK, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
1084 if (*fdp == -1 && errno == EEXIST) {
1085 if (++count < MAX_LOCK_TRIES) {
1086 if (count == 1)
1087 cfga_msg(msgp, MSG_WAIT_LOCK, 0);
1088 (void) sleep(1);
1089 goto retry;
1093 if (*fdp == -1 && errno == EEXIST) {
1094 cfga_err(errstring, 0, ERRARG_QUIESCE_LOCK, SCFGA_LOCK, 0);
1095 return (SCFGA_SYSTEM_BUSY);
1096 } else if (*fdp == -1) {
1097 cfga_err(errstring, errno, ERRARG_QUIESCE_LOCK, SCFGA_LOCK, 0);
1098 return (SCFGA_LIB_ERR);
1101 CFGA_TRACE3((stdout, "create_lock[%d]: created lockfile: %s\n",
1102 s_getpid(), SCFGA_LOCK));
1104 return (SCFGA_OK);
1107 static scfga_ret_t
1108 syslock(int fd, char **errstring)
1110 struct flock lock;
1111 int count;
1112 int rval;
1114 assert(fd != -1);
1116 CFGA_TRACE3((stdout, "syslock[%d]: trying lock: %s\n",
1117 s_getpid(), SCFGA_LOCK));
1119 lock.l_type = F_WRLCK;
1120 lock.l_whence = SEEK_SET;
1121 lock.l_start = 0;
1122 lock.l_len = 0;
1124 count = 0;
1125 while ((rval = fcntl(fd, F_SETLKW, &lock)) == -1 && errno == EINTR) {
1126 if (++count >= MAX_LOCK_TRIES) {
1127 CFGA_TRACE1((stdout, "syslock[%d]: retry limit: %s\n",
1128 s_getpid(), SCFGA_LOCK));
1129 goto badlock;
1131 (void) sleep(1);
1134 if (rval != -1) {
1135 CFGA_TRACE3((stdout, "syslock[%d]: locked file: %s\n",
1136 s_getpid(), SCFGA_LOCK));
1137 return (SCFGA_OK);
1140 /*FALLTHROUGH*/
1141 badlock:
1142 cfga_err(errstring, errno, ERRARG_LOCK, SCFGA_LOCK, 0);
1143 /* trace message to display pid */
1144 CFGA_TRACE1((stdout, "syslock[%d]: cannot lock %s\n",
1145 s_getpid(), SCFGA_LOCK));
1146 return (SCFGA_LIB_ERR);
1149 static void
1150 wait_for_child(pid_t cpid)
1152 int status;
1153 pid_t rval;
1155 CFGA_TRACE2((stdout, "wait_for_child[%d]: child[%d]\n",
1156 s_getpid(), (int)cpid));
1158 for (;;) {
1159 while ((rval = waitpid(cpid, &status, 0)) != cpid) {
1160 if (errno == ECHILD) {
1161 CFGA_TRACE1((stdout, "waitpid[%d]: child[%d] "
1162 "doesn't exist\n", s_getpid(), (int)cpid));
1163 return;
1166 CFGA_TRACE3((stdout, "waitpid[%d]: returned: %d"
1167 ": errno: %s\n", s_getpid(), (int)rval,
1168 strerror(errno)));
1171 if (WIFEXITED(status)) {
1172 CFGA_TRACE2((stdout, "waitpid[%d]: child[%d]: "
1173 "normal exit\n", s_getpid(), (int)cpid));
1174 return;
1177 if (WIFSIGNALED(status)) {
1178 CFGA_TRACE2((stdout, "waitpid[%d]: child[%d]: "
1179 "signal exit\n", s_getpid(), (int)cpid));
1180 return;
1184 * The child has not terminated. We received status
1185 * because the child was either stopped or continued.
1186 * Wait for child termination by calling waitpid() again.
1191 static void
1192 wait_and_cleanup(int fd, apid_t *apidp)
1194 int l_errno;
1195 scfga_ret_t ret;
1197 /* This is the child */
1198 CFGA_TRACE2((stdout, "child[%d]: Entering wait_cleanup\n", s_getpid()));
1200 if (syslock(fd, NULL) != SCFGA_OK) {
1201 CFGA_TRACE1((stdout, "child[%d]: lock failure "
1202 " - _exit(1)\n", s_getpid()));
1204 * As a last resort, unlink the lock file. This is relatively
1205 * safe as the child doesn't unquiesce the bus in this case.
1207 s_unlink(SCFGA_LOCK);
1208 _exit(1);
1211 l_errno = 0;
1212 ret = devctl_cmd(apidp->hba_phys, SCFGA_BUS_UNQUIESCE, NULL, &l_errno);
1213 if (ret != SCFGA_OK) {
1214 if (l_errno == EALREADY)
1215 CFGA_TRACE3((stdout, "child[%d]: bus already "
1216 "unquiesced: %s\n", s_getpid(), apidp->hba_phys));
1217 else
1218 CFGA_TRACE1((stdout, "child[%d]: unquiesce failed: "
1219 "%s\n", s_getpid(), strerror(l_errno)));
1220 } else {
1221 CFGA_TRACE1((stdout, "child[%d]: unquiesced bus: %s\n",
1222 s_getpid(), apidp->hba_phys));
1225 s_unlink(SCFGA_LOCK);
1227 CFGA_TRACE2((stdout, "child[%d]: _exit(0)\n", s_getpid()));
1229 _exit(0);
1232 static void
1233 sigblk(sigset_t *osp)
1235 sigset_t set;
1237 (void) sigemptyset(&set);
1238 (void) sigemptyset(osp);
1239 (void) sigaddset(&set, SIGHUP);
1240 (void) sigaddset(&set, SIGINT);
1241 (void) sigaddset(&set, SIGQUIT);
1242 (void) sigaddset(&set, SIGTERM);
1243 (void) sigaddset(&set, SIGUSR1);
1244 (void) sigaddset(&set, SIGUSR2);
1245 (void) sigprocmask(SIG_BLOCK, &set, osp);
1248 static void
1249 sigunblk(sigset_t *osp)
1251 (void) sigprocmask(SIG_SETMASK, osp, NULL);
1255 * Here is the algorithm used to ensure that a SCSI bus is not
1256 * left in the quiesced state:
1258 * lock quiesce mutex // single threads this code
1259 * open(O_CREAT|O_EXCL) lock file // only 1 process at a time
1260 * exclusive record lock on lock file
1261 * fork1()
1262 * quiesce bus
1263 * do the physical hotplug operation
1264 * unquiesce bus
1265 * unlock record lock
1266 * -> *child*
1267 * -> wait for record lock
1268 * -> unconditionally unquiesce bus
1269 * -> unlink lock file
1270 * -> exit
1271 * wait for child to exit
1272 * unlock quiesce mutex
1274 * NOTE1: since record locks are per-process and a close() can
1275 * release a lock, to keep things MT-safe we need a quiesce mutex.
1277 * NOTE2: To ensure that the child does not unquiesce a bus quiesced
1278 * by an unrelated cfgadm_scsi operation, exactly 1 process in the
1279 * system can be doing an implicit quiesce operation The exclusive
1280 * creation of the lock file guarantees this.
1282 * NOTE3: This works even if the parent process dumps core and/or is
1283 * abnormally terminated. If the parent dies before the child is
1284 * forked, the bus is not quiesced. If the parent dies after the
1285 * bus is quiesced, the child process will ensure that the bus is
1286 * unquiesced.
1288 static scfga_ret_t
1289 dev_hotplug(
1290 apid_t *apidp,
1291 prompt_t *pt,
1292 cfga_flags_t flags,
1293 int do_quiesce,
1294 char **errstring)
1296 scfga_ret_t ret;
1297 pid_t cpid;
1298 int fd;
1299 sigset_t oset;
1301 assert(apidp->hba_phys != NULL);
1302 assert(apidp->path != NULL);
1304 /* If no quiesce required, prompt the user to do the operation */
1305 if (!do_quiesce)
1306 return (wait_for_hotplug(pt, CONF_NO_QUIESCE));
1308 (void) mutex_lock(&quiesce_mutex);
1310 ret = create_lock(&fd, pt->msgp, errstring);
1311 if (ret != SCFGA_OK) {
1312 (void) mutex_unlock(&quiesce_mutex);
1313 return (ret);
1316 ret = syslock(fd, errstring);
1317 if (ret != SCFGA_OK) {
1318 goto bad;
1322 * block signals in the child. Parent may
1323 * exit, causing signal to be sent to child.
1325 sigblk(&oset);
1327 switch (cpid = fork1()) {
1328 case 0:
1329 /* child */
1330 wait_and_cleanup(fd, apidp);
1331 _exit(0); /* paranoia */
1332 /*NOTREACHED*/
1333 case -1:
1334 cfga_err(errstring, errno, ERR_FORK, 0);
1335 sigunblk(&oset);
1336 ret = SCFGA_LIB_ERR;
1337 goto bad;
1338 default:
1339 /* parent */
1340 break;
1343 sigunblk(&oset);
1345 /* We have forked successfully - this is the parent */
1346 ret = bus_quiesce(apidp, pt, errstring, flags);
1348 (void) close(fd); /* also unlocks */
1350 wait_for_child(cpid);
1352 (void) mutex_unlock(&quiesce_mutex);
1354 return (ret);
1355 bad:
1356 (void) close(fd);
1357 s_unlink(SCFGA_LOCK);
1358 (void) mutex_unlock(&quiesce_mutex);
1359 return (ret);
1363 * Checks if HBA controls a critical file-system (/, /usr or swap)
1364 * This routine reads /etc/vfstab and is NOT foolproof.
1365 * If an error occurs, assumes that controller is NOT critical.
1367 static int
1368 critical_ctrlr(const char *hba_phys)
1370 FILE *fp;
1371 struct vfstab vfst;
1372 int vfsret = 1, rv = -1;
1373 char *bufp;
1374 const size_t buflen = PATH_MAX;
1375 char mount[MAXPATHLEN], fstype[MAXPATHLEN], spec[MAXPATHLEN];
1378 if ((bufp = calloc(1, buflen)) == NULL) {
1379 return (0);
1382 fp = NULL;
1383 if ((fp = fopen(ETC_VFSTAB, "r")) == NULL) {
1384 rv = 0;
1385 goto out;
1388 while ((vfsret = getvfsent(fp, &vfst)) == 0) {
1390 (void) strcpy(mount, S_STR(vfst.vfs_mountp));
1391 (void) strcpy(fstype, S_STR(vfst.vfs_fstype));
1392 (void) strcpy(spec, S_STR(vfst.vfs_special));
1394 /* Ignore non-critical entries */
1395 if (strcmp(mount, "/") && strcmp(mount, "/usr") &&
1396 strcmp(fstype, "swap")) {
1397 continue;
1400 /* get physical path */
1401 if (realpath(spec, bufp) == NULL) {
1402 continue;
1405 /* Check if critical partition is on the HBA */
1406 if (!(rv = hba_dev_cmp(hba_phys, bufp))) {
1407 break;
1411 rv = !vfsret;
1413 /*FALLTHRU*/
1414 out:
1415 S_FREE(bufp);
1416 if (fp != NULL) {
1417 (void) fclose(fp);
1419 return (rv);
1423 * Convert bus state to receptacle state
1425 static cfga_stat_t
1426 bus_devctl_to_recep_state(uint_t bus_dc_state)
1428 cfga_stat_t rs;
1430 switch (bus_dc_state) {
1431 case BUS_ACTIVE:
1432 rs = CFGA_STAT_CONNECTED;
1433 break;
1434 case BUS_QUIESCED:
1435 case BUS_SHUTDOWN:
1436 rs = CFGA_STAT_DISCONNECTED;
1437 break;
1438 default:
1439 rs = CFGA_STAT_NONE;
1440 break;
1443 return (rs);
1446 static int
1447 add_dev(di_node_t node, void *arg)
1449 int ndevs, len;
1450 char *path, *p;
1451 struct larg *largp = (struct larg *)arg;
1453 /* ignore hba itself and all detached nodes */
1454 if (di_parent_node(node) == DI_NODE_NIL ||
1455 di_node_state(node) < DS_ATTACHED)
1456 return (DI_WALK_CONTINUE);
1458 if ((path = di_devfs_path(node)) == NULL) {
1459 largp->ndevs = -1;
1460 return (DI_WALK_TERMINATE);
1463 /* sizeof (DEVICES_DIR) includes the null terminator */
1464 len = strlen(path) + sizeof (DEVICES_DIR);
1465 if ((p = malloc(len)) == NULL) {
1466 di_devfs_path_free(path);
1467 largp->ndevs = -1;
1468 return (DI_WALK_TERMINATE);
1470 (void) snprintf(p, len, "%s%s", DEVICES_DIR, path);
1471 di_devfs_path_free(path);
1473 /* ignore device to be excluded */
1474 if (largp->dev && strcmp(largp->dev, p) == 0) {
1475 free(p);
1476 return (DI_WALK_CONTINUE);
1479 /* grow dev_list to allow room for one more device */
1480 if (alloc_dev_list(largp) != 0) {
1481 free(p);
1482 return (DI_WALK_TERMINATE);
1484 ndevs = largp->ndevs;
1485 largp->ndevs++;
1486 largp->dev_list[ndevs] = p;
1487 largp->dev_list[ndevs + 1] = NULL;
1488 return (DI_WALK_CONTINUE);
1492 * Get list of children excluding dev_excl (if not null).
1494 static int
1495 get_hba_children(char *bus_path, char *dev_excl, char ***dev_listp)
1497 int err, ret;
1498 walkarg_t u;
1499 struct larg larg;
1501 *dev_listp = NULL;
1503 u.node_args.flags = DI_WALK_CLDFIRST;
1504 u.node_args.fcn = add_dev;
1506 larg.ndevs = 0;
1507 larg.nelem = 0;
1508 larg.dev = dev_excl;
1509 larg.dev_list = NULL;
1511 ret = walk_tree(bus_path, &larg, DINFOSUBTREE, &u, SCFGA_WALK_NODE,
1512 &err);
1513 if (larg.ndevs == -1) {
1514 free_dev_list(larg.dev_list);
1515 return (SCFGA_ERR);
1517 *dev_listp = larg.dev_list;
1518 return (ret);
1521 static char *
1522 get_node_path(char *minor_path)
1524 char *path, *cp;
1526 if ((path = strdup(minor_path)) == NULL)
1527 return (NULL);
1528 if ((cp = strrchr(path, ':')) != NULL)
1529 *cp = '\0';
1530 return (path);
1534 * Ensure largp->dev_list has room for one more device.
1535 * Returns 0 on success, -1 on failure.
1537 static int
1538 alloc_dev_list(struct larg *largp)
1540 int nelem;
1541 char **p;
1543 if (largp->nelem > largp->ndevs + 2) /* +1 for NULL termination */
1544 return (0);
1546 nelem = largp->nelem + 16;
1547 p = reallocarray(largp->dev_list, nelem, sizeof (char *));
1548 if (p == NULL)
1549 return (-1);
1551 largp->dev_list = p;
1552 largp->nelem = nelem;
1553 return (0);
1556 static void
1557 free_dev_list_elements(char **dev_list)
1559 while (*dev_list) {
1560 free(*dev_list);
1561 dev_list++;
1565 static void
1566 free_dev_list(char **dev_list)
1568 if (dev_list == NULL)
1569 return;
1571 free_dev_list_elements(dev_list);
1572 free(dev_list);