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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include "cfga_scsi.h"
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
;
62 cfga_cmd_t state_change_cmd
,
64 struct cfga_confirm
*confp
,
68 int l_errno
= 0, force
;
70 cfga_stat_t bus_state
;
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);
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);
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
107 * This check is not foolproof, get user confirmation
110 if (critical_ctrlr(apidp
->path
)) {
111 cfga_err(errstring
, 0, ERR_CTRLR_CRIT
, 0);
114 } else if (!disconnect(confp
)) {
120 cmd
= SCFGA_BUS_QUIESCE
;
121 errid
= ERR_BUS_QUIESCE
;
122 prereq
= CFGA_STAT_CONNECTED
;
126 case CFGA_CMD_CONNECT
: /* unquiesce bus */
127 cmd
= SCFGA_BUS_UNQUIESCE
;
128 errid
= ERR_BUS_UNQUIESCE
;
129 prereq
= CFGA_STAT_DISCONNECTED
;
133 case CFGA_CMD_CONFIGURE
:
134 cmd
= SCFGA_BUS_CONFIGURE
;
135 errid
= ERR_BUS_CONFIGURE
;
136 prereq
= CFGA_STAT_CONNECTED
;
140 case CFGA_CMD_UNCONFIGURE
:
141 cmd
= SCFGA_BUS_UNCONFIGURE
;
142 errid
= ERR_BUS_UNCONFIGURE
;
143 prereq
= CFGA_STAT_CONNECTED
;
147 if (bus_state
!= prereq
) {
148 cfga_err(errstring
, 0,
149 (prereq
== CFGA_STAT_CONNECTED
)
150 ? ERR_BUS_NOTCONNECTED
151 : ERR_BUS_CONNECTED
, 0);
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
) {
170 if (cmd
== SCFGA_BUS_QUIESCE
) {
171 if ((ret
= scsi_rcm_suspend(dev_list
,
172 errstring
, flags
, 1)) != SCFGA_OK
) {
175 } else if (cmd
== SCFGA_BUS_UNCONFIGURE
) {
176 if ((ret
= scsi_rcm_offline(dev_list
,
177 errstring
, flags
)) != SCFGA_OK
) {
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.
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
,
203 (flags
& (~CFGA_FLAG_FORCE
)), 1);
204 else if (cmd
== SCFGA_BUS_UNCONFIGURE
) {
205 (void) devctl_cmd(apidp
->path
,
206 SCFGA_BUS_CONFIGURE
, NULL
,
208 (void) scsi_rcm_online(dev_list
,
210 (flags
& (~CFGA_FLAG_FORCE
)));
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
)));
234 case CFGA_CMD_UNLOAD
:
235 ret
= SCFGA_OPNOTSUPP
;
239 cfga_err(errstring
, 0, ERR_CMD_INVAL
, 0);
244 free_dev_list(dev_list
);
250 cfga_cmd_t state_change_cmd
,
257 cfga_stat_t bus_state
;
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);
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);
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
;
289 case CFGA_CMD_UNCONFIGURE
: /* offline device */
290 cmd
= SCFGA_DEV_UNCONFIGURE
;
291 errid
= ERR_DEV_UNCONFIGURE
;
294 if (bus_state
!= CFGA_STAT_CONNECTED
) {
295 cfga_err(errstring
, 0, ERR_BUS_NOTCONNECTED
, 0);
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
);
306 * When unconfiguring a device, first offline it
309 if ((apidp
->flags
& FLAG_DISABLE_RCM
) == 0) {
310 if (cmd
== SCFGA_DEV_UNCONFIGURE
) {
312 get_node_path(apidp
->path
);
313 if (dev_list
[0] == NULL
) {
317 if ((ret
= scsi_rcm_offline(dev_list
,
318 errstring
, flags
)) != SCFGA_OK
) {
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
,
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
,
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);
361 case CFGA_CMD_UNLOAD
:
362 ret
= SCFGA_OPNOTSUPP
;
365 cfga_err(errstring
, 0, ERR_CMD_INVAL
, 0);
370 free_dev_list_elements(dev_list
);
384 int proceed
, l_errno
= 0;
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);
399 ret
= quiesce_confirm(apidp
, MSG_RMDEV
, prp
, &proceed
, &do_quiesce
,
401 if (ret
!= SCFGA_OK
) {
402 cfga_err(errstring
, l_errno
, ERR_DEV_REMOVE
, 0);
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
)
417 if ((ret
= scsi_rcm_offline(dev_list
, errstring
, flags
))
419 free_dev_list_elements(dev_list
);
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
);
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
,
453 if ((apidp
->flags
& FLAG_DISABLE_RCM
) == 0)
454 ret
= scsi_rcm_remove(dev_list
, errstring
, flags
);
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
)
464 if ((apidp
->flags
& FLAG_DISABLE_RCM
) == 0)
465 (void) scsi_rcm_online(dev_list
, errstring
,
468 char *cp
= strrchr(apidp
->path
, ':');
471 cfga_err(errstring
, l_errno
, ERR_DEV_RECONFIGURE
,
475 if ((apidp
->flags
& FLAG_DISABLE_RCM
) == 0)
476 (void) scsi_rcm_remove(dev_list
, errstring
,
481 free_dev_list_elements(dev_list
);
495 int proceed
, l_errno
= 0;
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);
509 ret
= quiesce_confirm(apidp
, MSG_INSDEV
, prp
, &proceed
, &do_quiesce
,
511 if (ret
!= SCFGA_OK
) {
512 cfga_err(errstring
, l_errno
, ERR_DEV_INSERT
, 0);
520 /* Do the physical addition */
521 ret
= dev_hotplug(apidp
, prp
, flags
, do_quiesce
, errstring
);
522 if (ret
!= SCFGA_OK
) {
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);
549 int proceed
, l_errno
= 0;
550 scfga_ret_t ret
, ret2
;
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);
564 ret
= quiesce_confirm(apidp
, MSG_REPLDEV
, prp
, &proceed
, &do_quiesce
,
566 if (ret
!= SCFGA_OK
) {
567 cfga_err(errstring
, l_errno
, ERR_DEV_REPLACE
, 0);
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
)
580 if ((ret
= scsi_rcm_offline(dev_list
, errstring
, flags
))
582 free_dev_list_elements(dev_list
);
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
);
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
616 if ((apidp
->flags
& FLAG_DISABLE_RCM
) == 0) {
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
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.
645 return (plat_dev_led(func
, cmd
, apidp
, prp
, flags
, errstring
));
647 cfga_err(errstring
, 0, ERR_UNAVAILABLE
, 0);
665 assert(apidp
->path
!= NULL
);
666 assert(apidp
->hba_phys
!= NULL
);
669 case SCFGA_RESET_DEV
:
670 if (apidp
->dyncomp
== NULL
) {
671 cfga_err(errstring
, 0, ERR_NOT_BUSOP
, 0);
676 case SCFGA_RESET_BUS
:
677 case SCFGA_RESET_ALL
:
678 if (apidp
->dyncomp
!= NULL
) {
679 cfga_err(errstring
, 0, ERR_NOT_DEVOP
, 0);
684 cfga_err(errstring
, 0, ERR_CMD_INVAL
, 0);
688 ret
= devctl_cmd(apidp
->path
, cmd
, NULL
, &l_errno
);
689 if (ret
!= SCFGA_OK
) {
690 cfga_err(errstring
, l_errno
, ERR_RESET
, 0);
697 disconnect(struct cfga_confirm
*confp
)
699 int ans
, append_newline
;
703 cq
= cfga_str(append_newline
, WARN_DISCONNECT
, 0);
705 ans
= confp
->confirm(confp
->appdata_ptr
, cq
);
713 * Check for "scsi-no-quiesce" property
714 * Return code: -1 error, 0 quiesce not required, 1 quiesce required
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
;
724 /* take libdevinfo snapshot of subtree at hba */
725 bus_path
= apidp
->hba_phys
+ strlen(DEVICES_DIR
);
726 bus_end
= strrchr(bus_path
, ':');
730 bus_node
= di_init(bus_path
, DINFOSUBTREE
|DINFOPROP
);
733 if (bus_node
== DI_NODE_NIL
) {
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
,
742 return (0); /* quiesce not required */
745 /* if this ap is HBA, return with quiesce required */
746 if (apidp
->dyncomp
== NULL
) {
751 /* check device node for property */
752 dev_path
= apidp
->path
+ strlen(DEVICES_DIR
);
753 dev_end
= strrchr(dev_path
, ':');
757 dev_node
= di_child_node(bus_node
);
758 while (dev_node
!= DI_NODE_NIL
) {
760 child_path
= di_devfs_path(dev_node
);
761 if (strcmp(child_path
, dev_path
) == 0) {
762 di_devfs_path_free(child_path
);
765 di_devfs_path_free(child_path
);
766 dev_node
= di_sibling_node(dev_node
);
771 if (dev_node
== DI_NODE_NIL
) {
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",
780 return (0); /* quiesce not required */
782 return (1); /* quiesce required */
794 char *buf
= NULL
, *hbap
= NULL
, *cq1
= NULL
, *cq2
= NULL
;
797 int i
= 0, append_newline
;
800 assert(apidp
->path
!= NULL
);
801 assert(apidp
->hba_phys
!= NULL
);
803 *quiesce
= quiesce_required(apidp
, l_errnop
);
806 else if (*quiesce
== 0)
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
) {
817 return (SCFGA_LIB_ERR
);
821 assert(hbap
!= NULL
);
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
) {
835 (void) strcpy(buf
, cq1
);
836 (void) strcat(buf
, cq2
);
842 /* Remove minor name (if any) from phys path */
843 if ((cp
= strrchr(apidp
->path
, ':')) != NULL
) {
847 /* describe operation being attempted */
848 cfga_msg(prp
->msgp
, cmd_msg
, apidp
->path
, 0);
850 /* Restore minor name */
855 /* request permission to quiesce */
856 assert(prp
->confp
!= NULL
&& prp
->confp
->confirm
!= NULL
);
857 *okp
= prp
->confp
->confirm(prp
->confp
->appdata_ptr
, buf
);
870 char ***suspend_list_ptr
,
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
)
885 /* The bus_path is the HBA path without its minor */
886 if ((bus_path
= get_node_path(apidp
->hba_phys
)) == NULL
)
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
) {
901 if ((ret
= get_hba_children(bus_path
, dev_path
, &suspend_list
))
903 free_dev_list(suspend_list
);
907 if (scsi_rcm_suspend(suspend_list
, errstring
, flags
, 0) != SCFGA_OK
) {
909 free_dev_list(suspend_list
);
912 *suspend_list_ptr
= suspend_list
;
922 * Resume the bus through RCM if it successfully
932 if (apidp
->flags
& FLAG_DISABLE_RCM
)
935 (void) scsi_rcm_resume(suspend_list
, errstring
, flags
, 0);
937 free_dev_list(suspend_list
);
941 wait_for_hotplug(prompt_t
*pt
, int msg
)
944 int append_newline
= 0;
947 cu
= cfga_str(append_newline
, msg
, 0);
948 if (pt
->confp
->confirm(pt
->confp
->appdata_ptr
, cu
) != 1) {
958 bus_quiesce(apid_t
*apidp
, prompt_t
*pt
, char **errstring
, cfga_flags_t flags
)
963 char **suspend_list
= NULL
;
965 ret
= suspend_in_rcm(apidp
, &suspend_list
, errstring
, flags
);
966 if (ret
!= SCFGA_OK
) {
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.
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);
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).
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);
1001 resume_in_rcm(apidp
, suspend_list
, errstring
, flags
);
1006 #define MAX_LOCK_TRIES 20
1007 #define MAX_UNLINK_TRIES 60
1008 #define s_getpid (int)getpid /* else lint causes problems */
1011 s_unlink(char *file
)
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
)));
1023 if (++count
< MAX_UNLINK_TRIES
) {
1027 CFGA_TRACE1((stdout
, "s_unlink[%d]: retry limit: %s\n",
1030 CFGA_TRACE3((stdout
, "s_unlink[%d]: unlinked: %s\n",
1036 create_lock(int *fdp
, struct cfga_msg
*msgp
, char **errstring
)
1040 struct extmnttab ent
;
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.
1052 if ((fp
= fopen(MNTTAB
, "r")) == NULL
) {
1053 cfga_err(errstring
, errno
, ERRARG_OPEN
, MNTTAB
, 0);
1054 return (SCFGA_LIB_ERR
);
1060 while (getextmntent(fp
, &ent
, sizeof (ent
)) == 0) {
1061 if (strcmp(ent
.mnt_mountp
, "/var/run") == 0) {
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.
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
) {
1087 cfga_msg(msgp
, MSG_WAIT_LOCK
, 0);
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
));
1108 syslock(int fd
, char **errstring
)
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
;
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
));
1135 CFGA_TRACE3((stdout
, "syslock[%d]: locked file: %s\n",
1136 s_getpid(), SCFGA_LOCK
));
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
);
1150 wait_for_child(pid_t cpid
)
1155 CFGA_TRACE2((stdout
, "wait_for_child[%d]: child[%d]\n",
1156 s_getpid(), (int)cpid
));
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
));
1166 CFGA_TRACE3((stdout
, "waitpid[%d]: returned: %d"
1167 ": errno: %s\n", s_getpid(), (int)rval
,
1171 if (WIFEXITED(status
)) {
1172 CFGA_TRACE2((stdout
, "waitpid[%d]: child[%d]: "
1173 "normal exit\n", s_getpid(), (int)cpid
));
1177 if (WIFSIGNALED(status
)) {
1178 CFGA_TRACE2((stdout
, "waitpid[%d]: child[%d]: "
1179 "signal exit\n", s_getpid(), (int)cpid
));
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.
1192 wait_and_cleanup(int fd
, apid_t
*apidp
)
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
);
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
));
1218 CFGA_TRACE1((stdout
, "child[%d]: unquiesce failed: "
1219 "%s\n", s_getpid(), strerror(l_errno
)));
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()));
1233 sigblk(sigset_t
*osp
)
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
);
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
1263 * do the physical hotplug operation
1265 * unlock record lock
1267 * -> wait for record lock
1268 * -> unconditionally unquiesce bus
1269 * -> unlink lock file
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
1301 assert(apidp
->hba_phys
!= NULL
);
1302 assert(apidp
->path
!= NULL
);
1304 /* If no quiesce required, prompt the user to do the operation */
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
);
1316 ret
= syslock(fd
, errstring
);
1317 if (ret
!= SCFGA_OK
) {
1322 * block signals in the child. Parent may
1323 * exit, causing signal to be sent to child.
1327 switch (cpid
= fork1()) {
1330 wait_and_cleanup(fd
, apidp
);
1331 _exit(0); /* paranoia */
1334 cfga_err(errstring
, errno
, ERR_FORK
, 0);
1336 ret
= SCFGA_LIB_ERR
;
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
);
1357 s_unlink(SCFGA_LOCK
);
1358 (void) mutex_unlock(&quiesce_mutex
);
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.
1368 critical_ctrlr(const char *hba_phys
)
1372 int vfsret
= 1, rv
= -1;
1374 const size_t buflen
= PATH_MAX
;
1375 char mount
[MAXPATHLEN
], fstype
[MAXPATHLEN
], spec
[MAXPATHLEN
];
1378 if ((bufp
= calloc(1, buflen
)) == NULL
) {
1383 if ((fp
= fopen(ETC_VFSTAB
, "r")) == NULL
) {
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")) {
1400 /* get physical path */
1401 if (realpath(spec
, bufp
) == NULL
) {
1405 /* Check if critical partition is on the HBA */
1406 if (!(rv
= hba_dev_cmp(hba_phys
, bufp
))) {
1423 * Convert bus state to receptacle state
1426 bus_devctl_to_recep_state(uint_t bus_dc_state
)
1430 switch (bus_dc_state
) {
1432 rs
= CFGA_STAT_CONNECTED
;
1436 rs
= CFGA_STAT_DISCONNECTED
;
1439 rs
= CFGA_STAT_NONE
;
1447 add_dev(di_node_t node
, void *arg
)
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
) {
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
);
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) {
1476 return (DI_WALK_CONTINUE
);
1479 /* grow dev_list to allow room for one more device */
1480 if (alloc_dev_list(largp
) != 0) {
1482 return (DI_WALK_TERMINATE
);
1484 ndevs
= 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).
1495 get_hba_children(char *bus_path
, char *dev_excl
, char ***dev_listp
)
1503 u
.node_args
.flags
= DI_WALK_CLDFIRST
;
1504 u
.node_args
.fcn
= add_dev
;
1508 larg
.dev
= dev_excl
;
1509 larg
.dev_list
= NULL
;
1511 ret
= walk_tree(bus_path
, &larg
, DINFOSUBTREE
, &u
, SCFGA_WALK_NODE
,
1513 if (larg
.ndevs
== -1) {
1514 free_dev_list(larg
.dev_list
);
1517 *dev_listp
= larg
.dev_list
;
1522 get_node_path(char *minor_path
)
1526 if ((path
= strdup(minor_path
)) == NULL
)
1528 if ((cp
= strrchr(path
, ':')) != NULL
)
1534 * Ensure largp->dev_list has room for one more device.
1535 * Returns 0 on success, -1 on failure.
1538 alloc_dev_list(struct larg
*largp
)
1543 if (largp
->nelem
> largp
->ndevs
+ 2) /* +1 for NULL termination */
1546 nelem
= largp
->nelem
+ 16;
1547 p
= reallocarray(largp
->dev_list
, nelem
, sizeof (char *));
1551 largp
->dev_list
= p
;
1552 largp
->nelem
= nelem
;
1557 free_dev_list_elements(char **dev_list
)
1566 free_dev_list(char **dev_list
)
1568 if (dev_list
== NULL
)
1571 free_dev_list_elements(dev_list
);