1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM *
4*7836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM *
8*7836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM * and limitations under the License.
12*7836SJohn.Forte@Sun.COM *
13*7836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM *
19*7836SJohn.Forte@Sun.COM * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23*7836SJohn.Forte@Sun.COM * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM */
25*7836SJohn.Forte@Sun.COM
26*7836SJohn.Forte@Sun.COM
27*7836SJohn.Forte@Sun.COM
28*7836SJohn.Forte@Sun.COM /*LINTLIBRARY*/
29*7836SJohn.Forte@Sun.COM
30*7836SJohn.Forte@Sun.COM
31*7836SJohn.Forte@Sun.COM /*
32*7836SJohn.Forte@Sun.COM * Hotplug program for SENA, RSM and SSA
33*7836SJohn.Forte@Sun.COM * subsystems and individual FC_AL devices.
34*7836SJohn.Forte@Sun.COM */
35*7836SJohn.Forte@Sun.COM
36*7836SJohn.Forte@Sun.COM /* #define _POSIX_SOURCE 1 */
37*7836SJohn.Forte@Sun.COM
38*7836SJohn.Forte@Sun.COM /*
39*7836SJohn.Forte@Sun.COM * I18N message number ranges
40*7836SJohn.Forte@Sun.COM * This file: 5500 - 5999
41*7836SJohn.Forte@Sun.COM * Shared common messages: 1 - 1999
42*7836SJohn.Forte@Sun.COM */
43*7836SJohn.Forte@Sun.COM
44*7836SJohn.Forte@Sun.COM
45*7836SJohn.Forte@Sun.COM /* Includes */
46*7836SJohn.Forte@Sun.COM #include <stdlib.h>
47*7836SJohn.Forte@Sun.COM #include <stdio.h>
48*7836SJohn.Forte@Sun.COM #include <sys/file.h>
49*7836SJohn.Forte@Sun.COM #include <sys/errno.h>
50*7836SJohn.Forte@Sun.COM #include <sys/types.h>
51*7836SJohn.Forte@Sun.COM #include <sys/stat.h>
52*7836SJohn.Forte@Sun.COM #include <sys/utsname.h>
53*7836SJohn.Forte@Sun.COM #include <fcntl.h>
54*7836SJohn.Forte@Sun.COM #include <unistd.h>
55*7836SJohn.Forte@Sun.COM #include <errno.h>
56*7836SJohn.Forte@Sun.COM #include <string.h>
57*7836SJohn.Forte@Sun.COM #include <sys/sunddi.h>
58*7836SJohn.Forte@Sun.COM #include <sys/ddi.h> /* for min */
59*7836SJohn.Forte@Sun.COM #include <sys/scsi/scsi.h>
60*7836SJohn.Forte@Sun.COM #include <nl_types.h>
61*7836SJohn.Forte@Sun.COM #include <dirent.h>
62*7836SJohn.Forte@Sun.COM #include <sys/wait.h>
63*7836SJohn.Forte@Sun.COM #include <l_common.h>
64*7836SJohn.Forte@Sun.COM #include <l_error.h>
65*7836SJohn.Forte@Sun.COM #include <stgcom.h>
66*7836SJohn.Forte@Sun.COM #include <a_state.h>
67*7836SJohn.Forte@Sun.COM #include <a5k.h>
68*7836SJohn.Forte@Sun.COM #include <rom.h>
69*7836SJohn.Forte@Sun.COM #include "hot.h"
70*7836SJohn.Forte@Sun.COM #include "common.h"
71*7836SJohn.Forte@Sun.COM #include "luxadm.h"
72*7836SJohn.Forte@Sun.COM
73*7836SJohn.Forte@Sun.COM
74*7836SJohn.Forte@Sun.COM /* Internal variables. */
75*7836SJohn.Forte@Sun.COM static char *cmdStrg[][4] = {
76*7836SJohn.Forte@Sun.COM { "disks", "-C", 0, 0 },
77*7836SJohn.Forte@Sun.COM { "disks", 0, 0, 0 },
78*7836SJohn.Forte@Sun.COM { "drvconfig", "-i", "ssd", 0 },
79*7836SJohn.Forte@Sun.COM { "drvconfig", 0, 0, 0 },
80*7836SJohn.Forte@Sun.COM { "devlinks", 0, 0, 0 },
81*7836SJohn.Forte@Sun.COM { "tapes", "-C", 0, 0 }
82*7836SJohn.Forte@Sun.COM };
83*7836SJohn.Forte@Sun.COM
84*7836SJohn.Forte@Sun.COM /* External variables */
85*7836SJohn.Forte@Sun.COM extern char *dtype[]; /* From adm.c */
86*7836SJohn.Forte@Sun.COM extern int Options;
87*7836SJohn.Forte@Sun.COM extern const int OPTION_CAPF;
88*7836SJohn.Forte@Sun.COM
89*7836SJohn.Forte@Sun.COM /* Internal functions */
90*7836SJohn.Forte@Sun.COM /* SENA and Individual FC device Hotplug */
91*7836SJohn.Forte@Sun.COM static int h_pre_insert_encl_dev(timestruc_t *, timestruc_t *,
92*7836SJohn.Forte@Sun.COM timestruc_t *);
93*7836SJohn.Forte@Sun.COM static int h_post_insert_dev(timestruc_t, timestruc_t);
94*7836SJohn.Forte@Sun.COM static int h_pre_remove_dev(Hotplug_Devlist *,
95*7836SJohn.Forte@Sun.COM WWN_list *wwn_list, int, int);
96*7836SJohn.Forte@Sun.COM static int h_post_remove_dev(Hotplug_Devlist *, int, int);
97*7836SJohn.Forte@Sun.COM static int h_pre_hotplug(Hotplug_Devlist **,
98*7836SJohn.Forte@Sun.COM WWN_list *, int, int, int);
99*7836SJohn.Forte@Sun.COM static int h_post_hotplug(Hotplug_Devlist *,
100*7836SJohn.Forte@Sun.COM WWN_list *, int, int, int, int);
101*7836SJohn.Forte@Sun.COM static int h_post_insert_encl(timestruc_t);
102*7836SJohn.Forte@Sun.COM static int h_pre_hotplug_sena(Hotplug_Devlist *,
103*7836SJohn.Forte@Sun.COM WWN_list *, int, int, int);
104*7836SJohn.Forte@Sun.COM static int h_post_hotplug_sena(Hotplug_Devlist *,
105*7836SJohn.Forte@Sun.COM WWN_list *, int, int, int, int);
106*7836SJohn.Forte@Sun.COM static int h_remove_ses_nodes(struct dlist *);
107*7836SJohn.Forte@Sun.COM static int h_print_list_warn(Hotplug_Devlist *, int, int);
108*7836SJohn.Forte@Sun.COM static int h_display_logical_nodes(struct dlist *);
109*7836SJohn.Forte@Sun.COM static void h_print_logical_nodes(struct dlist *);
110*7836SJohn.Forte@Sun.COM static int h_remove_nodes(struct dlist *);
111*7836SJohn.Forte@Sun.COM static int h_print_list(Hotplug_Devlist *, int *, int);
112*7836SJohn.Forte@Sun.COM static int h_get_fcdev_state(char *, char *, int, int *, int *, int);
113*7836SJohn.Forte@Sun.COM static int h_chk_dev_busy(Hotplug_Devlist *,
114*7836SJohn.Forte@Sun.COM WWN_list *, int *, int, int);
115*7836SJohn.Forte@Sun.COM static int h_execCmnd(char **, int);
116*7836SJohn.Forte@Sun.COM int hotplug(int, char **, int, int);
117*7836SJohn.Forte@Sun.COM int h_insertSena_fcdev();
118*7836SJohn.Forte@Sun.COM static int h_find_new_device_link(char *, timestruc_t);
119*7836SJohn.Forte@Sun.COM
120*7836SJohn.Forte@Sun.COM
121*7836SJohn.Forte@Sun.COM
122*7836SJohn.Forte@Sun.COM /*
123*7836SJohn.Forte@Sun.COM * Assists the user in hot inserting FC_AL
124*7836SJohn.Forte@Sun.COM * individual device(s) and SENA enclosure(s).
125*7836SJohn.Forte@Sun.COM *
126*7836SJohn.Forte@Sun.COM * RETURNS:
127*7836SJohn.Forte@Sun.COM * 0 if OK
128*7836SJohn.Forte@Sun.COM * non-zero otherwise
129*7836SJohn.Forte@Sun.COM */
130*7836SJohn.Forte@Sun.COM int
h_insertSena_fcdev()131*7836SJohn.Forte@Sun.COM h_insertSena_fcdev()
132*7836SJohn.Forte@Sun.COM {
133*7836SJohn.Forte@Sun.COM timestruc_t ses_time, dsk_time, rmt_time;
134*7836SJohn.Forte@Sun.COM int err;
135*7836SJohn.Forte@Sun.COM struct stat ses_stat;
136*7836SJohn.Forte@Sun.COM
137*7836SJohn.Forte@Sun.COM if ((err = h_pre_insert_encl_dev(&ses_time, &dsk_time,
138*7836SJohn.Forte@Sun.COM &rmt_time)) != 0) {
139*7836SJohn.Forte@Sun.COM return (err);
140*7836SJohn.Forte@Sun.COM }
141*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5500,
142*7836SJohn.Forte@Sun.COM "Please hit <RETURN> when you have finished"
143*7836SJohn.Forte@Sun.COM " adding Fibre Channel Enclosure(s)/Device(s): "));
144*7836SJohn.Forte@Sun.COM (void) getchar();
145*7836SJohn.Forte@Sun.COM
146*7836SJohn.Forte@Sun.COM if ((err = h_post_insert_dev(dsk_time, rmt_time)) != 0) {
147*7836SJohn.Forte@Sun.COM return (err);
148*7836SJohn.Forte@Sun.COM }
149*7836SJohn.Forte@Sun.COM
150*7836SJohn.Forte@Sun.COM if (stat(SES_DIR, &ses_stat) < 0) {
151*7836SJohn.Forte@Sun.COM /*
152*7836SJohn.Forte@Sun.COM * Non existence of /dev/es dir indicates
153*7836SJohn.Forte@Sun.COM * no ses devices inserted.
154*7836SJohn.Forte@Sun.COM * No need to call h_post_insert_encl().
155*7836SJohn.Forte@Sun.COM */
156*7836SJohn.Forte@Sun.COM if (errno == ENOENT) {
157*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5662,
158*7836SJohn.Forte@Sun.COM " No new enclosure(s) were added!!\n\n"));
159*7836SJohn.Forte@Sun.COM return (0);
160*7836SJohn.Forte@Sun.COM } else {
161*7836SJohn.Forte@Sun.COM return (L_LSTAT_ES_DIR_ERROR);
162*7836SJohn.Forte@Sun.COM }
163*7836SJohn.Forte@Sun.COM }
164*7836SJohn.Forte@Sun.COM
165*7836SJohn.Forte@Sun.COM /*
166*7836SJohn.Forte@Sun.COM * if the latest mod time of /dev/es is not newer than
167*7836SJohn.Forte@Sun.COM * the original mod time no need to call
168*7836SJohn.Forte@Sun.COM * h_post_insert_encl().
169*7836SJohn.Forte@Sun.COM */
170*7836SJohn.Forte@Sun.COM if ((&ses_time != (timestruc_t *)NULL) &&
171*7836SJohn.Forte@Sun.COM !(NEWER(ses_stat.st_ctim, ses_time))) {
172*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5662,
173*7836SJohn.Forte@Sun.COM " No new enclosure(s) were added!!\n\n"));
174*7836SJohn.Forte@Sun.COM return (0);
175*7836SJohn.Forte@Sun.COM }
176*7836SJohn.Forte@Sun.COM if ((err = h_post_insert_encl(ses_time)) != 0) {
177*7836SJohn.Forte@Sun.COM return (err);
178*7836SJohn.Forte@Sun.COM }
179*7836SJohn.Forte@Sun.COM return (0);
180*7836SJohn.Forte@Sun.COM }
181*7836SJohn.Forte@Sun.COM
182*7836SJohn.Forte@Sun.COM
183*7836SJohn.Forte@Sun.COM
184*7836SJohn.Forte@Sun.COM /*
185*7836SJohn.Forte@Sun.COM * gets the devices state - check for disk's reservations.
186*7836SJohn.Forte@Sun.COM *
187*7836SJohn.Forte@Sun.COM * RETURNS:
188*7836SJohn.Forte@Sun.COM * 0 if OK
189*7836SJohn.Forte@Sun.COM * non-zero otherwise
190*7836SJohn.Forte@Sun.COM */
191*7836SJohn.Forte@Sun.COM static int
h_get_fcdev_state(char * fc_dev,char * path_phys,int force_flag,int * busy_flag,int * reserve_flag,int verbose_flag)192*7836SJohn.Forte@Sun.COM h_get_fcdev_state(char *fc_dev, char *path_phys, int force_flag,
193*7836SJohn.Forte@Sun.COM int *busy_flag, int *reserve_flag, int verbose_flag)
194*7836SJohn.Forte@Sun.COM {
195*7836SJohn.Forte@Sun.COM int err;
196*7836SJohn.Forte@Sun.COM L_inquiry inq;
197*7836SJohn.Forte@Sun.COM L_disk_state l_disk_state;
198*7836SJohn.Forte@Sun.COM
199*7836SJohn.Forte@Sun.COM
200*7836SJohn.Forte@Sun.COM if ((err = g_get_inquiry(path_phys, &inq)) != 0) {
201*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
202*7836SJohn.Forte@Sun.COM MSGSTR(5501,
203*7836SJohn.Forte@Sun.COM "Inquiry failed for %s\n"),
204*7836SJohn.Forte@Sun.COM path_phys);
205*7836SJohn.Forte@Sun.COM return (err);
206*7836SJohn.Forte@Sun.COM }
207*7836SJohn.Forte@Sun.COM if (inq.inq_port) {
208*7836SJohn.Forte@Sun.COM if ((err = l_get_disk_port_status(path_phys, &l_disk_state,
209*7836SJohn.Forte@Sun.COM FC_PORT_B, verbose_flag)) != 0) {
210*7836SJohn.Forte@Sun.COM return (err);
211*7836SJohn.Forte@Sun.COM }
212*7836SJohn.Forte@Sun.COM } else {
213*7836SJohn.Forte@Sun.COM if ((err = l_get_disk_port_status(path_phys, &l_disk_state,
214*7836SJohn.Forte@Sun.COM FC_PORT_A, verbose_flag)) != 0) {
215*7836SJohn.Forte@Sun.COM return (err);
216*7836SJohn.Forte@Sun.COM }
217*7836SJohn.Forte@Sun.COM }
218*7836SJohn.Forte@Sun.COM
219*7836SJohn.Forte@Sun.COM /*
220*7836SJohn.Forte@Sun.COM * Don't print error msg. if disk is reserved
221*7836SJohn.Forte@Sun.COM * and tried to be removed from the same port.
222*7836SJohn.Forte@Sun.COM * If force flag is set, remove the disk without
223*7836SJohn.Forte@Sun.COM * checking the disk reservations.
224*7836SJohn.Forte@Sun.COM */
225*7836SJohn.Forte@Sun.COM if (!force_flag) {
226*7836SJohn.Forte@Sun.COM if (((inq.inq_port) &&
227*7836SJohn.Forte@Sun.COM (l_disk_state.g_disk_state.d_state_flags[FC_PORT_B] &
228*7836SJohn.Forte@Sun.COM L_RESERVED)) ||
229*7836SJohn.Forte@Sun.COM ((!inq.inq_port) &&
230*7836SJohn.Forte@Sun.COM (l_disk_state.g_disk_state.d_state_flags[FC_PORT_A] &
231*7836SJohn.Forte@Sun.COM L_RESERVED))) {
232*7836SJohn.Forte@Sun.COM *reserve_flag = 1;
233*7836SJohn.Forte@Sun.COM }
234*7836SJohn.Forte@Sun.COM }
235*7836SJohn.Forte@Sun.COM return (0);
236*7836SJohn.Forte@Sun.COM }
237*7836SJohn.Forte@Sun.COM
238*7836SJohn.Forte@Sun.COM
239*7836SJohn.Forte@Sun.COM /*
240*7836SJohn.Forte@Sun.COM * Forks a child process and let the child to
241*7836SJohn.Forte@Sun.COM * execute a given command string by calling the
242*7836SJohn.Forte@Sun.COM * the execvp() function. Then, the parent process
243*7836SJohn.Forte@Sun.COM * waits for the child to exit. Once the parent process
244*7836SJohn.Forte@Sun.COM * is notified by the kernel with the termination of
245*7836SJohn.Forte@Sun.COM * the child, then the parent checks for the exit
246*7836SJohn.Forte@Sun.COM * status of the child and return to the caller with -1 in case
247*7836SJohn.Forte@Sun.COM * of error and zero otherwise.
248*7836SJohn.Forte@Sun.COM *
249*7836SJohn.Forte@Sun.COM * RETURNS:
250*7836SJohn.Forte@Sun.COM * 0 if OK
251*7836SJohn.Forte@Sun.COM * non-zero otherwise
252*7836SJohn.Forte@Sun.COM */
253*7836SJohn.Forte@Sun.COM int
h_execCmnd(char * argStr[],int nArg)254*7836SJohn.Forte@Sun.COM h_execCmnd(char *argStr[], int nArg)
255*7836SJohn.Forte@Sun.COM {
256*7836SJohn.Forte@Sun.COM pid_t pid;
257*7836SJohn.Forte@Sun.COM int ix, status;
258*7836SJohn.Forte@Sun.COM
259*7836SJohn.Forte@Sun.COM if ((pid = fork()) < 0) {
260*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
261*7836SJohn.Forte@Sun.COM MSGSTR(133,
262*7836SJohn.Forte@Sun.COM "Error: Failed to fork a process.\n"));
263*7836SJohn.Forte@Sun.COM return (-1);
264*7836SJohn.Forte@Sun.COM } else if (pid == 0) {
265*7836SJohn.Forte@Sun.COM /* child process */
266*7836SJohn.Forte@Sun.COM if (execvp(argStr[0], argStr) < 0) {
267*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
268*7836SJohn.Forte@Sun.COM MSGSTR(5502,
269*7836SJohn.Forte@Sun.COM " Error: execvp() failed to run "
270*7836SJohn.Forte@Sun.COM "the command:"));
271*7836SJohn.Forte@Sun.COM for (ix = 0; ix < nArg; ix++) {
272*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
273*7836SJohn.Forte@Sun.COM " %s", argStr[ix]);
274*7836SJohn.Forte@Sun.COM }
275*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, "\n");
276*7836SJohn.Forte@Sun.COM /* let parent know about the error. */
277*7836SJohn.Forte@Sun.COM exit(ENOEXEC);
278*7836SJohn.Forte@Sun.COM }
279*7836SJohn.Forte@Sun.COM }
280*7836SJohn.Forte@Sun.COM
281*7836SJohn.Forte@Sun.COM /* parent executes the following. */
282*7836SJohn.Forte@Sun.COM if (waitpid(pid, &status, 0) != pid) {
283*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
284*7836SJohn.Forte@Sun.COM MSGSTR(5503,
285*7836SJohn.Forte@Sun.COM "Error: waitpid() failed.\n"));
286*7836SJohn.Forte@Sun.COM return (-1);
287*7836SJohn.Forte@Sun.COM }
288*7836SJohn.Forte@Sun.COM if (WIFEXITED(status) &&
289*7836SJohn.Forte@Sun.COM WEXITSTATUS(status) == ENOEXEC) {
290*7836SJohn.Forte@Sun.COM /* child failed to run the command string. */
291*7836SJohn.Forte@Sun.COM return (-1);
292*7836SJohn.Forte@Sun.COM }
293*7836SJohn.Forte@Sun.COM return (0);
294*7836SJohn.Forte@Sun.COM
295*7836SJohn.Forte@Sun.COM }
296*7836SJohn.Forte@Sun.COM
297*7836SJohn.Forte@Sun.COM
298*7836SJohn.Forte@Sun.COM
299*7836SJohn.Forte@Sun.COM
300*7836SJohn.Forte@Sun.COM /*
301*7836SJohn.Forte@Sun.COM * frees the hotplug disk list structure.
302*7836SJohn.Forte@Sun.COM *
303*7836SJohn.Forte@Sun.COM * RETURNS:
304*7836SJohn.Forte@Sun.COM * N/A
305*7836SJohn.Forte@Sun.COM */
306*7836SJohn.Forte@Sun.COM void
h_free_hotplug_dlist(Hotplug_Devlist ** hotplug_dlist)307*7836SJohn.Forte@Sun.COM h_free_hotplug_dlist(Hotplug_Devlist **hotplug_dlist)
308*7836SJohn.Forte@Sun.COM {
309*7836SJohn.Forte@Sun.COM Hotplug_Devlist *list = NULL;
310*7836SJohn.Forte@Sun.COM
311*7836SJohn.Forte@Sun.COM while (*hotplug_dlist != NULL) {
312*7836SJohn.Forte@Sun.COM list = *hotplug_dlist;
313*7836SJohn.Forte@Sun.COM *hotplug_dlist = (*hotplug_dlist)->next;
314*7836SJohn.Forte@Sun.COM (void) g_free_multipath(list->seslist);
315*7836SJohn.Forte@Sun.COM (void) g_free_multipath(list->dlhead);
316*7836SJohn.Forte@Sun.COM (void) free((void *)list);
317*7836SJohn.Forte@Sun.COM }
318*7836SJohn.Forte@Sun.COM }
319*7836SJohn.Forte@Sun.COM
320*7836SJohn.Forte@Sun.COM
321*7836SJohn.Forte@Sun.COM /*
322*7836SJohn.Forte@Sun.COM * finds whether device (SENA or an FCAL device) is busy or not.
323*7836SJohn.Forte@Sun.COM *
324*7836SJohn.Forte@Sun.COM * OUTPUT:
325*7836SJohn.Forte@Sun.COM * busy_flag = 1 (if device busy)
326*7836SJohn.Forte@Sun.COM *
327*7836SJohn.Forte@Sun.COM * RETURNS:
328*7836SJohn.Forte@Sun.COM * 0 if O.K.
329*7836SJohn.Forte@Sun.COM * non-zero otherwise
330*7836SJohn.Forte@Sun.COM */
331*7836SJohn.Forte@Sun.COM static int
h_chk_dev_busy(Hotplug_Devlist * hotplug_dev,WWN_list * wwn_list,int * busy_flag,int force_flag,int verbose_flag)332*7836SJohn.Forte@Sun.COM h_chk_dev_busy(Hotplug_Devlist *hotplug_dev, WWN_list *wwn_list,
333*7836SJohn.Forte@Sun.COM int *busy_flag, int force_flag, int verbose_flag)
334*7836SJohn.Forte@Sun.COM {
335*7836SJohn.Forte@Sun.COM int err;
336*7836SJohn.Forte@Sun.COM struct dlist *dlist;
337*7836SJohn.Forte@Sun.COM
338*7836SJohn.Forte@Sun.COM if (hotplug_dev->dev_type == DTYPE_ESI) {
339*7836SJohn.Forte@Sun.COM if ((err = l_offline_photon(hotplug_dev, wwn_list,
340*7836SJohn.Forte@Sun.COM force_flag, verbose_flag)) != 0) {
341*7836SJohn.Forte@Sun.COM if (err == L_DEV_BUSY) {
342*7836SJohn.Forte@Sun.COM *busy_flag = 1;
343*7836SJohn.Forte@Sun.COM } else {
344*7836SJohn.Forte@Sun.COM return (err);
345*7836SJohn.Forte@Sun.COM }
346*7836SJohn.Forte@Sun.COM }
347*7836SJohn.Forte@Sun.COM for (dlist = hotplug_dev->dlhead;
348*7836SJohn.Forte@Sun.COM dlist != NULL; dlist = dlist->next) {
349*7836SJohn.Forte@Sun.COM (void) g_online_drive(dlist->multipath,
350*7836SJohn.Forte@Sun.COM force_flag);
351*7836SJohn.Forte@Sun.COM }
352*7836SJohn.Forte@Sun.COM } else {
353*7836SJohn.Forte@Sun.COM if ((err = g_offline_drive(hotplug_dev->dlhead,
354*7836SJohn.Forte@Sun.COM force_flag)) != 0) {
355*7836SJohn.Forte@Sun.COM if (err == L_DEV_BUSY) {
356*7836SJohn.Forte@Sun.COM *busy_flag = 1;
357*7836SJohn.Forte@Sun.COM } else {
358*7836SJohn.Forte@Sun.COM return (err);
359*7836SJohn.Forte@Sun.COM }
360*7836SJohn.Forte@Sun.COM }
361*7836SJohn.Forte@Sun.COM (void) g_online_drive(hotplug_dev->dlhead, force_flag);
362*7836SJohn.Forte@Sun.COM }
363*7836SJohn.Forte@Sun.COM return (0);
364*7836SJohn.Forte@Sun.COM }
365*7836SJohn.Forte@Sun.COM
366*7836SJohn.Forte@Sun.COM
367*7836SJohn.Forte@Sun.COM
368*7836SJohn.Forte@Sun.COM /*
369*7836SJohn.Forte@Sun.COM * prints the given list to stdout,
370*7836SJohn.Forte@Sun.COM * gets the input from user whether
371*7836SJohn.Forte@Sun.COM * to skip the busy devices or quit
372*7836SJohn.Forte@Sun.COM * and passes that input to the calling
373*7836SJohn.Forte@Sun.COM * function.
374*7836SJohn.Forte@Sun.COM *
375*7836SJohn.Forte@Sun.COM * OUTPUT:
376*7836SJohn.Forte@Sun.COM * int *action
377*7836SJohn.Forte@Sun.COM * s = Skip
378*7836SJohn.Forte@Sun.COM * q = Quit
379*7836SJohn.Forte@Sun.COM *
380*7836SJohn.Forte@Sun.COM * RETURNS:
381*7836SJohn.Forte@Sun.COM * 0 if OK
382*7836SJohn.Forte@Sun.COM * non-zero otherwise
383*7836SJohn.Forte@Sun.COM */
384*7836SJohn.Forte@Sun.COM static int
h_print_list(Hotplug_Devlist * bsyRsrv_disk_list,int * action,int enc_type)385*7836SJohn.Forte@Sun.COM h_print_list(Hotplug_Devlist *bsyRsrv_disk_list, int *action, int enc_type)
386*7836SJohn.Forte@Sun.COM {
387*7836SJohn.Forte@Sun.COM Hotplug_Devlist *list;
388*7836SJohn.Forte@Sun.COM int i = 1;
389*7836SJohn.Forte@Sun.COM char choice[2];
390*7836SJohn.Forte@Sun.COM
391*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
392*7836SJohn.Forte@Sun.COM MSGSTR(5504, "The list of devices being used"
393*7836SJohn.Forte@Sun.COM " (either busy or reserved) by the host:\n"));
394*7836SJohn.Forte@Sun.COM for (list = bsyRsrv_disk_list; list != NULL; list = list->next, i++) {
395*7836SJohn.Forte@Sun.COM if ((list->dev_type == DTYPE_DIRECT) &&
396*7836SJohn.Forte@Sun.COM (list->dev_location == SENA)) {
397*7836SJohn.Forte@Sun.COM if (list->f_flag != NULL) {
398*7836SJohn.Forte@Sun.COM if (enc_type == DAK_ENC_TYPE) {
399*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5663,
400*7836SJohn.Forte@Sun.COM " %d: Box Name: \"%s\" slot %d\n"),
401*7836SJohn.Forte@Sun.COM i, list->box_name, list->slot);
402*7836SJohn.Forte@Sun.COM } else {
403*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(137,
404*7836SJohn.Forte@Sun.COM " %d: Box Name: \"%s\" front slot %d\n"),
405*7836SJohn.Forte@Sun.COM i, list->box_name, list->slot);
406*7836SJohn.Forte@Sun.COM }
407*7836SJohn.Forte@Sun.COM } else {
408*7836SJohn.Forte@Sun.COM if (enc_type == DAK_ENC_TYPE) {
409*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5663,
410*7836SJohn.Forte@Sun.COM " %d: Box Name: \"%s\" slot %d\n"),
411*7836SJohn.Forte@Sun.COM i, list->box_name, list->slot + (MAX_DRIVES_DAK/2));
412*7836SJohn.Forte@Sun.COM } else {
413*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(136,
414*7836SJohn.Forte@Sun.COM " %d: Box Name: \"%s\" rear slot %d\n"),
415*7836SJohn.Forte@Sun.COM i, list->box_name, list->slot);
416*7836SJohn.Forte@Sun.COM }
417*7836SJohn.Forte@Sun.COM }
418*7836SJohn.Forte@Sun.COM } else if (((list->dev_type == DTYPE_DIRECT) ||
419*7836SJohn.Forte@Sun.COM (list->dev_type == DTYPE_SEQUENTIAL)) &&
420*7836SJohn.Forte@Sun.COM (list->dev_location == NON_SENA)) {
421*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5505,
422*7836SJohn.Forte@Sun.COM " %d: Device %s\n"),
423*7836SJohn.Forte@Sun.COM i, list->dev_name);
424*7836SJohn.Forte@Sun.COM } else if (list->dev_type == DTYPE_ESI) {
425*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5506,
426*7836SJohn.Forte@Sun.COM " %d: Box: %s\n"),
427*7836SJohn.Forte@Sun.COM i, list->box_name);
428*7836SJohn.Forte@Sun.COM }
429*7836SJohn.Forte@Sun.COM }
430*7836SJohn.Forte@Sun.COM
431*7836SJohn.Forte@Sun.COM /* Get the user input and continue accordingly. */
432*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
433*7836SJohn.Forte@Sun.COM MSGSTR(5507,
434*7836SJohn.Forte@Sun.COM "\n\nPlease enter 's' or <CR> to Skip the \"busy/reserved\""
435*7836SJohn.Forte@Sun.COM " device(s) or\n'q' to Quit and run the"
436*7836SJohn.Forte@Sun.COM " subcommand with\n-F (force) option. [Default: s]: "));
437*7836SJohn.Forte@Sun.COM for (;;) {
438*7836SJohn.Forte@Sun.COM (void) gets(choice);
439*7836SJohn.Forte@Sun.COM if (choice[0] == 'q' || choice[0] == 'Q' ||
440*7836SJohn.Forte@Sun.COM choice[0] == 's' || choice[0] == 'S' ||
441*7836SJohn.Forte@Sun.COM choice[0] == '\0') {
442*7836SJohn.Forte@Sun.COM break;
443*7836SJohn.Forte@Sun.COM }
444*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5508,
445*7836SJohn.Forte@Sun.COM " Enter an appropriate option [s,<CR>,q]: "));
446*7836SJohn.Forte@Sun.COM }
447*7836SJohn.Forte@Sun.COM if (choice[0] == 'q' || choice[0] == 'Q') {
448*7836SJohn.Forte@Sun.COM *action = QUIT;
449*7836SJohn.Forte@Sun.COM } else {
450*7836SJohn.Forte@Sun.COM *action = SKIP;
451*7836SJohn.Forte@Sun.COM }
452*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\n\n");
453*7836SJohn.Forte@Sun.COM return (0);
454*7836SJohn.Forte@Sun.COM }
455*7836SJohn.Forte@Sun.COM
456*7836SJohn.Forte@Sun.COM
457*7836SJohn.Forte@Sun.COM
458*7836SJohn.Forte@Sun.COM /*
459*7836SJohn.Forte@Sun.COM * prints the warning message.
460*7836SJohn.Forte@Sun.COM *
461*7836SJohn.Forte@Sun.COM * RETURNS:
462*7836SJohn.Forte@Sun.COM * None.
463*7836SJohn.Forte@Sun.COM */
464*7836SJohn.Forte@Sun.COM static void
h_prt_warning()465*7836SJohn.Forte@Sun.COM h_prt_warning()
466*7836SJohn.Forte@Sun.COM {
467*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
468*7836SJohn.Forte@Sun.COM MSGSTR(5509,
469*7836SJohn.Forte@Sun.COM "\n WARNING!!! Please ensure that no"
470*7836SJohn.Forte@Sun.COM " filesystems are mounted on these device(s).\n"
471*7836SJohn.Forte@Sun.COM " All data on these devices should have been"
472*7836SJohn.Forte@Sun.COM " backed up.\n\n\n"));
473*7836SJohn.Forte@Sun.COM }
474*7836SJohn.Forte@Sun.COM
475*7836SJohn.Forte@Sun.COM
476*7836SJohn.Forte@Sun.COM
477*7836SJohn.Forte@Sun.COM /*
478*7836SJohn.Forte@Sun.COM * handle helper-mode hotplug commands
479*7836SJohn.Forte@Sun.COM *
480*7836SJohn.Forte@Sun.COM * RETURNS:
481*7836SJohn.Forte@Sun.COM * 0 if OK
482*7836SJohn.Forte@Sun.COM * non-zero otherwise
483*7836SJohn.Forte@Sun.COM */
484*7836SJohn.Forte@Sun.COM int
hotplug(int todo,char ** argv,int verbose_flag,int force_flag)485*7836SJohn.Forte@Sun.COM hotplug(int todo, char **argv, int verbose_flag, int force_flag)
486*7836SJohn.Forte@Sun.COM {
487*7836SJohn.Forte@Sun.COM char ses_path[MAXPATHLEN], dev_path[MAXPATHLEN];
488*7836SJohn.Forte@Sun.COM char *path_phys = NULL, code, node_wwn_s[WWN_S_LEN];
489*7836SJohn.Forte@Sun.COM char inq_path[MAXNAMELEN], *ptr = NULL;
490*7836SJohn.Forte@Sun.COM uchar_t node_wwn[WWN_SIZE], port_wwn[WWN_SIZE];
491*7836SJohn.Forte@Sun.COM int tid, slot, path_index, dtype, f_r, err = 0;
492*7836SJohn.Forte@Sun.COM int al_pa, i, dev_location, found_nullwwn = 0;
493*7836SJohn.Forte@Sun.COM int busy_flag = 0, reserve_flag = 0, action = 0;
494*7836SJohn.Forte@Sun.COM int pathcnt = 1;
495*7836SJohn.Forte@Sun.COM L_state l_state;
496*7836SJohn.Forte@Sun.COM gfc_map_t map;
497*7836SJohn.Forte@Sun.COM Path_struct *path_struct;
498*7836SJohn.Forte@Sun.COM WWN_list *wwn_list = NULL;
499*7836SJohn.Forte@Sun.COM Box_list *box_list;
500*7836SJohn.Forte@Sun.COM Hotplug_Devlist *disk_list, *disk_list_head, *disk_list_tail;
501*7836SJohn.Forte@Sun.COM Hotplug_Devlist *bsyRsrv_dskLst_head, *bsyRsrv_dskLst_tail;
502*7836SJohn.Forte@Sun.COM int enc_type;
503*7836SJohn.Forte@Sun.COM L_inquiry inq;
504*7836SJohn.Forte@Sun.COM char *physpath;
505*7836SJohn.Forte@Sun.COM Path_struct *p_pathstruct;
506*7836SJohn.Forte@Sun.COM char temp2path[MAXPATHLEN];
507*7836SJohn.Forte@Sun.COM mp_pathlist_t pathlist;
508*7836SJohn.Forte@Sun.COM int p_pw = 0, p_on = 0, p_st = 0;
509*7836SJohn.Forte@Sun.COM
510*7836SJohn.Forte@Sun.COM /* Initialize structures and pointers here */
511*7836SJohn.Forte@Sun.COM disk_list_head = disk_list_tail = (Hotplug_Devlist *)NULL;
512*7836SJohn.Forte@Sun.COM bsyRsrv_dskLst_head = (Hotplug_Devlist *)NULL;
513*7836SJohn.Forte@Sun.COM bsyRsrv_dskLst_tail = (Hotplug_Devlist *)NULL;
514*7836SJohn.Forte@Sun.COM map.dev_addr = NULL;
515*7836SJohn.Forte@Sun.COM
516*7836SJohn.Forte@Sun.COM #ifdef DEBUG
517*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
518*7836SJohn.Forte@Sun.COM "DEBUG: luxadm: hotplug() entering for \"%s\" ...\n",
519*7836SJohn.Forte@Sun.COM argv[0] ? argv[0] : "<null ptr>");
520*7836SJohn.Forte@Sun.COM #endif
521*7836SJohn.Forte@Sun.COM if ((err = l_get_box_list(&box_list, 0)) != 0) {
522*7836SJohn.Forte@Sun.COM return (err);
523*7836SJohn.Forte@Sun.COM }
524*7836SJohn.Forte@Sun.COM
525*7836SJohn.Forte@Sun.COM if (todo == REMOVE_DEVICE) {
526*7836SJohn.Forte@Sun.COM (void) h_prt_warning();
527*7836SJohn.Forte@Sun.COM }
528*7836SJohn.Forte@Sun.COM
529*7836SJohn.Forte@Sun.COM /*
530*7836SJohn.Forte@Sun.COM * At this point user want to insert or remove
531*7836SJohn.Forte@Sun.COM * one or more pathnames they've specified.
532*7836SJohn.Forte@Sun.COM */
533*7836SJohn.Forte@Sun.COM if ((err = g_get_wwn_list(&wwn_list, verbose_flag)) != 0) {
534*7836SJohn.Forte@Sun.COM (void) l_free_box_list(&box_list);
535*7836SJohn.Forte@Sun.COM return (err);
536*7836SJohn.Forte@Sun.COM }
537*7836SJohn.Forte@Sun.COM for (path_index = 0; argv[path_index] != NULL; path_index++) {
538*7836SJohn.Forte@Sun.COM if ((err = l_convert_name(argv[path_index], &path_phys,
539*7836SJohn.Forte@Sun.COM &path_struct, verbose_flag)) != 0) {
540*7836SJohn.Forte@Sun.COM /* Make sure we have a device path. */
541*7836SJohn.Forte@Sun.COM (void) strcpy(inq_path, argv[path_index]);
542*7836SJohn.Forte@Sun.COM if (((ptr = strstr(inq_path, ",")) != NULL) &&
543*7836SJohn.Forte@Sun.COM ((*(ptr + 1) == 'f') || (*(ptr + 1) == 'r') ||
544*7836SJohn.Forte@Sun.COM (*(ptr +1) == 's')) &&
545*7836SJohn.Forte@Sun.COM todo == REMOVE_DEVICE) {
546*7836SJohn.Forte@Sun.COM if (err != -1) {
547*7836SJohn.Forte@Sun.COM (void) print_errString(err,
548*7836SJohn.Forte@Sun.COM argv[path_index]);
549*7836SJohn.Forte@Sun.COM err = 0;
550*7836SJohn.Forte@Sun.COM continue;
551*7836SJohn.Forte@Sun.COM }
552*7836SJohn.Forte@Sun.COM *ptr = NULL;
553*7836SJohn.Forte@Sun.COM slot = path_struct->slot;
554*7836SJohn.Forte@Sun.COM f_r = path_struct->f_flag;
555*7836SJohn.Forte@Sun.COM if ((err = l_convert_name(inq_path, &path_phys,
556*7836SJohn.Forte@Sun.COM &path_struct, verbose_flag)) != 0) {
557*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, "\n");
558*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
559*7836SJohn.Forte@Sun.COM MSGSTR(33,
560*7836SJohn.Forte@Sun.COM " Error: converting"
561*7836SJohn.Forte@Sun.COM " %s to physical path.\n"
562*7836SJohn.Forte@Sun.COM " Invalid pathname.\n"),
563*7836SJohn.Forte@Sun.COM argv[path_index]);
564*7836SJohn.Forte@Sun.COM if (err != -1) {
565*7836SJohn.Forte@Sun.COM (void) print_errString(err,
566*7836SJohn.Forte@Sun.COM argv[path_index]);
567*7836SJohn.Forte@Sun.COM }
568*7836SJohn.Forte@Sun.COM err = 0;
569*7836SJohn.Forte@Sun.COM continue;
570*7836SJohn.Forte@Sun.COM }
571*7836SJohn.Forte@Sun.COM if ((err = print_devState(argv[path_index],
572*7836SJohn.Forte@Sun.COM path_struct->p_physical_path,
573*7836SJohn.Forte@Sun.COM f_r, slot, verbose_flag)) != 0) {
574*7836SJohn.Forte@Sun.COM err = 0;
575*7836SJohn.Forte@Sun.COM continue;
576*7836SJohn.Forte@Sun.COM }
577*7836SJohn.Forte@Sun.COM }
578*7836SJohn.Forte@Sun.COM if (path_struct->ib_path_flag) {
579*7836SJohn.Forte@Sun.COM path_phys = path_struct->p_physical_path;
580*7836SJohn.Forte@Sun.COM } else {
581*7836SJohn.Forte@Sun.COM if (err != -1) {
582*7836SJohn.Forte@Sun.COM (void) print_errString(err,
583*7836SJohn.Forte@Sun.COM argv[path_index]);
584*7836SJohn.Forte@Sun.COM } else {
585*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, "\n");
586*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
587*7836SJohn.Forte@Sun.COM MSGSTR(33,
588*7836SJohn.Forte@Sun.COM " Error: converting"
589*7836SJohn.Forte@Sun.COM " %s to physical path.\n"
590*7836SJohn.Forte@Sun.COM " Invalid pathname.\n"),
591*7836SJohn.Forte@Sun.COM argv[path_index]);
592*7836SJohn.Forte@Sun.COM }
593*7836SJohn.Forte@Sun.COM err = 0;
594*7836SJohn.Forte@Sun.COM continue;
595*7836SJohn.Forte@Sun.COM }
596*7836SJohn.Forte@Sun.COM }
597*7836SJohn.Forte@Sun.COM if (path_struct->slot_valid ||
598*7836SJohn.Forte@Sun.COM strstr(path_phys, DRV_NAME_SSD)) {
599*7836SJohn.Forte@Sun.COM dtype = DTYPE_DIRECT;
600*7836SJohn.Forte@Sun.COM } else if (strstr(path_phys, SLSH_DRV_NAME_ST)) {
601*7836SJohn.Forte@Sun.COM dtype = DTYPE_SEQUENTIAL;
602*7836SJohn.Forte@Sun.COM } else {
603*7836SJohn.Forte@Sun.COM dtype = DTYPE_ESI;
604*7836SJohn.Forte@Sun.COM }
605*7836SJohn.Forte@Sun.COM
606*7836SJohn.Forte@Sun.COM if (strstr(path_phys, SCSI_VHCI) != NULL) {
607*7836SJohn.Forte@Sun.COM /* obtain phci */
608*7836SJohn.Forte@Sun.COM (void) strcpy(temp2path, path_phys);
609*7836SJohn.Forte@Sun.COM if (err = g_get_pathlist(temp2path, &pathlist)) {
610*7836SJohn.Forte@Sun.COM (void) print_errString(err, NULL);
611*7836SJohn.Forte@Sun.COM exit(-1);
612*7836SJohn.Forte@Sun.COM }
613*7836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
614*7836SJohn.Forte@Sun.COM p_pw = p_on = p_st = 0;
615*7836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
616*7836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state <
617*7836SJohn.Forte@Sun.COM MAXPATHSTATE) {
618*7836SJohn.Forte@Sun.COM if (strstr(pathlist.path_info[i].
619*7836SJohn.Forte@Sun.COM path_addr,
620*7836SJohn.Forte@Sun.COM path_struct->argv) != NULL) {
621*7836SJohn.Forte@Sun.COM p_pw = i;
622*7836SJohn.Forte@Sun.COM break;
623*7836SJohn.Forte@Sun.COM }
624*7836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
625*7836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
626*7836SJohn.Forte@Sun.COM p_on = i;
627*7836SJohn.Forte@Sun.COM }
628*7836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
629*7836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
630*7836SJohn.Forte@Sun.COM p_st = i;
631*7836SJohn.Forte@Sun.COM }
632*7836SJohn.Forte@Sun.COM }
633*7836SJohn.Forte@Sun.COM }
634*7836SJohn.Forte@Sun.COM if (strstr(pathlist.path_info[p_pw].path_addr,
635*7836SJohn.Forte@Sun.COM path_struct->argv) != NULL) {
636*7836SJohn.Forte@Sun.COM /* matching input pwwn */
637*7836SJohn.Forte@Sun.COM (void) strcpy(temp2path,
638*7836SJohn.Forte@Sun.COM pathlist.path_info[p_pw].path_hba);
639*7836SJohn.Forte@Sun.COM } else if (pathlist.path_info[p_on].path_state ==
640*7836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
641*7836SJohn.Forte@Sun.COM /* on_line path */
642*7836SJohn.Forte@Sun.COM (void) strcpy(temp2path,
643*7836SJohn.Forte@Sun.COM pathlist.path_info[p_on].path_hba);
644*7836SJohn.Forte@Sun.COM } else {
645*7836SJohn.Forte@Sun.COM /* standby or path0 */
646*7836SJohn.Forte@Sun.COM (void) strcpy(temp2path,
647*7836SJohn.Forte@Sun.COM pathlist.path_info[p_st].path_hba);
648*7836SJohn.Forte@Sun.COM }
649*7836SJohn.Forte@Sun.COM free(pathlist.path_info);
650*7836SJohn.Forte@Sun.COM (void) strcat(temp2path, FC_CTLR);
651*7836SJohn.Forte@Sun.COM } else {
652*7836SJohn.Forte@Sun.COM (void) strcpy(temp2path, path_phys);
653*7836SJohn.Forte@Sun.COM }
654*7836SJohn.Forte@Sun.COM
655*7836SJohn.Forte@Sun.COM if ((err = g_get_dev_map(temp2path, &map, verbose_flag))
656*7836SJohn.Forte@Sun.COM != 0) {
657*7836SJohn.Forte@Sun.COM return (err);
658*7836SJohn.Forte@Sun.COM }
659*7836SJohn.Forte@Sun.COM
660*7836SJohn.Forte@Sun.COM if ((map.hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) ||
661*7836SJohn.Forte@Sun.COM (map.hba_addr.port_topology == FC_TOP_FABRIC)) {
662*7836SJohn.Forte@Sun.COM /* public or fabric loop device */
663*7836SJohn.Forte@Sun.COM free((void *)map.dev_addr);
664*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, MSGSTR(5540,
665*7836SJohn.Forte@Sun.COM "This operation is not "
666*7836SJohn.Forte@Sun.COM "supported in this topology.\n"));
667*7836SJohn.Forte@Sun.COM exit(-1);
668*7836SJohn.Forte@Sun.COM }
669*7836SJohn.Forte@Sun.COM
670*7836SJohn.Forte@Sun.COM if (todo == REPLACE_DEVICE) {
671*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
672*7836SJohn.Forte@Sun.COM MSGSTR(5511,
673*7836SJohn.Forte@Sun.COM "Error:"
674*7836SJohn.Forte@Sun.COM " replace_device is not supported"
675*7836SJohn.Forte@Sun.COM " on this subsystem.\n"));
676*7836SJohn.Forte@Sun.COM exit(-1);
677*7836SJohn.Forte@Sun.COM }
678*7836SJohn.Forte@Sun.COM
679*7836SJohn.Forte@Sun.COM if ((todo == REMOVE_DEVICE) &&
680*7836SJohn.Forte@Sun.COM (dtype == DTYPE_DIRECT ||
681*7836SJohn.Forte@Sun.COM dtype == DTYPE_SEQUENTIAL ||
682*7836SJohn.Forte@Sun.COM dtype == DTYPE_UNKNOWN)) {
683*7836SJohn.Forte@Sun.COM if (l_chk_null_wwn(path_struct, ses_path,
684*7836SJohn.Forte@Sun.COM &l_state, verbose_flag) == 1) {
685*7836SJohn.Forte@Sun.COM found_nullwwn = 1;
686*7836SJohn.Forte@Sun.COM /*
687*7836SJohn.Forte@Sun.COM * set dev_path to NULL,
688*7836SJohn.Forte@Sun.COM * if disk has null wwn.
689*7836SJohn.Forte@Sun.COM */
690*7836SJohn.Forte@Sun.COM *dev_path = NULL;
691*7836SJohn.Forte@Sun.COM dev_location = SENA;
692*7836SJohn.Forte@Sun.COM goto getinfo;
693*7836SJohn.Forte@Sun.COM }
694*7836SJohn.Forte@Sun.COM }
695*7836SJohn.Forte@Sun.COM
696*7836SJohn.Forte@Sun.COM (void) strcpy(ses_path, path_phys);
697*7836SJohn.Forte@Sun.COM
698*7836SJohn.Forte@Sun.COM if (strstr(ses_path, "ses") == NULL &&
699*7836SJohn.Forte@Sun.COM l_get_ses_path(path_phys, ses_path, &map,
700*7836SJohn.Forte@Sun.COM verbose_flag) != 0) {
701*7836SJohn.Forte@Sun.COM
702*7836SJohn.Forte@Sun.COM /* Could be a non-photon disk device */
703*7836SJohn.Forte@Sun.COM if ((todo == REMOVE_DEVICE) &&
704*7836SJohn.Forte@Sun.COM (dtype == DTYPE_DIRECT ||
705*7836SJohn.Forte@Sun.COM dtype == DTYPE_SEQUENTIAL)) {
706*7836SJohn.Forte@Sun.COM dev_location = NON_SENA;
707*7836SJohn.Forte@Sun.COM
708*7836SJohn.Forte@Sun.COM if ((err = h_get_fcdev_state(argv[path_index],
709*7836SJohn.Forte@Sun.COM path_phys, force_flag,
710*7836SJohn.Forte@Sun.COM &busy_flag, &reserve_flag,
711*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) {
712*7836SJohn.Forte@Sun.COM goto done;
713*7836SJohn.Forte@Sun.COM }
714*7836SJohn.Forte@Sun.COM (void) strcpy(dev_path, path_phys);
715*7836SJohn.Forte@Sun.COM if ((err = g_get_wwn(dev_path, port_wwn,
716*7836SJohn.Forte@Sun.COM node_wwn, &al_pa,
717*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) {
718*7836SJohn.Forte@Sun.COM goto done;
719*7836SJohn.Forte@Sun.COM }
720*7836SJohn.Forte@Sun.COM (void) sprintf(node_wwn_s,
721*7836SJohn.Forte@Sun.COM "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
722*7836SJohn.Forte@Sun.COM node_wwn[0], node_wwn[1], node_wwn[2],
723*7836SJohn.Forte@Sun.COM node_wwn[3], node_wwn[4], node_wwn[5],
724*7836SJohn.Forte@Sun.COM node_wwn[6], node_wwn[7]);
725*7836SJohn.Forte@Sun.COM tid = g_sf_alpa_to_switch[al_pa];
726*7836SJohn.Forte@Sun.COM goto loop;
727*7836SJohn.Forte@Sun.COM }
728*7836SJohn.Forte@Sun.COM continue;
729*7836SJohn.Forte@Sun.COM }
730*7836SJohn.Forte@Sun.COM
731*7836SJohn.Forte@Sun.COM if (strstr(ses_path, "ses") != NULL) {
732*7836SJohn.Forte@Sun.COM dev_location = SENA;
733*7836SJohn.Forte@Sun.COM if ((err = l_convert_name(ses_path, &physpath,
734*7836SJohn.Forte@Sun.COM &p_pathstruct, 0)) != 0) {
735*7836SJohn.Forte@Sun.COM free(physpath);
736*7836SJohn.Forte@Sun.COM free(p_pathstruct);
737*7836SJohn.Forte@Sun.COM goto done;
738*7836SJohn.Forte@Sun.COM
739*7836SJohn.Forte@Sun.COM }
740*7836SJohn.Forte@Sun.COM if ((err = g_get_inquiry(physpath, &inq)) != 0) {
741*7836SJohn.Forte@Sun.COM free(physpath);
742*7836SJohn.Forte@Sun.COM free(p_pathstruct);
743*7836SJohn.Forte@Sun.COM goto done;
744*7836SJohn.Forte@Sun.COM }
745*7836SJohn.Forte@Sun.COM enc_type = l_get_enc_type(inq);
746*7836SJohn.Forte@Sun.COM
747*7836SJohn.Forte@Sun.COM }
748*7836SJohn.Forte@Sun.COM if ((err = l_get_status(ses_path,
749*7836SJohn.Forte@Sun.COM &l_state, verbose_flag)) != 0) {
750*7836SJohn.Forte@Sun.COM goto done;
751*7836SJohn.Forte@Sun.COM }
752*7836SJohn.Forte@Sun.COM if (dtype == DTYPE_ESI) {
753*7836SJohn.Forte@Sun.COM /* could be removing a photon */
754*7836SJohn.Forte@Sun.COM if (todo == REMOVE_DEVICE) {
755*7836SJohn.Forte@Sun.COM /*
756*7836SJohn.Forte@Sun.COM * Need the select ID (tid) for the IB.
757*7836SJohn.Forte@Sun.COM */
758*7836SJohn.Forte@Sun.COM if ((err = g_get_wwn(ses_path, port_wwn,
759*7836SJohn.Forte@Sun.COM node_wwn, &al_pa,
760*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) {
761*7836SJohn.Forte@Sun.COM goto done;
762*7836SJohn.Forte@Sun.COM }
763*7836SJohn.Forte@Sun.COM (void) sprintf(node_wwn_s,
764*7836SJohn.Forte@Sun.COM "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
765*7836SJohn.Forte@Sun.COM node_wwn[0], node_wwn[1], node_wwn[2],
766*7836SJohn.Forte@Sun.COM node_wwn[3], node_wwn[4], node_wwn[5],
767*7836SJohn.Forte@Sun.COM node_wwn[6], node_wwn[7]);
768*7836SJohn.Forte@Sun.COM tid = g_sf_alpa_to_switch[al_pa];
769*7836SJohn.Forte@Sun.COM *dev_path = '\0';
770*7836SJohn.Forte@Sun.COM /*
771*7836SJohn.Forte@Sun.COM * Check if any disk in this photon
772*7836SJohn.Forte@Sun.COM * is reserved by another host
773*7836SJohn.Forte@Sun.COM */
774*7836SJohn.Forte@Sun.COM if (!force_flag) {
775*7836SJohn.Forte@Sun.COM for (
776*7836SJohn.Forte@Sun.COM i = 0;
777*7836SJohn.Forte@Sun.COM i < l_state.total_num_drv/2;
778*7836SJohn.Forte@Sun.COM i++) {
779*7836SJohn.Forte@Sun.COM if ((l_state.drv_front[i].g_disk_state.d_state_flags[PORT_A] &
780*7836SJohn.Forte@Sun.COM L_RESERVED) ||
781*7836SJohn.Forte@Sun.COM (l_state.drv_front[i].g_disk_state.d_state_flags[PORT_B] &
782*7836SJohn.Forte@Sun.COM L_RESERVED) ||
783*7836SJohn.Forte@Sun.COM (l_state.drv_rear[i].g_disk_state.d_state_flags[PORT_A] &
784*7836SJohn.Forte@Sun.COM L_RESERVED) ||
785*7836SJohn.Forte@Sun.COM (l_state.drv_rear[i].g_disk_state.d_state_flags[PORT_B] &
786*7836SJohn.Forte@Sun.COM L_RESERVED)) {
787*7836SJohn.Forte@Sun.COM reserve_flag = 1;
788*7836SJohn.Forte@Sun.COM }
789*7836SJohn.Forte@Sun.COM }
790*7836SJohn.Forte@Sun.COM }
791*7836SJohn.Forte@Sun.COM goto loop;
792*7836SJohn.Forte@Sun.COM }
793*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
794*7836SJohn.Forte@Sun.COM MSGSTR(5512,
795*7836SJohn.Forte@Sun.COM "Error: %s already exists!!\n"),
796*7836SJohn.Forte@Sun.COM argv[path_index]);
797*7836SJohn.Forte@Sun.COM goto done;
798*7836SJohn.Forte@Sun.COM }
799*7836SJohn.Forte@Sun.COM getinfo:
800*7836SJohn.Forte@Sun.COM if (!path_struct->slot_valid) {
801*7836SJohn.Forte@Sun.COM /* We are passing the disks path */
802*7836SJohn.Forte@Sun.COM if ((err = l_get_slot(path_struct, &l_state,
803*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) {
804*7836SJohn.Forte@Sun.COM goto done;
805*7836SJohn.Forte@Sun.COM }
806*7836SJohn.Forte@Sun.COM }
807*7836SJohn.Forte@Sun.COM
808*7836SJohn.Forte@Sun.COM slot = path_struct->slot;
809*7836SJohn.Forte@Sun.COM if (path_struct->f_flag) {
810*7836SJohn.Forte@Sun.COM tid = l_state.drv_front[slot].ib_status.sel_id;
811*7836SJohn.Forte@Sun.COM code = l_state.drv_front[slot].ib_status.code;
812*7836SJohn.Forte@Sun.COM (void) strcpy(node_wwn_s,
813*7836SJohn.Forte@Sun.COM l_state.drv_front[slot].g_disk_state.node_wwn_s);
814*7836SJohn.Forte@Sun.COM } else {
815*7836SJohn.Forte@Sun.COM tid = l_state.drv_rear[slot].ib_status.sel_id;
816*7836SJohn.Forte@Sun.COM code = l_state.drv_rear[slot].ib_status.code;
817*7836SJohn.Forte@Sun.COM (void) strcpy(node_wwn_s,
818*7836SJohn.Forte@Sun.COM l_state.drv_rear[slot].g_disk_state.node_wwn_s);
819*7836SJohn.Forte@Sun.COM }
820*7836SJohn.Forte@Sun.COM
821*7836SJohn.Forte@Sun.COM if (found_nullwwn) {
822*7836SJohn.Forte@Sun.COM goto loop;
823*7836SJohn.Forte@Sun.COM }
824*7836SJohn.Forte@Sun.COM
825*7836SJohn.Forte@Sun.COM l_make_node(ses_path, tid, dev_path, &map, 0);
826*7836SJohn.Forte@Sun.COM
827*7836SJohn.Forte@Sun.COM if ((todo == INSERT_DEVICE) &&
828*7836SJohn.Forte@Sun.COM (g_device_in_map(&map, tid) ||
829*7836SJohn.Forte@Sun.COM (code != S_NOT_INSTALLED))) {
830*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
831*7836SJohn.Forte@Sun.COM MSGSTR(5513, "\nNotice: %s may "
832*7836SJohn.Forte@Sun.COM "already be present.\n"),
833*7836SJohn.Forte@Sun.COM argv[path_index]);
834*7836SJohn.Forte@Sun.COM if (path_struct->f_flag) {
835*7836SJohn.Forte@Sun.COM if ((l_state.drv_front[slot].l_state_flag
836*7836SJohn.Forte@Sun.COM != L_NO_PATH_FOUND) &&
837*7836SJohn.Forte@Sun.COM (!l_state.drv_front[slot].ib_status.dev_off))
838*7836SJohn.Forte@Sun.COM continue;
839*7836SJohn.Forte@Sun.COM } else {
840*7836SJohn.Forte@Sun.COM if ((l_state.drv_rear[slot].l_state_flag
841*7836SJohn.Forte@Sun.COM != L_NO_PATH_FOUND) &&
842*7836SJohn.Forte@Sun.COM (!l_state.drv_rear[slot].ib_status.dev_off))
843*7836SJohn.Forte@Sun.COM continue;
844*7836SJohn.Forte@Sun.COM }
845*7836SJohn.Forte@Sun.COM }
846*7836SJohn.Forte@Sun.COM
847*7836SJohn.Forte@Sun.COM /* Check if disk is reserved */
848*7836SJohn.Forte@Sun.COM if ((todo == REMOVE_DEVICE) && (!force_flag)) {
849*7836SJohn.Forte@Sun.COM if (path_struct->f_flag) {
850*7836SJohn.Forte@Sun.COM if ((l_state.drv_front[slot].g_disk_state.d_state_flags[PORT_A] &
851*7836SJohn.Forte@Sun.COM L_RESERVED) ||
852*7836SJohn.Forte@Sun.COM (l_state.drv_front[slot].g_disk_state.d_state_flags[PORT_B] &
853*7836SJohn.Forte@Sun.COM L_RESERVED)) {
854*7836SJohn.Forte@Sun.COM reserve_flag = 1;
855*7836SJohn.Forte@Sun.COM }
856*7836SJohn.Forte@Sun.COM } else {
857*7836SJohn.Forte@Sun.COM if ((l_state.drv_rear[slot].g_disk_state.d_state_flags[PORT_A] &
858*7836SJohn.Forte@Sun.COM L_RESERVED) ||
859*7836SJohn.Forte@Sun.COM (l_state.drv_rear[slot].g_disk_state.d_state_flags[PORT_B] &
860*7836SJohn.Forte@Sun.COM L_RESERVED)) {
861*7836SJohn.Forte@Sun.COM reserve_flag = 1;
862*7836SJohn.Forte@Sun.COM }
863*7836SJohn.Forte@Sun.COM }
864*7836SJohn.Forte@Sun.COM }
865*7836SJohn.Forte@Sun.COM
866*7836SJohn.Forte@Sun.COM loop:
867*7836SJohn.Forte@Sun.COM if ((disk_list = (Hotplug_Devlist *)
868*7836SJohn.Forte@Sun.COM calloc(1, sizeof (Hotplug_Devlist))) == NULL) {
869*7836SJohn.Forte@Sun.COM (void) print_errString(L_MALLOC_FAILED, NULL);
870*7836SJohn.Forte@Sun.COM goto done;
871*7836SJohn.Forte@Sun.COM }
872*7836SJohn.Forte@Sun.COM
873*7836SJohn.Forte@Sun.COM /*
874*7836SJohn.Forte@Sun.COM * dev_path is NULL when removing a whole encloser. We
875*7836SJohn.Forte@Sun.COM * don't want to call g_get_multipath while removing whole
876*7836SJohn.Forte@Sun.COM * enclosure. Its being taken care later in the code path
877*7836SJohn.Forte@Sun.COM */
878*7836SJohn.Forte@Sun.COM
879*7836SJohn.Forte@Sun.COM if ((todo != INSERT_DEVICE) && (dtype != DTYPE_ESI)) {
880*7836SJohn.Forte@Sun.COM if ((err = g_get_multipath(dev_path,
881*7836SJohn.Forte@Sun.COM &(disk_list->dlhead),
882*7836SJohn.Forte@Sun.COM wwn_list, verbose_flag)) != 0) {
883*7836SJohn.Forte@Sun.COM if (disk_list->dlhead != NULL) {
884*7836SJohn.Forte@Sun.COM (void) g_free_multipath(
885*7836SJohn.Forte@Sun.COM disk_list->dlhead);
886*7836SJohn.Forte@Sun.COM }
887*7836SJohn.Forte@Sun.COM goto done;
888*7836SJohn.Forte@Sun.COM }
889*7836SJohn.Forte@Sun.COM }
890*7836SJohn.Forte@Sun.COM disk_list->dev_type = dtype;
891*7836SJohn.Forte@Sun.COM disk_list->dev_location = dev_location;
892*7836SJohn.Forte@Sun.COM (void) strcpy(disk_list->dev_name,
893*7836SJohn.Forte@Sun.COM argv[path_index]);
894*7836SJohn.Forte@Sun.COM disk_list->tid = tid;
895*7836SJohn.Forte@Sun.COM (void) strcpy(disk_list->node_wwn_s, node_wwn_s);
896*7836SJohn.Forte@Sun.COM if (dev_location == SENA) {
897*7836SJohn.Forte@Sun.COM if ((err = l_get_allses(ses_path, box_list,
898*7836SJohn.Forte@Sun.COM &(disk_list->seslist), 0)) != 0) {
899*7836SJohn.Forte@Sun.COM if (disk_list->seslist != NULL) {
900*7836SJohn.Forte@Sun.COM (void) g_free_multipath(disk_list->seslist);
901*7836SJohn.Forte@Sun.COM }
902*7836SJohn.Forte@Sun.COM goto done;
903*7836SJohn.Forte@Sun.COM }
904*7836SJohn.Forte@Sun.COM (void) strcpy(disk_list->box_name,
905*7836SJohn.Forte@Sun.COM (char *)l_state.ib_tbl.enclosure_name);
906*7836SJohn.Forte@Sun.COM disk_list->slot = slot;
907*7836SJohn.Forte@Sun.COM disk_list->f_flag = path_struct->f_flag;
908*7836SJohn.Forte@Sun.COM }
909*7836SJohn.Forte@Sun.COM if (todo == REMOVE_DEVICE && !force_flag && !reserve_flag) {
910*7836SJohn.Forte@Sun.COM if ((err = h_chk_dev_busy(disk_list, wwn_list,
911*7836SJohn.Forte@Sun.COM &busy_flag, force_flag, verbose_flag)) != 0) {
912*7836SJohn.Forte@Sun.COM goto done;
913*7836SJohn.Forte@Sun.COM }
914*7836SJohn.Forte@Sun.COM }
915*7836SJohn.Forte@Sun.COM
916*7836SJohn.Forte@Sun.COM if (reserve_flag || busy_flag) {
917*7836SJohn.Forte@Sun.COM if (reserve_flag)
918*7836SJohn.Forte@Sun.COM disk_list->reserve_flag = 1;
919*7836SJohn.Forte@Sun.COM if (busy_flag)
920*7836SJohn.Forte@Sun.COM disk_list->busy_flag = 1;
921*7836SJohn.Forte@Sun.COM
922*7836SJohn.Forte@Sun.COM if (bsyRsrv_dskLst_head == NULL) {
923*7836SJohn.Forte@Sun.COM bsyRsrv_dskLst_head =
924*7836SJohn.Forte@Sun.COM bsyRsrv_dskLst_tail = disk_list;
925*7836SJohn.Forte@Sun.COM } else {
926*7836SJohn.Forte@Sun.COM disk_list->prev = bsyRsrv_dskLst_tail;
927*7836SJohn.Forte@Sun.COM bsyRsrv_dskLst_tail->next = disk_list;
928*7836SJohn.Forte@Sun.COM bsyRsrv_dskLst_tail = disk_list;
929*7836SJohn.Forte@Sun.COM }
930*7836SJohn.Forte@Sun.COM reserve_flag = 0;
931*7836SJohn.Forte@Sun.COM busy_flag = 0;
932*7836SJohn.Forte@Sun.COM
933*7836SJohn.Forte@Sun.COM } else if (disk_list_head == NULL) {
934*7836SJohn.Forte@Sun.COM disk_list_head = disk_list_tail = disk_list;
935*7836SJohn.Forte@Sun.COM } else {
936*7836SJohn.Forte@Sun.COM disk_list->prev = disk_list_tail;
937*7836SJohn.Forte@Sun.COM disk_list_tail->next = disk_list;
938*7836SJohn.Forte@Sun.COM disk_list_tail = disk_list;
939*7836SJohn.Forte@Sun.COM }
940*7836SJohn.Forte@Sun.COM }
941*7836SJohn.Forte@Sun.COM
942*7836SJohn.Forte@Sun.COM if (bsyRsrv_dskLst_head != NULL) {
943*7836SJohn.Forte@Sun.COM if ((err = h_print_list(bsyRsrv_dskLst_head,
944*7836SJohn.Forte@Sun.COM &action, enc_type)) != 0) {
945*7836SJohn.Forte@Sun.COM goto done;
946*7836SJohn.Forte@Sun.COM }
947*7836SJohn.Forte@Sun.COM if (action == SKIP) {
948*7836SJohn.Forte@Sun.COM (void) h_free_hotplug_dlist(&bsyRsrv_dskLst_head);
949*7836SJohn.Forte@Sun.COM } else if (action == QUIT) {
950*7836SJohn.Forte@Sun.COM goto done;
951*7836SJohn.Forte@Sun.COM }
952*7836SJohn.Forte@Sun.COM }
953*7836SJohn.Forte@Sun.COM if (disk_list_head != NULL) {
954*7836SJohn.Forte@Sun.COM if ((h_print_list_warn(disk_list_head, todo, enc_type)) != 0) {
955*7836SJohn.Forte@Sun.COM goto done;
956*7836SJohn.Forte@Sun.COM }
957*7836SJohn.Forte@Sun.COM if ((err = h_pre_hotplug(&disk_list_head, wwn_list, todo, verbose_flag,
958*7836SJohn.Forte@Sun.COM force_flag)) != 0) {
959*7836SJohn.Forte@Sun.COM goto done;
960*7836SJohn.Forte@Sun.COM }
961*7836SJohn.Forte@Sun.COM if (disk_list_head != NULL) {
962*7836SJohn.Forte@Sun.COM if (todo == REMOVE_DEVICE) {
963*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5514,
964*7836SJohn.Forte@Sun.COM "\nHit <Return> after "
965*7836SJohn.Forte@Sun.COM "removing the device(s)."));
966*7836SJohn.Forte@Sun.COM } else {
967*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5515,
968*7836SJohn.Forte@Sun.COM "\nHit <Return> after "
969*7836SJohn.Forte@Sun.COM "inserting the device(s)."));
970*7836SJohn.Forte@Sun.COM }
971*7836SJohn.Forte@Sun.COM (void) getchar();
972*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\n");
973*7836SJohn.Forte@Sun.COM if ((err = h_post_hotplug(disk_list_head, wwn_list,
974*7836SJohn.Forte@Sun.COM todo, verbose_flag, force_flag,
975*7836SJohn.Forte@Sun.COM enc_type)) != 0) {
976*7836SJohn.Forte@Sun.COM goto done;
977*7836SJohn.Forte@Sun.COM }
978*7836SJohn.Forte@Sun.COM }
979*7836SJohn.Forte@Sun.COM }
980*7836SJohn.Forte@Sun.COM done:
981*7836SJohn.Forte@Sun.COM (void) l_free_box_list(&box_list);
982*7836SJohn.Forte@Sun.COM (void) g_free_wwn_list(&wwn_list);
983*7836SJohn.Forte@Sun.COM if (err && err != -1) {
984*7836SJohn.Forte@Sun.COM return (err);
985*7836SJohn.Forte@Sun.COM }
986*7836SJohn.Forte@Sun.COM free((void *)map.dev_addr);
987*7836SJohn.Forte@Sun.COM return (0);
988*7836SJohn.Forte@Sun.COM }
989*7836SJohn.Forte@Sun.COM
990*7836SJohn.Forte@Sun.COM
991*7836SJohn.Forte@Sun.COM
992*7836SJohn.Forte@Sun.COM
993*7836SJohn.Forte@Sun.COM /*
994*7836SJohn.Forte@Sun.COM * Internal routine to clean up ../'s in paths.
995*7836SJohn.Forte@Sun.COM * returns 0 if no "../" are left.
996*7836SJohn.Forte@Sun.COM *
997*7836SJohn.Forte@Sun.COM * Wouldn't it be nice if there was a standard system library
998*7836SJohn.Forte@Sun.COM * routine to do this...?
999*7836SJohn.Forte@Sun.COM */
1000*7836SJohn.Forte@Sun.COM static int
cleanup_dotdot_path(char * path)1001*7836SJohn.Forte@Sun.COM cleanup_dotdot_path(char *path)
1002*7836SJohn.Forte@Sun.COM {
1003*7836SJohn.Forte@Sun.COM char holder[MAXPATHLEN];
1004*7836SJohn.Forte@Sun.COM char *dotdot;
1005*7836SJohn.Forte@Sun.COM char *previous_slash;
1006*7836SJohn.Forte@Sun.COM
1007*7836SJohn.Forte@Sun.COM /* Find the first "/../" in the string */
1008*7836SJohn.Forte@Sun.COM dotdot = strstr(path, "/../");
1009*7836SJohn.Forte@Sun.COM if (dotdot == NULL) {
1010*7836SJohn.Forte@Sun.COM return (0);
1011*7836SJohn.Forte@Sun.COM }
1012*7836SJohn.Forte@Sun.COM
1013*7836SJohn.Forte@Sun.COM
1014*7836SJohn.Forte@Sun.COM /*
1015*7836SJohn.Forte@Sun.COM * If the [0] character is '/' and "../" immediatly
1016*7836SJohn.Forte@Sun.COM * follows it, then we can strip the ../
1017*7836SJohn.Forte@Sun.COM *
1018*7836SJohn.Forte@Sun.COM * /../../foo/bar == /foo/bar
1019*7836SJohn.Forte@Sun.COM *
1020*7836SJohn.Forte@Sun.COM */
1021*7836SJohn.Forte@Sun.COM if (dotdot == path) {
1022*7836SJohn.Forte@Sun.COM strcpy(holder, &path[3]); /* strip "/.." */
1023*7836SJohn.Forte@Sun.COM strcpy(path, holder);
1024*7836SJohn.Forte@Sun.COM return (1);
1025*7836SJohn.Forte@Sun.COM }
1026*7836SJohn.Forte@Sun.COM
1027*7836SJohn.Forte@Sun.COM /*
1028*7836SJohn.Forte@Sun.COM * Now look for the LAST "/" before the "/../"
1029*7836SJohn.Forte@Sun.COM * as this is the parent dir we can get rid of.
1030*7836SJohn.Forte@Sun.COM * We do this by temporarily truncating the string
1031*7836SJohn.Forte@Sun.COM * at the '/' just before "../" using the dotdot pointer.
1032*7836SJohn.Forte@Sun.COM */
1033*7836SJohn.Forte@Sun.COM *dotdot = '\0';
1034*7836SJohn.Forte@Sun.COM previous_slash = strrchr(path, '/');
1035*7836SJohn.Forte@Sun.COM if (previous_slash == NULL) {
1036*7836SJohn.Forte@Sun.COM /*
1037*7836SJohn.Forte@Sun.COM * hmm, somethings wrong. path looks something
1038*7836SJohn.Forte@Sun.COM * like "foo/../bar/" so we can't really deal with it.
1039*7836SJohn.Forte@Sun.COM */
1040*7836SJohn.Forte@Sun.COM return (0);
1041*7836SJohn.Forte@Sun.COM }
1042*7836SJohn.Forte@Sun.COM /*
1043*7836SJohn.Forte@Sun.COM * Now truncate the path just after the previous '/'
1044*7836SJohn.Forte@Sun.COM * and slam everything after the "../" back on
1045*7836SJohn.Forte@Sun.COM */
1046*7836SJohn.Forte@Sun.COM *(previous_slash+1) = '\0';
1047*7836SJohn.Forte@Sun.COM (void) strcat(path, dotdot+4);
1048*7836SJohn.Forte@Sun.COM return (1); /* We may have more "../"s */
1049*7836SJohn.Forte@Sun.COM }
1050*7836SJohn.Forte@Sun.COM
1051*7836SJohn.Forte@Sun.COM
1052*7836SJohn.Forte@Sun.COM /*
1053*7836SJohn.Forte@Sun.COM * Follow symbolic links from the logical device name to
1054*7836SJohn.Forte@Sun.COM * the /devfs physical device name. To be complete, we
1055*7836SJohn.Forte@Sun.COM * handle the case of multiple links. This function
1056*7836SJohn.Forte@Sun.COM * either returns NULL (no links, or some other error),
1057*7836SJohn.Forte@Sun.COM * or the physical device name, alloc'ed on the heap.
1058*7836SJohn.Forte@Sun.COM *
1059*7836SJohn.Forte@Sun.COM * For S10 the physical path may be non-existent.
1060*7836SJohn.Forte@Sun.COM *
1061*7836SJohn.Forte@Sun.COM * NOTE: If the path is relative, it will be forced into
1062*7836SJohn.Forte@Sun.COM * an absolute path by pre-pending the pwd to it.
1063*7836SJohn.Forte@Sun.COM */
1064*7836SJohn.Forte@Sun.COM char *
h_get_physical_name_from_link(char * path)1065*7836SJohn.Forte@Sun.COM h_get_physical_name_from_link(char *path)
1066*7836SJohn.Forte@Sun.COM {
1067*7836SJohn.Forte@Sun.COM struct stat stbuf;
1068*7836SJohn.Forte@Sun.COM char source[MAXPATHLEN];
1069*7836SJohn.Forte@Sun.COM char scratch[MAXPATHLEN];
1070*7836SJohn.Forte@Sun.COM char pwd[MAXPATHLEN];
1071*7836SJohn.Forte@Sun.COM char *tmp;
1072*7836SJohn.Forte@Sun.COM int cnt;
1073*7836SJohn.Forte@Sun.COM
1074*7836SJohn.Forte@Sun.COM /* return NULL if path is NULL */
1075*7836SJohn.Forte@Sun.COM if (path == NULL) {
1076*7836SJohn.Forte@Sun.COM return (NULL);
1077*7836SJohn.Forte@Sun.COM }
1078*7836SJohn.Forte@Sun.COM
1079*7836SJohn.Forte@Sun.COM strcpy(source, path);
1080*7836SJohn.Forte@Sun.COM for (;;) {
1081*7836SJohn.Forte@Sun.COM
1082*7836SJohn.Forte@Sun.COM /*
1083*7836SJohn.Forte@Sun.COM * First make sure the path is absolute. If not, make it.
1084*7836SJohn.Forte@Sun.COM * If it's already an absolute path, we have no need
1085*7836SJohn.Forte@Sun.COM * to determine the cwd, so the program should still
1086*7836SJohn.Forte@Sun.COM * function within security-by-obscurity directories.
1087*7836SJohn.Forte@Sun.COM */
1088*7836SJohn.Forte@Sun.COM if (source[0] != '/') {
1089*7836SJohn.Forte@Sun.COM tmp = getcwd(pwd, MAXPATHLEN);
1090*7836SJohn.Forte@Sun.COM if (tmp == NULL) {
1091*7836SJohn.Forte@Sun.COM O_DPRINTF("getcwd() failed - %s\n",
1092*7836SJohn.Forte@Sun.COM strerror(errno));
1093*7836SJohn.Forte@Sun.COM return (NULL);
1094*7836SJohn.Forte@Sun.COM }
1095*7836SJohn.Forte@Sun.COM /*
1096*7836SJohn.Forte@Sun.COM * Handle special case of "./foo/bar"
1097*7836SJohn.Forte@Sun.COM */
1098*7836SJohn.Forte@Sun.COM if (source[0] == '.' && source[1] == '/') {
1099*7836SJohn.Forte@Sun.COM strcpy(scratch, source+2);
1100*7836SJohn.Forte@Sun.COM } else { /* no "./" so just take everything */
1101*7836SJohn.Forte@Sun.COM strcpy(scratch, source);
1102*7836SJohn.Forte@Sun.COM }
1103*7836SJohn.Forte@Sun.COM strcpy(source, pwd);
1104*7836SJohn.Forte@Sun.COM (void) strcat(source, "/");
1105*7836SJohn.Forte@Sun.COM (void) strcat(source, scratch);
1106*7836SJohn.Forte@Sun.COM }
1107*7836SJohn.Forte@Sun.COM
1108*7836SJohn.Forte@Sun.COM /*
1109*7836SJohn.Forte@Sun.COM * Clean up any "../"s that are in the path
1110*7836SJohn.Forte@Sun.COM */
1111*7836SJohn.Forte@Sun.COM while (cleanup_dotdot_path(source));
1112*7836SJohn.Forte@Sun.COM
1113*7836SJohn.Forte@Sun.COM /*
1114*7836SJohn.Forte@Sun.COM * source is now an absolute path to the link we're
1115*7836SJohn.Forte@Sun.COM * concerned with
1116*7836SJohn.Forte@Sun.COM *
1117*7836SJohn.Forte@Sun.COM * S10: Do NOT ignore dangling links, pointing to devfs nodes.
1118*7836SJohn.Forte@Sun.COM */
1119*7836SJohn.Forte@Sun.COM if (strstr(source, "/devices")) {
1120*7836SJohn.Forte@Sun.COM return (g_alloc_string(source));
1121*7836SJohn.Forte@Sun.COM }
1122*7836SJohn.Forte@Sun.COM
1123*7836SJohn.Forte@Sun.COM if (lstat(source, &stbuf) == -1) {
1124*7836SJohn.Forte@Sun.COM O_DPRINTF("lstat() failed for - %s\n",
1125*7836SJohn.Forte@Sun.COM source, strerror(errno));
1126*7836SJohn.Forte@Sun.COM return (NULL);
1127*7836SJohn.Forte@Sun.COM }
1128*7836SJohn.Forte@Sun.COM /*
1129*7836SJohn.Forte@Sun.COM * If the file is not a link, we're done one
1130*7836SJohn.Forte@Sun.COM * way or the other. If there were links,
1131*7836SJohn.Forte@Sun.COM * return the full pathname of the resulting
1132*7836SJohn.Forte@Sun.COM * file.
1133*7836SJohn.Forte@Sun.COM *
1134*7836SJohn.Forte@Sun.COM * Note: All of our temp's are on the stack,
1135*7836SJohn.Forte@Sun.COM * so we have to copy the final result to the heap.
1136*7836SJohn.Forte@Sun.COM */
1137*7836SJohn.Forte@Sun.COM if (!S_ISLNK(stbuf.st_mode)) {
1138*7836SJohn.Forte@Sun.COM return (g_alloc_string(source));
1139*7836SJohn.Forte@Sun.COM }
1140*7836SJohn.Forte@Sun.COM cnt = readlink(source, scratch, sizeof (scratch));
1141*7836SJohn.Forte@Sun.COM if (cnt < 0) {
1142*7836SJohn.Forte@Sun.COM O_DPRINTF("readlink() failed - %s\n",
1143*7836SJohn.Forte@Sun.COM strerror(errno));
1144*7836SJohn.Forte@Sun.COM return (NULL);
1145*7836SJohn.Forte@Sun.COM }
1146*7836SJohn.Forte@Sun.COM /*
1147*7836SJohn.Forte@Sun.COM * scratch is on the heap, and for some reason readlink
1148*7836SJohn.Forte@Sun.COM * doesn't always terminate things properly so we have
1149*7836SJohn.Forte@Sun.COM * to make certain we're properly terminated
1150*7836SJohn.Forte@Sun.COM */
1151*7836SJohn.Forte@Sun.COM scratch[cnt] = '\0';
1152*7836SJohn.Forte@Sun.COM
1153*7836SJohn.Forte@Sun.COM /*
1154*7836SJohn.Forte@Sun.COM * Now check to see if the link is relative. If so,
1155*7836SJohn.Forte@Sun.COM * then we have to append it to the directory
1156*7836SJohn.Forte@Sun.COM * which the source was in. (This is non trivial)
1157*7836SJohn.Forte@Sun.COM */
1158*7836SJohn.Forte@Sun.COM if (scratch[0] != '/') {
1159*7836SJohn.Forte@Sun.COM tmp = strrchr(source, '/');
1160*7836SJohn.Forte@Sun.COM if (tmp == NULL) { /* Whoa! Something's hosed! */
1161*7836SJohn.Forte@Sun.COM O_DPRINTF("Internal error... corrupt path.\n");
1162*7836SJohn.Forte@Sun.COM return (NULL);
1163*7836SJohn.Forte@Sun.COM }
1164*7836SJohn.Forte@Sun.COM /* Now strip off just the directory path */
1165*7836SJohn.Forte@Sun.COM *(tmp+1) = '\0'; /* Keeping the last '/' */
1166*7836SJohn.Forte@Sun.COM /* and append the new link */
1167*7836SJohn.Forte@Sun.COM (void) strcat(source, scratch);
1168*7836SJohn.Forte@Sun.COM /*
1169*7836SJohn.Forte@Sun.COM * Note: At this point, source should have "../"s
1170*7836SJohn.Forte@Sun.COM * but we'll clean it up in the next pass through
1171*7836SJohn.Forte@Sun.COM * the loop.
1172*7836SJohn.Forte@Sun.COM */
1173*7836SJohn.Forte@Sun.COM } else {
1174*7836SJohn.Forte@Sun.COM /* It's an absolute link so no worries */
1175*7836SJohn.Forte@Sun.COM strcpy(source, scratch);
1176*7836SJohn.Forte@Sun.COM }
1177*7836SJohn.Forte@Sun.COM }
1178*7836SJohn.Forte@Sun.COM /* Never reach here */
1179*7836SJohn.Forte@Sun.COM }
1180*7836SJohn.Forte@Sun.COM
1181*7836SJohn.Forte@Sun.COM /*
1182*7836SJohn.Forte@Sun.COM * Function for getting physical pathnames
1183*7836SJohn.Forte@Sun.COM *
1184*7836SJohn.Forte@Sun.COM * For S10 the physical path may not exist at the time devctl calls
1185*7836SJohn.Forte@Sun.COM * are made. So we should not return error if stat fails on /devices path.
1186*7836SJohn.Forte@Sun.COM *
1187*7836SJohn.Forte@Sun.COM * This function can handle 2 different inputs.
1188*7836SJohn.Forte@Sun.COM *
1189*7836SJohn.Forte@Sun.COM * 1) Inputs of the form /dev/rdsk/cNtNdNsN
1190*7836SJohn.Forte@Sun.COM * These are identified by being a link
1191*7836SJohn.Forte@Sun.COM * The physical path they are linked to is returned.
1192*7836SJohn.Forte@Sun.COM *
1193*7836SJohn.Forte@Sun.COM * 2) Inputs of the form /devices/...
1194*7836SJohn.Forte@Sun.COM * These are actual physical names.
1195*7836SJohn.Forte@Sun.COM * They are not converted.
1196*7836SJohn.Forte@Sun.COM */
1197*7836SJohn.Forte@Sun.COM char *
h_get_physical_name(char * path)1198*7836SJohn.Forte@Sun.COM h_get_physical_name(char *path)
1199*7836SJohn.Forte@Sun.COM {
1200*7836SJohn.Forte@Sun.COM struct stat stbuf;
1201*7836SJohn.Forte@Sun.COM char s[MAXPATHLEN];
1202*7836SJohn.Forte@Sun.COM char savedir[MAXPATHLEN];
1203*7836SJohn.Forte@Sun.COM char *result = NULL;
1204*7836SJohn.Forte@Sun.COM int status = 0;
1205*7836SJohn.Forte@Sun.COM
1206*7836SJohn.Forte@Sun.COM /* return invalid path if path NULL */
1207*7836SJohn.Forte@Sun.COM if (path == NULL) {
1208*7836SJohn.Forte@Sun.COM return (NULL);
1209*7836SJohn.Forte@Sun.COM }
1210*7836SJohn.Forte@Sun.COM
1211*7836SJohn.Forte@Sun.COM (void) strcpy(s, path);
1212*7836SJohn.Forte@Sun.COM
1213*7836SJohn.Forte@Sun.COM status = lstat(s, &stbuf);
1214*7836SJohn.Forte@Sun.COM
1215*7836SJohn.Forte@Sun.COM /*
1216*7836SJohn.Forte@Sun.COM * S10: If string is devfs node we allow failed lstat.
1217*7836SJohn.Forte@Sun.COM */
1218*7836SJohn.Forte@Sun.COM if ((status == -1) || !S_ISLNK(stbuf.st_mode)) {
1219*7836SJohn.Forte@Sun.COM /* Make sure a full path as that is required. */
1220*7836SJohn.Forte@Sun.COM if (strstr(s, "/devices")) {
1221*7836SJohn.Forte@Sun.COM result = g_alloc_string(s);
1222*7836SJohn.Forte@Sun.COM } else {
1223*7836SJohn.Forte@Sun.COM if (getcwd(savedir,
1224*7836SJohn.Forte@Sun.COM sizeof (savedir)) == NULL) {
1225*7836SJohn.Forte@Sun.COM return (NULL);
1226*7836SJohn.Forte@Sun.COM }
1227*7836SJohn.Forte@Sun.COM /*
1228*7836SJohn.Forte@Sun.COM * Check for this format:
1229*7836SJohn.Forte@Sun.COM * ./ssd@0,1:g,raw
1230*7836SJohn.Forte@Sun.COM */
1231*7836SJohn.Forte@Sun.COM if (s[0] == '.') {
1232*7836SJohn.Forte@Sun.COM (void) strcat(savedir, &s[1]);
1233*7836SJohn.Forte@Sun.COM } else {
1234*7836SJohn.Forte@Sun.COM (void) strcat(savedir, "/");
1235*7836SJohn.Forte@Sun.COM (void) strcat(savedir, s);
1236*7836SJohn.Forte@Sun.COM }
1237*7836SJohn.Forte@Sun.COM if ((status != -1) || strstr(s, "/devices")) {
1238*7836SJohn.Forte@Sun.COM result = g_alloc_string(savedir);
1239*7836SJohn.Forte@Sun.COM }
1240*7836SJohn.Forte@Sun.COM }
1241*7836SJohn.Forte@Sun.COM } else {
1242*7836SJohn.Forte@Sun.COM /*
1243*7836SJohn.Forte@Sun.COM * Entry is linked file
1244*7836SJohn.Forte@Sun.COM * so follow link to physical name
1245*7836SJohn.Forte@Sun.COM */
1246*7836SJohn.Forte@Sun.COM result = h_get_physical_name_from_link(path);
1247*7836SJohn.Forte@Sun.COM }
1248*7836SJohn.Forte@Sun.COM
1249*7836SJohn.Forte@Sun.COM exit:
1250*7836SJohn.Forte@Sun.COM return (result);
1251*7836SJohn.Forte@Sun.COM }
1252*7836SJohn.Forte@Sun.COM
1253*7836SJohn.Forte@Sun.COM
1254*7836SJohn.Forte@Sun.COM /*
1255*7836SJohn.Forte@Sun.COM * handle expert-mode hotplug commands
1256*7836SJohn.Forte@Sun.COM *
1257*7836SJohn.Forte@Sun.COM * return 0 iff all is okay
1258*7836SJohn.Forte@Sun.COM */
1259*7836SJohn.Forte@Sun.COM int
hotplug_e(int todo,char ** argv,int verbose_flag,int force_flag)1260*7836SJohn.Forte@Sun.COM hotplug_e(int todo, char **argv, int verbose_flag, int force_flag)
1261*7836SJohn.Forte@Sun.COM {
1262*7836SJohn.Forte@Sun.COM char *path_phys = NULL;
1263*7836SJohn.Forte@Sun.COM char bus_path[MAXPATHLEN];
1264*7836SJohn.Forte@Sun.COM char *ptr;
1265*7836SJohn.Forte@Sun.COM int exit_code;
1266*7836SJohn.Forte@Sun.COM devctl_hdl_t dcp;
1267*7836SJohn.Forte@Sun.COM uint_t devstate;
1268*7836SJohn.Forte@Sun.COM int i = 0, pathcnt = 1;
1269*7836SJohn.Forte@Sun.COM mp_pathlist_t pathlist;
1270*7836SJohn.Forte@Sun.COM int p_pw = 0, p_on = 0, p_st = 0;
1271*7836SJohn.Forte@Sun.COM
1272*7836SJohn.Forte@Sun.COM
1273*7836SJohn.Forte@Sun.COM switch (todo) {
1274*7836SJohn.Forte@Sun.COM case DEV_ONLINE:
1275*7836SJohn.Forte@Sun.COM case DEV_OFFLINE:
1276*7836SJohn.Forte@Sun.COM case DEV_GETSTATE:
1277*7836SJohn.Forte@Sun.COM case DEV_RESET:
1278*7836SJohn.Forte@Sun.COM /* get physical name */
1279*7836SJohn.Forte@Sun.COM if ((path_phys = h_get_physical_name(argv[0])) == NULL) {
1280*7836SJohn.Forte@Sun.COM
1281*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1282*7836SJohn.Forte@Sun.COM MSGSTR(112, "Error: Invalid pathname (%s)"),
1283*7836SJohn.Forte@Sun.COM argv[0]);
1284*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, "\n");
1285*7836SJohn.Forte@Sun.COM return (1);
1286*7836SJohn.Forte@Sun.COM }
1287*7836SJohn.Forte@Sun.COM
1288*7836SJohn.Forte@Sun.COM if (verbose_flag) {
1289*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1290*7836SJohn.Forte@Sun.COM MSGSTR(5516,
1291*7836SJohn.Forte@Sun.COM "phys path = \"%s\"\n"),
1292*7836SJohn.Forte@Sun.COM path_phys);
1293*7836SJohn.Forte@Sun.COM }
1294*7836SJohn.Forte@Sun.COM
1295*7836SJohn.Forte@Sun.COM /* acquire rights to hack on device */
1296*7836SJohn.Forte@Sun.COM if ((dcp = devctl_device_acquire(path_phys,
1297*7836SJohn.Forte@Sun.COM force_flag ? 0 : DC_EXCL)) == NULL) {
1298*7836SJohn.Forte@Sun.COM
1299*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, MSGSTR(5517,
1300*7836SJohn.Forte@Sun.COM "Error: can't acquire \"%s\": %s\n"),
1301*7836SJohn.Forte@Sun.COM path_phys, strerror(errno));
1302*7836SJohn.Forte@Sun.COM return (1);
1303*7836SJohn.Forte@Sun.COM }
1304*7836SJohn.Forte@Sun.COM
1305*7836SJohn.Forte@Sun.COM switch (todo) {
1306*7836SJohn.Forte@Sun.COM case DEV_ONLINE:
1307*7836SJohn.Forte@Sun.COM exit_code = devctl_device_online(dcp);
1308*7836SJohn.Forte@Sun.COM break;
1309*7836SJohn.Forte@Sun.COM case DEV_OFFLINE:
1310*7836SJohn.Forte@Sun.COM exit_code = devctl_device_offline(dcp);
1311*7836SJohn.Forte@Sun.COM break;
1312*7836SJohn.Forte@Sun.COM case DEV_GETSTATE:
1313*7836SJohn.Forte@Sun.COM if ((exit_code = devctl_device_getstate(dcp,
1314*7836SJohn.Forte@Sun.COM &devstate)) == 0) {
1315*7836SJohn.Forte@Sun.COM print_dev_state(argv[0], devstate);
1316*7836SJohn.Forte@Sun.COM }
1317*7836SJohn.Forte@Sun.COM break;
1318*7836SJohn.Forte@Sun.COM case DEV_RESET:
1319*7836SJohn.Forte@Sun.COM exit_code = devctl_device_reset(dcp);
1320*7836SJohn.Forte@Sun.COM break;
1321*7836SJohn.Forte@Sun.COM }
1322*7836SJohn.Forte@Sun.COM
1323*7836SJohn.Forte@Sun.COM if (exit_code != 0) {
1324*7836SJohn.Forte@Sun.COM perror(MSGSTR(5518, "devctl"));
1325*7836SJohn.Forte@Sun.COM }
1326*7836SJohn.Forte@Sun.COM
1327*7836SJohn.Forte@Sun.COM /* all done now -- release device */
1328*7836SJohn.Forte@Sun.COM devctl_release(dcp);
1329*7836SJohn.Forte@Sun.COM break;
1330*7836SJohn.Forte@Sun.COM
1331*7836SJohn.Forte@Sun.COM /* for hotplugging bus operations */
1332*7836SJohn.Forte@Sun.COM case BUS_QUIESCE:
1333*7836SJohn.Forte@Sun.COM case BUS_UNQUIESCE:
1334*7836SJohn.Forte@Sun.COM case BUS_GETSTATE:
1335*7836SJohn.Forte@Sun.COM case BUS_RESET:
1336*7836SJohn.Forte@Sun.COM case BUS_RESETALL:
1337*7836SJohn.Forte@Sun.COM /* get physical name */
1338*7836SJohn.Forte@Sun.COM if ((path_phys = h_get_physical_name(argv[0])) ==
1339*7836SJohn.Forte@Sun.COM NULL) {
1340*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1341*7836SJohn.Forte@Sun.COM MSGSTR(112, "Error: Invalid pathname (%s)"),
1342*7836SJohn.Forte@Sun.COM argv[0]);
1343*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, "\n");
1344*7836SJohn.Forte@Sun.COM return (1);
1345*7836SJohn.Forte@Sun.COM }
1346*7836SJohn.Forte@Sun.COM if (verbose_flag) {
1347*7836SJohn.Forte@Sun.COM printf(MSGSTR(5519, "phys path = \"%s\"\n"), path_phys);
1348*7836SJohn.Forte@Sun.COM }
1349*7836SJohn.Forte@Sun.COM
1350*7836SJohn.Forte@Sun.COM /* acquire rights to hack on device */
1351*7836SJohn.Forte@Sun.COM /* delete leaf part from path_phys. */
1352*7836SJohn.Forte@Sun.COM if (strstr(path_phys, SCSI_VHCI) != NULL) {
1353*7836SJohn.Forte@Sun.COM /* obtain phci */
1354*7836SJohn.Forte@Sun.COM (void) strcpy(bus_path, path_phys);
1355*7836SJohn.Forte@Sun.COM if (g_get_pathlist(bus_path, &pathlist)) {
1356*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1357*7836SJohn.Forte@Sun.COM MSGSTR(112, "Error: Invalid pathname (%s)"),
1358*7836SJohn.Forte@Sun.COM path_phys);
1359*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, "\n");
1360*7836SJohn.Forte@Sun.COM return (1);
1361*7836SJohn.Forte@Sun.COM }
1362*7836SJohn.Forte@Sun.COM pathcnt = pathlist.path_count;
1363*7836SJohn.Forte@Sun.COM p_pw = p_on = p_st = 0;
1364*7836SJohn.Forte@Sun.COM for (i = 0; i < pathcnt; i++) {
1365*7836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state <
1366*7836SJohn.Forte@Sun.COM MAXPATHSTATE) {
1367*7836SJohn.Forte@Sun.COM if (strstr(pathlist.path_info[i].
1368*7836SJohn.Forte@Sun.COM path_addr,
1369*7836SJohn.Forte@Sun.COM argv[0]) != NULL) {
1370*7836SJohn.Forte@Sun.COM p_pw = i;
1371*7836SJohn.Forte@Sun.COM break;
1372*7836SJohn.Forte@Sun.COM }
1373*7836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
1374*7836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
1375*7836SJohn.Forte@Sun.COM p_on = i;
1376*7836SJohn.Forte@Sun.COM }
1377*7836SJohn.Forte@Sun.COM if (pathlist.path_info[i].path_state ==
1378*7836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_STANDBY) {
1379*7836SJohn.Forte@Sun.COM p_st = i;
1380*7836SJohn.Forte@Sun.COM }
1381*7836SJohn.Forte@Sun.COM }
1382*7836SJohn.Forte@Sun.COM }
1383*7836SJohn.Forte@Sun.COM if (strstr(pathlist.path_info[p_pw].path_addr,
1384*7836SJohn.Forte@Sun.COM argv[0]) != NULL) {
1385*7836SJohn.Forte@Sun.COM /* matching input pwwn */
1386*7836SJohn.Forte@Sun.COM (void) strcpy(bus_path,
1387*7836SJohn.Forte@Sun.COM pathlist.path_info[p_pw].path_hba);
1388*7836SJohn.Forte@Sun.COM } else if (pathlist.path_info[p_on].path_state ==
1389*7836SJohn.Forte@Sun.COM MDI_PATHINFO_STATE_ONLINE) {
1390*7836SJohn.Forte@Sun.COM /* on_line path */
1391*7836SJohn.Forte@Sun.COM (void) strcpy(bus_path,
1392*7836SJohn.Forte@Sun.COM pathlist.path_info[p_on].path_hba);
1393*7836SJohn.Forte@Sun.COM } else {
1394*7836SJohn.Forte@Sun.COM /* standby or path0 */
1395*7836SJohn.Forte@Sun.COM (void) strcpy(bus_path,
1396*7836SJohn.Forte@Sun.COM pathlist.path_info[p_st].path_hba);
1397*7836SJohn.Forte@Sun.COM }
1398*7836SJohn.Forte@Sun.COM free(pathlist.path_info);
1399*7836SJohn.Forte@Sun.COM } else {
1400*7836SJohn.Forte@Sun.COM
1401*7836SJohn.Forte@Sun.COM (void) strcpy(bus_path, path_phys);
1402*7836SJohn.Forte@Sun.COM ptr = strrchr(bus_path, '/');
1403*7836SJohn.Forte@Sun.COM if (ptr) {
1404*7836SJohn.Forte@Sun.COM *ptr = '\0';
1405*7836SJohn.Forte@Sun.COM } else {
1406*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1407*7836SJohn.Forte@Sun.COM MSGSTR(112, "Error: Invalid pathname (%s)"),
1408*7836SJohn.Forte@Sun.COM path_phys);
1409*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, "\n");
1410*7836SJohn.Forte@Sun.COM return (1);
1411*7836SJohn.Forte@Sun.COM }
1412*7836SJohn.Forte@Sun.COM }
1413*7836SJohn.Forte@Sun.COM
1414*7836SJohn.Forte@Sun.COM if ((dcp = devctl_bus_acquire(bus_path,
1415*7836SJohn.Forte@Sun.COM force_flag ? 0 : DC_EXCL)) == NULL) {
1416*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1417*7836SJohn.Forte@Sun.COM MSGSTR(5521,
1418*7836SJohn.Forte@Sun.COM " Error: can't acquire bus node from"
1419*7836SJohn.Forte@Sun.COM " the path \"%s\": %s\n"),
1420*7836SJohn.Forte@Sun.COM bus_path, strerror(errno));
1421*7836SJohn.Forte@Sun.COM return (1);
1422*7836SJohn.Forte@Sun.COM }
1423*7836SJohn.Forte@Sun.COM
1424*7836SJohn.Forte@Sun.COM switch (todo) {
1425*7836SJohn.Forte@Sun.COM case BUS_QUIESCE:
1426*7836SJohn.Forte@Sun.COM exit_code = devctl_bus_quiesce(dcp);
1427*7836SJohn.Forte@Sun.COM break;
1428*7836SJohn.Forte@Sun.COM case BUS_UNQUIESCE:
1429*7836SJohn.Forte@Sun.COM exit_code = devctl_bus_unquiesce(dcp);
1430*7836SJohn.Forte@Sun.COM break;
1431*7836SJohn.Forte@Sun.COM case BUS_GETSTATE:
1432*7836SJohn.Forte@Sun.COM if ((exit_code = devctl_bus_getstate(dcp,
1433*7836SJohn.Forte@Sun.COM &devstate)) == 0) {
1434*7836SJohn.Forte@Sun.COM print_bus_state(argv[0], devstate);
1435*7836SJohn.Forte@Sun.COM }
1436*7836SJohn.Forte@Sun.COM break;
1437*7836SJohn.Forte@Sun.COM case BUS_RESET:
1438*7836SJohn.Forte@Sun.COM exit_code = devctl_bus_reset(dcp);
1439*7836SJohn.Forte@Sun.COM break;
1440*7836SJohn.Forte@Sun.COM case BUS_RESETALL:
1441*7836SJohn.Forte@Sun.COM exit_code = devctl_bus_resetall(dcp);
1442*7836SJohn.Forte@Sun.COM break;
1443*7836SJohn.Forte@Sun.COM }
1444*7836SJohn.Forte@Sun.COM
1445*7836SJohn.Forte@Sun.COM if (exit_code != 0) {
1446*7836SJohn.Forte@Sun.COM perror(MSGSTR(5522, "devctl"));
1447*7836SJohn.Forte@Sun.COM }
1448*7836SJohn.Forte@Sun.COM
1449*7836SJohn.Forte@Sun.COM /* all done now -- release device */
1450*7836SJohn.Forte@Sun.COM devctl_release(dcp);
1451*7836SJohn.Forte@Sun.COM break;
1452*7836SJohn.Forte@Sun.COM }
1453*7836SJohn.Forte@Sun.COM
1454*7836SJohn.Forte@Sun.COM return (exit_code);
1455*7836SJohn.Forte@Sun.COM }
1456*7836SJohn.Forte@Sun.COM
1457*7836SJohn.Forte@Sun.COM
1458*7836SJohn.Forte@Sun.COM
1459*7836SJohn.Forte@Sun.COM /*
1460*7836SJohn.Forte@Sun.COM * Prepares an individual FC_AL device
1461*7836SJohn.Forte@Sun.COM * to be removed from the specified
1462*7836SJohn.Forte@Sun.COM * slot.
1463*7836SJohn.Forte@Sun.COM *
1464*7836SJohn.Forte@Sun.COM * RETURNS:
1465*7836SJohn.Forte@Sun.COM * 0 if OK
1466*7836SJohn.Forte@Sun.COM * non-zero otherwise.
1467*7836SJohn.Forte@Sun.COM */
1468*7836SJohn.Forte@Sun.COM static int
h_pre_remove_dev(Hotplug_Devlist * hotplug_disk,WWN_list * wwn_list,int verbose_flag,int force_flag)1469*7836SJohn.Forte@Sun.COM h_pre_remove_dev(Hotplug_Devlist *hotplug_disk, WWN_list *wwn_list,
1470*7836SJohn.Forte@Sun.COM int verbose_flag, int force_flag)
1471*7836SJohn.Forte@Sun.COM {
1472*7836SJohn.Forte@Sun.COM char *dev_path, device_name[MAXNAMELEN];
1473*7836SJohn.Forte@Sun.COM int err;
1474*7836SJohn.Forte@Sun.COM
1475*7836SJohn.Forte@Sun.COM /* Initialize pointers */
1476*7836SJohn.Forte@Sun.COM dev_path = NULL;
1477*7836SJohn.Forte@Sun.COM
1478*7836SJohn.Forte@Sun.COM if (hotplug_disk->dlhead != NULL) {
1479*7836SJohn.Forte@Sun.COM dev_path = hotplug_disk->dlhead->dev_path;
1480*7836SJohn.Forte@Sun.COM (void) strcpy(device_name, (hotplug_disk->dlhead)->logical_path);
1481*7836SJohn.Forte@Sun.COM }
1482*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1483*7836SJohn.Forte@Sun.COM MSGSTR(157,
1484*7836SJohn.Forte@Sun.COM "stopping: %s...."), device_name);
1485*7836SJohn.Forte@Sun.COM if (!(strstr(dev_path, SLSH_DRV_NAME_ST))) {
1486*7836SJohn.Forte@Sun.COM if ((err = g_dev_stop(dev_path, wwn_list, verbose_flag)) != 0)
1487*7836SJohn.Forte@Sun.COM return (err);
1488*7836SJohn.Forte@Sun.COM }
1489*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(156, "Done\n"));
1490*7836SJohn.Forte@Sun.COM
1491*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1492*7836SJohn.Forte@Sun.COM MSGSTR(158, "offlining: %s...."), device_name);
1493*7836SJohn.Forte@Sun.COM if ((err = g_offline_drive(hotplug_disk->dlhead,
1494*7836SJohn.Forte@Sun.COM force_flag)) != 0) {
1495*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1496*7836SJohn.Forte@Sun.COM MSGSTR(160,
1497*7836SJohn.Forte@Sun.COM "\nonlining: %s\n"), device_name);
1498*7836SJohn.Forte@Sun.COM
1499*7836SJohn.Forte@Sun.COM (void) g_online_drive(hotplug_disk->dlhead, force_flag);
1500*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1501*7836SJohn.Forte@Sun.COM MSGSTR(159, "starting: %s...."),
1502*7836SJohn.Forte@Sun.COM device_name);
1503*7836SJohn.Forte@Sun.COM if ((err = g_dev_start(dev_path, 0)) != 0) {
1504*7836SJohn.Forte@Sun.COM return (err);
1505*7836SJohn.Forte@Sun.COM }
1506*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(156, "Done\n"));
1507*7836SJohn.Forte@Sun.COM return (err);
1508*7836SJohn.Forte@Sun.COM }
1509*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(156, "Done\n"));
1510*7836SJohn.Forte@Sun.COM return (0);
1511*7836SJohn.Forte@Sun.COM }
1512*7836SJohn.Forte@Sun.COM
1513*7836SJohn.Forte@Sun.COM
1514*7836SJohn.Forte@Sun.COM
1515*7836SJohn.Forte@Sun.COM /*
1516*7836SJohn.Forte@Sun.COM * Prepares a SENA enclosure or SENA FC_AL device
1517*7836SJohn.Forte@Sun.COM * to be inserted/removed from a specified slot.
1518*7836SJohn.Forte@Sun.COM *
1519*7836SJohn.Forte@Sun.COM * RETURNS:
1520*7836SJohn.Forte@Sun.COM * 0 if OK
1521*7836SJohn.Forte@Sun.COM * non-zero otherwise.
1522*7836SJohn.Forte@Sun.COM */
1523*7836SJohn.Forte@Sun.COM static int
h_pre_hotplug_sena(Hotplug_Devlist * hotplug_dev,WWN_list * wwn_list,int todo,int verbose_flag,int force_flag)1524*7836SJohn.Forte@Sun.COM h_pre_hotplug_sena(Hotplug_Devlist *hotplug_dev,
1525*7836SJohn.Forte@Sun.COM WWN_list *wwn_list, int todo,
1526*7836SJohn.Forte@Sun.COM int verbose_flag, int force_flag)
1527*7836SJohn.Forte@Sun.COM {
1528*7836SJohn.Forte@Sun.COM int slot, f_r, i, found_null_wwn = 0, err;
1529*7836SJohn.Forte@Sun.COM char *ses_path, *dev_path, code;
1530*7836SJohn.Forte@Sun.COM char node_wwn_s[WWN_SIZE], device_name[MAXNAMELEN];
1531*7836SJohn.Forte@Sun.COM struct l_state_struct l_state;
1532*7836SJohn.Forte@Sun.COM struct dlist *dl;
1533*7836SJohn.Forte@Sun.COM
1534*7836SJohn.Forte@Sun.COM
1535*7836SJohn.Forte@Sun.COM if (hotplug_dev->dev_type == DTYPE_ESI) {
1536*7836SJohn.Forte@Sun.COM /* entire photon is being removed */
1537*7836SJohn.Forte@Sun.COM if ((err = l_offline_photon(hotplug_dev, wwn_list,
1538*7836SJohn.Forte@Sun.COM force_flag, verbose_flag)) != 0) {
1539*7836SJohn.Forte@Sun.COM return (err);
1540*7836SJohn.Forte@Sun.COM }
1541*7836SJohn.Forte@Sun.COM return (0);
1542*7836SJohn.Forte@Sun.COM }
1543*7836SJohn.Forte@Sun.COM
1544*7836SJohn.Forte@Sun.COM /* if device is an individual sena disk */
1545*7836SJohn.Forte@Sun.COM dl = hotplug_dev->seslist;
1546*7836SJohn.Forte@Sun.COM while (dl) {
1547*7836SJohn.Forte@Sun.COM ses_path = dl->dev_path;
1548*7836SJohn.Forte@Sun.COM if ((err = l_get_status(ses_path, &l_state,
1549*7836SJohn.Forte@Sun.COM verbose_flag)) == 0)
1550*7836SJohn.Forte@Sun.COM break;
1551*7836SJohn.Forte@Sun.COM dl = dl->next;
1552*7836SJohn.Forte@Sun.COM }
1553*7836SJohn.Forte@Sun.COM if (dl == NULL) {
1554*7836SJohn.Forte@Sun.COM return (L_GET_STATUS_FAILED);
1555*7836SJohn.Forte@Sun.COM }
1556*7836SJohn.Forte@Sun.COM
1557*7836SJohn.Forte@Sun.COM f_r = hotplug_dev->f_flag;
1558*7836SJohn.Forte@Sun.COM slot = hotplug_dev->slot;
1559*7836SJohn.Forte@Sun.COM (void) l_get_drive_name(device_name, slot, f_r, hotplug_dev->box_name);
1560*7836SJohn.Forte@Sun.COM
1561*7836SJohn.Forte@Sun.COM /* check if disk has null wwn */
1562*7836SJohn.Forte@Sun.COM if (f_r) {
1563*7836SJohn.Forte@Sun.COM (void) strncpy(node_wwn_s,
1564*7836SJohn.Forte@Sun.COM l_state.drv_front[slot].g_disk_state.node_wwn_s, WWN_SIZE);
1565*7836SJohn.Forte@Sun.COM } else {
1566*7836SJohn.Forte@Sun.COM (void) strncpy(node_wwn_s,
1567*7836SJohn.Forte@Sun.COM l_state.drv_rear[slot].g_disk_state.node_wwn_s, WWN_SIZE);
1568*7836SJohn.Forte@Sun.COM }
1569*7836SJohn.Forte@Sun.COM for (i = 0; i < WWN_SIZE; i++) {
1570*7836SJohn.Forte@Sun.COM if (node_wwn_s[i] != '0')
1571*7836SJohn.Forte@Sun.COM break;
1572*7836SJohn.Forte@Sun.COM found_null_wwn = 1;
1573*7836SJohn.Forte@Sun.COM }
1574*7836SJohn.Forte@Sun.COM
1575*7836SJohn.Forte@Sun.COM switch (todo) {
1576*7836SJohn.Forte@Sun.COM case INSERT_DEVICE:
1577*7836SJohn.Forte@Sun.COM if (hotplug_dev->f_flag) {
1578*7836SJohn.Forte@Sun.COM code =
1579*7836SJohn.Forte@Sun.COM l_state.drv_front[slot].ib_status.code;
1580*7836SJohn.Forte@Sun.COM } else {
1581*7836SJohn.Forte@Sun.COM code =
1582*7836SJohn.Forte@Sun.COM l_state.drv_rear[slot].ib_status.code;
1583*7836SJohn.Forte@Sun.COM }
1584*7836SJohn.Forte@Sun.COM if (code & S_NOT_INSTALLED) {
1585*7836SJohn.Forte@Sun.COM /*
1586*7836SJohn.Forte@Sun.COM * At this point we know that the drive is not
1587*7836SJohn.Forte@Sun.COM * there. Turn on the RQST INSERT bit to make
1588*7836SJohn.Forte@Sun.COM * the LED blink
1589*7836SJohn.Forte@Sun.COM */
1590*7836SJohn.Forte@Sun.COM if ((err = l_encl_status_page_funcs
1591*7836SJohn.Forte@Sun.COM (SET_RQST_INSRT, 0, todo,
1592*7836SJohn.Forte@Sun.COM ses_path, &l_state, f_r, slot,
1593*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) {
1594*7836SJohn.Forte@Sun.COM (void) print_errString(err,
1595*7836SJohn.Forte@Sun.COM device_name);
1596*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1597*7836SJohn.Forte@Sun.COM MSGSTR(5530,
1598*7836SJohn.Forte@Sun.COM " %s: could not turn "
1599*7836SJohn.Forte@Sun.COM "on LED\n"),
1600*7836SJohn.Forte@Sun.COM device_name);
1601*7836SJohn.Forte@Sun.COM }
1602*7836SJohn.Forte@Sun.COM } else {
1603*7836SJohn.Forte@Sun.COM /*
1604*7836SJohn.Forte@Sun.COM * Drive is there so start it.
1605*7836SJohn.Forte@Sun.COM */
1606*7836SJohn.Forte@Sun.COM if ((err = l_encl_status_page_funcs
1607*7836SJohn.Forte@Sun.COM (SET_DRV_ON, 0, todo,
1608*7836SJohn.Forte@Sun.COM ses_path, &l_state, f_r, slot,
1609*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) {
1610*7836SJohn.Forte@Sun.COM (void) print_errString(err,
1611*7836SJohn.Forte@Sun.COM device_name);
1612*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1613*7836SJohn.Forte@Sun.COM MSGSTR(5531,
1614*7836SJohn.Forte@Sun.COM " could not enable"
1615*7836SJohn.Forte@Sun.COM " %s\n"),
1616*7836SJohn.Forte@Sun.COM device_name);
1617*7836SJohn.Forte@Sun.COM }
1618*7836SJohn.Forte@Sun.COM }
1619*7836SJohn.Forte@Sun.COM break;
1620*7836SJohn.Forte@Sun.COM
1621*7836SJohn.Forte@Sun.COM case REMOVE_DEVICE:
1622*7836SJohn.Forte@Sun.COM /*
1623*7836SJohn.Forte@Sun.COM * if disk has null wwn, then
1624*7836SJohn.Forte@Sun.COM * there is no need to check the
1625*7836SJohn.Forte@Sun.COM * disk/loop status.
1626*7836SJohn.Forte@Sun.COM */
1627*7836SJohn.Forte@Sun.COM if (found_null_wwn == 1) {
1628*7836SJohn.Forte@Sun.COM if (getenv("_LUX_W_DEBUG") != NULL) {
1629*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1630*7836SJohn.Forte@Sun.COM "Device %s has "
1631*7836SJohn.Forte@Sun.COM "null WWN.\n",
1632*7836SJohn.Forte@Sun.COM device_name);
1633*7836SJohn.Forte@Sun.COM }
1634*7836SJohn.Forte@Sun.COM goto rmv;
1635*7836SJohn.Forte@Sun.COM }
1636*7836SJohn.Forte@Sun.COM if (hotplug_dev->f_flag) {
1637*7836SJohn.Forte@Sun.COM if (
1638*7836SJohn.Forte@Sun.COM l_state.drv_front[slot].ib_status.code
1639*7836SJohn.Forte@Sun.COM == S_NOT_INSTALLED) {
1640*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1641*7836SJohn.Forte@Sun.COM MSGSTR(86,
1642*7836SJohn.Forte@Sun.COM " Notice: %s may already"
1643*7836SJohn.Forte@Sun.COM " be removed.\n"),
1644*7836SJohn.Forte@Sun.COM device_name);
1645*7836SJohn.Forte@Sun.COM return (0);
1646*7836SJohn.Forte@Sun.COM }
1647*7836SJohn.Forte@Sun.COM } else if (
1648*7836SJohn.Forte@Sun.COM l_state.drv_rear[slot].ib_status.code
1649*7836SJohn.Forte@Sun.COM == S_NOT_INSTALLED) {
1650*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1651*7836SJohn.Forte@Sun.COM MSGSTR(86,
1652*7836SJohn.Forte@Sun.COM " Notice: %s may already"
1653*7836SJohn.Forte@Sun.COM " be removed.\n"),
1654*7836SJohn.Forte@Sun.COM device_name);
1655*7836SJohn.Forte@Sun.COM return (0);
1656*7836SJohn.Forte@Sun.COM }
1657*7836SJohn.Forte@Sun.COM
1658*7836SJohn.Forte@Sun.COM rmv:
1659*7836SJohn.Forte@Sun.COM if (hotplug_dev->dlhead == NULL) {
1660*7836SJohn.Forte@Sun.COM dev_path = NULL;
1661*7836SJohn.Forte@Sun.COM } else {
1662*7836SJohn.Forte@Sun.COM dev_path = hotplug_dev->dlhead->dev_path;
1663*7836SJohn.Forte@Sun.COM }
1664*7836SJohn.Forte@Sun.COM
1665*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1666*7836SJohn.Forte@Sun.COM MSGSTR(157,
1667*7836SJohn.Forte@Sun.COM "stopping: %s...."), device_name);
1668*7836SJohn.Forte@Sun.COM if ((err = g_dev_stop(dev_path, wwn_list, 0)) != 0) {
1669*7836SJohn.Forte@Sun.COM return (err);
1670*7836SJohn.Forte@Sun.COM }
1671*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(156, "Done\n"));
1672*7836SJohn.Forte@Sun.COM
1673*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1674*7836SJohn.Forte@Sun.COM MSGSTR(158, "offlining: %s...."),
1675*7836SJohn.Forte@Sun.COM device_name);
1676*7836SJohn.Forte@Sun.COM if ((err = g_offline_drive(hotplug_dev->dlhead,
1677*7836SJohn.Forte@Sun.COM force_flag)) != 0) {
1678*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1679*7836SJohn.Forte@Sun.COM MSGSTR(160,
1680*7836SJohn.Forte@Sun.COM "\nonlining: %s\n"), device_name);
1681*7836SJohn.Forte@Sun.COM (void) g_online_drive(hotplug_dev->dlhead, force_flag);
1682*7836SJohn.Forte@Sun.COM
1683*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1684*7836SJohn.Forte@Sun.COM MSGSTR(159, "starting: %s...."),
1685*7836SJohn.Forte@Sun.COM device_name);
1686*7836SJohn.Forte@Sun.COM (void) g_dev_start(dev_path, 0);
1687*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(156, "Done\n"));
1688*7836SJohn.Forte@Sun.COM return (err);
1689*7836SJohn.Forte@Sun.COM }
1690*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(156, "Done\n"));
1691*7836SJohn.Forte@Sun.COM
1692*7836SJohn.Forte@Sun.COM /*
1693*7836SJohn.Forte@Sun.COM * Take the drive off the loop
1694*7836SJohn.Forte@Sun.COM * and blink the LED.
1695*7836SJohn.Forte@Sun.COM */
1696*7836SJohn.Forte@Sun.COM if (hotplug_dev->dev_location == SENA) {
1697*7836SJohn.Forte@Sun.COM if ((err = l_encl_status_page_funcs(SET_RQST_RMV, 0,
1698*7836SJohn.Forte@Sun.COM todo, ses_path, &l_state, f_r,
1699*7836SJohn.Forte@Sun.COM slot, verbose_flag)) != 0) {
1700*7836SJohn.Forte@Sun.COM (void) print_errString(err, device_name);
1701*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1702*7836SJohn.Forte@Sun.COM MSGSTR(5539,
1703*7836SJohn.Forte@Sun.COM " %s: could not blink"
1704*7836SJohn.Forte@Sun.COM " the yellow LED\n"),
1705*7836SJohn.Forte@Sun.COM device_name);
1706*7836SJohn.Forte@Sun.COM }
1707*7836SJohn.Forte@Sun.COM }
1708*7836SJohn.Forte@Sun.COM break;
1709*7836SJohn.Forte@Sun.COM }
1710*7836SJohn.Forte@Sun.COM return (0);
1711*7836SJohn.Forte@Sun.COM }
1712*7836SJohn.Forte@Sun.COM
1713*7836SJohn.Forte@Sun.COM
1714*7836SJohn.Forte@Sun.COM
1715*7836SJohn.Forte@Sun.COM /*
1716*7836SJohn.Forte@Sun.COM * Performs the post removal operations for
1717*7836SJohn.Forte@Sun.COM * a SENA enclosure or a SENA FC_AL disk.
1718*7836SJohn.Forte@Sun.COM *
1719*7836SJohn.Forte@Sun.COM * RETURNS:
1720*7836SJohn.Forte@Sun.COM * 0 if OK
1721*7836SJohn.Forte@Sun.COM * non-zero otherwise
1722*7836SJohn.Forte@Sun.COM */
1723*7836SJohn.Forte@Sun.COM static int
h_post_hotplug_sena(Hotplug_Devlist * hotplug_dev,WWN_list * wwn_list,int todo,int verbose_flag,int force_flag,int enc_type)1724*7836SJohn.Forte@Sun.COM h_post_hotplug_sena(Hotplug_Devlist *hotplug_dev,
1725*7836SJohn.Forte@Sun.COM WWN_list *wwn_list, int todo,
1726*7836SJohn.Forte@Sun.COM int verbose_flag, int force_flag, int enc_type)
1727*7836SJohn.Forte@Sun.COM {
1728*7836SJohn.Forte@Sun.COM char *ses_path, *dev_path = NULL, device_name[MAXNAMELEN];
1729*7836SJohn.Forte@Sun.COM int tid, slot, f_r, al_pa, timeout = 0;
1730*7836SJohn.Forte@Sun.COM uchar_t port_wwn[WWN_SIZE], node_wwn[WWN_SIZE];
1731*7836SJohn.Forte@Sun.COM char code;
1732*7836SJohn.Forte@Sun.COM int wait_spinup_flag = 0, wait_map_flag = 0;
1733*7836SJohn.Forte@Sun.COM int wait_node_flag = 0, err = 0, nArg;
1734*7836SJohn.Forte@Sun.COM gfc_map_t map;
1735*7836SJohn.Forte@Sun.COM WWN_list *newWwn_list = NULL;
1736*7836SJohn.Forte@Sun.COM struct dlist *dl, *dl1;
1737*7836SJohn.Forte@Sun.COM struct l_state_struct l_state;
1738*7836SJohn.Forte@Sun.COM
1739*7836SJohn.Forte@Sun.COM
1740*7836SJohn.Forte@Sun.COM dl = hotplug_dev->seslist;
1741*7836SJohn.Forte@Sun.COM slot = hotplug_dev->slot;
1742*7836SJohn.Forte@Sun.COM f_r = hotplug_dev->f_flag;
1743*7836SJohn.Forte@Sun.COM tid = hotplug_dev->tid;
1744*7836SJohn.Forte@Sun.COM
1745*7836SJohn.Forte@Sun.COM if (hotplug_dev->dev_type == DTYPE_ESI) {
1746*7836SJohn.Forte@Sun.COM /*
1747*7836SJohn.Forte@Sun.COM * See if photon has really been removed. If not,
1748*7836SJohn.Forte@Sun.COM * try onlining the devices if applicable
1749*7836SJohn.Forte@Sun.COM */
1750*7836SJohn.Forte@Sun.COM H_DPRINTF(" post_hotplug_sena: Seeing if enclosure "
1751*7836SJohn.Forte@Sun.COM "has really been removed:\n"
1752*7836SJohn.Forte@Sun.COM " tid=0x%x, ses_path %s\n",
1753*7836SJohn.Forte@Sun.COM tid, dl->dev_path);
1754*7836SJohn.Forte@Sun.COM
1755*7836SJohn.Forte@Sun.COM while (dl) {
1756*7836SJohn.Forte@Sun.COM ses_path = dl->dev_path;
1757*7836SJohn.Forte@Sun.COM if ((err = g_get_dev_map(ses_path, &map, 0)) == 0) {
1758*7836SJohn.Forte@Sun.COM if ((map.hba_addr.port_topology ==
1759*7836SJohn.Forte@Sun.COM FC_TOP_PUBLIC_LOOP) ||
1760*7836SJohn.Forte@Sun.COM (map.hba_addr.port_topology ==
1761*7836SJohn.Forte@Sun.COM FC_TOP_FABRIC)) {
1762*7836SJohn.Forte@Sun.COM /* public or fabric loop device */
1763*7836SJohn.Forte@Sun.COM free((void *)map.dev_addr);
1764*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5540,
1765*7836SJohn.Forte@Sun.COM "This operation is not "
1766*7836SJohn.Forte@Sun.COM "supported in this topology.\n"));
1767*7836SJohn.Forte@Sun.COM return (0);
1768*7836SJohn.Forte@Sun.COM }
1769*7836SJohn.Forte@Sun.COM if ((err = g_get_wwn(ses_path, port_wwn,
1770*7836SJohn.Forte@Sun.COM node_wwn, &al_pa, verbose_flag)) == 0) {
1771*7836SJohn.Forte@Sun.COM tid = g_sf_alpa_to_switch[al_pa];
1772*7836SJohn.Forte@Sun.COM if (g_device_in_map(&map, tid)) {
1773*7836SJohn.Forte@Sun.COM free((void *)map.dev_addr);
1774*7836SJohn.Forte@Sun.COM break;
1775*7836SJohn.Forte@Sun.COM }
1776*7836SJohn.Forte@Sun.COM }
1777*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
1778*7836SJohn.Forte@Sun.COM }
1779*7836SJohn.Forte@Sun.COM
1780*7836SJohn.Forte@Sun.COM dl = dl->next;
1781*7836SJohn.Forte@Sun.COM }
1782*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
1783*7836SJohn.Forte@Sun.COM if (dl) {
1784*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5640,
1785*7836SJohn.Forte@Sun.COM "Photon \"%s\" not removed."
1786*7836SJohn.Forte@Sun.COM " Onlining Drives in enclosure.\n"),
1787*7836SJohn.Forte@Sun.COM hotplug_dev->box_name);
1788*7836SJohn.Forte@Sun.COM for (dl = hotplug_dev->dlhead; dl; ) {
1789*7836SJohn.Forte@Sun.COM (void) g_online_drive(dl->multipath,
1790*7836SJohn.Forte@Sun.COM force_flag);
1791*7836SJohn.Forte@Sun.COM (void) g_free_multipath(dl->multipath);
1792*7836SJohn.Forte@Sun.COM dl1 = dl;
1793*7836SJohn.Forte@Sun.COM dl = dl->next;
1794*7836SJohn.Forte@Sun.COM (void) free(dl1);
1795*7836SJohn.Forte@Sun.COM }
1796*7836SJohn.Forte@Sun.COM hotplug_dev->dlhead = NULL;
1797*7836SJohn.Forte@Sun.COM return (0);
1798*7836SJohn.Forte@Sun.COM }
1799*7836SJohn.Forte@Sun.COM /*
1800*7836SJohn.Forte@Sun.COM * Remove logical nodes for this
1801*7836SJohn.Forte@Sun.COM * photon, this includes ses and
1802*7836SJohn.Forte@Sun.COM * /dev/dsk entries.
1803*7836SJohn.Forte@Sun.COM * In Solaris7, disks with -C option
1804*7836SJohn.Forte@Sun.COM * removes the /dev/dsk entries.
1805*7836SJohn.Forte@Sun.COM * The -C option is available
1806*7836SJohn.Forte@Sun.COM * only for Solaris7. From Solaris8
1807*7836SJohn.Forte@Sun.COM * or higher releases, the "disks"
1808*7836SJohn.Forte@Sun.COM * program will be replaced by the
1809*7836SJohn.Forte@Sun.COM * devfsadm program.
1810*7836SJohn.Forte@Sun.COM */
1811*7836SJohn.Forte@Sun.COM /* pass "disks -C" as cmdStrg. */
1812*7836SJohn.Forte@Sun.COM nArg = 2;
1813*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[0], nArg) != 0) {
1814*7836SJohn.Forte@Sun.COM for (dl = hotplug_dev->dlhead;
1815*7836SJohn.Forte@Sun.COM dl != NULL; dl = dl->next) {
1816*7836SJohn.Forte@Sun.COM if ((err = h_remove_nodes(dl->multipath))
1817*7836SJohn.Forte@Sun.COM != 0) {
1818*7836SJohn.Forte@Sun.COM return (err);
1819*7836SJohn.Forte@Sun.COM }
1820*7836SJohn.Forte@Sun.COM }
1821*7836SJohn.Forte@Sun.COM } else {
1822*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1823*7836SJohn.Forte@Sun.COM MSGSTR(5541,
1824*7836SJohn.Forte@Sun.COM " Logical Nodes being removed"
1825*7836SJohn.Forte@Sun.COM " under /dev/dsk/ and /dev/rdsk:\n"));
1826*7836SJohn.Forte@Sun.COM for (dl = hotplug_dev->dlhead;
1827*7836SJohn.Forte@Sun.COM dl != NULL; dl = dl->next) {
1828*7836SJohn.Forte@Sun.COM (void) h_print_logical_nodes(dl->multipath);
1829*7836SJohn.Forte@Sun.COM }
1830*7836SJohn.Forte@Sun.COM }
1831*7836SJohn.Forte@Sun.COM
1832*7836SJohn.Forte@Sun.COM for (dl = hotplug_dev->dlhead; dl != NULL; ) {
1833*7836SJohn.Forte@Sun.COM (void) g_free_multipath(dl->multipath);
1834*7836SJohn.Forte@Sun.COM dl1 = dl;
1835*7836SJohn.Forte@Sun.COM dl = dl->next;
1836*7836SJohn.Forte@Sun.COM (void) free(dl1);
1837*7836SJohn.Forte@Sun.COM }
1838*7836SJohn.Forte@Sun.COM hotplug_dev->dlhead = NULL;
1839*7836SJohn.Forte@Sun.COM if ((err = h_remove_ses_nodes(hotplug_dev->seslist)) != 0) {
1840*7836SJohn.Forte@Sun.COM return (err);
1841*7836SJohn.Forte@Sun.COM }
1842*7836SJohn.Forte@Sun.COM return (0);
1843*7836SJohn.Forte@Sun.COM }
1844*7836SJohn.Forte@Sun.COM
1845*7836SJohn.Forte@Sun.COM /* post hotplug operations for a SENA disk. */
1846*7836SJohn.Forte@Sun.COM if (enc_type == DAK_ENC_TYPE) {
1847*7836SJohn.Forte@Sun.COM (void) sprintf(device_name, MSGSTR(5664,
1848*7836SJohn.Forte@Sun.COM " Drive in Box Name \"%s\" slot %d"),
1849*7836SJohn.Forte@Sun.COM hotplug_dev->box_name,
1850*7836SJohn.Forte@Sun.COM f_r ? slot : slot + (MAX_DRIVES_DAK/2));
1851*7836SJohn.Forte@Sun.COM } else {
1852*7836SJohn.Forte@Sun.COM if (tid & 0x10) {
1853*7836SJohn.Forte@Sun.COM (void) sprintf(device_name, MSGSTR(5542,
1854*7836SJohn.Forte@Sun.COM " Drive in Box Name \"%s\" rear slot %d"),
1855*7836SJohn.Forte@Sun.COM hotplug_dev->box_name, slot);
1856*7836SJohn.Forte@Sun.COM } else {
1857*7836SJohn.Forte@Sun.COM (void) sprintf(device_name, MSGSTR(5543,
1858*7836SJohn.Forte@Sun.COM " Drive in Box Name \"%s\" front slot %d"),
1859*7836SJohn.Forte@Sun.COM hotplug_dev->box_name, slot);
1860*7836SJohn.Forte@Sun.COM }
1861*7836SJohn.Forte@Sun.COM }
1862*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "%s\n", device_name);
1863*7836SJohn.Forte@Sun.COM
1864*7836SJohn.Forte@Sun.COM dl = hotplug_dev->seslist;
1865*7836SJohn.Forte@Sun.COM while (dl) {
1866*7836SJohn.Forte@Sun.COM ses_path = dl->dev_path;
1867*7836SJohn.Forte@Sun.COM if ((err = l_get_status(ses_path, &l_state,
1868*7836SJohn.Forte@Sun.COM verbose_flag)) == 0)
1869*7836SJohn.Forte@Sun.COM break;
1870*7836SJohn.Forte@Sun.COM dl = dl->next;
1871*7836SJohn.Forte@Sun.COM }
1872*7836SJohn.Forte@Sun.COM if (dl == NULL) {
1873*7836SJohn.Forte@Sun.COM print_errString(err, ses_path);
1874*7836SJohn.Forte@Sun.COM return (L_GET_STATUS_FAILED);
1875*7836SJohn.Forte@Sun.COM }
1876*7836SJohn.Forte@Sun.COM
1877*7836SJohn.Forte@Sun.COM code = 0;
1878*7836SJohn.Forte@Sun.COM while (((err = l_encl_status_page_funcs(OVERALL_STATUS,
1879*7836SJohn.Forte@Sun.COM &code, todo, ses_path, &l_state, f_r, slot,
1880*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) || (code != 0)) {
1881*7836SJohn.Forte@Sun.COM if (err) {
1882*7836SJohn.Forte@Sun.COM (void) print_errString(err, ses_path);
1883*7836SJohn.Forte@Sun.COM } else if (todo == REMOVE_DEVICE) {
1884*7836SJohn.Forte@Sun.COM if (code == S_OK) {
1885*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1886*7836SJohn.Forte@Sun.COM MSGSTR(5544,
1887*7836SJohn.Forte@Sun.COM "\n Warning: Device has not been"
1888*7836SJohn.Forte@Sun.COM " removed from the enclosure\n"
1889*7836SJohn.Forte@Sun.COM " and is still on the loop."));
1890*7836SJohn.Forte@Sun.COM return (0);
1891*7836SJohn.Forte@Sun.COM } else {
1892*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1893*7836SJohn.Forte@Sun.COM MSGSTR(5545,
1894*7836SJohn.Forte@Sun.COM " Notice: Device has not been"
1895*7836SJohn.Forte@Sun.COM " removed from the enclosure.\n"
1896*7836SJohn.Forte@Sun.COM " It has been removed from the"
1897*7836SJohn.Forte@Sun.COM " loop and is ready to be\n"
1898*7836SJohn.Forte@Sun.COM " removed"
1899*7836SJohn.Forte@Sun.COM " from the enclosure, and"
1900*7836SJohn.Forte@Sun.COM " the LED is blinking.\n\n"));
1901*7836SJohn.Forte@Sun.COM }
1902*7836SJohn.Forte@Sun.COM goto loop2;
1903*7836SJohn.Forte@Sun.COM } else if ((todo == INSERT_DEVICE) &&
1904*7836SJohn.Forte@Sun.COM ((code != S_NOT_AVAILABLE) ||
1905*7836SJohn.Forte@Sun.COM (timeout >
1906*7836SJohn.Forte@Sun.COM PHOTON_SPINUP_TIMEOUT) ||
1907*7836SJohn.Forte@Sun.COM err)) {
1908*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1909*7836SJohn.Forte@Sun.COM MSGSTR(5546,
1910*7836SJohn.Forte@Sun.COM "\n Warning: Disk status is"
1911*7836SJohn.Forte@Sun.COM " Not OK!\n\n"));
1912*7836SJohn.Forte@Sun.COM return (0);
1913*7836SJohn.Forte@Sun.COM }
1914*7836SJohn.Forte@Sun.COM (void) sleep(PHOTON_SPINUP_DELAY);
1915*7836SJohn.Forte@Sun.COM if (wait_spinup_flag++ == 0) {
1916*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5547,
1917*7836SJohn.Forte@Sun.COM " Waiting for the disk to spin up:"));
1918*7836SJohn.Forte@Sun.COM } else {
1919*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, ".");
1920*7836SJohn.Forte@Sun.COM }
1921*7836SJohn.Forte@Sun.COM timeout++;
1922*7836SJohn.Forte@Sun.COM }
1923*7836SJohn.Forte@Sun.COM if (wait_spinup_flag) {
1924*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\n");
1925*7836SJohn.Forte@Sun.COM }
1926*7836SJohn.Forte@Sun.COM loop2:
1927*7836SJohn.Forte@Sun.COM switch (todo) {
1928*7836SJohn.Forte@Sun.COM case INSERT_DEVICE:
1929*7836SJohn.Forte@Sun.COM /* check loop map that drive is present */
1930*7836SJohn.Forte@Sun.COM for (;;) {
1931*7836SJohn.Forte@Sun.COM dl = hotplug_dev->seslist;
1932*7836SJohn.Forte@Sun.COM map.dev_addr = (gfc_port_dev_info_t *)NULL;
1933*7836SJohn.Forte@Sun.COM while (dl) {
1934*7836SJohn.Forte@Sun.COM ses_path = dl->dev_path;
1935*7836SJohn.Forte@Sun.COM if ((err = g_get_dev_map(ses_path,
1936*7836SJohn.Forte@Sun.COM &map, verbose_flag)) != 0) {
1937*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1938*7836SJohn.Forte@Sun.COM MSGSTR(5548,
1939*7836SJohn.Forte@Sun.COM " Error: Could not get"
1940*7836SJohn.Forte@Sun.COM " map for %s.\n"),
1941*7836SJohn.Forte@Sun.COM ses_path);
1942*7836SJohn.Forte@Sun.COM return (err);
1943*7836SJohn.Forte@Sun.COM }
1944*7836SJohn.Forte@Sun.COM if (g_device_in_map(&map, tid)) {
1945*7836SJohn.Forte@Sun.COM goto loop3;
1946*7836SJohn.Forte@Sun.COM }
1947*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
1948*7836SJohn.Forte@Sun.COM dl = dl->next;
1949*7836SJohn.Forte@Sun.COM }
1950*7836SJohn.Forte@Sun.COM if (timeout > PHOTON_SPINUP_TIMEOUT) {
1951*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1952*7836SJohn.Forte@Sun.COM MSGSTR(5549,
1953*7836SJohn.Forte@Sun.COM " Warning: Device not in"
1954*7836SJohn.Forte@Sun.COM " loop map.\n"));
1955*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
1956*7836SJohn.Forte@Sun.COM return (0);
1957*7836SJohn.Forte@Sun.COM }
1958*7836SJohn.Forte@Sun.COM if (wait_map_flag++ == 0) {
1959*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
1960*7836SJohn.Forte@Sun.COM MSGSTR(5550,
1961*7836SJohn.Forte@Sun.COM " Waiting for the device "
1962*7836SJohn.Forte@Sun.COM "to appear in the loop map:"));
1963*7836SJohn.Forte@Sun.COM } else {
1964*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, ".");
1965*7836SJohn.Forte@Sun.COM }
1966*7836SJohn.Forte@Sun.COM timeout++;
1967*7836SJohn.Forte@Sun.COM (void) sleep(PHOTON_SPINUP_DELAY);
1968*7836SJohn.Forte@Sun.COM }
1969*7836SJohn.Forte@Sun.COM loop3:
1970*7836SJohn.Forte@Sun.COM if (wait_map_flag) {
1971*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\n");
1972*7836SJohn.Forte@Sun.COM }
1973*7836SJohn.Forte@Sun.COM
1974*7836SJohn.Forte@Sun.COM /*
1975*7836SJohn.Forte@Sun.COM * Run drvconfig and disks to create
1976*7836SJohn.Forte@Sun.COM * logical nodes
1977*7836SJohn.Forte@Sun.COM */
1978*7836SJohn.Forte@Sun.COM for (;;) {
1979*7836SJohn.Forte@Sun.COM /* pass "disks" as cmdStrg */
1980*7836SJohn.Forte@Sun.COM nArg = 3;
1981*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[2], nArg) != 0) {
1982*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1983*7836SJohn.Forte@Sun.COM MSGSTR(5551,
1984*7836SJohn.Forte@Sun.COM " Could not "
1985*7836SJohn.Forte@Sun.COM "run drvconfig.\n"));
1986*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
1987*7836SJohn.Forte@Sun.COM return (L_DRVCONFIG_ERROR);
1988*7836SJohn.Forte@Sun.COM }
1989*7836SJohn.Forte@Sun.COM
1990*7836SJohn.Forte@Sun.COM if (l_device_present(ses_path, tid, &map,
1991*7836SJohn.Forte@Sun.COM verbose_flag, &dev_path) == 1)
1992*7836SJohn.Forte@Sun.COM break;
1993*7836SJohn.Forte@Sun.COM if (timeout > PHOTON_SPINUP_TIMEOUT) {
1994*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
1995*7836SJohn.Forte@Sun.COM MSGSTR(5552,
1996*7836SJohn.Forte@Sun.COM " Warning: Could not find "
1997*7836SJohn.Forte@Sun.COM "any node for inserted "
1998*7836SJohn.Forte@Sun.COM "device\n"));
1999*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
2000*7836SJohn.Forte@Sun.COM return (0);
2001*7836SJohn.Forte@Sun.COM }
2002*7836SJohn.Forte@Sun.COM if (wait_node_flag++ == 0) {
2003*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2004*7836SJohn.Forte@Sun.COM MSGSTR(5553,
2005*7836SJohn.Forte@Sun.COM " Waiting for the logical "
2006*7836SJohn.Forte@Sun.COM "node to be created:"));
2007*7836SJohn.Forte@Sun.COM } else {
2008*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, ".");
2009*7836SJohn.Forte@Sun.COM }
2010*7836SJohn.Forte@Sun.COM timeout++;
2011*7836SJohn.Forte@Sun.COM (void) sleep(PHOTON_SPINUP_DELAY);
2012*7836SJohn.Forte@Sun.COM }
2013*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
2014*7836SJohn.Forte@Sun.COM if (wait_node_flag) {
2015*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\n");
2016*7836SJohn.Forte@Sun.COM }
2017*7836SJohn.Forte@Sun.COM /*
2018*7836SJohn.Forte@Sun.COM * In Solaris7, disks with -C
2019*7836SJohn.Forte@Sun.COM * option creates the new links
2020*7836SJohn.Forte@Sun.COM * and removes any stale links.
2021*7836SJohn.Forte@Sun.COM * In pre-Solaris7 releases, just
2022*7836SJohn.Forte@Sun.COM * disks should do it all.
2023*7836SJohn.Forte@Sun.COM */
2024*7836SJohn.Forte@Sun.COM /* pass "disks -C" as cmdStrg */
2025*7836SJohn.Forte@Sun.COM nArg = 2;
2026*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[0], nArg) != 0) {
2027*7836SJohn.Forte@Sun.COM return (L_DISKS_ERROR);
2028*7836SJohn.Forte@Sun.COM }
2029*7836SJohn.Forte@Sun.COM /*
2030*7836SJohn.Forte@Sun.COM * Get a new wwn list here in order to
2031*7836SJohn.Forte@Sun.COM * get the multiple paths to a newly added
2032*7836SJohn.Forte@Sun.COM * device.
2033*7836SJohn.Forte@Sun.COM */
2034*7836SJohn.Forte@Sun.COM if ((err = g_get_wwn_list(&newWwn_list,
2035*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) {
2036*7836SJohn.Forte@Sun.COM return (err);
2037*7836SJohn.Forte@Sun.COM }
2038*7836SJohn.Forte@Sun.COM if ((err = g_get_multipath(dev_path, &dl,
2039*7836SJohn.Forte@Sun.COM newWwn_list, 0)) != 0) {
2040*7836SJohn.Forte@Sun.COM return (err);
2041*7836SJohn.Forte@Sun.COM }
2042*7836SJohn.Forte@Sun.COM if ((err = h_display_logical_nodes(dl)) != 0) {
2043*7836SJohn.Forte@Sun.COM return (err);
2044*7836SJohn.Forte@Sun.COM }
2045*7836SJohn.Forte@Sun.COM break;
2046*7836SJohn.Forte@Sun.COM
2047*7836SJohn.Forte@Sun.COM case REMOVE_DEVICE:
2048*7836SJohn.Forte@Sun.COM /*
2049*7836SJohn.Forte@Sun.COM * TBD
2050*7836SJohn.Forte@Sun.COM * Need to check all loops.
2051*7836SJohn.Forte@Sun.COM */
2052*7836SJohn.Forte@Sun.COM /* check whether device is still in loop map */
2053*7836SJohn.Forte@Sun.COM if ((err = g_get_dev_map(ses_path, &map,
2054*7836SJohn.Forte@Sun.COM verbose_flag)) != 0) {
2055*7836SJohn.Forte@Sun.COM return (err);
2056*7836SJohn.Forte@Sun.COM }
2057*7836SJohn.Forte@Sun.COM
2058*7836SJohn.Forte@Sun.COM if ((map.hba_addr.port_topology ==
2059*7836SJohn.Forte@Sun.COM FC_TOP_PUBLIC_LOOP) ||
2060*7836SJohn.Forte@Sun.COM (map.hba_addr.port_topology ==
2061*7836SJohn.Forte@Sun.COM FC_TOP_FABRIC)) {
2062*7836SJohn.Forte@Sun.COM /* public or fabric loop device */
2063*7836SJohn.Forte@Sun.COM free((void *)map.dev_addr);
2064*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, MSGSTR(5540,
2065*7836SJohn.Forte@Sun.COM "This operation is not "
2066*7836SJohn.Forte@Sun.COM "supported in this topology.\n"));
2067*7836SJohn.Forte@Sun.COM /*
2068*7836SJohn.Forte@Sun.COM * calling routine expects a 0 return code
2069*7836SJohn.Forte@Sun.COM * or a pre-defined luxadm error code.
2070*7836SJohn.Forte@Sun.COM * Here we do not have a pre-defined error
2071*7836SJohn.Forte@Sun.COM * code, a 0 is returned.
2072*7836SJohn.Forte@Sun.COM */
2073*7836SJohn.Forte@Sun.COM return (0);
2074*7836SJohn.Forte@Sun.COM }
2075*7836SJohn.Forte@Sun.COM
2076*7836SJohn.Forte@Sun.COM if (g_device_in_map(&map, tid)) {
2077*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, MSGSTR(5554,
2078*7836SJohn.Forte@Sun.COM " Warning: Device still in the loop map.\n"));
2079*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
2080*7836SJohn.Forte@Sun.COM return (0);
2081*7836SJohn.Forte@Sun.COM }
2082*7836SJohn.Forte@Sun.COM FREE_DEV_ADDR(map.dev_addr);
2083*7836SJohn.Forte@Sun.COM /*
2084*7836SJohn.Forte@Sun.COM * In Solaris7, "disks -C" program
2085*7836SJohn.Forte@Sun.COM * removes the /dev/{r}dsk entries.
2086*7836SJohn.Forte@Sun.COM * The -C option is available only
2087*7836SJohn.Forte@Sun.COM * for Solaris7. From Solaris8 or
2088*7836SJohn.Forte@Sun.COM * higher releases, the "disks" program
2089*7836SJohn.Forte@Sun.COM * will be replaced by devfsadm.
2090*7836SJohn.Forte@Sun.COM */
2091*7836SJohn.Forte@Sun.COM /* pass "disks -C" as cmdStrg */
2092*7836SJohn.Forte@Sun.COM nArg = 2;
2093*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[0], nArg) != 0) {
2094*7836SJohn.Forte@Sun.COM return (L_DISKS_ERROR);
2095*7836SJohn.Forte@Sun.COM }
2096*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2097*7836SJohn.Forte@Sun.COM MSGSTR(5555,
2098*7836SJohn.Forte@Sun.COM " Logical Nodes being removed"
2099*7836SJohn.Forte@Sun.COM " under /dev/dsk/ and /dev/rdsk:\n"));
2100*7836SJohn.Forte@Sun.COM (void) h_print_logical_nodes(
2101*7836SJohn.Forte@Sun.COM hotplug_dev->dlhead);
2102*7836SJohn.Forte@Sun.COM break;
2103*7836SJohn.Forte@Sun.COM }
2104*7836SJohn.Forte@Sun.COM return (0);
2105*7836SJohn.Forte@Sun.COM }
2106*7836SJohn.Forte@Sun.COM
2107*7836SJohn.Forte@Sun.COM
2108*7836SJohn.Forte@Sun.COM
2109*7836SJohn.Forte@Sun.COM
2110*7836SJohn.Forte@Sun.COM /*
2111*7836SJohn.Forte@Sun.COM * Creates new ses entries under /dev/es
2112*7836SJohn.Forte@Sun.COM * directory for the newly added
2113*7836SJohn.Forte@Sun.COM * enclosures.
2114*7836SJohn.Forte@Sun.COM *
2115*7836SJohn.Forte@Sun.COM * RETURNS:
2116*7836SJohn.Forte@Sun.COM * 0 if OK
2117*7836SJohn.Forte@Sun.COM * non-zero otherwise
2118*7836SJohn.Forte@Sun.COM */
2119*7836SJohn.Forte@Sun.COM static int
h_post_insert_encl(timestruc_t ses_lastmtim)2120*7836SJohn.Forte@Sun.COM h_post_insert_encl(timestruc_t ses_lastmtim)
2121*7836SJohn.Forte@Sun.COM {
2122*7836SJohn.Forte@Sun.COM struct stat ses_stat;
2123*7836SJohn.Forte@Sun.COM char lname[MAXPATHLEN];
2124*7836SJohn.Forte@Sun.COM int err, found_newlink = 0;
2125*7836SJohn.Forte@Sun.COM DIR *dir;
2126*7836SJohn.Forte@Sun.COM struct dirent *dirent;
2127*7836SJohn.Forte@Sun.COM Box_list *bl1, *box_list = NULL;
2128*7836SJohn.Forte@Sun.COM
2129*7836SJohn.Forte@Sun.COM
2130*7836SJohn.Forte@Sun.COM if ((dir = opendir(SES_DIR)) == NULL) {
2131*7836SJohn.Forte@Sun.COM return (L_OPEN_ES_DIR_FAILED);
2132*7836SJohn.Forte@Sun.COM }
2133*7836SJohn.Forte@Sun.COM if ((err = l_get_box_list(&box_list, 0)) != 0) {
2134*7836SJohn.Forte@Sun.COM closedir(dir);
2135*7836SJohn.Forte@Sun.COM return (err);
2136*7836SJohn.Forte@Sun.COM }
2137*7836SJohn.Forte@Sun.COM
2138*7836SJohn.Forte@Sun.COM /*
2139*7836SJohn.Forte@Sun.COM * The mod time of /dev/es was newer than the mod time prior to
2140*7836SJohn.Forte@Sun.COM * insert so dir entry is checked at this time.
2141*7836SJohn.Forte@Sun.COM */
2142*7836SJohn.Forte@Sun.COM while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2143*7836SJohn.Forte@Sun.COM if (strcmp(dirent->d_name, ".") == 0 ||
2144*7836SJohn.Forte@Sun.COM strcmp(dirent->d_name, "..") == 0)
2145*7836SJohn.Forte@Sun.COM continue;
2146*7836SJohn.Forte@Sun.COM
2147*7836SJohn.Forte@Sun.COM (void) sprintf(lname, SES_DIR"/%s", dirent->d_name);
2148*7836SJohn.Forte@Sun.COM if (lstat(lname, &ses_stat) < 0) {
2149*7836SJohn.Forte@Sun.COM (void) print_errString(L_LSTAT_ES_DIR_ERROR,
2150*7836SJohn.Forte@Sun.COM lname);
2151*7836SJohn.Forte@Sun.COM continue;
2152*7836SJohn.Forte@Sun.COM }
2153*7836SJohn.Forte@Sun.COM
2154*7836SJohn.Forte@Sun.COM for (bl1 = box_list; bl1; bl1 = bl1->box_next) {
2155*7836SJohn.Forte@Sun.COM if (strstr(lname, bl1->b_physical_path))
2156*7836SJohn.Forte@Sun.COM break;
2157*7836SJohn.Forte@Sun.COM }
2158*7836SJohn.Forte@Sun.COM
2159*7836SJohn.Forte@Sun.COM if (box_list && bl1)
2160*7836SJohn.Forte@Sun.COM continue;
2161*7836SJohn.Forte@Sun.COM
2162*7836SJohn.Forte@Sun.COM if (NEWER(ses_stat.st_ctim, ses_lastmtim)) {
2163*7836SJohn.Forte@Sun.COM /* New enclosure was detected. */
2164*7836SJohn.Forte@Sun.COM found_newlink++;
2165*7836SJohn.Forte@Sun.COM if (found_newlink == 1) {
2166*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5556,
2167*7836SJohn.Forte@Sun.COM " New Logical Nodes under /dev/es:\n"));
2168*7836SJohn.Forte@Sun.COM }
2169*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\t%s\n",
2170*7836SJohn.Forte@Sun.COM dirent->d_name);
2171*7836SJohn.Forte@Sun.COM }
2172*7836SJohn.Forte@Sun.COM }
2173*7836SJohn.Forte@Sun.COM if (!found_newlink) {
2174*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5662,
2175*7836SJohn.Forte@Sun.COM " No new enclosure(s) were added!!\n\n"));
2176*7836SJohn.Forte@Sun.COM }
2177*7836SJohn.Forte@Sun.COM
2178*7836SJohn.Forte@Sun.COM closedir(dir);
2179*7836SJohn.Forte@Sun.COM
2180*7836SJohn.Forte@Sun.COM (void) l_free_box_list(&box_list);
2181*7836SJohn.Forte@Sun.COM return (0);
2182*7836SJohn.Forte@Sun.COM }
2183*7836SJohn.Forte@Sun.COM
2184*7836SJohn.Forte@Sun.COM
2185*7836SJohn.Forte@Sun.COM
2186*7836SJohn.Forte@Sun.COM /*
2187*7836SJohn.Forte@Sun.COM * performs the post removal of individual
2188*7836SJohn.Forte@Sun.COM * FC_AL disks.
2189*7836SJohn.Forte@Sun.COM *
2190*7836SJohn.Forte@Sun.COM * RETURNS:
2191*7836SJohn.Forte@Sun.COM * 0 if OK
2192*7836SJohn.Forte@Sun.COM * non-zero otherwise
2193*7836SJohn.Forte@Sun.COM */
2194*7836SJohn.Forte@Sun.COM static int
h_post_remove_dev(Hotplug_Devlist * hotplug_disk,int todo,int verbose_flag)2195*7836SJohn.Forte@Sun.COM h_post_remove_dev(Hotplug_Devlist *hotplug_disk,
2196*7836SJohn.Forte@Sun.COM int todo, int verbose_flag)
2197*7836SJohn.Forte@Sun.COM {
2198*7836SJohn.Forte@Sun.COM char device_name[MAXNAMELEN], *dev_path = NULL;
2199*7836SJohn.Forte@Sun.COM int tid, err;
2200*7836SJohn.Forte@Sun.COM gfc_map_t map;
2201*7836SJohn.Forte@Sun.COM int nArg;
2202*7836SJohn.Forte@Sun.COM
2203*7836SJohn.Forte@Sun.COM
2204*7836SJohn.Forte@Sun.COM tid = hotplug_disk->tid;
2205*7836SJohn.Forte@Sun.COM (void) sprintf(device_name,
2206*7836SJohn.Forte@Sun.COM MSGSTR(5557,
2207*7836SJohn.Forte@Sun.COM "\n Device: %s"),
2208*7836SJohn.Forte@Sun.COM (hotplug_disk->dlhead)->logical_path);
2209*7836SJohn.Forte@Sun.COM
2210*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "%s\n", device_name);
2211*7836SJohn.Forte@Sun.COM
2212*7836SJohn.Forte@Sun.COM dev_path = (hotplug_disk->dlhead)->dev_path;
2213*7836SJohn.Forte@Sun.COM
2214*7836SJohn.Forte@Sun.COM /*
2215*7836SJohn.Forte@Sun.COM * On qlc, after a forcelip on a FC combo box, it sometimes takes 17
2216*7836SJohn.Forte@Sun.COM * seconds for the loop to come back online. During this 17 seconds,
2217*7836SJohn.Forte@Sun.COM * g_get_dev_map * will return L_NO_DEVICES_FOUND. This delay
2218*7836SJohn.Forte@Sun.COM * has been added to assure that the L_NO_DEVICES_FOUND returned from
2219*7836SJohn.Forte@Sun.COM * g_get_dev_map is not the result of the 17 second delay on FC combo.
2220*7836SJohn.Forte@Sun.COM * This only affects qlc.
2221*7836SJohn.Forte@Sun.COM */
2222*7836SJohn.Forte@Sun.COM if ((err = g_get_dev_map(dev_path, &map, verbose_flag)) != 0) {
2223*7836SJohn.Forte@Sun.COM if ((err == L_NO_DEVICES_FOUND) &&
2224*7836SJohn.Forte@Sun.COM (strstr(dev_path, "SUNW,qlc@") != NULL)) {
2225*7836SJohn.Forte@Sun.COM sleep(QLC_LIP_DELAY);
2226*7836SJohn.Forte@Sun.COM if ((err = g_get_dev_map(dev_path, &map, verbose_flag))
2227*7836SJohn.Forte@Sun.COM != 0) {
2228*7836SJohn.Forte@Sun.COM if (err != L_NO_DEVICES_FOUND)
2229*7836SJohn.Forte@Sun.COM return (err);
2230*7836SJohn.Forte@Sun.COM }
2231*7836SJohn.Forte@Sun.COM } else if (err != L_NO_DEVICES_FOUND)
2232*7836SJohn.Forte@Sun.COM return (err);
2233*7836SJohn.Forte@Sun.COM }
2234*7836SJohn.Forte@Sun.COM
2235*7836SJohn.Forte@Sun.COM /*
2236*7836SJohn.Forte@Sun.COM * if g_get_dev_map returns L_NO_DEVICES_FOUND, then there are not
2237*7836SJohn.Forte@Sun.COM * devices attached to the HBA and there is no sense in calling
2238*7836SJohn.Forte@Sun.COM * g_device_in_map().
2239*7836SJohn.Forte@Sun.COM */
2240*7836SJohn.Forte@Sun.COM if (err != L_NO_DEVICES_FOUND) {
2241*7836SJohn.Forte@Sun.COM if ((map.hba_addr.port_topology == FC_TOP_PUBLIC_LOOP) ||
2242*7836SJohn.Forte@Sun.COM (map.hba_addr.port_topology == FC_TOP_FABRIC)) {
2243*7836SJohn.Forte@Sun.COM /* public or fabric loop device */
2244*7836SJohn.Forte@Sun.COM free((void *)map.dev_addr);
2245*7836SJohn.Forte@Sun.COM (void) fprintf(stderr, MSGSTR(5540,
2246*7836SJohn.Forte@Sun.COM "This operation is not "
2247*7836SJohn.Forte@Sun.COM "supported in this topology.\n"));
2248*7836SJohn.Forte@Sun.COM return (0);
2249*7836SJohn.Forte@Sun.COM }
2250*7836SJohn.Forte@Sun.COM
2251*7836SJohn.Forte@Sun.COM if (g_device_in_map(&map, tid) != 0) {
2252*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
2253*7836SJohn.Forte@Sun.COM MSGSTR(5558,
2254*7836SJohn.Forte@Sun.COM " Warning: Device has"
2255*7836SJohn.Forte@Sun.COM " not been removed from\n"
2256*7836SJohn.Forte@Sun.COM " the slot and is still"
2257*7836SJohn.Forte@Sun.COM " in the loop map.\n\n"));
2258*7836SJohn.Forte@Sun.COM free((void *)map.dev_addr);
2259*7836SJohn.Forte@Sun.COM return (0);
2260*7836SJohn.Forte@Sun.COM }
2261*7836SJohn.Forte@Sun.COM free((void *)map.dev_addr);
2262*7836SJohn.Forte@Sun.COM }
2263*7836SJohn.Forte@Sun.COM /*
2264*7836SJohn.Forte@Sun.COM * In Solaris7, "disks -C" program
2265*7836SJohn.Forte@Sun.COM * removes the /dev/{r}dsk entries.
2266*7836SJohn.Forte@Sun.COM * The -C option is available only
2267*7836SJohn.Forte@Sun.COM * for Solaris7. From Solaris8 or
2268*7836SJohn.Forte@Sun.COM * higher releases, the "disks" program
2269*7836SJohn.Forte@Sun.COM * will be replaced by devfsadm.
2270*7836SJohn.Forte@Sun.COM */
2271*7836SJohn.Forte@Sun.COM /* pass "disks -C" as cmdStrg. */
2272*7836SJohn.Forte@Sun.COM nArg = 2;
2273*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[0], nArg) != 0) {
2274*7836SJohn.Forte@Sun.COM return (L_DISKS_ERROR);
2275*7836SJohn.Forte@Sun.COM }
2276*7836SJohn.Forte@Sun.COM /* pass "tapes -C as cmdStrg. */
2277*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[5], nArg) != 0) {
2278*7836SJohn.Forte@Sun.COM return (L_TAPES_ERROR);
2279*7836SJohn.Forte@Sun.COM }
2280*7836SJohn.Forte@Sun.COM (void) h_print_logical_nodes(hotplug_disk->dlhead);
2281*7836SJohn.Forte@Sun.COM
2282*7836SJohn.Forte@Sun.COM return (0);
2283*7836SJohn.Forte@Sun.COM }
2284*7836SJohn.Forte@Sun.COM
2285*7836SJohn.Forte@Sun.COM
2286*7836SJohn.Forte@Sun.COM
2287*7836SJohn.Forte@Sun.COM /*
2288*7836SJohn.Forte@Sun.COM * Gets the last modification time for
2289*7836SJohn.Forte@Sun.COM * /dev/es/ and /dev/rdsk directories
2290*7836SJohn.Forte@Sun.COM * and passes these values to the caller.
2291*7836SJohn.Forte@Sun.COM *
2292*7836SJohn.Forte@Sun.COM * RETURNS:
2293*7836SJohn.Forte@Sun.COM * 0 if OK
2294*7836SJohn.Forte@Sun.COM * non-zero in case of error
2295*7836SJohn.Forte@Sun.COM */
2296*7836SJohn.Forte@Sun.COM static int
h_pre_insert_encl_dev(timestruc_t * ses_time,timestruc_t * dsk_time,timestruc_t * rmt_time)2297*7836SJohn.Forte@Sun.COM h_pre_insert_encl_dev(timestruc_t *ses_time, timestruc_t *dsk_time,
2298*7836SJohn.Forte@Sun.COM timestruc_t *rmt_time)
2299*7836SJohn.Forte@Sun.COM {
2300*7836SJohn.Forte@Sun.COM struct stat ses_stat, dsk_stat, rmt_stat;
2301*7836SJohn.Forte@Sun.COM
2302*7836SJohn.Forte@Sun.COM if (stat(SES_DIR, &ses_stat) < 0) {
2303*7836SJohn.Forte@Sun.COM /*
2304*7836SJohn.Forte@Sun.COM * Even if there exists no /dev/es don't fail it.
2305*7836SJohn.Forte@Sun.COM * The host doesn't have to have any enclosure device
2306*7836SJohn.Forte@Sun.COM * configured.
2307*7836SJohn.Forte@Sun.COM */
2308*7836SJohn.Forte@Sun.COM if (errno == ENOENT) {
2309*7836SJohn.Forte@Sun.COM ses_time = (timestruc_t *)NULL;
2310*7836SJohn.Forte@Sun.COM } else {
2311*7836SJohn.Forte@Sun.COM return (L_LSTAT_ES_DIR_ERROR);
2312*7836SJohn.Forte@Sun.COM }
2313*7836SJohn.Forte@Sun.COM } else {
2314*7836SJohn.Forte@Sun.COM *ses_time = ses_stat.st_mtim;
2315*7836SJohn.Forte@Sun.COM }
2316*7836SJohn.Forte@Sun.COM
2317*7836SJohn.Forte@Sun.COM if (stat(DEV_DSK_DIR, &dsk_stat) < 0) {
2318*7836SJohn.Forte@Sun.COM return (L_STAT_DEV_DIR_ERROR);
2319*7836SJohn.Forte@Sun.COM } else {
2320*7836SJohn.Forte@Sun.COM *dsk_time = dsk_stat.st_mtim;
2321*7836SJohn.Forte@Sun.COM }
2322*7836SJohn.Forte@Sun.COM if (stat(DEV_TAPE_DIR, &rmt_stat) < 0) {
2323*7836SJohn.Forte@Sun.COM /*
2324*7836SJohn.Forte@Sun.COM * Even if there exists no /dev/rmt don't fail it.
2325*7836SJohn.Forte@Sun.COM * The host doesn't have to have any tape device
2326*7836SJohn.Forte@Sun.COM * configured.
2327*7836SJohn.Forte@Sun.COM */
2328*7836SJohn.Forte@Sun.COM if (errno == ENOENT) {
2329*7836SJohn.Forte@Sun.COM rmt_time = (timestruc_t *)NULL;
2330*7836SJohn.Forte@Sun.COM } else {
2331*7836SJohn.Forte@Sun.COM return (L_STAT_RMT_DIR_ERROR);
2332*7836SJohn.Forte@Sun.COM }
2333*7836SJohn.Forte@Sun.COM } else {
2334*7836SJohn.Forte@Sun.COM *rmt_time = rmt_stat.st_mtim;
2335*7836SJohn.Forte@Sun.COM }
2336*7836SJohn.Forte@Sun.COM
2337*7836SJohn.Forte@Sun.COM return (0);
2338*7836SJohn.Forte@Sun.COM }
2339*7836SJohn.Forte@Sun.COM
2340*7836SJohn.Forte@Sun.COM
2341*7836SJohn.Forte@Sun.COM
2342*7836SJohn.Forte@Sun.COM /*
2343*7836SJohn.Forte@Sun.COM * Waits for loop intialization to complete
2344*7836SJohn.Forte@Sun.COM * and runs drvconfig, disks and devlinks to create device nodes
2345*7836SJohn.Forte@Sun.COM * for devices that are being added and prints the newly created
2346*7836SJohn.Forte@Sun.COM * /dev/rdsk entries.
2347*7836SJohn.Forte@Sun.COM *
2348*7836SJohn.Forte@Sun.COM * RETURNS:
2349*7836SJohn.Forte@Sun.COM * 0 if OK
2350*7836SJohn.Forte@Sun.COM * non-zero in case of error
2351*7836SJohn.Forte@Sun.COM */
2352*7836SJohn.Forte@Sun.COM
2353*7836SJohn.Forte@Sun.COM static int
h_post_insert_dev(timestruc_t dsk_lastmtim,timestruc_t rmt_lastmtim)2354*7836SJohn.Forte@Sun.COM h_post_insert_dev(timestruc_t dsk_lastmtim, timestruc_t rmt_lastmtim)
2355*7836SJohn.Forte@Sun.COM {
2356*7836SJohn.Forte@Sun.COM int found_newlink = 0, nArg;
2357*7836SJohn.Forte@Sun.COM
2358*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2359*7836SJohn.Forte@Sun.COM MSGSTR(5560,
2360*7836SJohn.Forte@Sun.COM "\nWaiting for Loop Initialization to complete...\n"));
2361*7836SJohn.Forte@Sun.COM
2362*7836SJohn.Forte@Sun.COM /*
2363*7836SJohn.Forte@Sun.COM * We sleep here to let the system create nodes. Not sleeping
2364*7836SJohn.Forte@Sun.COM * could cause the drvconfig below to run too soon.
2365*7836SJohn.Forte@Sun.COM */
2366*7836SJohn.Forte@Sun.COM
2367*7836SJohn.Forte@Sun.COM (void) sleep(NODE_CREATION_TIME);
2368*7836SJohn.Forte@Sun.COM
2369*7836SJohn.Forte@Sun.COM /*
2370*7836SJohn.Forte@Sun.COM * Run drvconfig and disks to create
2371*7836SJohn.Forte@Sun.COM * logical nodes
2372*7836SJohn.Forte@Sun.COM */
2373*7836SJohn.Forte@Sun.COM /* pass "drvconfig" as cmdStrg */
2374*7836SJohn.Forte@Sun.COM nArg = 1;
2375*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[3], nArg) != 0) {
2376*7836SJohn.Forte@Sun.COM return (L_DRVCONFIG_ERROR);
2377*7836SJohn.Forte@Sun.COM }
2378*7836SJohn.Forte@Sun.COM
2379*7836SJohn.Forte@Sun.COM /*
2380*7836SJohn.Forte@Sun.COM * In 2.7, disks with the -C
2381*7836SJohn.Forte@Sun.COM * option should be used to
2382*7836SJohn.Forte@Sun.COM * create new links and remove
2383*7836SJohn.Forte@Sun.COM * any stale links.
2384*7836SJohn.Forte@Sun.COM * In pre-2.7 releases, just
2385*7836SJohn.Forte@Sun.COM * disks should do it all.
2386*7836SJohn.Forte@Sun.COM */
2387*7836SJohn.Forte@Sun.COM
2388*7836SJohn.Forte@Sun.COM /* pass "disks -C" as cmdStrg */
2389*7836SJohn.Forte@Sun.COM nArg = 2;
2390*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[0], nArg) != 0) {
2391*7836SJohn.Forte@Sun.COM return (L_DISKS_ERROR);
2392*7836SJohn.Forte@Sun.COM }
2393*7836SJohn.Forte@Sun.COM /* pass "tapes -C as cmdStrg */
2394*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[5], nArg) != 0) {
2395*7836SJohn.Forte@Sun.COM return (L_TAPES_ERROR);
2396*7836SJohn.Forte@Sun.COM }
2397*7836SJohn.Forte@Sun.COM
2398*7836SJohn.Forte@Sun.COM /* pass "devlinks" as cmdStrg */
2399*7836SJohn.Forte@Sun.COM nArg = 1;
2400*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[4], nArg) != 0) {
2401*7836SJohn.Forte@Sun.COM return (L_DEVLINKS_ERROR);
2402*7836SJohn.Forte@Sun.COM }
2403*7836SJohn.Forte@Sun.COM
2404*7836SJohn.Forte@Sun.COM /* check /dev/dsk and /dev/rmt for new links */
2405*7836SJohn.Forte@Sun.COM found_newlink = h_find_new_device_link(DEV_DSK_DIR, dsk_lastmtim) +
2406*7836SJohn.Forte@Sun.COM h_find_new_device_link(DEV_TAPE_DIR, rmt_lastmtim);
2407*7836SJohn.Forte@Sun.COM
2408*7836SJohn.Forte@Sun.COM if (!found_newlink) {
2409*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5562,
2410*7836SJohn.Forte@Sun.COM " No new device(s) were added!!\n\n"));
2411*7836SJohn.Forte@Sun.COM }
2412*7836SJohn.Forte@Sun.COM
2413*7836SJohn.Forte@Sun.COM return (0);
2414*7836SJohn.Forte@Sun.COM }
2415*7836SJohn.Forte@Sun.COM
2416*7836SJohn.Forte@Sun.COM
2417*7836SJohn.Forte@Sun.COM
2418*7836SJohn.Forte@Sun.COM /*
2419*7836SJohn.Forte@Sun.COM * Performs the pre hotplug operations on SENA enclosure(s),
2420*7836SJohn.Forte@Sun.COM * SENA disk(s) and individual fcal disk(s).
2421*7836SJohn.Forte@Sun.COM * If the device is failed to remove, then it removes the device from the
2422*7836SJohn.Forte@Sun.COM * hotplug list and continues with the next device in the list.
2423*7836SJohn.Forte@Sun.COM *
2424*7836SJohn.Forte@Sun.COM * RETURNS:
2425*7836SJohn.Forte@Sun.COM * 0 if OK
2426*7836SJohn.Forte@Sun.COM * prints an error message to stderr and returns 0
2427*7836SJohn.Forte@Sun.COM */
2428*7836SJohn.Forte@Sun.COM static int
h_pre_hotplug(Hotplug_Devlist ** disk_list_head_ptr,WWN_list * wwn_list,int todo,int verbose_flag,int force_flag)2429*7836SJohn.Forte@Sun.COM h_pre_hotplug(Hotplug_Devlist **disk_list_head_ptr,
2430*7836SJohn.Forte@Sun.COM WWN_list *wwn_list, int todo,
2431*7836SJohn.Forte@Sun.COM int verbose_flag, int force_flag)
2432*7836SJohn.Forte@Sun.COM {
2433*7836SJohn.Forte@Sun.COM Hotplug_Devlist *list, *disk_list;
2434*7836SJohn.Forte@Sun.COM int err = 0;
2435*7836SJohn.Forte@Sun.COM
2436*7836SJohn.Forte@Sun.COM disk_list = *disk_list_head_ptr;
2437*7836SJohn.Forte@Sun.COM while (disk_list != NULL) {
2438*7836SJohn.Forte@Sun.COM if ((disk_list->dev_type == DTYPE_ESI) ||
2439*7836SJohn.Forte@Sun.COM (disk_list->dev_location == SENA)) {
2440*7836SJohn.Forte@Sun.COM if ((err = h_pre_hotplug_sena(disk_list, wwn_list,
2441*7836SJohn.Forte@Sun.COM todo, verbose_flag, force_flag)) != 0) {
2442*7836SJohn.Forte@Sun.COM (void) print_errString(err,
2443*7836SJohn.Forte@Sun.COM disk_list->dev_name);
2444*7836SJohn.Forte@Sun.COM goto delete;
2445*7836SJohn.Forte@Sun.COM }
2446*7836SJohn.Forte@Sun.COM } else if (disk_list->dev_location == NON_SENA) {
2447*7836SJohn.Forte@Sun.COM if ((err = h_pre_remove_dev(disk_list, wwn_list,
2448*7836SJohn.Forte@Sun.COM verbose_flag, force_flag)) != 0) {
2449*7836SJohn.Forte@Sun.COM (void) print_errString(err,
2450*7836SJohn.Forte@Sun.COM disk_list->dev_name);
2451*7836SJohn.Forte@Sun.COM goto delete;
2452*7836SJohn.Forte@Sun.COM }
2453*7836SJohn.Forte@Sun.COM }
2454*7836SJohn.Forte@Sun.COM disk_list = disk_list->next;
2455*7836SJohn.Forte@Sun.COM continue;
2456*7836SJohn.Forte@Sun.COM delete:
2457*7836SJohn.Forte@Sun.COM list = disk_list->prev;
2458*7836SJohn.Forte@Sun.COM if (list != NULL) {
2459*7836SJohn.Forte@Sun.COM list->next = disk_list->next;
2460*7836SJohn.Forte@Sun.COM if (list->next != NULL)
2461*7836SJohn.Forte@Sun.COM list->next->prev = list;
2462*7836SJohn.Forte@Sun.COM }
2463*7836SJohn.Forte@Sun.COM list = disk_list;
2464*7836SJohn.Forte@Sun.COM disk_list = disk_list->next;
2465*7836SJohn.Forte@Sun.COM if (list == *disk_list_head_ptr)
2466*7836SJohn.Forte@Sun.COM *disk_list_head_ptr = disk_list;
2467*7836SJohn.Forte@Sun.COM (void) g_free_multipath(list->seslist);
2468*7836SJohn.Forte@Sun.COM (void) g_free_multipath(list->dlhead);
2469*7836SJohn.Forte@Sun.COM (void) free(list);
2470*7836SJohn.Forte@Sun.COM }
2471*7836SJohn.Forte@Sun.COM return (0);
2472*7836SJohn.Forte@Sun.COM }
2473*7836SJohn.Forte@Sun.COM
2474*7836SJohn.Forte@Sun.COM
2475*7836SJohn.Forte@Sun.COM
2476*7836SJohn.Forte@Sun.COM /*
2477*7836SJohn.Forte@Sun.COM * Performs the post removal of a list of SENA enclosure(s),
2478*7836SJohn.Forte@Sun.COM * SENA disk(s) and individual fcal disk(s).
2479*7836SJohn.Forte@Sun.COM *
2480*7836SJohn.Forte@Sun.COM * RETURNS:
2481*7836SJohn.Forte@Sun.COM * 0 O.K.
2482*7836SJohn.Forte@Sun.COM * non-zero otherwise
2483*7836SJohn.Forte@Sun.COM */
2484*7836SJohn.Forte@Sun.COM static int
h_post_hotplug(Hotplug_Devlist * hotplug_dlist,WWN_list * wwn_list,int todo,int verbose_flag,int force_flag,int enc_type)2485*7836SJohn.Forte@Sun.COM h_post_hotplug(Hotplug_Devlist *hotplug_dlist,
2486*7836SJohn.Forte@Sun.COM WWN_list *wwn_list, int todo,
2487*7836SJohn.Forte@Sun.COM int verbose_flag, int force_flag, int enc_type)
2488*7836SJohn.Forte@Sun.COM {
2489*7836SJohn.Forte@Sun.COM Hotplug_Devlist *list;
2490*7836SJohn.Forte@Sun.COM int err;
2491*7836SJohn.Forte@Sun.COM
2492*7836SJohn.Forte@Sun.COM /* Do a lip on every loop so that we get the latest loop maps */
2493*7836SJohn.Forte@Sun.COM if (todo != INSERT_DEVICE) {
2494*7836SJohn.Forte@Sun.COM if ((err = g_forcelip_all(hotplug_dlist)) != 0) {
2495*7836SJohn.Forte@Sun.COM return (err);
2496*7836SJohn.Forte@Sun.COM }
2497*7836SJohn.Forte@Sun.COM }
2498*7836SJohn.Forte@Sun.COM
2499*7836SJohn.Forte@Sun.COM while (hotplug_dlist != NULL) {
2500*7836SJohn.Forte@Sun.COM if ((hotplug_dlist->dev_location == SENA) ||
2501*7836SJohn.Forte@Sun.COM (hotplug_dlist->dev_type == DTYPE_ESI)) {
2502*7836SJohn.Forte@Sun.COM if ((err = h_post_hotplug_sena(hotplug_dlist, wwn_list, todo,
2503*7836SJohn.Forte@Sun.COM verbose_flag, force_flag, enc_type)) != 0)
2504*7836SJohn.Forte@Sun.COM (void) print_errString(err, hotplug_dlist->dev_name);
2505*7836SJohn.Forte@Sun.COM } else if (hotplug_dlist->dev_location == NON_SENA) {
2506*7836SJohn.Forte@Sun.COM if ((err = h_post_remove_dev(hotplug_dlist,
2507*7836SJohn.Forte@Sun.COM todo, verbose_flag)) != 0)
2508*7836SJohn.Forte@Sun.COM (void) print_errString(err,
2509*7836SJohn.Forte@Sun.COM hotplug_dlist->dev_name);
2510*7836SJohn.Forte@Sun.COM }
2511*7836SJohn.Forte@Sun.COM list = hotplug_dlist;
2512*7836SJohn.Forte@Sun.COM hotplug_dlist = hotplug_dlist->next;
2513*7836SJohn.Forte@Sun.COM (void) g_free_multipath(list->seslist);
2514*7836SJohn.Forte@Sun.COM (void) g_free_multipath(list->dlhead);
2515*7836SJohn.Forte@Sun.COM (void) free(list);
2516*7836SJohn.Forte@Sun.COM }
2517*7836SJohn.Forte@Sun.COM return (0);
2518*7836SJohn.Forte@Sun.COM }
2519*7836SJohn.Forte@Sun.COM
2520*7836SJohn.Forte@Sun.COM
2521*7836SJohn.Forte@Sun.COM /*
2522*7836SJohn.Forte@Sun.COM * removes the device's logical paths.
2523*7836SJohn.Forte@Sun.COM *
2524*7836SJohn.Forte@Sun.COM * RETURNS:
2525*7836SJohn.Forte@Sun.COM * 0 if OK
2526*7836SJohn.Forte@Sun.COM * non-zero otherwise
2527*7836SJohn.Forte@Sun.COM */
2528*7836SJohn.Forte@Sun.COM static int
h_remove_nodes(struct dlist * dl)2529*7836SJohn.Forte@Sun.COM h_remove_nodes(struct dlist *dl)
2530*7836SJohn.Forte@Sun.COM {
2531*7836SJohn.Forte@Sun.COM char link[MAXPATHLEN], path[MAXPATHLEN];
2532*7836SJohn.Forte@Sun.COM char lname[MAXPATHLEN], *ptr;
2533*7836SJohn.Forte@Sun.COM DIR *dir;
2534*7836SJohn.Forte@Sun.COM struct dirent *dirent;
2535*7836SJohn.Forte@Sun.COM struct dlist *dlist;
2536*7836SJohn.Forte@Sun.COM
2537*7836SJohn.Forte@Sun.COM if ((dir = opendir(DEV_DSK_DIR)) == NULL) {
2538*7836SJohn.Forte@Sun.COM return (L_READ_DEV_DIR_ERROR);
2539*7836SJohn.Forte@Sun.COM }
2540*7836SJohn.Forte@Sun.COM if (dl == NULL) {
2541*7836SJohn.Forte@Sun.COM /* pass "disks" as cmdStrg */
2542*7836SJohn.Forte@Sun.COM if (h_execCmnd(cmdStrg[1], 1) != 0) {
2543*7836SJohn.Forte@Sun.COM return (L_DISKS_ERROR);
2544*7836SJohn.Forte@Sun.COM }
2545*7836SJohn.Forte@Sun.COM }
2546*7836SJohn.Forte@Sun.COM
2547*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2548*7836SJohn.Forte@Sun.COM MSGSTR(5563,
2549*7836SJohn.Forte@Sun.COM " Removing Logical Nodes: \n"));
2550*7836SJohn.Forte@Sun.COM
2551*7836SJohn.Forte@Sun.COM while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2552*7836SJohn.Forte@Sun.COM if (strcmp(dirent->d_name, ".") == 0 ||
2553*7836SJohn.Forte@Sun.COM strcmp(dirent->d_name, "..") == 0) {
2554*7836SJohn.Forte@Sun.COM continue;
2555*7836SJohn.Forte@Sun.COM }
2556*7836SJohn.Forte@Sun.COM (void) sprintf(lname, DEV_DSK_DIR"/%s", dirent->d_name);
2557*7836SJohn.Forte@Sun.COM if (readlink((const char *)lname, (char *)link,
2558*7836SJohn.Forte@Sun.COM (size_t)MAXPATHLEN) <= 0) {
2559*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
2560*7836SJohn.Forte@Sun.COM MSGSTR(5564,
2561*7836SJohn.Forte@Sun.COM " Error: Could not read %s\n"),
2562*7836SJohn.Forte@Sun.COM lname);
2563*7836SJohn.Forte@Sun.COM continue;
2564*7836SJohn.Forte@Sun.COM }
2565*7836SJohn.Forte@Sun.COM for (dlist = dl; dlist != NULL; dlist = dlist->next) {
2566*7836SJohn.Forte@Sun.COM (void) strcpy(path, dlist->dev_path);
2567*7836SJohn.Forte@Sun.COM ptr = strrchr(path, ':');
2568*7836SJohn.Forte@Sun.COM if (ptr)
2569*7836SJohn.Forte@Sun.COM *ptr = '\0';
2570*7836SJohn.Forte@Sun.COM if (strstr(link, path)) {
2571*7836SJohn.Forte@Sun.COM (void) unlink(lname);
2572*7836SJohn.Forte@Sun.COM (void) sprintf(lname, "/dev/rdsk/%s",
2573*7836SJohn.Forte@Sun.COM dirent->d_name);
2574*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2575*7836SJohn.Forte@Sun.COM MSGSTR(5565,
2576*7836SJohn.Forte@Sun.COM "\tRemoving %s\n"),
2577*7836SJohn.Forte@Sun.COM dirent->d_name);
2578*7836SJohn.Forte@Sun.COM (void) unlink(lname);
2579*7836SJohn.Forte@Sun.COM }
2580*7836SJohn.Forte@Sun.COM }
2581*7836SJohn.Forte@Sun.COM }
2582*7836SJohn.Forte@Sun.COM closedir(dir);
2583*7836SJohn.Forte@Sun.COM return (0);
2584*7836SJohn.Forte@Sun.COM }
2585*7836SJohn.Forte@Sun.COM
2586*7836SJohn.Forte@Sun.COM
2587*7836SJohn.Forte@Sun.COM
2588*7836SJohn.Forte@Sun.COM /*
2589*7836SJohn.Forte@Sun.COM * removes the SENA's ses paths.
2590*7836SJohn.Forte@Sun.COM *
2591*7836SJohn.Forte@Sun.COM * RETURNS:
2592*7836SJohn.Forte@Sun.COM * 0 if OK
2593*7836SJohn.Forte@Sun.COM * non-zero otherwise
2594*7836SJohn.Forte@Sun.COM */
2595*7836SJohn.Forte@Sun.COM static int
h_remove_ses_nodes(struct dlist * dlist)2596*7836SJohn.Forte@Sun.COM h_remove_ses_nodes(struct dlist *dlist)
2597*7836SJohn.Forte@Sun.COM {
2598*7836SJohn.Forte@Sun.COM char link[MAXPATHLEN], lname[MAXPATHLEN];
2599*7836SJohn.Forte@Sun.COM DIR *dir;
2600*7836SJohn.Forte@Sun.COM struct dirent *dirent;
2601*7836SJohn.Forte@Sun.COM struct dlist *dl;
2602*7836SJohn.Forte@Sun.COM
2603*7836SJohn.Forte@Sun.COM
2604*7836SJohn.Forte@Sun.COM if ((dir = opendir(SES_DIR)) == NULL) {
2605*7836SJohn.Forte@Sun.COM return (L_READ_DEV_DIR_ERROR);
2606*7836SJohn.Forte@Sun.COM }
2607*7836SJohn.Forte@Sun.COM
2608*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5566, " Removing Ses Nodes:\n"));
2609*7836SJohn.Forte@Sun.COM
2610*7836SJohn.Forte@Sun.COM /*
2611*7836SJohn.Forte@Sun.COM * Remove the ses entries
2612*7836SJohn.Forte@Sun.COM * of the form ses<#>
2613*7836SJohn.Forte@Sun.COM * from the /dev/es directory.
2614*7836SJohn.Forte@Sun.COM */
2615*7836SJohn.Forte@Sun.COM
2616*7836SJohn.Forte@Sun.COM while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2617*7836SJohn.Forte@Sun.COM if (strcmp(dirent->d_name, ".") == 0 ||
2618*7836SJohn.Forte@Sun.COM strcmp(dirent->d_name, "..") == 0)
2619*7836SJohn.Forte@Sun.COM continue;
2620*7836SJohn.Forte@Sun.COM
2621*7836SJohn.Forte@Sun.COM (void) sprintf(lname, SES_DIR"/%s", dirent->d_name);
2622*7836SJohn.Forte@Sun.COM if (readlink((const char *)lname, (char *)link,
2623*7836SJohn.Forte@Sun.COM (size_t)MAXPATHLEN) <= 0) {
2624*7836SJohn.Forte@Sun.COM (void) fprintf(stderr,
2625*7836SJohn.Forte@Sun.COM MSGSTR(5564,
2626*7836SJohn.Forte@Sun.COM " Error: Could not read %s\n"),
2627*7836SJohn.Forte@Sun.COM lname);
2628*7836SJohn.Forte@Sun.COM continue;
2629*7836SJohn.Forte@Sun.COM }
2630*7836SJohn.Forte@Sun.COM for (dl = dlist; dl != NULL; dl = dl->next) {
2631*7836SJohn.Forte@Sun.COM if (strstr(link, dl->dev_path)) {
2632*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2633*7836SJohn.Forte@Sun.COM MSGSTR(5568,
2634*7836SJohn.Forte@Sun.COM "\tRemoving %s\n"),
2635*7836SJohn.Forte@Sun.COM lname);
2636*7836SJohn.Forte@Sun.COM (void) unlink(lname);
2637*7836SJohn.Forte@Sun.COM }
2638*7836SJohn.Forte@Sun.COM }
2639*7836SJohn.Forte@Sun.COM }
2640*7836SJohn.Forte@Sun.COM closedir(dir);
2641*7836SJohn.Forte@Sun.COM (void) g_free_multipath(dlist);
2642*7836SJohn.Forte@Sun.COM return (0);
2643*7836SJohn.Forte@Sun.COM }
2644*7836SJohn.Forte@Sun.COM
2645*7836SJohn.Forte@Sun.COM
2646*7836SJohn.Forte@Sun.COM /*
2647*7836SJohn.Forte@Sun.COM * prints the device's logical
2648*7836SJohn.Forte@Sun.COM * paths for disks to stdout.
2649*7836SJohn.Forte@Sun.COM *
2650*7836SJohn.Forte@Sun.COM * RETURNS:
2651*7836SJohn.Forte@Sun.COM * 0 if OK
2652*7836SJohn.Forte@Sun.COM * non-zero otherwise
2653*7836SJohn.Forte@Sun.COM */
2654*7836SJohn.Forte@Sun.COM static void
h_print_logical_nodes(struct dlist * disk_list)2655*7836SJohn.Forte@Sun.COM h_print_logical_nodes(struct dlist *disk_list)
2656*7836SJohn.Forte@Sun.COM {
2657*7836SJohn.Forte@Sun.COM char *lpath, *ptr, *buf_ptr, buf[MAXNAMELEN], dev[MAXNAMELEN];
2658*7836SJohn.Forte@Sun.COM struct dlist *dlist;
2659*7836SJohn.Forte@Sun.COM int i, found_dev = 0;
2660*7836SJohn.Forte@Sun.COM char *tape_entries[] = { "", "b", "bn", "c", "cb", "cbn", "cn",
2661*7836SJohn.Forte@Sun.COM "h", "hb", "hbn", "hn", "l", "lb",
2662*7836SJohn.Forte@Sun.COM "lbn", "ln", "m", "mb", "mbn", "mn",
2663*7836SJohn.Forte@Sun.COM "n", "u", "ub", "ubn", "un", NULL};
2664*7836SJohn.Forte@Sun.COM
2665*7836SJohn.Forte@Sun.COM for (dlist = disk_list; dlist != NULL; dlist = dlist->next) {
2666*7836SJohn.Forte@Sun.COM lpath = dlist->logical_path;
2667*7836SJohn.Forte@Sun.COM if ((ptr = strrchr(lpath, 'c')) == NULL)
2668*7836SJohn.Forte@Sun.COM continue;
2669*7836SJohn.Forte@Sun.COM (void) strcpy(buf, ptr);
2670*7836SJohn.Forte@Sun.COM if ((ptr = strrchr(buf, 's')) == NULL)
2671*7836SJohn.Forte@Sun.COM continue;
2672*7836SJohn.Forte@Sun.COM *(++ptr) = NULL;
2673*7836SJohn.Forte@Sun.COM found_dev++;
2674*7836SJohn.Forte@Sun.COM if (found_dev == 1)
2675*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2676*7836SJohn.Forte@Sun.COM MSGSTR(5559, " Logical Nodes being "
2677*7836SJohn.Forte@Sun.COM "removed under /dev/dsk/ and "
2678*7836SJohn.Forte@Sun.COM "/dev/rdsk:\n"));
2679*7836SJohn.Forte@Sun.COM for (i = 0; i <= 7; i++) {
2680*7836SJohn.Forte@Sun.COM (void) sprintf(dev, "%s%d", buf, i);
2681*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\t%s\n", dev);
2682*7836SJohn.Forte@Sun.COM }
2683*7836SJohn.Forte@Sun.COM }
2684*7836SJohn.Forte@Sun.COM found_dev = 0;
2685*7836SJohn.Forte@Sun.COM for (dlist = disk_list; dlist != NULL; dlist = dlist->next) {
2686*7836SJohn.Forte@Sun.COM lpath = dlist->logical_path;
2687*7836SJohn.Forte@Sun.COM if (strstr(lpath, DEV_TAPE_DIR)) {
2688*7836SJohn.Forte@Sun.COM if ((ptr = strrchr(lpath, '/')) == NULL)
2689*7836SJohn.Forte@Sun.COM continue;
2690*7836SJohn.Forte@Sun.COM found_dev++;
2691*7836SJohn.Forte@Sun.COM if (found_dev == 1)
2692*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "Logical Nodes being "
2693*7836SJohn.Forte@Sun.COM "removed under /dev/rmt:\n");
2694*7836SJohn.Forte@Sun.COM ptr++;
2695*7836SJohn.Forte@Sun.COM buf_ptr = ptr;
2696*7836SJohn.Forte@Sun.COM while (*ptr >= '0' && *ptr <= '9')
2697*7836SJohn.Forte@Sun.COM ptr++;
2698*7836SJohn.Forte@Sun.COM *ptr = NULL;
2699*7836SJohn.Forte@Sun.COM for (i = 0, ptr = tape_entries[0];
2700*7836SJohn.Forte@Sun.COM ptr != NULL;
2701*7836SJohn.Forte@Sun.COM i++, ptr = tape_entries[i]) {
2702*7836SJohn.Forte@Sun.COM (void) sprintf(dev, "%s%s", buf_ptr, ptr);
2703*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\t%s\n", dev);
2704*7836SJohn.Forte@Sun.COM }
2705*7836SJohn.Forte@Sun.COM }
2706*7836SJohn.Forte@Sun.COM }
2707*7836SJohn.Forte@Sun.COM }
2708*7836SJohn.Forte@Sun.COM
2709*7836SJohn.Forte@Sun.COM /*
2710*7836SJohn.Forte@Sun.COM * displays logical paths to a
2711*7836SJohn.Forte@Sun.COM * device to stdout.
2712*7836SJohn.Forte@Sun.COM *
2713*7836SJohn.Forte@Sun.COM * RETURNS:
2714*7836SJohn.Forte@Sun.COM * 0 if OK
2715*7836SJohn.Forte@Sun.COM * non-zero otherwise
2716*7836SJohn.Forte@Sun.COM */
2717*7836SJohn.Forte@Sun.COM static int
h_display_logical_nodes(struct dlist * dlist)2718*7836SJohn.Forte@Sun.COM h_display_logical_nodes(struct dlist *dlist)
2719*7836SJohn.Forte@Sun.COM {
2720*7836SJohn.Forte@Sun.COM char link[MAXPATHLEN], path[MAXPATHLEN];
2721*7836SJohn.Forte@Sun.COM char lname[MAXPATHLEN], *d1;
2722*7836SJohn.Forte@Sun.COM DIR *dir;
2723*7836SJohn.Forte@Sun.COM struct dirent *dirent;
2724*7836SJohn.Forte@Sun.COM struct dlist *dl;
2725*7836SJohn.Forte@Sun.COM
2726*7836SJohn.Forte@Sun.COM
2727*7836SJohn.Forte@Sun.COM if ((dir = opendir(DEV_DSK_DIR)) == NULL) {
2728*7836SJohn.Forte@Sun.COM return (L_READ_DEV_DIR_ERROR);
2729*7836SJohn.Forte@Sun.COM }
2730*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2731*7836SJohn.Forte@Sun.COM MSGSTR(5569,
2732*7836SJohn.Forte@Sun.COM " Logical Nodes under /dev/dsk and /dev/rdsk :\n"));
2733*7836SJohn.Forte@Sun.COM
2734*7836SJohn.Forte@Sun.COM while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2735*7836SJohn.Forte@Sun.COM if (strcmp(dirent->d_name, ".") == 0 ||
2736*7836SJohn.Forte@Sun.COM strcmp(dirent->d_name, "..") == 0) {
2737*7836SJohn.Forte@Sun.COM continue;
2738*7836SJohn.Forte@Sun.COM }
2739*7836SJohn.Forte@Sun.COM (void) sprintf(lname, DEV_DSK_DIR"/%s", dirent->d_name);
2740*7836SJohn.Forte@Sun.COM if (readlink((const char *)lname, (char *)link,
2741*7836SJohn.Forte@Sun.COM (size_t)MAXPATHLEN) <= 0) {
2742*7836SJohn.Forte@Sun.COM (void) print_errString(L_SYMLINK_ERROR, lname);
2743*7836SJohn.Forte@Sun.COM continue;
2744*7836SJohn.Forte@Sun.COM }
2745*7836SJohn.Forte@Sun.COM for (dl = dlist; dl; dl = dl->next) {
2746*7836SJohn.Forte@Sun.COM (void) strcpy(path, dl->dev_path);
2747*7836SJohn.Forte@Sun.COM d1 = strrchr(path, ':');
2748*7836SJohn.Forte@Sun.COM if (d1)
2749*7836SJohn.Forte@Sun.COM *d1 = '\0';
2750*7836SJohn.Forte@Sun.COM if (strstr(link, path)) {
2751*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2752*7836SJohn.Forte@Sun.COM "\t%s\n",
2753*7836SJohn.Forte@Sun.COM dirent->d_name);
2754*7836SJohn.Forte@Sun.COM }
2755*7836SJohn.Forte@Sun.COM }
2756*7836SJohn.Forte@Sun.COM }
2757*7836SJohn.Forte@Sun.COM
2758*7836SJohn.Forte@Sun.COM closedir(dir);
2759*7836SJohn.Forte@Sun.COM return (0);
2760*7836SJohn.Forte@Sun.COM }
2761*7836SJohn.Forte@Sun.COM
2762*7836SJohn.Forte@Sun.COM
2763*7836SJohn.Forte@Sun.COM
2764*7836SJohn.Forte@Sun.COM /*
2765*7836SJohn.Forte@Sun.COM * prints a list of devices which
2766*7836SJohn.Forte@Sun.COM * will be inserted or removed
2767*7836SJohn.Forte@Sun.COM * to the stdout and asks for
2768*7836SJohn.Forte@Sun.COM * the user's confirmation.
2769*7836SJohn.Forte@Sun.COM *
2770*7836SJohn.Forte@Sun.COM * RETURNS:
2771*7836SJohn.Forte@Sun.COM * 0 if OK
2772*7836SJohn.Forte@Sun.COM * non-zero otherwise
2773*7836SJohn.Forte@Sun.COM */
2774*7836SJohn.Forte@Sun.COM static int
h_print_list_warn(Hotplug_Devlist * disk_list_head,int todo,int enc_type)2775*7836SJohn.Forte@Sun.COM h_print_list_warn(Hotplug_Devlist *disk_list_head, int todo, int enc_type)
2776*7836SJohn.Forte@Sun.COM {
2777*7836SJohn.Forte@Sun.COM int i;
2778*7836SJohn.Forte@Sun.COM char choice[2];
2779*7836SJohn.Forte@Sun.COM struct dlist *dl_ses, *dl_multi;
2780*7836SJohn.Forte@Sun.COM Hotplug_Devlist *disk_list = disk_list_head;
2781*7836SJohn.Forte@Sun.COM
2782*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2783*7836SJohn.Forte@Sun.COM MSGSTR(5570, "The list of devices which will be "));
2784*7836SJohn.Forte@Sun.COM switch (todo) {
2785*7836SJohn.Forte@Sun.COM case INSERT_DEVICE:
2786*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2787*7836SJohn.Forte@Sun.COM MSGSTR(5571, "inserted is:\n"));
2788*7836SJohn.Forte@Sun.COM break;
2789*7836SJohn.Forte@Sun.COM case REMOVE_DEVICE:
2790*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2791*7836SJohn.Forte@Sun.COM MSGSTR(5572, "removed is:\n"));
2792*7836SJohn.Forte@Sun.COM break;
2793*7836SJohn.Forte@Sun.COM }
2794*7836SJohn.Forte@Sun.COM
2795*7836SJohn.Forte@Sun.COM for (i = 1; disk_list; i++, disk_list = disk_list->next) {
2796*7836SJohn.Forte@Sun.COM if ((disk_list->dev_type == DTYPE_DIRECT) &&
2797*7836SJohn.Forte@Sun.COM (disk_list->dev_location == SENA)) {
2798*7836SJohn.Forte@Sun.COM if (disk_list->f_flag != NULL) {
2799*7836SJohn.Forte@Sun.COM if (enc_type == DAK_ENC_TYPE) {
2800*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5665,
2801*7836SJohn.Forte@Sun.COM " %d: Box Name: \"%s\" slot %d\n"),
2802*7836SJohn.Forte@Sun.COM i, disk_list->box_name, disk_list->slot);
2803*7836SJohn.Forte@Sun.COM } else {
2804*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(137,
2805*7836SJohn.Forte@Sun.COM " %d: Box Name: \"%s\" front slot %d\n"),
2806*7836SJohn.Forte@Sun.COM i, disk_list->box_name, disk_list->slot);
2807*7836SJohn.Forte@Sun.COM }
2808*7836SJohn.Forte@Sun.COM } else {
2809*7836SJohn.Forte@Sun.COM if (enc_type == DAK_ENC_TYPE) {
2810*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5665,
2811*7836SJohn.Forte@Sun.COM " %d: Box Name: \"%s\" slot %d\n"),
2812*7836SJohn.Forte@Sun.COM i, disk_list->box_name,
2813*7836SJohn.Forte@Sun.COM disk_list->slot + (MAX_DRIVES_DAK/2));
2814*7836SJohn.Forte@Sun.COM } else {
2815*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(136,
2816*7836SJohn.Forte@Sun.COM " %d: Box Name: \"%s\" rear slot %d\n"),
2817*7836SJohn.Forte@Sun.COM i, disk_list->box_name, disk_list->slot);
2818*7836SJohn.Forte@Sun.COM }
2819*7836SJohn.Forte@Sun.COM }
2820*7836SJohn.Forte@Sun.COM } else if (((disk_list->dev_type == DTYPE_DIRECT) ||
2821*7836SJohn.Forte@Sun.COM (disk_list->dev_type == DTYPE_SEQUENTIAL)) &&
2822*7836SJohn.Forte@Sun.COM (disk_list->dev_location == NON_SENA)) {
2823*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5573,
2824*7836SJohn.Forte@Sun.COM " %d: Device name: %s\n"),
2825*7836SJohn.Forte@Sun.COM i, disk_list->dev_name);
2826*7836SJohn.Forte@Sun.COM } else if (disk_list->dev_type == DTYPE_ESI) {
2827*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5574,
2828*7836SJohn.Forte@Sun.COM " %d: Box name: %s\n"),
2829*7836SJohn.Forte@Sun.COM i, disk_list->box_name);
2830*7836SJohn.Forte@Sun.COM }
2831*7836SJohn.Forte@Sun.COM if (getenv("_LUX_H_DEBUG") != NULL) {
2832*7836SJohn.Forte@Sun.COM if (disk_list->dev_location == SENA) {
2833*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2834*7836SJohn.Forte@Sun.COM " Select ID:\t0x%x\n",
2835*7836SJohn.Forte@Sun.COM disk_list->tid);
2836*7836SJohn.Forte@Sun.COM if (disk_list->dev_type != DTYPE_ESI) {
2837*7836SJohn.Forte@Sun.COM if (enc_type == DAK_ENC_TYPE) {
2838*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2839*7836SJohn.Forte@Sun.COM " Location: \tSlot %d \n",
2840*7836SJohn.Forte@Sun.COM disk_list->f_flag
2841*7836SJohn.Forte@Sun.COM ? disk_list->slot
2842*7836SJohn.Forte@Sun.COM : disk_list->slot
2843*7836SJohn.Forte@Sun.COM +MAX_DRIVES_DAK/2);
2844*7836SJohn.Forte@Sun.COM } else {
2845*7836SJohn.Forte@Sun.COM (void) fprintf(stdout,
2846*7836SJohn.Forte@Sun.COM " Location: \tSlot %d %s \n",
2847*7836SJohn.Forte@Sun.COM disk_list->slot, disk_list->f_flag
2848*7836SJohn.Forte@Sun.COM ? "front" : "rear");
2849*7836SJohn.Forte@Sun.COM }
2850*7836SJohn.Forte@Sun.COM }
2851*7836SJohn.Forte@Sun.COM }
2852*7836SJohn.Forte@Sun.COM }
2853*7836SJohn.Forte@Sun.COM if (todo == REMOVE_DEVICE) {
2854*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, " ");
2855*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(90, "Node WWN:"));
2856*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, " %s\n",
2857*7836SJohn.Forte@Sun.COM disk_list->node_wwn_s);
2858*7836SJohn.Forte@Sun.COM
2859*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, " ");
2860*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(35, "Device Type:"));
2861*7836SJohn.Forte@Sun.COM if (disk_list->dev_type == DTYPE_ESI) {
2862*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5581,
2863*7836SJohn.Forte@Sun.COM " SENA (%s)\n"),
2864*7836SJohn.Forte@Sun.COM dtype[disk_list->dev_type]);
2865*7836SJohn.Forte@Sun.COM } else {
2866*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "%s\n",
2867*7836SJohn.Forte@Sun.COM dtype[disk_list->dev_type]);
2868*7836SJohn.Forte@Sun.COM }
2869*7836SJohn.Forte@Sun.COM
2870*7836SJohn.Forte@Sun.COM if (disk_list->dev_type == DTYPE_ESI) {
2871*7836SJohn.Forte@Sun.COM dl_ses = disk_list->seslist;
2872*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5575,
2873*7836SJohn.Forte@Sun.COM " SES Paths:\n"));
2874*7836SJohn.Forte@Sun.COM while (dl_ses) {
2875*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5576,
2876*7836SJohn.Forte@Sun.COM " %s\n"), dl_ses->dev_path);
2877*7836SJohn.Forte@Sun.COM dl_ses = dl_ses->next;
2878*7836SJohn.Forte@Sun.COM }
2879*7836SJohn.Forte@Sun.COM } else {
2880*7836SJohn.Forte@Sun.COM dl_multi = disk_list->dlhead;
2881*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5577,
2882*7836SJohn.Forte@Sun.COM " Device Paths:\n"));
2883*7836SJohn.Forte@Sun.COM while (dl_multi) {
2884*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5578,
2885*7836SJohn.Forte@Sun.COM " %s\n"),
2886*7836SJohn.Forte@Sun.COM dl_multi->logical_path);
2887*7836SJohn.Forte@Sun.COM dl_multi = dl_multi->next;
2888*7836SJohn.Forte@Sun.COM }
2889*7836SJohn.Forte@Sun.COM }
2890*7836SJohn.Forte@Sun.COM }
2891*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\n");
2892*7836SJohn.Forte@Sun.COM }
2893*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5579,
2894*7836SJohn.Forte@Sun.COM "\nPlease verify the above list of devices"
2895*7836SJohn.Forte@Sun.COM " and\nthen enter 'c' or <CR> to Continue"
2896*7836SJohn.Forte@Sun.COM " or 'q' to Quit. [Default: c]: "));
2897*7836SJohn.Forte@Sun.COM
2898*7836SJohn.Forte@Sun.COM /* Get the user input and continue accordingly. */
2899*7836SJohn.Forte@Sun.COM for (;;) {
2900*7836SJohn.Forte@Sun.COM (void) gets(choice);
2901*7836SJohn.Forte@Sun.COM if (choice[0] == 'c' || choice[0] == 'C' ||
2902*7836SJohn.Forte@Sun.COM choice[0] == 'q' || choice[0] == 'Q' ||
2903*7836SJohn.Forte@Sun.COM choice[0] == '\0') {
2904*7836SJohn.Forte@Sun.COM break;
2905*7836SJohn.Forte@Sun.COM }
2906*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5580,
2907*7836SJohn.Forte@Sun.COM " Enter an appropriate option [c,<CR>,q]: "));
2908*7836SJohn.Forte@Sun.COM }
2909*7836SJohn.Forte@Sun.COM
2910*7836SJohn.Forte@Sun.COM if (choice[0] == 'q' || choice[0] == 'Q') {
2911*7836SJohn.Forte@Sun.COM return (-1);
2912*7836SJohn.Forte@Sun.COM }
2913*7836SJohn.Forte@Sun.COM return (0);
2914*7836SJohn.Forte@Sun.COM }
2915*7836SJohn.Forte@Sun.COM
2916*7836SJohn.Forte@Sun.COM
2917*7836SJohn.Forte@Sun.COM static int
h_find_new_device_link(char * device_dir,timestruc_t lastmtim)2918*7836SJohn.Forte@Sun.COM h_find_new_device_link(char *device_dir, timestruc_t lastmtim)
2919*7836SJohn.Forte@Sun.COM {
2920*7836SJohn.Forte@Sun.COM struct stat dsk_stat;
2921*7836SJohn.Forte@Sun.COM char lname[MAXPATHLEN], link[MAXPATHLEN];
2922*7836SJohn.Forte@Sun.COM char *link_ptr;
2923*7836SJohn.Forte@Sun.COM DIR *dir;
2924*7836SJohn.Forte@Sun.COM struct dirent *dirent;
2925*7836SJohn.Forte@Sun.COM int found_newlink = 0;
2926*7836SJohn.Forte@Sun.COM
2927*7836SJohn.Forte@Sun.COM
2928*7836SJohn.Forte@Sun.COM if ((dir = opendir(device_dir)) == NULL) {
2929*7836SJohn.Forte@Sun.COM if (errno == ENOENT) {
2930*7836SJohn.Forte@Sun.COM return (0);
2931*7836SJohn.Forte@Sun.COM } else {
2932*7836SJohn.Forte@Sun.COM return (L_READ_DEV_DIR_ERROR);
2933*7836SJohn.Forte@Sun.COM }
2934*7836SJohn.Forte@Sun.COM }
2935*7836SJohn.Forte@Sun.COM
2936*7836SJohn.Forte@Sun.COM while ((dirent = readdir(dir)) != (struct dirent *)NULL) {
2937*7836SJohn.Forte@Sun.COM if (strcmp(dirent->d_name, ".") == 0 ||
2938*7836SJohn.Forte@Sun.COM strcmp(dirent->d_name, "..") == 0) {
2939*7836SJohn.Forte@Sun.COM continue;
2940*7836SJohn.Forte@Sun.COM }
2941*7836SJohn.Forte@Sun.COM (void) sprintf(lname, "%s/%s", device_dir, dirent->d_name);
2942*7836SJohn.Forte@Sun.COM if (lstat(lname, &dsk_stat) < 0) {
2943*7836SJohn.Forte@Sun.COM (void) print_errString(L_LSTAT_ES_DIR_ERROR,
2944*7836SJohn.Forte@Sun.COM lname);
2945*7836SJohn.Forte@Sun.COM continue;
2946*7836SJohn.Forte@Sun.COM }
2947*7836SJohn.Forte@Sun.COM if (readlink((const char *)lname, (char *)link,
2948*7836SJohn.Forte@Sun.COM (size_t)MAXPATHLEN) <= 0) {
2949*7836SJohn.Forte@Sun.COM (void) print_errString(L_SYMLINK_ERROR, lname);
2950*7836SJohn.Forte@Sun.COM continue;
2951*7836SJohn.Forte@Sun.COM }
2952*7836SJohn.Forte@Sun.COM
2953*7836SJohn.Forte@Sun.COM /*
2954*7836SJohn.Forte@Sun.COM * "link" can be a relative pathname. But, since
2955*7836SJohn.Forte@Sun.COM * g_get_path_type() only accepts absolute paths, we
2956*7836SJohn.Forte@Sun.COM * will skip to the part where "/devices/" begins and pass a
2957*7836SJohn.Forte@Sun.COM * pointer from there. Since "link" is got from readlink(),
2958*7836SJohn.Forte@Sun.COM * it is unlikely that it will not have /devices string, but
2959*7836SJohn.Forte@Sun.COM * we will check for it anyways.
2960*7836SJohn.Forte@Sun.COM */
2961*7836SJohn.Forte@Sun.COM if (!(link_ptr = strstr(link, "/devices/")))
2962*7836SJohn.Forte@Sun.COM continue;
2963*7836SJohn.Forte@Sun.COM if (!g_get_path_type(link_ptr)) {
2964*7836SJohn.Forte@Sun.COM continue;
2965*7836SJohn.Forte@Sun.COM }
2966*7836SJohn.Forte@Sun.COM if (NEWER(dsk_stat.st_ctim, lastmtim)) {
2967*7836SJohn.Forte@Sun.COM found_newlink++;
2968*7836SJohn.Forte@Sun.COM if (found_newlink == 1) {
2969*7836SJohn.Forte@Sun.COM if (! (strcmp(device_dir, DEV_DSK_DIR))) {
2970*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, MSGSTR(5561,
2971*7836SJohn.Forte@Sun.COM " New Logical Nodes under "
2972*7836SJohn.Forte@Sun.COM "/dev/dsk and /dev/rdsk :\n"));
2973*7836SJohn.Forte@Sun.COM } else { /* device_dir is /dev/rmt */
2974*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "New Logical "
2975*7836SJohn.Forte@Sun.COM "Node under /dev/rmt:\n");
2976*7836SJohn.Forte@Sun.COM }
2977*7836SJohn.Forte@Sun.COM }
2978*7836SJohn.Forte@Sun.COM (void) fprintf(stdout, "\t%s\n", dirent->d_name);
2979*7836SJohn.Forte@Sun.COM }
2980*7836SJohn.Forte@Sun.COM }
2981*7836SJohn.Forte@Sun.COM closedir(dir);
2982*7836SJohn.Forte@Sun.COM return (found_newlink);
2983*7836SJohn.Forte@Sun.COM }
2984*7836SJohn.Forte@Sun.COM
2985*7836SJohn.Forte@Sun.COM
2986*7836SJohn.Forte@Sun.COM /*
2987*7836SJohn.Forte@Sun.COM * prints the device state.
2988*7836SJohn.Forte@Sun.COM *
2989*7836SJohn.Forte@Sun.COM * RETURNS:
2990*7836SJohn.Forte@Sun.COM * None.
2991*7836SJohn.Forte@Sun.COM */
2992*7836SJohn.Forte@Sun.COM void
print_dev_state(char * devname,int state)2993*7836SJohn.Forte@Sun.COM print_dev_state(char *devname, int state)
2994*7836SJohn.Forte@Sun.COM {
2995*7836SJohn.Forte@Sun.COM (void) printf("\t%s: ", devname);
2996*7836SJohn.Forte@Sun.COM if (state & DEVICE_ONLINE) {
2997*7836SJohn.Forte@Sun.COM (void) printf(MSGSTR(3000, "Online"));
2998*7836SJohn.Forte@Sun.COM if (state & DEVICE_BUSY) {
2999*7836SJohn.Forte@Sun.COM (void) printf(" ");
3000*7836SJohn.Forte@Sun.COM (void) printf(MSGSTR(37, "Busy"));
3001*7836SJohn.Forte@Sun.COM }
3002*7836SJohn.Forte@Sun.COM if (state & DEVICE_DOWN) {
3003*7836SJohn.Forte@Sun.COM (void) printf(" ");
3004*7836SJohn.Forte@Sun.COM (void) printf(MSGSTR(118, "Down"));
3005*7836SJohn.Forte@Sun.COM }
3006*7836SJohn.Forte@Sun.COM } else {
3007*7836SJohn.Forte@Sun.COM if (state & DEVICE_OFFLINE) {
3008*7836SJohn.Forte@Sun.COM (void) printf(MSGSTR(3001, "Offline"));
3009*7836SJohn.Forte@Sun.COM if (state & DEVICE_DOWN) {
3010*7836SJohn.Forte@Sun.COM (void) printf(" ");
3011*7836SJohn.Forte@Sun.COM (void) printf(MSGSTR(118, "Down"));
3012*7836SJohn.Forte@Sun.COM }
3013*7836SJohn.Forte@Sun.COM }
3014*7836SJohn.Forte@Sun.COM }
3015*7836SJohn.Forte@Sun.COM (void) printf("\n");
3016*7836SJohn.Forte@Sun.COM }
3017*7836SJohn.Forte@Sun.COM
3018*7836SJohn.Forte@Sun.COM
3019*7836SJohn.Forte@Sun.COM /*
3020*7836SJohn.Forte@Sun.COM * prints the bus state.
3021*7836SJohn.Forte@Sun.COM *
3022*7836SJohn.Forte@Sun.COM * RETURNS:
3023*7836SJohn.Forte@Sun.COM * None.
3024*7836SJohn.Forte@Sun.COM */
3025*7836SJohn.Forte@Sun.COM void
print_bus_state(char * devname,int state)3026*7836SJohn.Forte@Sun.COM print_bus_state(char *devname, int state)
3027*7836SJohn.Forte@Sun.COM {
3028*7836SJohn.Forte@Sun.COM (void) printf("\t%s: ", devname);
3029*7836SJohn.Forte@Sun.COM if (state == BUS_QUIESCED) {
3030*7836SJohn.Forte@Sun.COM (void) printf(MSGSTR(3002, "Quiesced"));
3031*7836SJohn.Forte@Sun.COM } else if (state == BUS_ACTIVE) {
3032*7836SJohn.Forte@Sun.COM (void) printf(MSGSTR(39, "Active"));
3033*7836SJohn.Forte@Sun.COM } else if (state == BUS_SHUTDOWN) {
3034*7836SJohn.Forte@Sun.COM (void) printf(MSGSTR(3003, "Shutdown"));
3035*7836SJohn.Forte@Sun.COM }
3036*7836SJohn.Forte@Sun.COM (void) printf("\n");
3037*7836SJohn.Forte@Sun.COM }
3038