1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <wchar.h>
28 #include <strings.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <libintl.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <assert.h>
37 #include <libnvpair.h>
38 #include <pthread.h>
39 #include <syslog.h>
40 #include <libstmf.h>
41 #include <netinet/in.h>
42 #include <inttypes.h>
43 #include <store.h>
44 #include <locale.h>
45 #include <math.h>
46 #include <libstmf_impl.h>
47 #include <sys/stmf_ioctl.h>
48 #include <sys/stmf_sbd_ioctl.h>
49 #include <sys/pppt_ioctl.h>
50 #include <macros.h>
51
52 #define STMF_PATH "/devices/pseudo/stmf@0:admin"
53 #define SBD_PATH "/devices/pseudo/stmf_sbd@0:admin"
54 #define PPPT_PATH "/devices/pseudo/pppt@0:pppt"
55
56 #define EUI "eui."
57 #define WWN "wwn."
58 #define IQN "iqn."
59 #define LU_ASCII_GUID_SIZE 32
60 #define LU_GUID_SIZE 16
61 #define OUI_ASCII_SIZE 6
62 #define HOST_ID_ASCII_SIZE 8
63 #define OUI_SIZE 3
64 #define HOST_ID_SIZE 4
65 #define IDENT_LENGTH_BYTE 3
66
67 /* various initial allocation values */
68 #define ALLOC_LU 8192
69 #define ALLOC_TARGET_PORT 2048
70 #define ALLOC_PROVIDER 64
71 #define ALLOC_GROUP 2048
72 #define ALLOC_SESSION 2048
73 #define ALLOC_VE 256
74 #define ALLOC_PP_DATA_SIZE 128*1024
75 #define ALLOC_GRP_MEMBER 256
76
77 #define MAX_ISCSI_NAME 223
78 #define MAX_SERIAL_SIZE 252 + 1
79 #define MAX_LU_ALIAS_SIZE 256
80 #define MAX_SBD_PROPS MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
81
82 #define OPEN_STMF 0
83 #define OPEN_EXCL_STMF O_EXCL
84
85 #define OPEN_SBD 0
86 #define OPEN_EXCL_SBD O_EXCL
87
88 #define OPEN_PPPT 0
89 #define OPEN_EXCL_PPPT O_EXCL
90
91 #define LOGICAL_UNIT_TYPE 0
92 #define TARGET_TYPE 1
93 #define STMF_SERVICE_TYPE 2
94
95 #define HOST_GROUP 1
96 #define TARGET_GROUP 2
97
98 /* set default persistence here */
99 #define STMF_DEFAULT_PERSIST STMF_PERSIST_SMF
100
101 #define MAX_PROVIDER_RETRY 30
102
103 static int openStmf(int, int *fd);
104 static int openSbd(int, int *fd);
105 static int openPppt(int, int *fd);
106 static int groupIoctl(int fd, int cmd, stmfGroupName *);
107 static int loadStore(int fd);
108 static int initializeConfig();
109 static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *);
110 static int guidCompare(const void *, const void *);
111 static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *);
112 static int loadHostGroups(int fd, stmfGroupList *);
113 static int loadTargetGroups(int fd, stmfGroupList *);
114 static int getStmfState(stmf_state_desc_t *);
115 static int setStmfState(int fd, stmf_state_desc_t *, int);
116 static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *);
117 static int createDiskResource(luResourceImpl *);
118 static int createDiskLu(diskResource *, stmfGuid *);
119 static int deleteDiskLu(stmfGuid *luGuid);
120 static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *);
121 static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl);
122 static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *);
123 static int removeGuidFromDiskStore(stmfGuid *);
124 static int addGuidToDiskStore(stmfGuid *, char *);
125 static int persistDiskGuid(stmfGuid *, char *, boolean_t);
126 static int setDiskProp(luResourceImpl *, uint32_t, const char *);
127 static int getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen);
128 static int checkHexUpper(char *);
129 static int strToShift(const char *);
130 static int niceStrToNum(const char *, uint64_t *);
131 static void diskError(uint32_t, int *);
132 static int importDiskLu(char *fname, stmfGuid *);
133 static int modifyDiskLu(diskResource *, stmfGuid *, const char *);
134 static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *);
135 static int validateModifyDiskProp(uint32_t);
136 static uint8_t iGetPersistMethod();
137 static int groupListIoctl(stmfGroupList **, int);
138 static int iLoadGroupFromPs(stmfGroupList **, int);
139 static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int);
140 static int getProviderData(char *, nvlist_t **, int, uint64_t *);
141 static int setDiskStandby(stmfGuid *luGuid);
142 static int setDiskGlobalProp(uint32_t, const char *);
143 static int viewEntryCompare(const void *, const void *);
144 static void deleteNonActiveLus();
145 static int loadStmfProp(int fd);
146
147 static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER;
148 static int iPersistType = 0;
149 /* when B_TRUE, no need to access SMF anymore. Just use iPersistType */
150 static boolean_t iLibSetPersist = B_FALSE;
151
152 /*
153 * Open for stmf module
154 *
155 * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
156 * fd - pointer to integer. On success, contains the stmf file descriptor
157 */
158 static int
159 openStmf(int flag, int *fd)
160 {
161 int ret = STMF_STATUS_ERROR;
162
163 if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
164 ret = STMF_STATUS_SUCCESS;
165 } else {
166 if (errno == EBUSY) {
167 ret = STMF_ERROR_BUSY;
168 } else if (errno == EACCES) {
169 ret = STMF_ERROR_PERM;
170 } else {
171 ret = STMF_STATUS_ERROR;
172 }
173 syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
174 STMF_PATH, errno);
175 }
176
177 return (ret);
178 }
179
180 /*
181 * Open for sbd module
182 *
183 * flag - open flag (OPEN_SBD, OPEN_EXCL_SBD)
184 * fd - pointer to integer. On success, contains the stmf file descriptor
185 */
186 static int
187 openSbd(int flag, int *fd)
188 {
189 int ret = STMF_STATUS_ERROR;
190
191 if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
192 ret = STMF_STATUS_SUCCESS;
193 } else {
194 if (errno == EBUSY) {
195 ret = STMF_ERROR_BUSY;
196 } else if (errno == EACCES) {
197 ret = STMF_ERROR_PERM;
198 } else {
199 ret = STMF_STATUS_ERROR;
200 }
201 syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)",
202 SBD_PATH, errno);
203 }
204
205 return (ret);
206 }
207
208 /*
209 * Open for pppt module
210 *
211 * flag - open flag (OPEN_PPPT, OPEN_EXCL_PPPT)
212 * fd - pointer to integer. On success, contains the stmf file descriptor
213 */
214 static int
215 openPppt(int flag, int *fd)
216 {
217 int ret = STMF_STATUS_ERROR;
218
219 if ((*fd = open(PPPT_PATH, O_RDONLY | flag)) != -1) {
220 ret = STMF_STATUS_SUCCESS;
221 } else {
222 if (errno == EBUSY) {
223 ret = STMF_ERROR_BUSY;
224 } else if (errno == EACCES) {
225 ret = STMF_ERROR_PERM;
226 } else {
227 ret = STMF_STATUS_ERROR;
228 }
229 syslog(LOG_DEBUG, "openPppt:open failure:%s:errno(%d)",
230 PPPT_PATH, errno);
231 }
232
233 return (ret);
234 }
235
236 /*
237 * initializeConfig
238 *
239 * This routine should be called before any ioctl requiring initialization
240 * which is basically everything except stmfGetState(), setStmfState() and
241 * stmfLoadConfig().
242 */
243 static int
244 initializeConfig()
245 {
246 int ret;
247 stmfState state;
248
249
250 ret = stmfGetState(&state);
251 if (ret != STMF_STATUS_SUCCESS) {
252 return (ret);
253 }
254
255 /* if we've already initialized or in the process, return success */
256 if (state.configState == STMF_CONFIG_STATE_INIT_DONE ||
257 state.configState == STMF_CONFIG_STATE_INIT) {
258 return (STMF_STATUS_SUCCESS);
259 }
260
261 ret = stmfLoadConfig();
262 if (ret != STMF_STATUS_SUCCESS) {
263 syslog(LOG_DEBUG,
264 "initializeConfig:stmfLoadConfig:error(%d)", ret);
265 return (ret);
266 }
267
268 ret = stmfGetState(&state);
269 if (ret != STMF_STATUS_SUCCESS) {
270 syslog(LOG_DEBUG,
271 "initializeConfig:stmfGetState:error(%d)", ret);
272 return (ret);
273 }
274
275 if (state.configState != STMF_CONFIG_STATE_INIT_DONE) {
276 syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)",
277 state.configState);
278 ret = STMF_STATUS_ERROR;
279 }
280
281 return (ret);
282 }
283
284
285 /*
286 * groupIoctl
287 *
288 * Purpose: issue ioctl for create/delete on group
289 *
290 * cmd - valid STMF ioctl group cmd
291 * groupName - groupName to create or delete
292 */
293 static int
294 groupIoctl(int fd, int cmd, stmfGroupName *groupName)
295 {
296 int ret = STMF_STATUS_SUCCESS;
297 int ioctlRet;
298 stmf_iocdata_t stmfIoctl;
299 stmf_group_name_t iGroupName;
300
301 bzero(&iGroupName, sizeof (iGroupName));
302
303 bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
304
305 iGroupName.name_size = strlen((char *)groupName);
306
307 bzero(&stmfIoctl, sizeof (stmfIoctl));
308 /*
309 * Issue ioctl to create the host group
310 */
311 stmfIoctl.stmf_version = STMF_VERSION_1;
312 stmfIoctl.stmf_ibuf_size = sizeof (iGroupName);
313 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
314 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
315 if (ioctlRet != 0) {
316 switch (errno) {
317 case EPERM:
318 case EACCES:
319 ret = STMF_ERROR_PERM;
320 break;
321 default:
322 switch (stmfIoctl.stmf_error) {
323 case STMF_IOCERR_TG_EXISTS:
324 case STMF_IOCERR_HG_EXISTS:
325 ret = STMF_ERROR_EXISTS;
326 break;
327 case STMF_IOCERR_TG_IN_USE:
328 case STMF_IOCERR_HG_IN_USE:
329 ret = STMF_ERROR_GROUP_IN_USE;
330 break;
331 case STMF_IOCERR_INVALID_HG:
332 case STMF_IOCERR_INVALID_TG:
333 ret = STMF_ERROR_NOT_FOUND;
334 break;
335 default:
336 syslog(LOG_DEBUG,
337 "groupIoctl:error(%d)",
338 stmfIoctl.stmf_error);
339 ret = STMF_STATUS_ERROR;
340 break;
341 }
342 break;
343 }
344 }
345 done:
346 return (ret);
347 }
348
349 /*
350 * groupMemberIoctl
351 *
352 * Purpose: issue ioctl for add/remove member on group
353 *
354 * cmd - valid STMF ioctl group member cmd
355 * groupName - groupName to add to or remove from
356 * devid - group member to add or remove
357 */
358 static int
359 groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid)
360 {
361 int ret = STMF_STATUS_SUCCESS;
362 int ioctlRet;
363 stmf_iocdata_t stmfIoctl;
364 stmf_group_op_data_t stmfGroupData;
365
366 bzero(&stmfGroupData, sizeof (stmfGroupData));
367
368 bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName));
369
370 stmfGroupData.group.name_size = strlen((char *)groupName);
371 stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength;
372 bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1],
373 devid->identLength);
374
375 bzero(&stmfIoctl, sizeof (stmfIoctl));
376 /*
377 * Issue ioctl to add to the host group
378 */
379 stmfIoctl.stmf_version = STMF_VERSION_1;
380 stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData);
381 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData;
382 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
383 if (ioctlRet != 0) {
384 switch (errno) {
385 case EBUSY:
386 switch (stmfIoctl.stmf_error) {
387 case STMF_IOCERR_TG_NEED_TG_OFFLINE:
388 ret = STMF_ERROR_TG_ONLINE;
389 break;
390 default:
391 ret = STMF_ERROR_BUSY;
392 break;
393 }
394 break;
395 case EPERM:
396 case EACCES:
397 ret = STMF_ERROR_PERM;
398 break;
399 default:
400 switch (stmfIoctl.stmf_error) {
401 case STMF_IOCERR_TG_ENTRY_EXISTS:
402 case STMF_IOCERR_HG_ENTRY_EXISTS:
403 ret = STMF_ERROR_EXISTS;
404 break;
405 case STMF_IOCERR_INVALID_TG_ENTRY:
406 case STMF_IOCERR_INVALID_HG_ENTRY:
407 ret =
408 STMF_ERROR_MEMBER_NOT_FOUND;
409 break;
410 case STMF_IOCERR_INVALID_TG:
411 case STMF_IOCERR_INVALID_HG:
412 ret =
413 STMF_ERROR_GROUP_NOT_FOUND;
414 break;
415 default:
416 syslog(LOG_DEBUG,
417 "groupMemberIoctl:error"
418 "(%d)",
419 stmfIoctl.stmf_error);
420 ret = STMF_STATUS_ERROR;
421 break;
422 }
423 break;
424 }
425 }
426 done:
427 return (ret);
428 }
429
430 /*
431 * qsort function
432 * sort on veIndex
433 */
434 static int
435 viewEntryCompare(const void *p1, const void *p2)
436 {
437
438 stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
439 if (v1->veIndex > v2->veIndex)
440 return (1);
441 if (v1->veIndex < v2->veIndex)
442 return (-1);
443 return (0);
444 }
445
446 /*
447 * guidCompare
448 *
449 * qsort function
450 * sort on guid
451 */
452 static int
453 guidCompare(const void *p1, const void *p2)
454 {
455
456 stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2;
457 int i;
458
459 for (i = 0; i < sizeof (stmfGuid); i++) {
460 if (g1->guid[i] > g2->guid[i])
461 return (1);
462 if (g1->guid[i] < g2->guid[i])
463 return (-1);
464 }
465
466 return (0);
467 }
468
469 /*
470 * stmfAddToHostGroup
471 *
472 * Purpose: Adds an initiator to an existing host group
473 *
474 * hostGroupName - name of an existing host group
475 * hostName - name of initiator to add
476 */
477 int
478 stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
479 {
480 int ret;
481 int fd;
482
483 if (hostGroupName == NULL ||
484 (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
485 == sizeof (stmfGroupName)) || hostName == NULL) {
486 return (STMF_ERROR_INVALID_ARG);
487 }
488
489 /* call init */
490 ret = initializeConfig();
491 if (ret != STMF_STATUS_SUCCESS) {
492 return (ret);
493 }
494
495 /*
496 * Open control node for stmf
497 */
498 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
499 return (ret);
500
501 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName,
502 hostName)) != STMF_STATUS_SUCCESS) {
503 goto done;
504 }
505
506 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
507 goto done;
508 }
509
510 ret = psAddHostGroupMember((char *)hostGroupName,
511 (char *)hostName->ident);
512 switch (ret) {
513 case STMF_PS_SUCCESS:
514 ret = STMF_STATUS_SUCCESS;
515 break;
516 case STMF_PS_ERROR_EXISTS:
517 ret = STMF_ERROR_EXISTS;
518 break;
519 case STMF_PS_ERROR_GROUP_NOT_FOUND:
520 ret = STMF_ERROR_GROUP_NOT_FOUND;
521 break;
522 case STMF_PS_ERROR_BUSY:
523 ret = STMF_ERROR_BUSY;
524 break;
525 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
526 ret = STMF_ERROR_SERVICE_NOT_FOUND;
527 break;
528 case STMF_PS_ERROR_VERSION_MISMATCH:
529 ret = STMF_ERROR_SERVICE_DATA_VERSION;
530 break;
531 default:
532 syslog(LOG_DEBUG,
533 "stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
534 ret);
535 ret = STMF_STATUS_ERROR;
536 break;
537 }
538
539 done:
540 (void) close(fd);
541 return (ret);
542 }
543
544 /*
545 * stmfAddToTargetGroup
546 *
547 * Purpose: Adds a local port to an existing target group
548 *
549 * targetGroupName - name of an existing target group
550 * targetName - name of target to add
551 */
552 int
553 stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
554 {
555 int ret;
556 int fd;
557
558 if (targetGroupName == NULL ||
559 (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
560 == sizeof (stmfGroupName)) || targetName == NULL) {
561 return (STMF_ERROR_INVALID_ARG);
562 }
563
564 /* call init */
565 ret = initializeConfig();
566 if (ret != STMF_STATUS_SUCCESS) {
567 return (ret);
568 }
569
570 /*
571 * Open control node for stmf
572 */
573 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
574 return (ret);
575
576 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
577 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
578 goto done;
579 }
580
581 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
582 goto done;
583 }
584
585 ret = psAddTargetGroupMember((char *)targetGroupName,
586 (char *)targetName->ident);
587 switch (ret) {
588 case STMF_PS_SUCCESS:
589 ret = STMF_STATUS_SUCCESS;
590 break;
591 case STMF_PS_ERROR_EXISTS:
592 ret = STMF_ERROR_EXISTS;
593 break;
594 case STMF_PS_ERROR_GROUP_NOT_FOUND:
595 ret = STMF_ERROR_GROUP_NOT_FOUND;
596 break;
597 case STMF_PS_ERROR_BUSY:
598 ret = STMF_ERROR_BUSY;
599 break;
600 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
601 ret = STMF_ERROR_SERVICE_NOT_FOUND;
602 break;
603 case STMF_PS_ERROR_VERSION_MISMATCH:
604 ret = STMF_ERROR_SERVICE_DATA_VERSION;
605 break;
606 default:
607 syslog(LOG_DEBUG,
608 "stmfAddToTargetGroup:psAddTargetGroupMember:"
609 "error(%d)", ret);
610 ret = STMF_STATUS_ERROR;
611 break;
612 }
613
614 done:
615 (void) close(fd);
616 return (ret);
617 }
618
619 /*
620 * addViewEntryIoctl
621 *
622 * Purpose: Issues ioctl to add a view entry
623 *
624 * lu - Logical Unit identifier to which the view entry is added
625 * viewEntry - view entry to add
626 * init - When set to B_TRUE, we are in the init state, i.e. don't call open
627 */
628 static int
629 addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry)
630 {
631 int ret = STMF_STATUS_SUCCESS;
632 int ioctlRet;
633 stmf_iocdata_t stmfIoctl;
634 stmf_view_op_entry_t ioctlViewEntry;
635
636 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
637 /*
638 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
639 * false on input
640 */
641 ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
642 ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
643 ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
644
645 if (viewEntry->allHosts == B_FALSE) {
646 bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
647 sizeof (stmfGroupName));
648 ioctlViewEntry.ve_host_group.name_size =
649 strlen((char *)viewEntry->hostGroup);
650 }
651 if (viewEntry->allTargets == B_FALSE) {
652 bcopy(viewEntry->targetGroup,
653 &ioctlViewEntry.ve_target_group.name,
654 sizeof (stmfGroupName));
655 ioctlViewEntry.ve_target_group.name_size =
656 strlen((char *)viewEntry->targetGroup);
657 }
658 if (viewEntry->luNbrValid) {
659 bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
660 sizeof (ioctlViewEntry.ve_lu_nbr));
661 }
662 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
663
664 bzero(&stmfIoctl, sizeof (stmfIoctl));
665 /*
666 * Issue ioctl to add to the view entry
667 */
668 stmfIoctl.stmf_version = STMF_VERSION_1;
669 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
670 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
671 stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
672 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
673 ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl);
674 if (ioctlRet != 0) {
675 switch (errno) {
676 case EBUSY:
677 ret = STMF_ERROR_BUSY;
678 break;
679 case EPERM:
680 ret = STMF_ERROR_PERM;
681 break;
682 case EACCES:
683 switch (stmfIoctl.stmf_error) {
684 case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
685 ret = STMF_ERROR_CONFIG_NONE;
686 break;
687 default:
688 ret = STMF_ERROR_PERM;
689 break;
690 }
691 break;
692 default:
693 switch (stmfIoctl.stmf_error) {
694 case STMF_IOCERR_LU_NUMBER_IN_USE:
695 ret = STMF_ERROR_LUN_IN_USE;
696 break;
697 case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
698 ret = STMF_ERROR_VE_CONFLICT;
699 break;
700 case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
701 ret = STMF_ERROR_CONFIG_NONE;
702 break;
703 case STMF_IOCERR_INVALID_HG:
704 ret = STMF_ERROR_INVALID_HG;
705 break;
706 case STMF_IOCERR_INVALID_TG:
707 ret = STMF_ERROR_INVALID_TG;
708 break;
709 default:
710 syslog(LOG_DEBUG,
711 "addViewEntryIoctl"
712 ":error(%d)",
713 stmfIoctl.stmf_error);
714 ret = STMF_STATUS_ERROR;
715 break;
716 }
717 break;
718 }
719 goto done;
720 }
721
722 /* copy lu nbr back to caller's view entry on success */
723 viewEntry->veIndex = ioctlViewEntry.ve_ndx;
724 if (ioctlViewEntry.ve_lu_number_valid) {
725 bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
726 sizeof (ioctlViewEntry.ve_lu_nbr));
727 }
728 viewEntry->luNbrValid = B_TRUE;
729
730 done:
731 return (ret);
732 }
733
734 /*
735 * stmfAddViewEntry
736 *
737 * Purpose: Adds a view entry to a logical unit
738 *
739 * lu - guid of the logical unit to which the view entry is added
740 * viewEntry - view entry structure to add
741 */
742 int
743 stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
744 {
745 int ret;
746 int fd;
747 stmfViewEntry iViewEntry;
748
749 if (lu == NULL || viewEntry == NULL) {
750 return (STMF_ERROR_INVALID_ARG);
751 }
752
753 /* initialize and set internal view entry */
754 bzero(&iViewEntry, sizeof (iViewEntry));
755
756 if (!viewEntry->allHosts) {
757 bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
758 sizeof (iViewEntry.hostGroup));
759 } else {
760 iViewEntry.allHosts = B_TRUE;
761 }
762
763 if (!viewEntry->allTargets) {
764 bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
765 sizeof (iViewEntry.targetGroup));
766 } else {
767 iViewEntry.allTargets = B_TRUE;
768 }
769
770 if (viewEntry->luNbrValid) {
771 iViewEntry.luNbrValid = B_TRUE;
772 bcopy(viewEntry->luNbr, iViewEntry.luNbr,
773 sizeof (iViewEntry.luNbr));
774 }
775
776 /*
777 * set users return view entry index valid flag to false
778 * in case of failure
779 */
780 viewEntry->veIndexValid = B_FALSE;
781
782 /* Check to ensure service exists */
783 if (psCheckService() != STMF_STATUS_SUCCESS) {
784 return (STMF_ERROR_SERVICE_NOT_FOUND);
785 }
786
787 /* call init */
788 ret = initializeConfig();
789 if (ret != STMF_STATUS_SUCCESS) {
790 return (ret);
791 }
792
793 /*
794 * Open control node for stmf
795 */
796 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
797 return (ret);
798
799 /*
800 * First add the view entry to the driver
801 */
802 ret = addViewEntryIoctl(fd, lu, &iViewEntry);
803 if (ret != STMF_STATUS_SUCCESS) {
804 goto done;
805 }
806
807 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
808 goto done;
809 }
810
811 /*
812 * If the add to driver was successful, add it to the persistent
813 * store.
814 */
815 ret = psAddViewEntry(lu, &iViewEntry);
816 switch (ret) {
817 case STMF_PS_SUCCESS:
818 ret = STMF_STATUS_SUCCESS;
819 break;
820 case STMF_PS_ERROR_NOT_FOUND:
821 ret = STMF_ERROR_NOT_FOUND;
822 break;
823 case STMF_PS_ERROR_BUSY:
824 ret = STMF_ERROR_BUSY;
825 break;
826 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
827 ret = STMF_ERROR_SERVICE_NOT_FOUND;
828 break;
829 case STMF_PS_ERROR_VERSION_MISMATCH:
830 ret = STMF_ERROR_SERVICE_DATA_VERSION;
831 break;
832 default:
833 syslog(LOG_DEBUG,
834 "stmfAddViewEntry:psAddViewEntry:error(%d)", ret);
835 ret = STMF_STATUS_ERROR;
836 break;
837 }
838
839 done:
840 (void) close(fd);
841
842 if (ret == STMF_STATUS_SUCCESS) {
843 /* set caller's view entry on success */
844 viewEntry->veIndexValid = iViewEntry.veIndexValid;
845 viewEntry->veIndex = iViewEntry.veIndex;
846 viewEntry->luNbrValid = B_TRUE;
847 bcopy(iViewEntry.luNbr, viewEntry->luNbr,
848 sizeof (iViewEntry.luNbr));
849 }
850 return (ret);
851 }
852
853 /*
854 * stmfClearProviderData
855 *
856 * Purpose: delete all provider data for specified provider
857 *
858 * providerName - name of provider for which data should be deleted
859 */
860 int
861 stmfClearProviderData(char *providerName, int providerType)
862 {
863 int ret;
864 int fd;
865 int ioctlRet;
866 int savedErrno;
867 stmf_iocdata_t stmfIoctl;
868 stmf_ppioctl_data_t ppi;
869
870 /* call init */
871 ret = initializeConfig();
872 if (ret != STMF_STATUS_SUCCESS) {
873 return (ret);
874 }
875
876 if (providerName == NULL) {
877 return (STMF_ERROR_INVALID_ARG);
878 }
879
880 if (providerType != STMF_LU_PROVIDER_TYPE &&
881 providerType != STMF_PORT_PROVIDER_TYPE) {
882 return (STMF_ERROR_INVALID_ARG);
883 }
884
885 /*
886 * Open control node for stmf
887 */
888 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
889 return (ret);
890
891 bzero(&ppi, sizeof (ppi));
892
893 (void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name));
894
895 switch (providerType) {
896 case STMF_LU_PROVIDER_TYPE:
897 ppi.ppi_lu_provider = 1;
898 break;
899 case STMF_PORT_PROVIDER_TYPE:
900 ppi.ppi_port_provider = 1;
901 break;
902 default:
903 ret = STMF_ERROR_INVALID_ARG;
904 goto done;
905 }
906
907 bzero(&stmfIoctl, sizeof (stmfIoctl));
908
909 stmfIoctl.stmf_version = STMF_VERSION_1;
910 stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
911 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
912
913 ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl);
914 if (ioctlRet != 0) {
915 savedErrno = errno;
916 switch (savedErrno) {
917 case EBUSY:
918 ret = STMF_ERROR_BUSY;
919 break;
920 case EPERM:
921 case EACCES:
922 ret = STMF_ERROR_PERM;
923 break;
924 default:
925 syslog(LOG_DEBUG,
926 "stmfClearProviderData:ioctl error(%d)",
927 ioctlRet);
928 ret = STMF_STATUS_ERROR;
929 break;
930 }
931 if (savedErrno != ENOENT) {
932 goto done;
933 }
934 }
935
936 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
937 goto done;
938 }
939
940 ret = psClearProviderData(providerName, providerType);
941 switch (ret) {
942 case STMF_PS_SUCCESS:
943 ret = STMF_STATUS_SUCCESS;
944 break;
945 case STMF_PS_ERROR_NOT_FOUND:
946 ret = STMF_ERROR_NOT_FOUND;
947 break;
948 case STMF_PS_ERROR_BUSY:
949 ret = STMF_ERROR_BUSY;
950 break;
951 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
952 ret = STMF_ERROR_SERVICE_NOT_FOUND;
953 break;
954 case STMF_PS_ERROR_VERSION_MISMATCH:
955 ret = STMF_ERROR_SERVICE_DATA_VERSION;
956 break;
957 default:
958 syslog(LOG_DEBUG,
959 "stmfClearProviderData:psClearProviderData"
960 ":error(%d)", ret);
961 ret = STMF_STATUS_ERROR;
962 break;
963 }
964
965 done:
966 (void) close(fd);
967 return (ret);
968 }
969
970 /*
971 * stmfCreateHostGroup
972 *
973 * Purpose: Create a new initiator group
974 *
975 * hostGroupName - name of host group to create
976 */
977 int
978 stmfCreateHostGroup(stmfGroupName *hostGroupName)
979 {
980 int ret;
981 int fd;
982
983 if (hostGroupName == NULL ||
984 (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
985 == sizeof (stmfGroupName))) {
986 return (STMF_ERROR_INVALID_ARG);
987 }
988
989 /* Check to ensure service exists */
990 if (psCheckService() != STMF_STATUS_SUCCESS) {
991 return (STMF_ERROR_SERVICE_NOT_FOUND);
992 }
993
994 /* call init */
995 ret = initializeConfig();
996 if (ret != STMF_STATUS_SUCCESS) {
997 return (ret);
998 }
999
1000 /*
1001 * Open control node for stmf
1002 */
1003 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1004 return (ret);
1005
1006 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
1007 hostGroupName)) != STMF_STATUS_SUCCESS) {
1008 goto done;
1009 }
1010
1011 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
1012 goto done;
1013 }
1014
1015 ret = psCreateHostGroup((char *)hostGroupName);
1016 switch (ret) {
1017 case STMF_PS_SUCCESS:
1018 ret = STMF_STATUS_SUCCESS;
1019 break;
1020 case STMF_PS_ERROR_EXISTS:
1021 ret = STMF_ERROR_EXISTS;
1022 break;
1023 case STMF_PS_ERROR_BUSY:
1024 ret = STMF_ERROR_BUSY;
1025 break;
1026 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1027 ret = STMF_ERROR_SERVICE_NOT_FOUND;
1028 break;
1029 case STMF_PS_ERROR_VERSION_MISMATCH:
1030 ret = STMF_ERROR_SERVICE_DATA_VERSION;
1031 break;
1032 default:
1033 syslog(LOG_DEBUG,
1034 "stmfCreateHostGroup:psCreateHostGroup:error(%d)",
1035 ret);
1036 ret = STMF_STATUS_ERROR;
1037 break;
1038 }
1039
1040 done:
1041 (void) close(fd);
1042 return (ret);
1043 }
1044
1045 /*
1046 * stmfCreateLu
1047 *
1048 * Purpose: Create a logical unit
1049 *
1050 * hdl - handle to logical unit resource created via stmfCreateLuResource
1051 *
1052 * luGuid - If non-NULL, on success, contains the guid of the created logical
1053 * unit
1054 */
1055 int
1056 stmfCreateLu(luResource hdl, stmfGuid *luGuid)
1057 {
1058 int ret = STMF_STATUS_SUCCESS;
1059 luResourceImpl *luPropsHdl = hdl;
1060
1061 if (hdl == NULL) {
1062 return (STMF_ERROR_INVALID_ARG);
1063 }
1064
1065 if (luPropsHdl->type == STMF_DISK) {
1066 ret = createDiskLu((diskResource *)luPropsHdl->resource,
1067 luGuid);
1068 } else {
1069 return (STMF_ERROR_INVALID_ARG);
1070 }
1071
1072 return (ret);
1073 }
1074
1075 /*
1076 * stmfCreateLuResource
1077 *
1078 * Purpose: Create resource handle for a logical unit
1079 *
1080 * dType - Type of logical unit resource to create
1081 * Can be: STMF_DISK
1082 *
1083 * hdl - pointer to luResource
1084 */
1085 int
1086 stmfCreateLuResource(uint16_t dType, luResource *hdl)
1087 {
1088 int ret = STMF_STATUS_SUCCESS;
1089
1090 if (dType != STMF_DISK || hdl == NULL) {
1091 return (STMF_ERROR_INVALID_ARG);
1092 }
1093
1094 *hdl = calloc(1, sizeof (luResourceImpl));
1095 if (*hdl == NULL) {
1096 return (STMF_ERROR_NOMEM);
1097 }
1098
1099 ret = createDiskResource((luResourceImpl *)*hdl);
1100 if (ret != STMF_STATUS_SUCCESS) {
1101 free(*hdl);
1102 return (ret);
1103 }
1104
1105 return (STMF_STATUS_SUCCESS);
1106 }
1107
1108 /*
1109 * Creates a disk logical unit
1110 *
1111 * disk - pointer to diskResource structure that represents the properties
1112 * for the disk logical unit to be created.
1113 */
1114 static int
1115 createDiskLu(diskResource *disk, stmfGuid *createdGuid)
1116 {
1117 int ret = STMF_STATUS_SUCCESS;
1118 int dataFileNameLen = 0;
1119 int metaFileNameLen = 0;
1120 int serialNumLen = 0;
1121 int luAliasLen = 0;
1122 int luMgmtUrlLen = 0;
1123 int sluBufSize = 0;
1124 int bufOffset = 0;
1125 int fd = 0;
1126 int ioctlRet;
1127 int savedErrno;
1128 stmfGuid guid;
1129 stmf_iocdata_t sbdIoctl = {0};
1130
1131 sbd_create_and_reg_lu_t *sbdLu = NULL;
1132
1133 /*
1134 * Open control node for sbd
1135 */
1136 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1137 return (ret);
1138
1139 /* data file name must be specified */
1140 if (disk->luDataFileNameValid) {
1141 dataFileNameLen = strlen(disk->luDataFileName);
1142 } else {
1143 (void) close(fd);
1144 return (STMF_ERROR_MISSING_PROP_VAL);
1145 }
1146
1147 sluBufSize += dataFileNameLen + 1;
1148
1149 if (disk->luMetaFileNameValid) {
1150 metaFileNameLen = strlen(disk->luMetaFileName);
1151 sluBufSize += metaFileNameLen + 1;
1152 }
1153
1154 serialNumLen = strlen(disk->serialNum);
1155 sluBufSize += serialNumLen;
1156
1157 if (disk->luAliasValid) {
1158 luAliasLen = strlen(disk->luAlias);
1159 sluBufSize += luAliasLen + 1;
1160 }
1161
1162 if (disk->luMgmtUrlValid) {
1163 luMgmtUrlLen = strlen(disk->luMgmtUrl);
1164 sluBufSize += luMgmtUrlLen + 1;
1165 }
1166
1167 /*
1168 * 8 is the size of the buffer set aside for
1169 * concatenation of variable length fields
1170 */
1171 sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
1172 sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
1173 if (sbdLu == NULL) {
1174 return (STMF_ERROR_NOMEM);
1175 }
1176
1177 sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
1178 sluBufSize - 8;
1179
1180 if (metaFileNameLen) {
1181 sbdLu->slu_meta_fname_valid = 1;
1182 sbdLu->slu_meta_fname_off = bufOffset;
1183 bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
1184 metaFileNameLen + 1);
1185 bufOffset += metaFileNameLen + 1;
1186 }
1187
1188 bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
1189 dataFileNameLen + 1);
1190 sbdLu->slu_data_fname_off = bufOffset;
1191 bufOffset += dataFileNameLen + 1;
1192
1193 /* currently, serial # is not passed null terminated to the driver */
1194 if (disk->serialNumValid) {
1195 sbdLu->slu_serial_valid = 1;
1196 sbdLu->slu_serial_off = bufOffset;
1197 sbdLu->slu_serial_size = serialNumLen;
1198 bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
1199 serialNumLen);
1200 bufOffset += serialNumLen;
1201 }
1202
1203 if (disk->luAliasValid) {
1204 sbdLu->slu_alias_valid = 1;
1205 sbdLu->slu_alias_off = bufOffset;
1206 bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
1207 luAliasLen + 1);
1208 bufOffset += luAliasLen + 1;
1209 }
1210
1211 if (disk->luMgmtUrlValid) {
1212 sbdLu->slu_mgmt_url_valid = 1;
1213 sbdLu->slu_mgmt_url_off = bufOffset;
1214 bcopy(disk->luMgmtUrl, &(sbdLu->slu_buf[bufOffset]),
1215 luMgmtUrlLen + 1);
1216 bufOffset += luMgmtUrlLen + 1;
1217 }
1218
1219 if (disk->luSizeValid) {
1220 sbdLu->slu_lu_size_valid = 1;
1221 sbdLu->slu_lu_size = disk->luSize;
1222 }
1223
1224 if (disk->luGuidValid) {
1225 sbdLu->slu_guid_valid = 1;
1226 bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
1227 }
1228
1229 if (disk->vidValid) {
1230 sbdLu->slu_vid_valid = 1;
1231 bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
1232 }
1233
1234 if (disk->pidValid) {
1235 sbdLu->slu_pid_valid = 1;
1236 bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
1237 }
1238
1239 if (disk->revValid) {
1240 sbdLu->slu_rev_valid = 1;
1241 bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
1242 }
1243
1244 if (disk->companyIdValid) {
1245 sbdLu->slu_company_id_valid = 1;
1246 sbdLu->slu_company_id = disk->companyId;
1247 }
1248
1249 if (disk->hostIdValid) {
1250 sbdLu->slu_host_id_valid = 1;
1251 sbdLu->slu_host_id = disk->hostId;
1252 }
1253
1254 if (disk->blkSizeValid) {
1255 sbdLu->slu_blksize_valid = 1;
1256 sbdLu->slu_blksize = disk->blkSize;
1257 }
1258
1259 if (disk->writeProtectEnableValid) {
1260 if (disk->writeProtectEnable) {
1261 sbdLu->slu_write_protected = 1;
1262 }
1263 }
1264
1265 if (disk->unmapValid) {
1266 sbdLu->slu_unmap_valid = 1;
1267 if (disk->unmap) {
1268 sbdLu->slu_unmap = 1;
1269 }
1270 }
1271
1272 if (disk->writebackCacheDisableValid) {
1273 sbdLu->slu_writeback_cache_disable_valid = 1;
1274 if (disk->writebackCacheDisable) {
1275 sbdLu->slu_writeback_cache_disable = 1;
1276 }
1277 }
1278
1279 sbdIoctl.stmf_version = STMF_VERSION_1;
1280 sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
1281 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1282 sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
1283 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
1284
1285 ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
1286 if (ioctlRet != 0) {
1287 savedErrno = errno;
1288 switch (savedErrno) {
1289 case EBUSY:
1290 ret = STMF_ERROR_BUSY;
1291 break;
1292 case EPERM:
1293 case EACCES:
1294 ret = STMF_ERROR_PERM;
1295 break;
1296 default:
1297 diskError(sbdIoctl.stmf_error, &ret);
1298 if (ret == STMF_STATUS_ERROR) {
1299 syslog(LOG_DEBUG,
1300 "createDiskLu:ioctl "
1301 "error(%d) (%d) (%d)", ioctlRet,
1302 sbdIoctl.stmf_error, savedErrno);
1303 }
1304 break;
1305 }
1306 }
1307
1308 if (ret != STMF_STATUS_SUCCESS) {
1309 goto done;
1310 }
1311
1312 /*
1313 * on success, copy the resulting guid into the caller's guid if not
1314 * NULL
1315 */
1316 if (createdGuid) {
1317 bcopy(sbdLu->slu_guid, createdGuid->guid,
1318 sizeof (sbdLu->slu_guid));
1319 }
1320
1321 bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid));
1322 if (disk->luMetaFileNameValid) {
1323 ret = addGuidToDiskStore(&guid, disk->luMetaFileName);
1324 } else {
1325 ret = addGuidToDiskStore(&guid, disk->luDataFileName);
1326 }
1327 done:
1328 free(sbdLu);
1329 (void) close(fd);
1330 return (ret);
1331 }
1332
1333
1334 /*
1335 * stmfImportLu
1336 *
1337 * Purpose: Import a previously created logical unit
1338 *
1339 * dType - Type of logical unit
1340 * Can be: STMF_DISK
1341 *
1342 * luGuid - If non-NULL, on success, contains the guid of the imported logical
1343 * unit
1344 *
1345 * fname - A file name where the metadata resides
1346 *
1347 */
1348 int
1349 stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid)
1350 {
1351 int ret = STMF_STATUS_SUCCESS;
1352
1353 if (dType == STMF_DISK) {
1354 ret = importDiskLu(fname, luGuid);
1355 } else {
1356 return (STMF_ERROR_INVALID_ARG);
1357 }
1358
1359 return (ret);
1360 }
1361
1362 /*
1363 * importDiskLu
1364 *
1365 * filename - filename to import
1366 * createdGuid - if not NULL, on success contains the imported guid
1367 *
1368 */
1369 static int
1370 importDiskLu(char *fname, stmfGuid *createdGuid)
1371 {
1372 int ret = STMF_STATUS_SUCCESS;
1373 int fd = 0;
1374 int ioctlRet;
1375 int savedErrno;
1376 int metaFileNameLen;
1377 stmfGuid iGuid;
1378 int iluBufSize = 0;
1379 sbd_import_lu_t *sbdLu = NULL;
1380 stmf_iocdata_t sbdIoctl = {0};
1381
1382 if (fname == NULL) {
1383 return (STMF_ERROR_INVALID_ARG);
1384 }
1385
1386 /*
1387 * Open control node for sbd
1388 */
1389 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1390 return (ret);
1391
1392 metaFileNameLen = strlen(fname);
1393 iluBufSize += metaFileNameLen + 1;
1394
1395 /*
1396 * 8 is the size of the buffer set aside for
1397 * concatenation of variable length fields
1398 */
1399 sbdLu = (sbd_import_lu_t *)calloc(1,
1400 sizeof (sbd_import_lu_t) + iluBufSize - 8);
1401 if (sbdLu == NULL) {
1402 (void) close(fd);
1403 return (STMF_ERROR_NOMEM);
1404 }
1405
1406 /*
1407 * Accept either a data file or meta data file.
1408 * sbd will do the right thing here either way.
1409 * i.e. if it's a data file, it assumes that the
1410 * meta data is shared with the data.
1411 */
1412 (void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen);
1413
1414 sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8;
1415
1416 sbdIoctl.stmf_version = STMF_VERSION_1;
1417 sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size;
1418 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1419 sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size;
1420 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
1421
1422 ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl);
1423 if (ioctlRet != 0) {
1424
1425 if (createdGuid && sbdIoctl.stmf_error ==
1426 SBD_RET_FILE_ALREADY_REGISTERED) {
1427 bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
1428 sizeof (sbdLu->ilu_ret_guid));
1429 }
1430
1431 savedErrno = errno;
1432 switch (savedErrno) {
1433 case EBUSY:
1434 ret = STMF_ERROR_BUSY;
1435 break;
1436 case EPERM:
1437 case EACCES:
1438 ret = STMF_ERROR_PERM;
1439 break;
1440 default:
1441 diskError(sbdIoctl.stmf_error, &ret);
1442 if (ret == STMF_STATUS_ERROR) {
1443 syslog(LOG_DEBUG,
1444 "importDiskLu:ioctl "
1445 "error(%d) (%d) (%d)", ioctlRet,
1446 sbdIoctl.stmf_error, savedErrno);
1447 }
1448 break;
1449 }
1450 }
1451
1452
1453 if (ret != STMF_STATUS_SUCCESS) {
1454 goto done;
1455 }
1456
1457 /*
1458 * on success, copy the resulting guid into the caller's guid if not
1459 * NULL and add it to the persistent store for sbd
1460 */
1461 if (createdGuid) {
1462 bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
1463 sizeof (sbdLu->ilu_ret_guid));
1464 ret = addGuidToDiskStore(createdGuid, fname);
1465 } else {
1466 bcopy(sbdLu->ilu_ret_guid, iGuid.guid,
1467 sizeof (sbdLu->ilu_ret_guid));
1468 ret = addGuidToDiskStore(&iGuid, fname);
1469 }
1470 done:
1471 free(sbdLu);
1472 (void) close(fd);
1473 return (ret);
1474 }
1475
1476 /*
1477 * diskError
1478 *
1479 * Purpose: Translate sbd driver error
1480 */
1481 static void
1482 diskError(uint32_t stmfError, int *ret)
1483 {
1484 switch (stmfError) {
1485 case SBD_RET_META_CREATION_FAILED:
1486 case SBD_RET_ZFS_META_CREATE_FAILED:
1487 *ret = STMF_ERROR_META_CREATION;
1488 break;
1489 case SBD_RET_INVALID_BLKSIZE:
1490 *ret = STMF_ERROR_INVALID_BLKSIZE;
1491 break;
1492 case SBD_RET_FILE_ALREADY_REGISTERED:
1493 *ret = STMF_ERROR_FILE_IN_USE;
1494 break;
1495 case SBD_RET_GUID_ALREADY_REGISTERED:
1496 *ret = STMF_ERROR_GUID_IN_USE;
1497 break;
1498 case SBD_RET_META_PATH_NOT_ABSOLUTE:
1499 case SBD_RET_META_FILE_LOOKUP_FAILED:
1500 case SBD_RET_META_FILE_OPEN_FAILED:
1501 case SBD_RET_META_FILE_GETATTR_FAILED:
1502 case SBD_RET_NO_META:
1503 *ret = STMF_ERROR_META_FILE_NAME;
1504 break;
1505 case SBD_RET_DATA_PATH_NOT_ABSOLUTE:
1506 case SBD_RET_DATA_FILE_LOOKUP_FAILED:
1507 case SBD_RET_DATA_FILE_OPEN_FAILED:
1508 case SBD_RET_DATA_FILE_GETATTR_FAILED:
1509 *ret = STMF_ERROR_DATA_FILE_NAME;
1510 break;
1511 case SBD_RET_FILE_SIZE_ERROR:
1512 *ret = STMF_ERROR_FILE_SIZE_INVALID;
1513 break;
1514 case SBD_RET_SIZE_OUT_OF_RANGE:
1515 *ret = STMF_ERROR_SIZE_OUT_OF_RANGE;
1516 break;
1517 case SBD_RET_LU_BUSY:
1518 *ret = STMF_ERROR_LU_BUSY;
1519 break;
1520 case SBD_RET_WRITE_CACHE_SET_FAILED:
1521 *ret = STMF_ERROR_WRITE_CACHE_SET;
1522 break;
1523 case SBD_RET_UNMAP_SET_FAILED:
1524 *ret = STMF_ERROR_UNMAP_SET;
1525 break;
1526 case SBD_RET_ACCESS_STATE_FAILED:
1527 *ret = STMF_ERROR_ACCESS_STATE_SET;
1528 break;
1529 default:
1530 *ret = STMF_STATUS_ERROR;
1531 break;
1532 }
1533 }
1534
1535 /*
1536 * Creates a logical unit resource of type STMF_DISK.
1537 *
1538 * No defaults should be set here as all defaults are derived from the
1539 * driver's default settings.
1540 */
1541 static int
1542 createDiskResource(luResourceImpl *hdl)
1543 {
1544 hdl->type = STMF_DISK;
1545
1546 hdl->resource = calloc(1, sizeof (diskResource));
1547 if (hdl->resource == NULL) {
1548 return (STMF_ERROR_NOMEM);
1549 }
1550
1551 return (STMF_STATUS_SUCCESS);
1552 }
1553
1554 /*
1555 * stmfDeleteLu
1556 *
1557 * Purpose: Delete a logical unit
1558 *
1559 * hdl - handle to logical unit resource created via stmfCreateLuResource
1560 *
1561 * luGuid - If non-NULL, on success, contains the guid of the created logical
1562 * unit
1563 */
1564 int
1565 stmfDeleteLu(stmfGuid *luGuid)
1566 {
1567 int ret = STMF_STATUS_SUCCESS;
1568 stmfLogicalUnitProperties luProps;
1569
1570 if (luGuid == NULL) {
1571 return (STMF_ERROR_INVALID_ARG);
1572 }
1573
1574 /* Check logical unit provider name to call correct dtype function */
1575 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1576 != STMF_STATUS_SUCCESS) {
1577 return (ret);
1578 } else {
1579 if (strcmp(luProps.providerName, "sbd") == 0) {
1580 ret = deleteDiskLu(luGuid);
1581 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1582 return (STMF_ERROR_NOT_FOUND);
1583 } else {
1584 return (STMF_ERROR_INVALID_ARG);
1585 }
1586 }
1587
1588 return (ret);
1589 }
1590
1591 static int
1592 deleteDiskLu(stmfGuid *luGuid)
1593 {
1594 int ret = STMF_STATUS_SUCCESS;
1595 int fd;
1596 int savedErrno;
1597 int ioctlRet;
1598 sbd_delete_lu_t deleteLu = {0};
1599
1600 stmf_iocdata_t sbdIoctl = {0};
1601
1602 /*
1603 * Open control node for sbd
1604 */
1605 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1606 return (ret);
1607
1608 ret = removeGuidFromDiskStore(luGuid);
1609 if (ret != STMF_STATUS_SUCCESS) {
1610 goto done;
1611 }
1612
1613 bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid));
1614 deleteLu.dlu_by_guid = 1;
1615
1616 sbdIoctl.stmf_version = STMF_VERSION_1;
1617 sbdIoctl.stmf_ibuf_size = sizeof (deleteLu);
1618 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu;
1619 ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl);
1620 if (ioctlRet != 0) {
1621 savedErrno = errno;
1622 switch (savedErrno) {
1623 case EBUSY:
1624 ret = STMF_ERROR_BUSY;
1625 break;
1626 case EPERM:
1627 case EACCES:
1628 ret = STMF_ERROR_PERM;
1629 break;
1630 case ENOENT:
1631 ret = STMF_ERROR_NOT_FOUND;
1632 break;
1633 default:
1634 syslog(LOG_DEBUG,
1635 "deleteDiskLu:ioctl error(%d) (%d) (%d)",
1636 ioctlRet, sbdIoctl.stmf_error, savedErrno);
1637 ret = STMF_STATUS_ERROR;
1638 break;
1639 }
1640 }
1641
1642 done:
1643 (void) close(fd);
1644 return (ret);
1645 }
1646
1647 /*
1648 * stmfLuStandby
1649 *
1650 * Purpose: Sets access state to standby
1651 *
1652 * luGuid - guid of registered logical unit
1653 *
1654 */
1655 int
1656 stmfLuStandby(stmfGuid *luGuid)
1657 {
1658 int ret = STMF_STATUS_SUCCESS;
1659 stmfLogicalUnitProperties luProps;
1660
1661 if (luGuid == NULL) {
1662 return (STMF_ERROR_INVALID_ARG);
1663 }
1664
1665 /* Check logical unit provider name to call correct dtype function */
1666 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1667 != STMF_STATUS_SUCCESS) {
1668 return (ret);
1669 } else {
1670 if (strcmp(luProps.providerName, "sbd") == 0) {
1671 ret = setDiskStandby(luGuid);
1672 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1673 return (STMF_ERROR_NOT_FOUND);
1674 } else {
1675 return (STMF_ERROR_INVALID_ARG);
1676 }
1677 }
1678
1679 return (ret);
1680 }
1681
1682 static int
1683 setDiskStandby(stmfGuid *luGuid)
1684 {
1685 int ret = STMF_STATUS_SUCCESS;
1686 stmf_iocdata_t sbdIoctl = {0};
1687 sbd_set_lu_standby_t sbdLu = {0};
1688 int ioctlRet;
1689 int savedErrno;
1690 int fd = 0;
1691
1692 /*
1693 * Open control node for sbd
1694 */
1695 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1696 return (ret);
1697
1698 bcopy(luGuid, &sbdLu.stlu_guid, sizeof (stmfGuid));
1699
1700 sbdIoctl.stmf_version = STMF_VERSION_1;
1701 sbdIoctl.stmf_ibuf_size = sizeof (sbd_set_lu_standby_t);
1702 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&sbdLu;
1703
1704 ioctlRet = ioctl(fd, SBD_IOCTL_SET_LU_STANDBY, &sbdIoctl);
1705 if (ioctlRet != 0) {
1706 savedErrno = errno;
1707 switch (savedErrno) {
1708 case EBUSY:
1709 ret = STMF_ERROR_BUSY;
1710 break;
1711 case EPERM:
1712 case EACCES:
1713 ret = STMF_ERROR_PERM;
1714 break;
1715 default:
1716 diskError(sbdIoctl.stmf_error, &ret);
1717 if (ret == STMF_STATUS_ERROR) {
1718 syslog(LOG_DEBUG,
1719 "setDiskStandby:ioctl "
1720 "error(%d) (%d) (%d)", ioctlRet,
1721 sbdIoctl.stmf_error, savedErrno);
1722 }
1723 break;
1724 }
1725 }
1726 (void) close(fd);
1727 return (ret);
1728 }
1729
1730 /*
1731 * stmfModifyLu
1732 *
1733 * Purpose: Modify properties of a logical unit
1734 *
1735 * luGuid - guid of registered logical unit
1736 * prop - property to modify
1737 * propVal - property value to set
1738 *
1739 */
1740 int
1741 stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal)
1742 {
1743 int ret = STMF_STATUS_SUCCESS;
1744 stmfLogicalUnitProperties luProps;
1745
1746 if (luGuid == NULL) {
1747 return (STMF_ERROR_INVALID_ARG);
1748 }
1749
1750 /* Check logical unit provider name to call correct dtype function */
1751 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1752 != STMF_STATUS_SUCCESS) {
1753 return (ret);
1754 } else {
1755 if (strcmp(luProps.providerName, "sbd") == 0) {
1756 ret = modifyDiskLuProp(luGuid, NULL, prop, propVal);
1757 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1758 return (STMF_ERROR_NOT_FOUND);
1759 } else {
1760 return (STMF_ERROR_INVALID_ARG);
1761 }
1762 }
1763
1764 return (ret);
1765 }
1766
1767 /*
1768 * stmfModifyLuByFname
1769 *
1770 * Purpose: Modify a device by filename. Device does not need to be registered.
1771 *
1772 * dType - type of device to modify
1773 * STMF_DISK
1774 *
1775 * fname - filename or meta filename
1776 * prop - valid property identifier
1777 * propVal - property value
1778 *
1779 */
1780 int
1781 stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
1782 const char *propVal)
1783 {
1784 int ret = STMF_STATUS_SUCCESS;
1785 if (fname == NULL) {
1786 return (STMF_ERROR_INVALID_ARG);
1787 }
1788
1789 if (dType == STMF_DISK) {
1790 ret = modifyDiskLuProp(NULL, fname, prop, propVal);
1791 } else {
1792 return (STMF_ERROR_INVALID_ARG);
1793 }
1794
1795 return (ret);
1796 }
1797
1798 static int
1799 modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop,
1800 const char *propVal)
1801 {
1802 int ret = STMF_STATUS_SUCCESS;
1803 luResource hdl = NULL;
1804 luResourceImpl *luPropsHdl;
1805
1806 ret = stmfCreateLuResource(STMF_DISK, &hdl);
1807 if (ret != STMF_STATUS_SUCCESS) {
1808 return (ret);
1809 }
1810 ret = validateModifyDiskProp(prop);
1811 if (ret != STMF_STATUS_SUCCESS) {
1812 (void) stmfFreeLuResource(hdl);
1813 return (STMF_ERROR_INVALID_PROP);
1814 }
1815 ret = stmfSetLuProp(hdl, prop, propVal);
1816 if (ret != STMF_STATUS_SUCCESS) {
1817 (void) stmfFreeLuResource(hdl);
1818 return (ret);
1819 }
1820 luPropsHdl = hdl;
1821 ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname);
1822 (void) stmfFreeLuResource(hdl);
1823 return (ret);
1824 }
1825
1826 static int
1827 validateModifyDiskProp(uint32_t prop)
1828 {
1829 switch (prop) {
1830 case STMF_LU_PROP_ALIAS:
1831 case STMF_LU_PROP_SIZE:
1832 case STMF_LU_PROP_MGMT_URL:
1833 case STMF_LU_PROP_WRITE_PROTECT:
1834 case STMF_LU_PROP_WRITE_CACHE_DISABLE:
1835 case STMF_LU_PROP_UNMAP:
1836 return (STMF_STATUS_SUCCESS);
1837 break;
1838 default:
1839 return (STMF_STATUS_ERROR);
1840 break;
1841 }
1842 }
1843
1844 static int
1845 modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname)
1846 {
1847 int ret = STMF_STATUS_SUCCESS;
1848 int luAliasLen = 0;
1849 int luMgmtUrlLen = 0;
1850 int mluBufSize = 0;
1851 int bufOffset = 0;
1852 int fd = 0;
1853 int ioctlRet;
1854 int savedErrno;
1855 int fnameSize = 0;
1856 stmf_iocdata_t sbdIoctl = {0};
1857
1858 sbd_modify_lu_t *sbdLu = NULL;
1859
1860 if (luGuid == NULL && fname == NULL) {
1861 return (STMF_ERROR_INVALID_ARG);
1862 }
1863
1864 if (fname) {
1865 fnameSize = strlen(fname) + 1;
1866 mluBufSize += fnameSize;
1867 }
1868
1869 /*
1870 * Open control node for sbd
1871 */
1872 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1873 return (ret);
1874
1875 if (disk->luAliasValid) {
1876 luAliasLen = strlen(disk->luAlias);
1877 mluBufSize += luAliasLen + 1;
1878 }
1879
1880 if (disk->luMgmtUrlValid) {
1881 luMgmtUrlLen = strlen(disk->luMgmtUrl);
1882 mluBufSize += luMgmtUrlLen + 1;
1883 }
1884
1885 /*
1886 * 8 is the size of the buffer set aside for
1887 * concatenation of variable length fields
1888 */
1889 sbdLu = (sbd_modify_lu_t *)calloc(1,
1890 sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize);
1891 if (sbdLu == NULL) {
1892 (void) close(fd);
1893 return (STMF_ERROR_NOMEM);
1894 }
1895
1896 sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) +
1897 mluBufSize - 8 + fnameSize;
1898
1899 if (disk->luAliasValid) {
1900 sbdLu->mlu_alias_valid = 1;
1901 sbdLu->mlu_alias_off = bufOffset;
1902 bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]),
1903 luAliasLen + 1);
1904 bufOffset += luAliasLen + 1;
1905 }
1906
1907 if (disk->luMgmtUrlValid) {
1908 sbdLu->mlu_mgmt_url_valid = 1;
1909 sbdLu->mlu_mgmt_url_off = bufOffset;
1910 bcopy(disk->luMgmtUrl, &(sbdLu->mlu_buf[bufOffset]),
1911 luMgmtUrlLen + 1);
1912 bufOffset += luMgmtUrlLen + 1;
1913 }
1914
1915 if (disk->luSizeValid) {
1916 sbdLu->mlu_lu_size_valid = 1;
1917 sbdLu->mlu_lu_size = disk->luSize;
1918 }
1919
1920 if (disk->unmapValid) {
1921 sbdLu->mlu_unmap_valid = 1;
1922 if (disk->unmap)
1923 sbdLu->mlu_unmap = 1;
1924 }
1925
1926 if (disk->writeProtectEnableValid) {
1927 sbdLu->mlu_write_protected_valid = 1;
1928 if (disk->writeProtectEnable) {
1929 sbdLu->mlu_write_protected = 1;
1930 }
1931 }
1932
1933 if (disk->writebackCacheDisableValid) {
1934 sbdLu->mlu_writeback_cache_disable_valid = 1;
1935 if (disk->writebackCacheDisable) {
1936 sbdLu->mlu_writeback_cache_disable = 1;
1937 }
1938 }
1939
1940 if (luGuid) {
1941 bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid));
1942 sbdLu->mlu_by_guid = 1;
1943 } else {
1944 sbdLu->mlu_fname_off = bufOffset;
1945 bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1);
1946 sbdLu->mlu_by_fname = 1;
1947 }
1948
1949 sbdIoctl.stmf_version = STMF_VERSION_1;
1950 sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size;
1951 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1952
1953 ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl);
1954 if (ioctlRet != 0) {
1955 savedErrno = errno;
1956 switch (savedErrno) {
1957 case EBUSY:
1958 ret = STMF_ERROR_BUSY;
1959 break;
1960 case EPERM:
1961 case EACCES:
1962 ret = STMF_ERROR_PERM;
1963 break;
1964 default:
1965 diskError(sbdIoctl.stmf_error, &ret);
1966 if (ret == STMF_STATUS_ERROR) {
1967 syslog(LOG_DEBUG,
1968 "modifyDiskLu:ioctl "
1969 "error(%d) (%d) (%d)", ioctlRet,
1970 sbdIoctl.stmf_error, savedErrno);
1971 }
1972 break;
1973 }
1974 }
1975
1976 if (ret != STMF_STATUS_SUCCESS) {
1977 goto done;
1978 }
1979
1980 done:
1981 free(sbdLu);
1982 (void) close(fd);
1983 return (ret);
1984 }
1985
1986 /*
1987 * removeGuidFromDiskStore
1988 *
1989 * Purpose: delete a logical unit from the sbd provider data
1990 */
1991 static int
1992 removeGuidFromDiskStore(stmfGuid *guid)
1993 {
1994 return (persistDiskGuid(guid, NULL, B_FALSE));
1995 }
1996
1997
1998 /*
1999 * addGuidToDiskStore
2000 *
2001 * Purpose: add a logical unit to the sbd provider data
2002 */
2003 static int
2004 addGuidToDiskStore(stmfGuid *guid, char *filename)
2005 {
2006 return (persistDiskGuid(guid, filename, B_TRUE));
2007 }
2008
2009
2010 /*
2011 * persistDiskGuid
2012 *
2013 * Purpose: Persist or unpersist a guid for the sbd provider data
2014 *
2015 */
2016 static int
2017 persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist)
2018 {
2019 char guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0};
2020 nvlist_t *nvl = NULL;
2021
2022 uint64_t setToken;
2023 boolean_t retryGetProviderData = B_FALSE;
2024 boolean_t newData = B_FALSE;
2025 int ret = STMF_STATUS_SUCCESS;
2026 int retryCnt = 0;
2027 int stmfRet;
2028
2029 /* if we're persisting a guid, there must be a filename */
2030 if (persist && !filename) {
2031 return (1);
2032 }
2033
2034 /* guid is stored in lowercase ascii hex */
2035 (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
2036 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
2037 "%02x%02x%02x%02x%02x%02x",
2038 guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3],
2039 guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7],
2040 guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11],
2041 guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]);
2042
2043
2044 do {
2045 retryGetProviderData = B_FALSE;
2046 stmfRet = stmfGetProviderDataProt("sbd", &nvl,
2047 STMF_LU_PROVIDER_TYPE, &setToken);
2048 if (stmfRet != STMF_STATUS_SUCCESS) {
2049 if (persist && stmfRet == STMF_ERROR_NOT_FOUND) {
2050 ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
2051 if (ret != 0) {
2052 syslog(LOG_DEBUG,
2053 "unpersistGuid:nvlist_alloc(%d)",
2054 ret);
2055 ret = STMF_STATUS_ERROR;
2056 goto done;
2057 }
2058 newData = B_TRUE;
2059 } else {
2060 /*
2061 * if we're persisting the data, it's
2062 * an error. Otherwise, just return
2063 */
2064 if (persist) {
2065 ret = stmfRet;
2066 }
2067 goto done;
2068 }
2069 }
2070 if (persist) {
2071 ret = nvlist_add_string(nvl, guidAsciiBuf, filename);
2072 } else {
2073 ret = nvlist_remove(nvl, guidAsciiBuf,
2074 DATA_TYPE_STRING);
2075 if (ret == ENOENT) {
2076 ret = 0;
2077 }
2078 }
2079 if (ret == 0) {
2080 if (newData) {
2081 stmfRet = stmfSetProviderDataProt("sbd", nvl,
2082 STMF_LU_PROVIDER_TYPE, NULL);
2083 } else {
2084 stmfRet = stmfSetProviderDataProt("sbd", nvl,
2085 STMF_LU_PROVIDER_TYPE, &setToken);
2086 }
2087 if (stmfRet != STMF_STATUS_SUCCESS) {
2088 if (stmfRet == STMF_ERROR_BUSY) {
2089 /* get/set failed, try again */
2090 retryGetProviderData = B_TRUE;
2091 if (retryCnt++ > MAX_PROVIDER_RETRY) {
2092 ret = stmfRet;
2093 break;
2094 }
2095 continue;
2096 } else if (stmfRet ==
2097 STMF_ERROR_PROV_DATA_STALE) {
2098 /* update failed, try again */
2099 nvlist_free(nvl);
2100 nvl = NULL;
2101 retryGetProviderData = B_TRUE;
2102 if (retryCnt++ > MAX_PROVIDER_RETRY) {
2103 ret = stmfRet;
2104 break;
2105 }
2106 continue;
2107 } else {
2108 syslog(LOG_DEBUG,
2109 "unpersistGuid:error(%x)", stmfRet);
2110 ret = stmfRet;
2111 }
2112 break;
2113 }
2114 } else {
2115 syslog(LOG_DEBUG,
2116 "unpersistGuid:error nvlist_add/remove(%d)",
2117 ret);
2118 ret = STMF_STATUS_ERROR;
2119 }
2120 } while (retryGetProviderData);
2121
2122 done:
2123 nvlist_free(nvl);
2124 return (ret);
2125 }
2126
2127
2128 /*
2129 * stmfGetLuProp
2130 *
2131 * Purpose: Get current value for a resource property
2132 *
2133 * hdl - luResource from a previous call to stmfCreateLuResource
2134 *
2135 * resourceProp - a valid resource property type
2136 *
2137 * propVal - void pointer to a pointer of the value to be retrieved
2138 */
2139 int
2140 stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen)
2141 {
2142 int ret = STMF_STATUS_SUCCESS;
2143 luResourceImpl *luPropsHdl = hdl;
2144 if (hdl == NULL || propLen == NULL || propVal == NULL) {
2145 return (STMF_ERROR_INVALID_ARG);
2146 }
2147
2148 if (luPropsHdl->type == STMF_DISK) {
2149 ret = getDiskProp(luPropsHdl, prop, propVal, propLen);
2150 } else {
2151 return (STMF_ERROR_INVALID_ARG);
2152 }
2153
2154 return (ret);
2155 }
2156
2157 /*
2158 * stmfGetLuResource
2159 *
2160 * Purpose: Get a logical unit resource handle for a given logical unit.
2161 *
2162 * hdl - pointer to luResource
2163 */
2164 int
2165 stmfGetLuResource(stmfGuid *luGuid, luResource *hdl)
2166 {
2167 int ret = STMF_STATUS_SUCCESS;
2168 stmfLogicalUnitProperties luProps;
2169
2170 if (hdl == NULL) {
2171 return (STMF_ERROR_INVALID_ARG);
2172 }
2173
2174 /* Check logical unit provider name to call correct dtype function */
2175 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
2176 != STMF_STATUS_SUCCESS) {
2177 return (ret);
2178 } else {
2179 if (strcmp(luProps.providerName, "sbd") == 0) {
2180 ret = getDiskAllProps(luGuid, hdl);
2181 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
2182 return (STMF_ERROR_NOT_FOUND);
2183 } else {
2184 return (STMF_ERROR_INVALID_ARG);
2185 }
2186 }
2187
2188 return (ret);
2189 }
2190
2191 /*
2192 * getDiskAllProps
2193 *
2194 * Purpose: load all disk properties from sbd driver
2195 *
2196 * luGuid - guid of disk device for which properties are to be retrieved
2197 * hdl - allocated luResource into which properties are to be copied
2198 *
2199 */
2200 static int
2201 getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
2202 {
2203 int ret = STMF_STATUS_SUCCESS;
2204 int fd;
2205 sbd_lu_props_t *sbdProps;
2206 int ioctlRet;
2207 int savedErrno;
2208 int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
2209 stmf_iocdata_t sbdIoctl = {0};
2210
2211 /*
2212 * Open control node for sbd
2213 */
2214 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
2215 return (ret);
2216
2217
2218 *hdl = calloc(1, sizeof (luResourceImpl));
2219 if (*hdl == NULL) {
2220 (void) close(fd);
2221 return (STMF_ERROR_NOMEM);
2222 }
2223
2224 sbdProps = calloc(1, sbdPropsSize);
2225 if (sbdProps == NULL) {
2226 free(*hdl);
2227 (void) close(fd);
2228 return (STMF_ERROR_NOMEM);
2229 }
2230
2231 ret = createDiskResource((luResourceImpl *)*hdl);
2232 if (ret != STMF_STATUS_SUCCESS) {
2233 free(*hdl);
2234 free(sbdProps);
2235 (void) close(fd);
2236 return (ret);
2237 }
2238
2239 sbdProps->slp_input_guid = 1;
2240 bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
2241
2242 sbdIoctl.stmf_version = STMF_VERSION_1;
2243 sbdIoctl.stmf_ibuf_size = sbdPropsSize;
2244 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
2245 sbdIoctl.stmf_obuf_size = sbdPropsSize;
2246 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
2247 ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
2248 if (ioctlRet != 0) {
2249 savedErrno = errno;
2250 switch (savedErrno) {
2251 case EBUSY:
2252 ret = STMF_ERROR_BUSY;
2253 break;
2254 case EPERM:
2255 case EACCES:
2256 ret = STMF_ERROR_PERM;
2257 break;
2258 case ENOENT:
2259 ret = STMF_ERROR_NOT_FOUND;
2260 break;
2261 default:
2262 syslog(LOG_DEBUG,
2263 "getDiskAllProps:ioctl error(%d) (%d) (%d)",
2264 ioctlRet, sbdIoctl.stmf_error, savedErrno);
2265 ret = STMF_STATUS_ERROR;
2266 break;
2267 }
2268 }
2269
2270 if (ret == STMF_STATUS_SUCCESS) {
2271 ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
2272 }
2273
2274 free(sbdProps);
2275 (void) close(fd);
2276 return (ret);
2277 }
2278
2279 /*
2280 * loadDiskPropsFromDriver
2281 *
2282 * Purpose: Retrieve all disk type properties from sbd driver
2283 *
2284 * hdl - Allocated luResourceImpl
2285 * sbdProps - sbd_lu_props_t structure returned from sbd driver
2286 *
2287 */
2288 static int
2289 loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
2290 {
2291 int ret = STMF_STATUS_SUCCESS;
2292 diskResource *diskLu = hdl->resource;
2293 /* copy guid */
2294 diskLu->luGuidValid = B_TRUE;
2295 bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
2296
2297 if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
2298 diskLu->luMetaFileNameValid = B_TRUE;
2299 if (strlcpy(diskLu->luMetaFileName,
2300 (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
2301 sizeof (diskLu->luMetaFileName)) >=
2302 sizeof (diskLu->luMetaFileName)) {
2303 return (STMF_STATUS_ERROR);
2304 }
2305 }
2306
2307 if (sbdProps->slp_data_fname_valid) {
2308 diskLu->luDataFileNameValid = B_TRUE;
2309 if (strlcpy(diskLu->luDataFileName,
2310 (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
2311 sizeof (diskLu->luDataFileName)) >=
2312 sizeof (diskLu->luDataFileName)) {
2313 return (STMF_STATUS_ERROR);
2314 }
2315 }
2316
2317 if (sbdProps->slp_serial_valid) {
2318 diskLu->serialNumValid = B_TRUE;
2319 bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
2320 diskLu->serialNum, sbdProps->slp_serial_size);
2321 }
2322
2323 if (sbdProps->slp_mgmt_url_valid) {
2324 diskLu->luMgmtUrlValid = B_TRUE;
2325 if (strlcpy(diskLu->luMgmtUrl,
2326 (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]),
2327 sizeof (diskLu->luMgmtUrl)) >=
2328 sizeof (diskLu->luMgmtUrl)) {
2329 return (STMF_STATUS_ERROR);
2330 }
2331 }
2332
2333 if (sbdProps->slp_alias_valid) {
2334 diskLu->luAliasValid = B_TRUE;
2335 if (strlcpy(diskLu->luAlias,
2336 (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
2337 sizeof (diskLu->luAlias)) >=
2338 sizeof (diskLu->luAlias)) {
2339 return (STMF_STATUS_ERROR);
2340 }
2341 } else { /* set alias to data filename if not set */
2342 if (sbdProps->slp_data_fname_valid) {
2343 diskLu->luAliasValid = B_TRUE;
2344 if (strlcpy(diskLu->luAlias,
2345 (char *)&(sbdProps->slp_buf[
2346 sbdProps->slp_data_fname_off]),
2347 sizeof (diskLu->luAlias)) >=
2348 sizeof (diskLu->luAlias)) {
2349 return (STMF_STATUS_ERROR);
2350 }
2351 }
2352 }
2353
2354 diskLu->vidValid = B_TRUE;
2355 bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
2356
2357 diskLu->pidValid = B_TRUE;
2358 bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
2359
2360 diskLu->revValid = B_TRUE;
2361 bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
2362
2363 diskLu->unmapValid = B_TRUE;
2364 if (sbdProps->slp_unmap_cur)
2365 diskLu->unmap = B_TRUE;
2366
2367 diskLu->writeProtectEnableValid = B_TRUE;
2368 if (sbdProps->slp_write_protected) {
2369 diskLu->writeProtectEnable = B_TRUE;
2370 }
2371
2372 diskLu->writebackCacheDisableValid = B_TRUE;
2373 if (sbdProps->slp_writeback_cache_disable_cur) {
2374 diskLu->writebackCacheDisable = B_TRUE;
2375 }
2376
2377 diskLu->blkSizeValid = B_TRUE;
2378 diskLu->blkSize = sbdProps->slp_blksize;
2379
2380 diskLu->luSizeValid = B_TRUE;
2381 diskLu->luSize = sbdProps->slp_lu_size;
2382
2383 diskLu->accessState = sbdProps->slp_access_state;
2384
2385 return (ret);
2386 }
2387
2388 /*
2389 * stmfGetGlobalLuProp
2390 *
2391 * Purpose: get a global property for a device type
2392 *
2393 */
2394 int
2395 stmfGetGlobalLuProp(uint16_t dType, uint32_t prop, char *propVal,
2396 size_t *propLen)
2397 {
2398 int ret = STMF_STATUS_SUCCESS;
2399 if (dType != STMF_DISK || propVal == NULL) {
2400 return (STMF_ERROR_INVALID_ARG);
2401 }
2402
2403 ret = getDiskGlobalProp(prop, propVal, propLen);
2404
2405 return (ret);
2406 }
2407
2408 /*
2409 * getDiskGlobalProp
2410 *
2411 * Purpose: get global property from sbd driver
2412 *
2413 */
2414 static int
2415 getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen)
2416 {
2417 int ret = STMF_STATUS_SUCCESS;
2418 int fd;
2419 sbd_global_props_t *sbdProps;
2420 void *sbd_realloc;
2421 int retryCnt = 0;
2422 boolean_t retry;
2423 int ioctlRet;
2424 int savedErrno;
2425 int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
2426 stmf_iocdata_t sbdIoctl = {0};
2427 size_t reqLen;
2428
2429 switch (prop) {
2430 case STMF_LU_PROP_MGMT_URL:
2431 break;
2432 default:
2433 return (STMF_ERROR_INVALID_PROP);
2434 }
2435
2436 /*
2437 * Open control node for sbd
2438 */
2439 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
2440 return (ret);
2441
2442 sbdProps = calloc(1, sbdPropsSize);
2443 if (sbdProps == NULL) {
2444 (void) close(fd);
2445 return (STMF_ERROR_NOMEM);
2446 }
2447
2448 do {
2449 retry = B_FALSE;
2450 sbdIoctl.stmf_version = STMF_VERSION_1;
2451 sbdIoctl.stmf_obuf_size = sbdPropsSize;
2452 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
2453 ioctlRet = ioctl(fd, SBD_IOCTL_GET_GLOBAL_LU, &sbdIoctl);
2454 if (ioctlRet != 0) {
2455 savedErrno = errno;
2456 switch (savedErrno) {
2457 case EBUSY:
2458 ret = STMF_ERROR_BUSY;
2459 break;
2460 case EPERM:
2461 case EACCES:
2462 ret = STMF_ERROR_PERM;
2463 break;
2464 case ENOMEM:
2465 if (sbdIoctl.stmf_error ==
2466 SBD_RET_INSUFFICIENT_BUF_SPACE &&
2467 retryCnt++ < 3) {
2468 sbdPropsSize =
2469 sizeof (*sbdProps) +
2470 sbdProps->
2471 mlu_buf_size_needed;
2472
2473 sbd_realloc = sbdProps;
2474 sbdProps = realloc(sbdProps,
2475 sbdPropsSize);
2476 if (sbdProps == NULL) {
2477 free(sbd_realloc);
2478 ret = STMF_ERROR_NOMEM;
2479 break;
2480 }
2481 retry = B_TRUE;
2482 } else {
2483 ret = STMF_ERROR_NOMEM;
2484 }
2485 break;
2486 default:
2487 syslog(LOG_DEBUG,
2488 "getDiskGlobalProp:ioctl error(%d)"
2489 "(%d)(%d)", ioctlRet,
2490 sbdIoctl.stmf_error, savedErrno);
2491 ret = STMF_STATUS_ERROR;
2492 break;
2493 }
2494
2495 }
2496 } while (retry);
2497
2498 if (ret != STMF_STATUS_SUCCESS) {
2499 goto done;
2500 }
2501
2502 switch (prop) {
2503 case STMF_LU_PROP_MGMT_URL:
2504 if (sbdProps->mlu_mgmt_url_valid == 0) {
2505 ret = STMF_ERROR_NO_PROP;
2506 goto done;
2507 }
2508 if ((reqLen = strlcpy(propVal, (char *)&(
2509 sbdProps->mlu_buf[sbdProps->mlu_mgmt_url_off]),
2510 *propLen)) >= *propLen) {
2511 *propLen = reqLen + 1;
2512 ret = STMF_ERROR_INVALID_ARG;
2513 goto done;
2514 }
2515 break;
2516 }
2517
2518 done:
2519 free(sbdProps);
2520 (void) close(fd);
2521 return (ret);
2522 }
2523
2524 /*
2525 * stmfSetGlobalLuProp
2526 *
2527 * Purpose: set a global property for a device type
2528 *
2529 */
2530 int
2531 stmfSetGlobalLuProp(uint16_t dType, uint32_t prop, const char *propVal)
2532 {
2533 int ret = STMF_STATUS_SUCCESS;
2534 if (dType != STMF_DISK || propVal == NULL) {
2535 return (STMF_ERROR_INVALID_ARG);
2536 }
2537
2538 ret = setDiskGlobalProp(prop, propVal);
2539
2540 return (ret);
2541 }
2542
2543 /*
2544 * setDiskGlobalProp
2545 *
2546 * Purpose: set properties for resource of type disk
2547 *
2548 * resourceProp - valid resource identifier
2549 * propVal - valid resource value
2550 */
2551 static int
2552 setDiskGlobalProp(uint32_t resourceProp, const char *propVal)
2553 {
2554 int ret = STMF_STATUS_SUCCESS;
2555 sbd_global_props_t *sbdGlobalProps = NULL;
2556 int sbdGlobalPropsSize = 0;
2557 int propLen;
2558 int mluBufSize = 0;
2559 int fd;
2560 int savedErrno;
2561 int ioctlRet;
2562 stmf_iocdata_t sbdIoctl = {0};
2563
2564 switch (resourceProp) {
2565 case STMF_LU_PROP_MGMT_URL:
2566 break;
2567 default:
2568 return (STMF_ERROR_INVALID_PROP);
2569 break;
2570 }
2571
2572 /*
2573 * Open control node for sbd
2574 */
2575 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
2576 return (ret);
2577
2578 propLen = strlen(propVal);
2579 mluBufSize += propLen + 1;
2580 sbdGlobalPropsSize += sizeof (sbd_global_props_t) - 8 +
2581 max(8, mluBufSize);
2582 /*
2583 * 8 is the size of the buffer set aside for
2584 * concatenation of variable length fields
2585 */
2586 sbdGlobalProps = (sbd_global_props_t *)calloc(1, sbdGlobalPropsSize);
2587 if (sbdGlobalProps == NULL) {
2588 (void) close(fd);
2589 return (STMF_ERROR_NOMEM);
2590 }
2591
2592 sbdGlobalProps->mlu_struct_size = sbdGlobalPropsSize;
2593
2594 switch (resourceProp) {
2595 case STMF_LU_PROP_MGMT_URL:
2596 sbdGlobalProps->mlu_mgmt_url_valid = 1;
2597 bcopy(propVal, &(sbdGlobalProps->mlu_buf),
2598 propLen + 1);
2599 break;
2600 default:
2601 ret = STMF_ERROR_NO_PROP;
2602 goto done;
2603 }
2604
2605 sbdIoctl.stmf_version = STMF_VERSION_1;
2606 sbdIoctl.stmf_ibuf_size = sbdGlobalProps->mlu_struct_size;
2607 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdGlobalProps;
2608
2609 ioctlRet = ioctl(fd, SBD_IOCTL_SET_GLOBAL_LU, &sbdIoctl);
2610 if (ioctlRet != 0) {
2611 savedErrno = errno;
2612 switch (savedErrno) {
2613 case EBUSY:
2614 ret = STMF_ERROR_BUSY;
2615 break;
2616 case EPERM:
2617 case EACCES:
2618 ret = STMF_ERROR_PERM;
2619 break;
2620 default:
2621 diskError(sbdIoctl.stmf_error, &ret);
2622 if (ret == STMF_STATUS_ERROR) {
2623 syslog(LOG_DEBUG,
2624 "modifyDiskLu:ioctl "
2625 "error(%d) (%d) (%d)", ioctlRet,
2626 sbdIoctl.stmf_error, savedErrno);
2627 }
2628 break;
2629 }
2630 }
2631
2632 done:
2633 free(sbdGlobalProps);
2634 (void) close(fd);
2635 return (ret);
2636 }
2637
2638
2639 /*
2640 * stmfSetLuProp
2641 *
2642 * Purpose: set a property on an luResource
2643 *
2644 * hdl - allocated luResource
2645 * prop - property identifier
2646 * propVal - property value to be set
2647 */
2648 int
2649 stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
2650 {
2651 int ret = STMF_STATUS_SUCCESS;
2652 luResourceImpl *luPropsHdl = hdl;
2653 if (hdl == NULL) {
2654 return (STMF_ERROR_INVALID_ARG);
2655 }
2656
2657 if (luPropsHdl->type == STMF_DISK) {
2658 ret = setDiskProp(luPropsHdl, prop, propVal);
2659 } else {
2660 return (STMF_ERROR_INVALID_ARG);
2661 }
2662
2663 return (ret);
2664 }
2665
2666 /*
2667 * getDiskProp
2668 *
2669 * Purpose: retrieve a given property from a logical unit resource of type disk
2670 *
2671 * hdl - allocated luResourceImpl
2672 * prop - property identifier
2673 * propVal - pointer to character to contain the retrieved property value
2674 * propLen - On input this is the length of propVal. On failure, it contains the
2675 * number of bytes required for propVal
2676 */
2677 static int
2678 getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
2679 {
2680 int ret = STMF_STATUS_SUCCESS;
2681 diskResource *diskLu = hdl->resource;
2682 char accessState[20];
2683 size_t reqLen;
2684
2685 if (prop == STMF_LU_PROP_ACCESS_STATE) {
2686 if (diskLu->accessState == SBD_LU_ACTIVE) {
2687 (void) strlcpy(accessState, STMF_ACCESS_ACTIVE,
2688 sizeof (accessState));
2689 } else if (diskLu->accessState == SBD_LU_TRANSITION_TO_ACTIVE) {
2690 (void) strlcpy(accessState,
2691 STMF_ACCESS_STANDBY_TO_ACTIVE,
2692 sizeof (accessState));
2693 } else if (diskLu->accessState == SBD_LU_STANDBY) {
2694 (void) strlcpy(accessState, STMF_ACCESS_STANDBY,
2695 sizeof (accessState));
2696 } else if (diskLu->accessState ==
2697 SBD_LU_TRANSITION_TO_STANDBY) {
2698 (void) strlcpy(accessState,
2699 STMF_ACCESS_ACTIVE_TO_STANDBY,
2700 sizeof (accessState));
2701 }
2702 if ((reqLen = strlcpy(propVal, accessState,
2703 *propLen)) >= *propLen) {
2704 *propLen = reqLen + 1;
2705 return (STMF_ERROR_INVALID_ARG);
2706 }
2707 return (0);
2708 }
2709
2710 if (diskLu->accessState != SBD_LU_ACTIVE) {
2711 return (STMF_ERROR_NO_PROP_STANDBY);
2712 }
2713
2714 switch (prop) {
2715 case STMF_LU_PROP_BLOCK_SIZE:
2716 if (diskLu->blkSizeValid == B_FALSE) {
2717 return (STMF_ERROR_NO_PROP);
2718 }
2719 reqLen = snprintf(propVal, *propLen, "%llu",
2720 (u_longlong_t)diskLu->blkSize);
2721 if (reqLen >= *propLen) {
2722 *propLen = reqLen + 1;
2723 return (STMF_ERROR_INVALID_ARG);
2724 }
2725 break;
2726 case STMF_LU_PROP_FILENAME:
2727 if (diskLu->luDataFileNameValid == B_FALSE) {
2728 return (STMF_ERROR_NO_PROP);
2729 }
2730 if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
2731 *propLen)) >= *propLen) {
2732 *propLen = reqLen + 1;
2733 return (STMF_ERROR_INVALID_ARG);
2734 }
2735 break;
2736 case STMF_LU_PROP_META_FILENAME:
2737 if (diskLu->luMetaFileNameValid == B_FALSE) {
2738 return (STMF_ERROR_NO_PROP);
2739 }
2740 if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
2741 *propLen)) >= *propLen) {
2742 *propLen = reqLen + 1;
2743 return (STMF_ERROR_INVALID_ARG);
2744 }
2745 break;
2746 case STMF_LU_PROP_MGMT_URL:
2747 if (diskLu->luMgmtUrlValid == B_FALSE) {
2748 return (STMF_ERROR_NO_PROP);
2749 }
2750 if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl,
2751 *propLen)) >= *propLen) {
2752 *propLen = reqLen + 1;
2753 return (STMF_ERROR_INVALID_ARG);
2754 }
2755 break;
2756 case STMF_LU_PROP_GUID:
2757 if (diskLu->luGuidValid == B_FALSE) {
2758 return (STMF_ERROR_NO_PROP);
2759 }
2760 reqLen = snprintf(propVal, *propLen,
2761 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
2762 "%02X%02X%02X%02X",
2763 diskLu->luGuid[0], diskLu->luGuid[1],
2764 diskLu->luGuid[2], diskLu->luGuid[3],
2765 diskLu->luGuid[4], diskLu->luGuid[5],
2766 diskLu->luGuid[6], diskLu->luGuid[7],
2767 diskLu->luGuid[8], diskLu->luGuid[9],
2768 diskLu->luGuid[10], diskLu->luGuid[11],
2769 diskLu->luGuid[12], diskLu->luGuid[13],
2770 diskLu->luGuid[14], diskLu->luGuid[15]);
2771 if (reqLen >= *propLen) {
2772 *propLen = reqLen + 1;
2773 return (STMF_ERROR_INVALID_ARG);
2774 }
2775 break;
2776 case STMF_LU_PROP_SERIAL_NUM:
2777 if (diskLu->serialNumValid == B_FALSE) {
2778 return (STMF_ERROR_NO_PROP);
2779 }
2780 if ((reqLen = strlcpy(propVal, diskLu->serialNum,
2781 *propLen)) >= *propLen) {
2782 *propLen = reqLen + 1;
2783 return (STMF_ERROR_INVALID_ARG);
2784 }
2785 break;
2786 case STMF_LU_PROP_SIZE:
2787 if (diskLu->luSizeValid == B_FALSE) {
2788 return (STMF_ERROR_NO_PROP);
2789 }
2790 (void) snprintf(propVal, *propLen, "%llu",
2791 (u_longlong_t)diskLu->luSize);
2792 break;
2793 case STMF_LU_PROP_ALIAS:
2794 if (diskLu->luAliasValid == B_FALSE) {
2795 return (STMF_ERROR_NO_PROP);
2796 }
2797 if ((reqLen = strlcpy(propVal, diskLu->luAlias,
2798 *propLen)) >= *propLen) {
2799 *propLen = reqLen + 1;
2800 return (STMF_ERROR_INVALID_ARG);
2801 }
2802 break;
2803 case STMF_LU_PROP_VID:
2804 if (diskLu->vidValid == B_FALSE) {
2805 return (STMF_ERROR_NO_PROP);
2806 }
2807 if (*propLen <= sizeof (diskLu->vid)) {
2808 return (STMF_ERROR_INVALID_ARG);
2809 }
2810 bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
2811 propVal[sizeof (diskLu->vid)] = 0;
2812 break;
2813 case STMF_LU_PROP_PID:
2814 if (diskLu->pidValid == B_FALSE) {
2815 return (STMF_ERROR_NO_PROP);
2816 }
2817 if (*propLen <= sizeof (diskLu->pid)) {
2818 return (STMF_ERROR_INVALID_ARG);
2819 }
2820 bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
2821 propVal[sizeof (diskLu->pid)] = 0;
2822 break;
2823 case STMF_LU_PROP_WRITE_PROTECT:
2824 if (diskLu->writeProtectEnableValid == B_FALSE) {
2825 return (STMF_ERROR_NO_PROP);
2826 }
2827 if (diskLu->writeProtectEnable) {
2828 if ((reqLen = strlcpy(propVal, "true",
2829 *propLen)) >= *propLen) {
2830 *propLen = reqLen + 1;
2831 return (STMF_ERROR_INVALID_ARG);
2832 }
2833 } else {
2834 if ((reqLen = strlcpy(propVal, "false",
2835 *propLen)) >= *propLen) {
2836 *propLen = reqLen + 1;
2837 return (STMF_ERROR_INVALID_ARG);
2838 }
2839 }
2840 break;
2841 case STMF_LU_PROP_UNMAP:
2842 if (!diskLu->unmapValid)
2843 return (STMF_ERROR_NO_PROP);
2844 if (diskLu->unmap) {
2845 if ((reqLen = strlcpy(propVal, "true",
2846 *propLen)) >= *propLen) {
2847 *propLen = reqLen + 1;
2848 return (STMF_ERROR_INVALID_ARG);
2849 }
2850 } else {
2851 if ((reqLen = strlcpy(propVal, "false",
2852 *propLen)) >= *propLen) {
2853 *propLen = reqLen + 1;
2854 return (STMF_ERROR_INVALID_ARG);
2855 }
2856 }
2857 break;
2858 case STMF_LU_PROP_WRITE_CACHE_DISABLE:
2859 if (diskLu->writebackCacheDisableValid == B_FALSE) {
2860 return (STMF_ERROR_NO_PROP);
2861 }
2862 if (diskLu->writebackCacheDisable) {
2863 if ((reqLen = strlcpy(propVal, "true",
2864 *propLen)) >= *propLen) {
2865 *propLen = reqLen + 1;
2866 return (STMF_ERROR_INVALID_ARG);
2867 }
2868 } else {
2869 if ((reqLen = strlcpy(propVal, "false",
2870 *propLen)) >= *propLen) {
2871 *propLen = reqLen + 1;
2872 return (STMF_ERROR_INVALID_ARG);
2873 }
2874 }
2875 break;
2876 default:
2877 ret = STMF_ERROR_INVALID_PROP;
2878 break;
2879 }
2880
2881 return (ret);
2882 }
2883
2884 /*
2885 * setDiskProp
2886 *
2887 * Purpose: set properties for resource of type disk
2888 *
2889 * hdl - allocated luResourceImpl
2890 * resourceProp - valid resource identifier
2891 * propVal - valid resource value
2892 */
2893 static int
2894 setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
2895 {
2896 int ret = STMF_STATUS_SUCCESS;
2897 int i;
2898 diskResource *diskLu = hdl->resource;
2899 unsigned long long numericProp = 0;
2900 char guidProp[LU_ASCII_GUID_SIZE + 1];
2901 char ouiProp[OUI_ASCII_SIZE + 1];
2902 char hostIdProp[HOST_ID_ASCII_SIZE + 1];
2903 unsigned int oui[OUI_SIZE];
2904 unsigned int hostId[HOST_ID_SIZE];
2905 unsigned int guid[LU_GUID_SIZE];
2906 int propSize;
2907
2908
2909 if (propVal == NULL) {
2910 return (STMF_ERROR_INVALID_ARG);
2911 }
2912
2913 switch (resourceProp) {
2914 case STMF_LU_PROP_ALIAS:
2915 if (strlcpy(diskLu->luAlias, propVal,
2916 sizeof (diskLu->luAlias)) >=
2917 sizeof (diskLu->luAlias)) {
2918 return (STMF_ERROR_INVALID_PROPSIZE);
2919 }
2920 diskLu->luAliasValid = B_TRUE;
2921 break;
2922 case STMF_LU_PROP_BLOCK_SIZE: {
2923 const char *tmp = propVal;
2924 while (*tmp) {
2925 if (!isdigit(*tmp++)) {
2926 return (STMF_ERROR_INVALID_ARG);
2927 }
2928 }
2929 (void) sscanf(propVal, "%llu", &numericProp);
2930 if (numericProp > UINT16_MAX) {
2931 return (STMF_ERROR_INVALID_PROPSIZE);
2932 }
2933 diskLu->blkSize = numericProp;
2934 diskLu->blkSizeValid = B_TRUE;
2935 break;
2936 }
2937 case STMF_LU_PROP_COMPANY_ID:
2938 if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
2939 sizeof (ouiProp)) {
2940 return (STMF_ERROR_INVALID_ARG);
2941 }
2942 if (checkHexUpper(ouiProp) != 0) {
2943 return (STMF_ERROR_INVALID_ARG);
2944 }
2945 (void) sscanf(ouiProp, "%2X%2X%2X",
2946 &oui[0], &oui[1], &oui[2]);
2947
2948 diskLu->companyId = 0;
2949 diskLu->companyId += oui[0] << 16;
2950 diskLu->companyId += oui[1] << 8;
2951 diskLu->companyId += oui[2];
2952 if (diskLu->companyId == 0) {
2953 return (STMF_ERROR_INVALID_ARG);
2954 }
2955 diskLu->companyIdValid = B_TRUE;
2956 break;
2957 case STMF_LU_PROP_HOST_ID:
2958 if ((strlcpy(hostIdProp, propVal,
2959 sizeof (hostIdProp))) >= sizeof (hostIdProp)) {
2960 return (STMF_ERROR_INVALID_ARG);
2961 }
2962 if (checkHexUpper(hostIdProp) != 0) {
2963 return (STMF_ERROR_INVALID_ARG);
2964 }
2965 (void) sscanf(hostIdProp, "%2X%2X%2X%2X",
2966 &hostId[0], &hostId[1], &hostId[2], &hostId[3]);
2967
2968 diskLu->hostId = 0;
2969 diskLu->hostId += hostId[0] << 24;
2970 diskLu->hostId += hostId[1] << 16;
2971 diskLu->hostId += hostId[2] << 8;
2972 diskLu->hostId += hostId[3];
2973 if (diskLu->hostId == 0) {
2974 return (STMF_ERROR_INVALID_ARG);
2975 }
2976 diskLu->hostIdValid = B_TRUE;
2977 break;
2978 case STMF_LU_PROP_GUID:
2979 if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
2980 return (STMF_ERROR_INVALID_PROPSIZE);
2981 }
2982
2983 if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
2984 sizeof (guidProp)) {
2985 return (STMF_ERROR_INVALID_ARG);
2986 }
2987
2988 if (checkHexUpper(guidProp) != 0) {
2989 return (STMF_ERROR_INVALID_ARG);
2990 }
2991
2992 (void) sscanf(guidProp,
2993 "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
2994 &guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
2995 &guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
2996 &guid[10], &guid[11], &guid[12], &guid[13],
2997 &guid[14], &guid[15]);
2998 for (i = 0; i < sizeof (diskLu->luGuid); i++) {
2999 diskLu->luGuid[i] = guid[i];
3000 }
3001 diskLu->luGuidValid = B_TRUE;
3002 break;
3003 case STMF_LU_PROP_FILENAME:
3004 if ((strlcpy(diskLu->luDataFileName, propVal,
3005 sizeof (diskLu->luDataFileName))) >=
3006 sizeof (diskLu->luDataFileName)) {
3007 return (STMF_ERROR_INVALID_PROPSIZE);
3008 }
3009 diskLu->luDataFileNameValid = B_TRUE;
3010 break;
3011 case STMF_LU_PROP_META_FILENAME:
3012 if ((strlcpy(diskLu->luMetaFileName, propVal,
3013 sizeof (diskLu->luMetaFileName))) >=
3014 sizeof (diskLu->luMetaFileName)) {
3015 return (STMF_ERROR_INVALID_PROPSIZE);
3016 }
3017 diskLu->luMetaFileNameValid = B_TRUE;
3018 break;
3019 case STMF_LU_PROP_MGMT_URL:
3020 if ((strlcpy(diskLu->luMgmtUrl, propVal,
3021 sizeof (diskLu->luMgmtUrl))) >=
3022 sizeof (diskLu->luMgmtUrl)) {
3023 return (STMF_ERROR_INVALID_PROPSIZE);
3024 }
3025 diskLu->luMgmtUrlValid = B_TRUE;
3026 break;
3027 case STMF_LU_PROP_PID:
3028 if ((propSize = strlen(propVal)) >
3029 sizeof (diskLu->pid)) {
3030 return (STMF_ERROR_INVALID_PROPSIZE);
3031 }
3032 (void) strncpy(diskLu->pid, propVal, propSize);
3033 diskLu->pidValid = B_TRUE;
3034 break;
3035 case STMF_LU_PROP_SERIAL_NUM:
3036 if ((propSize = strlen(propVal)) >
3037 (sizeof (diskLu->serialNum) - 1)) {
3038 return (STMF_ERROR_INVALID_PROPSIZE);
3039 }
3040 (void) strncpy(diskLu->serialNum, propVal, propSize);
3041 diskLu->serialNumValid = B_TRUE;
3042 break;
3043 case STMF_LU_PROP_SIZE:
3044 if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
3045 return (STMF_ERROR_INVALID_ARG);
3046 }
3047 diskLu->luSizeValid = B_TRUE;
3048 break;
3049 case STMF_LU_PROP_VID:
3050 if ((propSize = strlen(propVal)) >
3051 sizeof (diskLu->vid)) {
3052 return (STMF_ERROR_INVALID_PROPSIZE);
3053 }
3054 (void) strncpy(diskLu->vid, propVal, propSize);
3055 diskLu->vidValid = B_TRUE;
3056 break;
3057 case STMF_LU_PROP_WRITE_PROTECT:
3058 if (strcasecmp(propVal, "TRUE") == 0) {
3059 diskLu->writeProtectEnable = B_TRUE;
3060 } else if (strcasecmp(propVal, "FALSE") == 0) {
3061 diskLu->writeProtectEnable = B_FALSE;
3062 } else {
3063 return (STMF_ERROR_INVALID_ARG);
3064 }
3065 diskLu->writeProtectEnableValid = B_TRUE;
3066 break;
3067 case STMF_LU_PROP_WRITE_CACHE_DISABLE:
3068 if (strcasecmp(propVal, "TRUE") == 0) {
3069 diskLu->writebackCacheDisable = B_TRUE;
3070 } else if (strcasecmp(propVal, "FALSE") == 0) {
3071 diskLu->writebackCacheDisable = B_FALSE;
3072 } else {
3073 return (STMF_ERROR_INVALID_ARG);
3074 }
3075 diskLu->writebackCacheDisableValid = B_TRUE;
3076 break;
3077 case STMF_LU_PROP_UNMAP:
3078 if (strcasecmp(propVal, "TRUE") == 0) {
3079 diskLu->unmap = B_TRUE;
3080 } else if (strcasecmp(propVal, "FALSE") == 0) {
3081 diskLu->unmap = B_FALSE;
3082 } else {
3083 return (STMF_ERROR_INVALID_ARG);
3084 }
3085 diskLu->unmapValid = B_TRUE;
3086 break;
3087 case STMF_LU_PROP_ACCESS_STATE:
3088 ret = STMF_ERROR_INVALID_PROP;
3089 break;
3090 default:
3091 ret = STMF_ERROR_INVALID_PROP;
3092 break;
3093 }
3094 return (ret);
3095 }
3096
3097 static int
3098 checkHexUpper(char *buf)
3099 {
3100 int i;
3101
3102 for (i = 0; i < strlen(buf); i++) {
3103 if (isxdigit(buf[i])) {
3104 buf[i] = toupper(buf[i]);
3105 continue;
3106 }
3107 return (-1);
3108 }
3109
3110 return (0);
3111 }
3112
3113 /*
3114 * Given a numeric suffix, convert the value into a number of bits that the
3115 * resulting value must be shifted.
3116 * Code lifted from libzfs_util.c
3117 */
3118 static int
3119 strToShift(const char *buf)
3120 {
3121 const char *ends = "BKMGTPE";
3122 int i;
3123
3124 if (buf[0] == '\0')
3125 return (0);
3126
3127 for (i = 0; i < strlen(ends); i++) {
3128 if (toupper(buf[0]) == ends[i])
3129 return (10*i);
3130 }
3131
3132 return (-1);
3133 }
3134
3135 int
3136 stmfFreeLuResource(luResource hdl)
3137 {
3138 int ret = STMF_STATUS_SUCCESS;
3139 if (hdl == NULL) {
3140 return (STMF_ERROR_INVALID_ARG);
3141 }
3142
3143 luResourceImpl *hdlImpl = hdl;
3144 free(hdlImpl->resource);
3145 free(hdlImpl);
3146 return (ret);
3147 }
3148
3149 /*
3150 * Convert a string of the form '100G' into a real number. Used when setting
3151 * the size of a logical unit.
3152 * Code lifted from libzfs_util.c
3153 */
3154 static int
3155 niceStrToNum(const char *value, uint64_t *num)
3156 {
3157 char *end;
3158 int shift;
3159
3160 *num = 0;
3161
3162 /* Check to see if this looks like a number. */
3163 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
3164 return (-1);
3165 }
3166
3167 /* Rely on stroull() to process the numeric portion. */
3168 errno = 0;
3169 *num = strtoull(value, &end, 10);
3170
3171 /*
3172 * Check for ERANGE, which indicates that the value is too large to fit
3173 * in a 64-bit value.
3174 */
3175 if (errno == ERANGE) {
3176 return (-1);
3177 }
3178
3179 /*
3180 * If we have a decimal value, then do the computation with floating
3181 * point arithmetic. Otherwise, use standard arithmetic.
3182 */
3183 if (*end == '.') {
3184 double fval = strtod(value, &end);
3185
3186 if ((shift = strToShift(end)) == -1) {
3187 return (-1);
3188 }
3189
3190 fval *= pow(2, shift);
3191
3192 if (fval > UINT64_MAX) {
3193 return (-1);
3194 }
3195
3196 *num = (uint64_t)fval;
3197 } else {
3198 if ((shift = strToShift(end)) == -1) {
3199 return (-1);
3200 }
3201
3202 /* Check for overflow */
3203 if (shift >= 64 || (*num << shift) >> shift != *num) {
3204 return (-1);
3205 }
3206
3207 *num <<= shift;
3208 }
3209
3210 return (0);
3211 }
3212
3213 /*
3214 * stmfCreateTargetGroup
3215 *
3216 * Purpose: Create a local port group
3217 *
3218 * targetGroupName - name of local port group to create
3219 */
3220 int
3221 stmfCreateTargetGroup(stmfGroupName *targetGroupName)
3222 {
3223 int ret;
3224 int fd;
3225
3226 if (targetGroupName == NULL ||
3227 (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
3228 == sizeof (stmfGroupName))) {
3229 return (STMF_ERROR_INVALID_ARG);
3230 }
3231
3232 /* Check to ensure service exists */
3233 if (psCheckService() != STMF_STATUS_SUCCESS) {
3234 return (STMF_ERROR_SERVICE_NOT_FOUND);
3235 }
3236
3237 /* call init */
3238 ret = initializeConfig();
3239 if (ret != STMF_STATUS_SUCCESS) {
3240 return (ret);
3241 }
3242
3243 /*
3244 * Open control node for stmf
3245 */
3246 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3247 return (ret);
3248
3249 /*
3250 * Add the group to the driver
3251 */
3252 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
3253 targetGroupName)) != STMF_STATUS_SUCCESS) {
3254 goto done;
3255 }
3256
3257 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
3258 goto done;
3259 }
3260
3261 /*
3262 * If the add to the driver was successful, add it to the persistent
3263 * store.
3264 */
3265 ret = psCreateTargetGroup((char *)targetGroupName);
3266 switch (ret) {
3267 case STMF_PS_SUCCESS:
3268 ret = STMF_STATUS_SUCCESS;
3269 break;
3270 case STMF_PS_ERROR_EXISTS:
3271 ret = STMF_ERROR_EXISTS;
3272 break;
3273 case STMF_PS_ERROR_BUSY:
3274 ret = STMF_ERROR_BUSY;
3275 break;
3276 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3277 ret = STMF_ERROR_SERVICE_NOT_FOUND;
3278 break;
3279 case STMF_PS_ERROR_VERSION_MISMATCH:
3280 ret = STMF_ERROR_SERVICE_DATA_VERSION;
3281 break;
3282 default:
3283 syslog(LOG_DEBUG,
3284 "stmfCreateTargetGroup:psCreateTargetGroup"
3285 ":error(%d)", ret);
3286 ret = STMF_STATUS_ERROR;
3287 break;
3288 }
3289
3290 done:
3291 (void) close(fd);
3292 return (ret);
3293 }
3294
3295 /*
3296 * stmfDeleteHostGroup
3297 *
3298 * Purpose: Delete an initiator or local port group
3299 *
3300 * hostGroupName - group to delete
3301 */
3302 int
3303 stmfDeleteHostGroup(stmfGroupName *hostGroupName)
3304 {
3305 int ret;
3306 int fd;
3307
3308 if (hostGroupName == NULL) {
3309 return (STMF_ERROR_INVALID_ARG);
3310 }
3311
3312 /* Check to ensure service exists */
3313 if (psCheckService() != STMF_STATUS_SUCCESS) {
3314 return (STMF_ERROR_SERVICE_NOT_FOUND);
3315 }
3316
3317 /* call init */
3318 ret = initializeConfig();
3319 if (ret != STMF_STATUS_SUCCESS) {
3320 return (ret);
3321 }
3322
3323 /*
3324 * Open control node for stmf
3325 */
3326 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3327 return (ret);
3328
3329 /*
3330 * Remove the group from the driver
3331 */
3332 if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
3333 hostGroupName)) != STMF_STATUS_SUCCESS) {
3334 goto done;
3335 }
3336
3337 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
3338 goto done;
3339 }
3340
3341 /*
3342 * If the remove from the driver was successful, remove it from the
3343 * persistent store.
3344 */
3345 ret = psDeleteHostGroup((char *)hostGroupName);
3346 switch (ret) {
3347 case STMF_PS_SUCCESS:
3348 ret = STMF_STATUS_SUCCESS;
3349 break;
3350 case STMF_PS_ERROR_NOT_FOUND:
3351 ret = STMF_ERROR_NOT_FOUND;
3352 break;
3353 case STMF_PS_ERROR_BUSY:
3354 ret = STMF_ERROR_BUSY;
3355 break;
3356 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3357 ret = STMF_ERROR_SERVICE_NOT_FOUND;
3358 break;
3359 case STMF_PS_ERROR_VERSION_MISMATCH:
3360 ret = STMF_ERROR_SERVICE_DATA_VERSION;
3361 break;
3362 default:
3363 syslog(LOG_DEBUG,
3364 "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
3365 ret);
3366 ret = STMF_STATUS_ERROR;
3367 break;
3368 }
3369
3370 done:
3371 (void) close(fd);
3372 return (ret);
3373 }
3374
3375 /*
3376 * stmfDeleteTargetGroup
3377 *
3378 * Purpose: Delete an initiator or local port group
3379 *
3380 * targetGroupName - group to delete
3381 */
3382 int
3383 stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
3384 {
3385 int ret = STMF_STATUS_SUCCESS;
3386 int fd;
3387
3388 if (targetGroupName == NULL) {
3389 return (STMF_ERROR_INVALID_ARG);
3390 }
3391
3392 /* Check to ensure service exists */
3393 if (psCheckService() != STMF_STATUS_SUCCESS) {
3394 return (STMF_ERROR_SERVICE_NOT_FOUND);
3395 }
3396
3397 /* call init */
3398 ret = initializeConfig();
3399 if (ret != STMF_STATUS_SUCCESS) {
3400 return (ret);
3401 }
3402
3403 /*
3404 * Open control node for stmf
3405 */
3406 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3407 return (ret);
3408
3409 /*
3410 * Remove the group from the driver
3411 */
3412 if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
3413 targetGroupName)) != STMF_STATUS_SUCCESS) {
3414 goto done;
3415 }
3416
3417 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
3418 goto done;
3419 }
3420
3421 /*
3422 * If the remove from the driver was successful, remove it from the
3423 * persistent store.
3424 */
3425 ret = psDeleteTargetGroup((char *)targetGroupName);
3426 switch (ret) {
3427 case STMF_PS_SUCCESS:
3428 ret = STMF_STATUS_SUCCESS;
3429 break;
3430 case STMF_PS_ERROR_NOT_FOUND:
3431 ret = STMF_ERROR_NOT_FOUND;
3432 break;
3433 case STMF_PS_ERROR_BUSY:
3434 ret = STMF_ERROR_BUSY;
3435 break;
3436 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3437 ret = STMF_ERROR_SERVICE_NOT_FOUND;
3438 break;
3439 case STMF_PS_ERROR_VERSION_MISMATCH:
3440 ret = STMF_ERROR_SERVICE_DATA_VERSION;
3441 break;
3442 default:
3443 syslog(LOG_DEBUG,
3444 "stmfDeleteTargetGroup:psDeleteTargetGroup"
3445 ":error(%d)", ret);
3446 ret = STMF_STATUS_ERROR;
3447 break;
3448 }
3449
3450 done:
3451 (void) close(fd);
3452 return (ret);
3453 }
3454
3455 /*
3456 * stmfDevidFromIscsiName
3457 *
3458 * Purpose: convert an iSCSI name to an stmf devid
3459 *
3460 * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
3461 * devid - on success, contains the converted iscsi name
3462 */
3463 int
3464 stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
3465 {
3466 if (devid == NULL || iscsiName == NULL)
3467 return (STMF_ERROR_INVALID_ARG);
3468
3469 bzero(devid, sizeof (stmfDevid));
3470
3471 /* Validate size of target */
3472 if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
3473 devid->identLength < strlen(EUI) ||
3474 devid->identLength < strlen(IQN)) {
3475 return (STMF_ERROR_INVALID_ARG);
3476 }
3477
3478 if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
3479 strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
3480 return (STMF_ERROR_INVALID_ARG);
3481 }
3482
3483 /* copy UTF-8 bytes to ident */
3484 bcopy(iscsiName, devid->ident, devid->identLength);
3485
3486 return (STMF_STATUS_SUCCESS);
3487 }
3488
3489 /*
3490 * stmfDevidFromWwn
3491 *
3492 * Purpose: convert a WWN to an stmf devid
3493 *
3494 * wwn - 8-byte wwn identifier
3495 * devid - on success, contains the converted wwn
3496 */
3497 int
3498 stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid)
3499 {
3500 if (wwn == NULL || devid == NULL)
3501 return (STMF_ERROR_INVALID_ARG);
3502
3503 bzero(devid, sizeof (stmfDevid));
3504
3505 /* Copy eui prefix */
3506 (void) bcopy(WWN, devid->ident, strlen(WWN));
3507
3508 /* Convert to ASCII uppercase hexadecimal string */
3509 (void) snprintf((char *)&devid->ident[strlen(WWN)],
3510 sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
3511 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
3512
3513 devid->identLength = strlen((char *)devid->ident);
3514
3515 return (STMF_STATUS_SUCCESS);
3516 }
3517
3518 /*
3519 * stmfFreeMemory
3520 *
3521 * Purpose: Free memory allocated by this library
3522 *
3523 * memory - previously allocated pointer of memory managed by library
3524 */
3525 void
3526 stmfFreeMemory(void *memory)
3527 {
3528 free(memory);
3529 }
3530
3531 /*
3532 * get host group, target group list from stmf
3533 *
3534 * groupType - HOST_GROUP, TARGET_GROUP
3535 */
3536 static int
3537 groupListIoctl(stmfGroupList **groupList, int groupType)
3538 {
3539 int ret;
3540 int fd;
3541 int ioctlRet;
3542 int i;
3543 int cmd;
3544 stmf_iocdata_t stmfIoctl;
3545 /* framework group list */
3546 stmf_group_name_t *iGroupList = NULL;
3547 uint32_t groupListSize;
3548
3549 if (groupList == NULL) {
3550 return (STMF_ERROR_INVALID_ARG);
3551 }
3552
3553 if (groupType == HOST_GROUP) {
3554 cmd = STMF_IOCTL_GET_HG_LIST;
3555 } else if (groupType == TARGET_GROUP) {
3556 cmd = STMF_IOCTL_GET_TG_LIST;
3557 } else {
3558 return (STMF_ERROR_INVALID_ARG);
3559 }
3560
3561 /* call init */
3562 ret = initializeConfig();
3563 if (ret != STMF_STATUS_SUCCESS) {
3564 return (ret);
3565 }
3566
3567 /*
3568 * Open control node for stmf
3569 */
3570 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3571 return (ret);
3572
3573 /*
3574 * Allocate ioctl input buffer
3575 */
3576 groupListSize = ALLOC_GROUP;
3577 groupListSize = groupListSize * (sizeof (stmf_group_name_t));
3578 iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
3579 if (iGroupList == NULL) {
3580 ret = STMF_ERROR_NOMEM;
3581 goto done;
3582 }
3583
3584 bzero(&stmfIoctl, sizeof (stmfIoctl));
3585 /*
3586 * Issue ioctl to get the group list
3587 */
3588 stmfIoctl.stmf_version = STMF_VERSION_1;
3589 stmfIoctl.stmf_obuf_size = groupListSize;
3590 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
3591 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3592 if (ioctlRet != 0) {
3593 switch (errno) {
3594 case EBUSY:
3595 ret = STMF_ERROR_BUSY;
3596 break;
3597 case EPERM:
3598 case EACCES:
3599 ret = STMF_ERROR_PERM;
3600 break;
3601 default:
3602 syslog(LOG_DEBUG,
3603 "groupListIoctl:ioctl errno(%d)",
3604 errno);
3605 ret = STMF_STATUS_ERROR;
3606 break;
3607 }
3608 goto done;
3609 }
3610 /*
3611 * Check whether input buffer was large enough
3612 */
3613 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
3614 groupListSize = stmfIoctl.stmf_obuf_max_nentries *
3615 sizeof (stmf_group_name_t);
3616 iGroupList = realloc(iGroupList, groupListSize);
3617 if (iGroupList == NULL) {
3618 ret = STMF_ERROR_NOMEM;
3619 goto done;
3620 }
3621 stmfIoctl.stmf_obuf_size = groupListSize;
3622 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
3623 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3624 if (ioctlRet != 0) {
3625 switch (errno) {
3626 case EBUSY:
3627 ret = STMF_ERROR_BUSY;
3628 break;
3629 case EPERM:
3630 case EACCES:
3631 ret = STMF_ERROR_PERM;
3632 break;
3633 default:
3634 syslog(LOG_DEBUG,
3635 "groupListIoctl:ioctl errno(%d)",
3636 errno);
3637 ret = STMF_STATUS_ERROR;
3638 break;
3639 }
3640 goto done;
3641 }
3642 }
3643
3644 /* allocate and copy to caller's buffer */
3645 *groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
3646 sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries);
3647 if (*groupList == NULL) {
3648 ret = STMF_ERROR_NOMEM;
3649 goto done;
3650 }
3651 (*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
3652 for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
3653 bcopy(iGroupList[i].name, (*groupList)->name[i],
3654 sizeof (stmfGroupName));
3655 }
3656
3657 done:
3658 free(iGroupList);
3659 (void) close(fd);
3660 return (ret);
3661 }
3662
3663 /*
3664 * get host group members, target group members from stmf
3665 *
3666 * groupProps - allocated on success
3667 *
3668 * groupType - HOST_GROUP, TARGET_GROUP
3669 */
3670 static int
3671 groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
3672 int groupType)
3673 {
3674 int ret;
3675 int fd;
3676 int ioctlRet;
3677 int i;
3678 int cmd;
3679 stmf_iocdata_t stmfIoctl;
3680 /* framework group list */
3681 stmf_group_name_t iGroupName;
3682 stmf_ge_ident_t *iGroupMembers;
3683 uint32_t groupListSize;
3684
3685 if (groupName == NULL) {
3686 return (STMF_ERROR_INVALID_ARG);
3687 }
3688
3689 if (groupType == HOST_GROUP) {
3690 cmd = STMF_IOCTL_GET_HG_ENTRIES;
3691 } else if (groupType == TARGET_GROUP) {
3692 cmd = STMF_IOCTL_GET_TG_ENTRIES;
3693 } else {
3694 return (STMF_ERROR_INVALID_ARG);
3695 }
3696
3697 /* call init */
3698 ret = initializeConfig();
3699 if (ret != STMF_STATUS_SUCCESS) {
3700 return (ret);
3701 }
3702
3703 /*
3704 * Open control node for stmf
3705 */
3706 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3707 return (ret);
3708
3709 bzero(&iGroupName, sizeof (iGroupName));
3710
3711 bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
3712
3713 iGroupName.name_size = strlen((char *)groupName);
3714
3715 /*
3716 * Allocate ioctl input buffer
3717 */
3718 groupListSize = ALLOC_GRP_MEMBER;
3719 groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
3720 iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
3721 if (iGroupMembers == NULL) {
3722 ret = STMF_ERROR_NOMEM;
3723 goto done;
3724 }
3725
3726 bzero(&stmfIoctl, sizeof (stmfIoctl));
3727 /*
3728 * Issue ioctl to get the group list
3729 */
3730 stmfIoctl.stmf_version = STMF_VERSION_1;
3731 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3732 stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
3733 stmfIoctl.stmf_obuf_size = groupListSize;
3734 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
3735 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3736 if (ioctlRet != 0) {
3737 switch (errno) {
3738 case EBUSY:
3739 ret = STMF_ERROR_BUSY;
3740 break;
3741 case EPERM:
3742 case EACCES:
3743 ret = STMF_ERROR_PERM;
3744 break;
3745 default:
3746 syslog(LOG_DEBUG,
3747 "groupListIoctl:ioctl errno(%d)",
3748 errno);
3749 ret = STMF_STATUS_ERROR;
3750 break;
3751 }
3752 goto done;
3753 }
3754 /*
3755 * Check whether input buffer was large enough
3756 */
3757 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
3758 groupListSize = stmfIoctl.stmf_obuf_max_nentries *
3759 sizeof (stmf_ge_ident_t);
3760 iGroupMembers = realloc(iGroupMembers, groupListSize);
3761 if (iGroupMembers == NULL) {
3762 ret = STMF_ERROR_NOMEM;
3763 goto done;
3764 }
3765 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3766 stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
3767 stmfIoctl.stmf_obuf_size = groupListSize;
3768 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
3769 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3770 if (ioctlRet != 0) {
3771 switch (errno) {
3772 case EBUSY:
3773 ret = STMF_ERROR_BUSY;
3774 break;
3775 case EPERM:
3776 case EACCES:
3777 ret = STMF_ERROR_PERM;
3778 break;
3779 default:
3780 syslog(LOG_DEBUG,
3781 "groupListIoctl:ioctl errno(%d)",
3782 errno);
3783 ret = STMF_STATUS_ERROR;
3784 break;
3785 }
3786 goto done;
3787 }
3788 }
3789
3790 /* allocate and copy to caller's buffer */
3791 *groupProps = (stmfGroupProperties *)calloc(1,
3792 sizeof (stmfGroupProperties) +
3793 sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries);
3794 if (*groupProps == NULL) {
3795 ret = STMF_ERROR_NOMEM;
3796 goto done;
3797 }
3798 (*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
3799 for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
3800 (*groupProps)->name[i].identLength =
3801 iGroupMembers[i].ident_size;
3802 bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident,
3803 iGroupMembers[i].ident_size);
3804 }
3805
3806 done:
3807 free(iGroupMembers);
3808 (void) close(fd);
3809 return (ret);
3810 }
3811
3812 /*
3813 * Purpose: access persistent config data for host groups and target groups
3814 */
3815 static int
3816 iLoadGroupFromPs(stmfGroupList **groupList, int type)
3817 {
3818 int ret;
3819
3820 if (groupList == NULL) {
3821 return (STMF_ERROR_INVALID_ARG);
3822 }
3823
3824 if (type == HOST_GROUP) {
3825 ret = psGetHostGroupList(groupList);
3826 } else if (type == TARGET_GROUP) {
3827 ret = psGetTargetGroupList(groupList);
3828 } else {
3829 return (STMF_ERROR_INVALID_ARG);
3830 }
3831 switch (ret) {
3832 case STMF_PS_SUCCESS:
3833 ret = STMF_STATUS_SUCCESS;
3834 break;
3835 case STMF_PS_ERROR_NOT_FOUND:
3836 ret = STMF_ERROR_NOT_FOUND;
3837 break;
3838 case STMF_PS_ERROR_BUSY:
3839 ret = STMF_ERROR_BUSY;
3840 break;
3841 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3842 ret = STMF_ERROR_SERVICE_NOT_FOUND;
3843 break;
3844 case STMF_PS_ERROR_VERSION_MISMATCH:
3845 ret = STMF_ERROR_SERVICE_DATA_VERSION;
3846 break;
3847 default:
3848 syslog(LOG_DEBUG,
3849 "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
3850 ret);
3851 ret = STMF_STATUS_ERROR;
3852 break;
3853 }
3854
3855 return (ret);
3856 }
3857
3858 /*
3859 * stmfGetHostGroupList
3860 *
3861 * Purpose: Retrieves the list of initiator group oids
3862 *
3863 * hostGroupList - pointer to pointer to hostGroupList structure
3864 * on success, this contains the host group list.
3865 */
3866 int
3867 stmfGetHostGroupList(stmfGroupList **hostGroupList)
3868 {
3869 int ret = STMF_STATUS_ERROR;
3870
3871 if (hostGroupList == NULL) {
3872 return (STMF_ERROR_INVALID_ARG);
3873 }
3874
3875 ret = groupListIoctl(hostGroupList, HOST_GROUP);
3876 return (ret);
3877 }
3878
3879
3880 /*
3881 * Purpose: access persistent config data for host groups and target groups
3882 */
3883 static int
3884 iLoadGroupMembersFromPs(stmfGroupName *groupName,
3885 stmfGroupProperties **groupProp, int type)
3886 {
3887 int ret;
3888
3889 if (groupName == NULL) {
3890 return (STMF_ERROR_INVALID_ARG);
3891 }
3892
3893 if (type == HOST_GROUP) {
3894 ret = psGetHostGroupMemberList((char *)groupName, groupProp);
3895 } else if (type == TARGET_GROUP) {
3896 ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
3897 } else {
3898 return (STMF_ERROR_INVALID_ARG);
3899 }
3900 switch (ret) {
3901 case STMF_PS_SUCCESS:
3902 ret = STMF_STATUS_SUCCESS;
3903 break;
3904 case STMF_PS_ERROR_NOT_FOUND:
3905 ret = STMF_ERROR_NOT_FOUND;
3906 break;
3907 case STMF_PS_ERROR_BUSY:
3908 ret = STMF_ERROR_BUSY;
3909 break;
3910 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3911 ret = STMF_ERROR_SERVICE_NOT_FOUND;
3912 break;
3913 case STMF_PS_ERROR_VERSION_MISMATCH:
3914 ret = STMF_ERROR_SERVICE_DATA_VERSION;
3915 break;
3916 default:
3917 syslog(LOG_DEBUG,
3918 "iLoadGroupMembersFromPs:psGetHostGroupList:"
3919 "error(%d)", ret);
3920 ret = STMF_STATUS_ERROR;
3921 break;
3922 }
3923
3924 return (ret);
3925 }
3926
3927 /*
3928 * stmfGetHostGroupMembers
3929 *
3930 * Purpose: Retrieves the group properties for a host group
3931 *
3932 * groupName - name of group for which to retrieve host group members.
3933 * groupProp - pointer to pointer to stmfGroupProperties structure
3934 * on success, this contains the list of group members.
3935 */
3936 int
3937 stmfGetHostGroupMembers(stmfGroupName *groupName,
3938 stmfGroupProperties **groupProp)
3939 {
3940 int ret;
3941
3942 if (groupName == NULL || groupProp == NULL) {
3943 return (STMF_ERROR_INVALID_ARG);
3944 }
3945
3946 ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
3947
3948 return (ret);
3949 }
3950
3951 /*
3952 * stmfGetProviderData
3953 *
3954 * Purpose: Get provider data list
3955 *
3956 * providerName - name of provider for which to retrieve the data
3957 * nvl - pointer to nvlist_t pointer which will contain the nvlist data
3958 * retrieved.
3959 * providerType - type of provider for which to retrieve data.
3960 * STMF_LU_PROVIDER_TYPE
3961 * STMF_PORT_PROVIDER_TYPE
3962 */
3963 int
3964 stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
3965 {
3966 return (stmfGetProviderDataProt(providerName, nvl, providerType,
3967 NULL));
3968 }
3969
3970 /*
3971 * stmfGetProviderDataProt
3972 *
3973 * Purpose: Get provider data list with token
3974 *
3975 * providerName - name of provider for which to retrieve the data
3976 * nvl - pointer to nvlist_t pointer which will contain the nvlist data
3977 * retrieved.
3978 * providerType - type of provider for which to retrieve data.
3979 * STMF_LU_PROVIDER_TYPE
3980 * STMF_PORT_PROVIDER_TYPE
3981 * setToken - Returns the stale data token
3982 */
3983 int
3984 stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
3985 uint64_t *setToken)
3986 {
3987 int ret;
3988
3989 if (providerName == NULL || nvl == NULL) {
3990 return (STMF_ERROR_INVALID_ARG);
3991 }
3992 if (providerType != STMF_LU_PROVIDER_TYPE &&
3993 providerType != STMF_PORT_PROVIDER_TYPE) {
3994 return (STMF_ERROR_INVALID_ARG);
3995 }
3996 /* call init */
3997 ret = initializeConfig();
3998 if (ret != STMF_STATUS_SUCCESS) {
3999 return (ret);
4000 }
4001 return (getProviderData(providerName, nvl, providerType, setToken));
4002 }
4003
4004 /*
4005 * stmfGetProviderDataList
4006 *
4007 * Purpose: Get the list of providers currently persisting data
4008 *
4009 * providerList - pointer to pointer to an stmfProviderList structure allocated
4010 * by the caller. Will contain the list of providers on success.
4011 */
4012 int
4013 stmfGetProviderDataList(stmfProviderList **providerList)
4014 {
4015 int ret;
4016
4017 ret = psGetProviderDataList(providerList);
4018 switch (ret) {
4019 case STMF_PS_SUCCESS:
4020 ret = STMF_STATUS_SUCCESS;
4021 break;
4022 case STMF_PS_ERROR_BUSY:
4023 ret = STMF_ERROR_BUSY;
4024 break;
4025 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
4026 ret = STMF_ERROR_SERVICE_NOT_FOUND;
4027 break;
4028 case STMF_PS_ERROR_VERSION_MISMATCH:
4029 ret = STMF_ERROR_SERVICE_DATA_VERSION;
4030 break;
4031 default:
4032 syslog(LOG_DEBUG,
4033 "stmfGetProviderDataList:psGetProviderDataList"
4034 ":error(%d)", ret);
4035 ret = STMF_STATUS_ERROR;
4036 break;
4037 }
4038
4039 return (ret);
4040 }
4041
4042
4043 /*
4044 * stmfGetSessionList
4045 *
4046 * Purpose: Retrieves the session list for a target (devid)
4047 *
4048 * devid - devid of target for which to retrieve session information.
4049 * sessionList - pointer to pointer to stmfSessionList structure
4050 * on success, this contains the list of initiator sessions.
4051 */
4052 int
4053 stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
4054 {
4055 int ret = STMF_STATUS_SUCCESS;
4056 int fd;
4057 int ioctlRet;
4058 int cmd = STMF_IOCTL_SESSION_LIST;
4059 int i;
4060 stmf_iocdata_t stmfIoctl;
4061 slist_scsi_session_t *fSessionList, *fSessionListP = NULL;
4062 uint8_t ident[260];
4063 uint32_t fSessionListSize;
4064
4065 if (sessionList == NULL || devid == NULL) {
4066 ret = STMF_ERROR_INVALID_ARG;
4067 }
4068
4069 /* call init */
4070 ret = initializeConfig();
4071 if (ret != STMF_STATUS_SUCCESS) {
4072 return (ret);
4073 }
4074
4075 /*
4076 * Open control node for stmf
4077 */
4078 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4079 return (ret);
4080
4081 /*
4082 * Allocate ioctl input buffer
4083 */
4084 fSessionListSize = ALLOC_SESSION;
4085 fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
4086 fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
4087 fSessionListP = fSessionList;
4088 if (fSessionList == NULL) {
4089 ret = STMF_ERROR_NOMEM;
4090 goto done;
4091 }
4092
4093 ident[IDENT_LENGTH_BYTE] = devid->identLength;
4094 bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
4095 devid->identLength);
4096
4097 bzero(&stmfIoctl, sizeof (stmfIoctl));
4098 /*
4099 * Issue ioctl to get the session list
4100 */
4101 stmfIoctl.stmf_version = STMF_VERSION_1;
4102 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
4103 stmfIoctl.stmf_ibuf_size = sizeof (ident);
4104 stmfIoctl.stmf_obuf_size = fSessionListSize;
4105 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
4106 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4107 if (ioctlRet != 0) {
4108 switch (errno) {
4109 case EBUSY:
4110 ret = STMF_ERROR_BUSY;
4111 break;
4112 case EPERM:
4113 case EACCES:
4114 ret = STMF_ERROR_PERM;
4115 break;
4116 default:
4117 syslog(LOG_DEBUG,
4118 "stmfGetSessionList:ioctl errno(%d)",
4119 errno);
4120 ret = STMF_STATUS_ERROR;
4121 break;
4122 }
4123 goto done;
4124 }
4125 /*
4126 * Check whether input buffer was large enough
4127 */
4128 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
4129 fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
4130 sizeof (slist_scsi_session_t);
4131 fSessionList = realloc(fSessionList, fSessionListSize);
4132 if (fSessionList == NULL) {
4133 ret = STMF_ERROR_NOMEM;
4134 goto done;
4135 }
4136 fSessionListP = fSessionList;
4137 stmfIoctl.stmf_obuf_size = fSessionListSize;
4138 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
4139 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4140 if (ioctlRet != 0) {
4141 switch (errno) {
4142 case EBUSY:
4143 ret = STMF_ERROR_BUSY;
4144 break;
4145 case EPERM:
4146 case EACCES:
4147 ret = STMF_ERROR_PERM;
4148 break;
4149 default:
4150 syslog(LOG_DEBUG,
4151 "stmfGetSessionList:ioctl "
4152 "errno(%d)", errno);
4153 ret = STMF_STATUS_ERROR;
4154 break;
4155 }
4156 goto done;
4157 }
4158 }
4159
4160 /*
4161 * allocate caller's buffer with the final size
4162 */
4163 *sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
4164 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
4165 if (*sessionList == NULL) {
4166 ret = STMF_ERROR_NOMEM;
4167 free(sessionList);
4168 goto done;
4169 }
4170
4171 (*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
4172
4173 /*
4174 * copy session info to caller's buffer
4175 */
4176 for (i = 0; i < (*sessionList)->cnt; i++) {
4177 (*sessionList)->session[i].initiator.identLength =
4178 fSessionList->initiator[IDENT_LENGTH_BYTE];
4179 bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
4180 (*sessionList)->session[i].initiator.ident,
4181 STMF_IDENT_LENGTH);
4182 bcopy(&(fSessionList->alias),
4183 &((*sessionList)->session[i].alias),
4184 sizeof ((*sessionList)->session[i].alias));
4185 bcopy(&(fSessionList++->creation_time),
4186 &((*sessionList)->session[i].creationTime),
4187 sizeof (time_t));
4188 }
4189 done:
4190 (void) close(fd);
4191 free(fSessionListP);
4192 return (ret);
4193 }
4194
4195 /*
4196 * stmfGetTargetGroupList
4197 *
4198 * Purpose: Retrieves the list of target groups
4199 *
4200 * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
4201 * success, it contains the list of target groups.
4202 */
4203 int
4204 stmfGetTargetGroupList(stmfGroupList **targetGroupList)
4205 {
4206 int ret;
4207
4208 if (targetGroupList == NULL) {
4209 return (STMF_ERROR_INVALID_ARG);
4210 }
4211
4212 ret = groupListIoctl(targetGroupList, TARGET_GROUP);
4213 return (ret);
4214 }
4215
4216 /*
4217 * stmfGetTargetGroupMembers
4218 *
4219 * Purpose: Retrieves the group members for a target group
4220 *
4221 * groupName - name of target group for which to retrieve members.
4222 * groupProp - pointer to pointer to stmfGroupProperties structure
4223 * on success, this contains the list of group members.
4224 */
4225 int
4226 stmfGetTargetGroupMembers(stmfGroupName *groupName,
4227 stmfGroupProperties **groupProp)
4228 {
4229 int ret;
4230
4231 if (groupName == NULL || groupProp == NULL) {
4232 return (STMF_ERROR_INVALID_ARG);
4233 }
4234
4235 ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
4236
4237 return (ret);
4238 }
4239
4240 /*
4241 * stmfGetTargetList
4242 *
4243 * Purpose: Retrieves the list of target ports
4244 *
4245 * targetList - pointer to a pointer to an stmfDevidList structure.
4246 * On success, it contains the list of local ports (target).
4247 */
4248 int
4249 stmfGetTargetList(stmfDevidList **targetList)
4250 {
4251 int ret;
4252 int fd;
4253 int ioctlRet;
4254 int i;
4255 stmf_iocdata_t stmfIoctl;
4256 /* framework target port list */
4257 slist_target_port_t *fTargetList, *fTargetListP = NULL;
4258 uint32_t fTargetListSize;
4259
4260 if (targetList == NULL) {
4261 return (STMF_ERROR_INVALID_ARG);
4262 }
4263
4264 /* call init */
4265 ret = initializeConfig();
4266 if (ret != STMF_STATUS_SUCCESS) {
4267 return (ret);
4268 }
4269
4270 /*
4271 * Open control node for stmf
4272 */
4273 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4274 return (ret);
4275
4276 /*
4277 * Allocate ioctl input buffer
4278 */
4279 fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
4280 fTargetListP = fTargetList =
4281 (slist_target_port_t *)calloc(1, fTargetListSize);
4282 if (fTargetList == NULL) {
4283 ret = STMF_ERROR_NOMEM;
4284 goto done;
4285 }
4286
4287 bzero(&stmfIoctl, sizeof (stmfIoctl));
4288 /*
4289 * Issue ioctl to retrieve target list
4290 */
4291 stmfIoctl.stmf_version = STMF_VERSION_1;
4292 stmfIoctl.stmf_obuf_size = fTargetListSize;
4293 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
4294 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
4295 if (ioctlRet != 0) {
4296 switch (errno) {
4297 case EBUSY:
4298 ret = STMF_ERROR_BUSY;
4299 break;
4300 case EPERM:
4301 case EACCES:
4302 ret = STMF_ERROR_PERM;
4303 break;
4304 default:
4305 syslog(LOG_DEBUG,
4306 "stmfGetTargetList:ioctl errno(%d)", errno);
4307 ret = STMF_STATUS_ERROR;
4308 break;
4309 }
4310 goto done;
4311 }
4312 /*
4313 * Check whether input buffer was large enough
4314 */
4315 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
4316 fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
4317 sizeof (slist_target_port_t);
4318 fTargetListP = fTargetList =
4319 realloc(fTargetList, fTargetListSize);
4320 if (fTargetList == NULL) {
4321 ret = STMF_ERROR_NOMEM;
4322 goto done;
4323 }
4324 stmfIoctl.stmf_obuf_size = fTargetListSize;
4325 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
4326 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
4327 &stmfIoctl);
4328 if (ioctlRet != 0) {
4329 switch (errno) {
4330 case EBUSY:
4331 ret = STMF_ERROR_BUSY;
4332 break;
4333 case EPERM:
4334 case EACCES:
4335 ret = STMF_ERROR_PERM;
4336 break;
4337 default:
4338 syslog(LOG_DEBUG,
4339 "stmfGetTargetList:ioctl errno(%d)",
4340 errno);
4341 ret = STMF_STATUS_ERROR;
4342 break;
4343 }
4344 goto done;
4345 }
4346 }
4347
4348 *targetList = (stmfDevidList *)calloc(1,
4349 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
4350 sizeof (stmfDevidList));
4351 if (*targetList == NULL) {
4352 ret = STMF_ERROR_NOMEM;
4353 goto done;
4354 }
4355
4356 (*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
4357 for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
4358 (*targetList)->devid[i].identLength =
4359 fTargetList->target[IDENT_LENGTH_BYTE];
4360 bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
4361 &(*targetList)->devid[i].ident,
4362 fTargetList->target[IDENT_LENGTH_BYTE]);
4363 }
4364
4365 done:
4366 (void) close(fd);
4367 free(fTargetListP);
4368 return (ret);
4369 }
4370
4371 /*
4372 * stmfGetTargetProperties
4373 *
4374 * Purpose: Retrieves the properties for a logical unit
4375 *
4376 * devid - devid of the target for which to retrieve properties
4377 * targetProps - pointer to an stmfTargetProperties structure.
4378 * On success, it contains the target properties for
4379 * the specified devid.
4380 */
4381 int
4382 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
4383 {
4384 int ret = STMF_STATUS_SUCCESS;
4385 int fd;
4386 int ioctlRet;
4387 stmf_iocdata_t stmfIoctl;
4388 sioc_target_port_props_t targetProperties;
4389 scsi_devid_desc_t *scsiDevid;
4390
4391 if (devid == NULL || targetProps == NULL) {
4392 return (STMF_ERROR_INVALID_ARG);
4393 }
4394
4395 /* call init */
4396 ret = initializeConfig();
4397 if (ret != STMF_STATUS_SUCCESS) {
4398 return (ret);
4399 }
4400
4401 /*
4402 * Open control node for stmf
4403 */
4404 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4405 return (ret);
4406
4407 targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
4408 bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
4409 devid->identLength);
4410
4411 bzero(&stmfIoctl, sizeof (stmfIoctl));
4412 /*
4413 * Issue ioctl to add to the host group
4414 */
4415 stmfIoctl.stmf_version = STMF_VERSION_1;
4416 stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
4417 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
4418 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
4419 stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
4420 ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
4421 &stmfIoctl);
4422 if (ioctlRet != 0) {
4423 switch (errno) {
4424 case EBUSY:
4425 ret = STMF_ERROR_BUSY;
4426 break;
4427 case EPERM:
4428 case EACCES:
4429 ret = STMF_ERROR_PERM;
4430 break;
4431 case ENOENT:
4432 ret = STMF_ERROR_NOT_FOUND;
4433 break;
4434 default:
4435 syslog(LOG_DEBUG,
4436 "stmfGetTargetProperties:ioctl errno(%d)",
4437 errno);
4438 ret = STMF_STATUS_ERROR;
4439 break;
4440 }
4441 goto done;
4442 }
4443
4444 bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
4445 sizeof (targetProperties.tgt_provider_name));
4446 if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
4447 targetProps->status = STMF_TARGET_PORT_ONLINE;
4448 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
4449 targetProps->status = STMF_TARGET_PORT_OFFLINE;
4450 } else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
4451 targetProps->status = STMF_TARGET_PORT_ONLINING;
4452 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
4453 targetProps->status = STMF_TARGET_PORT_OFFLINING;
4454 }
4455 bcopy(targetProperties.tgt_alias, targetProps->alias,
4456 sizeof (targetProps->alias));
4457
4458 scsiDevid = (scsi_devid_desc_t *)&targetProperties.tgt_id;
4459 targetProps->protocol = scsiDevid->protocol_id;
4460
4461 done:
4462 (void) close(fd);
4463 return (ret);
4464 }
4465
4466 /*
4467 * stmfGetLogicalUnitList
4468 *
4469 * Purpose: Retrieves list of logical unit Object IDs
4470 *
4471 * luList - pointer to a pointer to a stmfGuidList structure. On success,
4472 * it contains the list of logical unit guids.
4473 *
4474 */
4475 int
4476 stmfGetLogicalUnitList(stmfGuidList **luList)
4477 {
4478 int ret;
4479 int fd;
4480 int ioctlRet;
4481 int cmd = STMF_IOCTL_LU_LIST;
4482 int i;
4483 stmf_iocdata_t stmfIoctl;
4484 slist_lu_t *fLuList;
4485 uint32_t fLuListSize;
4486 uint32_t listCnt;
4487
4488 if (luList == NULL) {
4489 return (STMF_ERROR_INVALID_ARG);
4490 }
4491
4492 /* call init */
4493 ret = initializeConfig();
4494 if (ret != STMF_STATUS_SUCCESS) {
4495 return (ret);
4496 }
4497
4498 /*
4499 * Open control node for stmf
4500 */
4501 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4502 return (ret);
4503
4504 /*
4505 * Allocate ioctl input buffer
4506 */
4507 fLuListSize = ALLOC_LU;
4508 fLuListSize = fLuListSize * (sizeof (slist_lu_t));
4509 fLuList = (slist_lu_t *)calloc(1, fLuListSize);
4510 if (fLuList == NULL) {
4511 ret = STMF_ERROR_NOMEM;
4512 goto done;
4513 }
4514
4515 bzero(&stmfIoctl, sizeof (stmfIoctl));
4516 /*
4517 * Issue ioctl to get the LU list
4518 */
4519 stmfIoctl.stmf_version = STMF_VERSION_1;
4520 stmfIoctl.stmf_obuf_size = fLuListSize;
4521 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
4522 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4523 if (ioctlRet != 0) {
4524 switch (errno) {
4525 case EBUSY:
4526 ret = STMF_ERROR_BUSY;
4527 break;
4528 case EPERM:
4529 case EACCES:
4530 ret = STMF_ERROR_PERM;
4531 break;
4532 default:
4533 syslog(LOG_DEBUG,
4534 "stmfGetLogicalUnitList:ioctl errno(%d)",
4535 errno);
4536 ret = STMF_STATUS_ERROR;
4537 break;
4538 }
4539 goto done;
4540 }
4541 /*
4542 * Check whether input buffer was large enough
4543 */
4544 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
4545 fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
4546 sizeof (slist_lu_t);
4547 free(fLuList);
4548 fLuList = (slist_lu_t *)calloc(1, fLuListSize);
4549 if (fLuList == NULL) {
4550 ret = STMF_ERROR_NOMEM;
4551 goto done;
4552 }
4553 stmfIoctl.stmf_obuf_size = fLuListSize;
4554 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
4555 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4556 if (ioctlRet != 0) {
4557 switch (errno) {
4558 case EBUSY:
4559 ret = STMF_ERROR_BUSY;
4560 break;
4561 case EPERM:
4562 case EACCES:
4563 ret = STMF_ERROR_PERM;
4564 break;
4565 default:
4566 syslog(LOG_DEBUG,
4567 "stmfGetLogicalUnitList:"
4568 "ioctl errno(%d)", errno);
4569 ret = STMF_STATUS_ERROR;
4570 break;
4571 }
4572 goto done;
4573 }
4574 }
4575
4576 if (ret != STMF_STATUS_SUCCESS) {
4577 goto done;
4578 }
4579
4580 listCnt = stmfIoctl.stmf_obuf_nentries;
4581
4582 /*
4583 * allocate caller's buffer with the final size
4584 */
4585 *luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
4586 listCnt * sizeof (stmfGuid));
4587 if (*luList == NULL) {
4588 ret = STMF_ERROR_NOMEM;
4589 goto done;
4590 }
4591
4592 (*luList)->cnt = listCnt;
4593
4594 /* copy to caller's buffer */
4595 for (i = 0; i < listCnt; i++) {
4596 bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
4597 sizeof (stmfGuid));
4598 }
4599
4600 /*
4601 * sort the list. This gives a consistent view across gets
4602 */
4603 qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
4604 sizeof (stmfGuid), guidCompare);
4605
4606 done:
4607 (void) close(fd);
4608 /*
4609 * free internal buffers
4610 */
4611 free(fLuList);
4612 return (ret);
4613 }
4614
4615 /*
4616 * stmfGetLogicalUnitProperties
4617 *
4618 * Purpose: Retrieves the properties for a logical unit
4619 *
4620 * lu - guid of the logical unit for which to retrieve properties
4621 * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
4622 * it contains the logical unit properties for the specified guid.
4623 */
4624 int
4625 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
4626 {
4627 int ret = STMF_STATUS_SUCCESS;
4628 int stmfRet;
4629 int fd;
4630 int ioctlRet;
4631 int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
4632 stmfViewEntryList *viewEntryList = NULL;
4633 stmf_iocdata_t stmfIoctl;
4634 sioc_lu_props_t fLuProps;
4635
4636 if (lu == NULL || luProps == NULL) {
4637 return (STMF_ERROR_INVALID_ARG);
4638 }
4639
4640 bzero(luProps, sizeof (stmfLogicalUnitProperties));
4641
4642 /* call init */
4643 ret = initializeConfig();
4644 if (ret != STMF_STATUS_SUCCESS) {
4645 return (ret);
4646 }
4647
4648 /*
4649 * Open control node for stmf
4650 */
4651 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4652 return (ret);
4653
4654 bzero(&stmfIoctl, sizeof (stmfIoctl));
4655 /*
4656 * Issue ioctl to add to the host group
4657 */
4658 stmfIoctl.stmf_version = STMF_VERSION_1;
4659 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
4660 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
4661 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
4662 stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
4663 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4664 if (ioctlRet != 0) {
4665 switch (errno) {
4666 case EBUSY:
4667 ret = STMF_ERROR_BUSY;
4668 break;
4669 case EPERM:
4670 case EACCES:
4671 ret = STMF_ERROR_PERM;
4672 break;
4673 case ENOENT:
4674 stmfRet = stmfGetViewEntryList(lu,
4675 &viewEntryList);
4676 if (stmfRet == STMF_STATUS_SUCCESS) {
4677 luProps->status =
4678 STMF_LOGICAL_UNIT_UNREGISTERED;
4679 if (viewEntryList->cnt > 0) {
4680 ret = STMF_STATUS_SUCCESS;
4681 } else {
4682 ret = STMF_ERROR_NOT_FOUND;
4683 }
4684 } else {
4685 ret = STMF_ERROR_NOT_FOUND;
4686 }
4687 stmfFreeMemory(viewEntryList);
4688 break;
4689 default:
4690 syslog(LOG_DEBUG,
4691 "stmfGetLogicalUnit:ioctl errno(%d)",
4692 errno);
4693 ret = STMF_STATUS_ERROR;
4694 break;
4695 }
4696 goto done;
4697 }
4698
4699 bcopy(fLuProps.lu_provider_name, luProps->providerName,
4700 sizeof (fLuProps.lu_provider_name));
4701 if (fLuProps.lu_state == STMF_STATE_ONLINE) {
4702 luProps->status = STMF_LOGICAL_UNIT_ONLINE;
4703 } else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
4704 luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
4705 } else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
4706 luProps->status = STMF_LOGICAL_UNIT_ONLINING;
4707 } else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
4708 luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
4709 }
4710 bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
4711 done:
4712 (void) close(fd);
4713 return (ret);
4714 }
4715
4716 /*
4717 * stmfGetState
4718 *
4719 * Purpose: retrieve the current state of the stmf module
4720 *
4721 * state - pointer to stmfState structure allocated by the caller
4722 * On success, contains the state of stmf
4723 */
4724 int
4725 stmfGetState(stmfState *state)
4726 {
4727 int ret;
4728 stmf_state_desc_t iState;
4729
4730 if (state == NULL) {
4731 return (STMF_ERROR_INVALID_ARG);
4732 }
4733
4734 ret = getStmfState(&iState);
4735 if (ret != STMF_STATUS_SUCCESS) {
4736 return (ret);
4737 }
4738 switch (iState.state) {
4739 case STMF_STATE_ONLINE:
4740 state->operationalState =
4741 STMF_SERVICE_STATE_ONLINE;
4742 break;
4743 case STMF_STATE_OFFLINE:
4744 state->operationalState =
4745 STMF_SERVICE_STATE_OFFLINE;
4746 break;
4747 case STMF_STATE_ONLINING:
4748 state->operationalState =
4749 STMF_SERVICE_STATE_ONLINING;
4750 break;
4751 case STMF_STATE_OFFLINING:
4752 state->operationalState =
4753 STMF_SERVICE_STATE_OFFLINING;
4754 break;
4755 default:
4756 state->operationalState =
4757 STMF_SERVICE_STATE_UNKNOWN;
4758 break;
4759 }
4760 switch (iState.config_state) {
4761 case STMF_CONFIG_NONE:
4762 state->configState = STMF_CONFIG_STATE_NONE;
4763 break;
4764 case STMF_CONFIG_INIT:
4765 state->configState = STMF_CONFIG_STATE_INIT;
4766 break;
4767 case STMF_CONFIG_INIT_DONE:
4768 state->configState =
4769 STMF_CONFIG_STATE_INIT_DONE;
4770 break;
4771 default:
4772 state->configState =
4773 STMF_CONFIG_STATE_UNKNOWN;
4774 break;
4775 }
4776 return (STMF_STATUS_SUCCESS);
4777 }
4778
4779 /*
4780 * stmfGetViewEntryList
4781 *
4782 * Purpose: Retrieves the list of view entries for the specified
4783 * logical unit.
4784 *
4785 * lu - the guid of the logical unit for which to retrieve the view entry list
4786 * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
4787 * success, contains the list of view entries.
4788 */
4789 int
4790 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
4791 {
4792 int ret;
4793 int fd;
4794 int ioctlRet;
4795 int cmd = STMF_IOCTL_LU_VE_LIST;
4796 int i;
4797 stmf_iocdata_t stmfIoctl;
4798 stmf_view_op_entry_t *fVeList;
4799 uint32_t fVeListSize;
4800 uint32_t listCnt;
4801
4802 if (lu == NULL || viewEntryList == NULL) {
4803 return (STMF_ERROR_INVALID_ARG);
4804 }
4805
4806 /* call init */
4807 ret = initializeConfig();
4808 if (ret != STMF_STATUS_SUCCESS) {
4809 return (ret);
4810 }
4811
4812 /*
4813 * Open control node for stmf
4814 */
4815 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4816 return (ret);
4817
4818 /*
4819 * Allocate ioctl input buffer
4820 */
4821 fVeListSize = ALLOC_VE;
4822 fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
4823 fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
4824 if (fVeList == NULL) {
4825 ret = STMF_ERROR_NOMEM;
4826 goto done;
4827 }
4828
4829 bzero(&stmfIoctl, sizeof (stmfIoctl));
4830 /*
4831 * Issue ioctl to get the LU list
4832 */
4833 stmfIoctl.stmf_version = STMF_VERSION_1;
4834 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
4835 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
4836 stmfIoctl.stmf_obuf_size = fVeListSize;
4837 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
4838 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4839 if (ioctlRet != 0) {
4840 switch (errno) {
4841 case EBUSY:
4842 ret = STMF_ERROR_BUSY;
4843 break;
4844 case EPERM:
4845 case EACCES:
4846 ret = STMF_ERROR_PERM;
4847 break;
4848 default:
4849 syslog(LOG_DEBUG,
4850 "stmfGetViewEntryList:ioctl errno(%d)",
4851 errno);
4852 ret = STMF_STATUS_ERROR;
4853 break;
4854 }
4855 goto done;
4856 }
4857 /*
4858 * Check whether input buffer was large enough
4859 */
4860 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
4861 bzero(&stmfIoctl, sizeof (stmfIoctl));
4862 fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
4863 sizeof (stmf_view_op_entry_t);
4864 free(fVeList);
4865 fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
4866 if (fVeList == NULL) {
4867 return (STMF_ERROR_NOMEM);
4868 }
4869 stmfIoctl.stmf_obuf_size = fVeListSize;
4870 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
4871 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4872 if (ioctlRet != 0) {
4873 switch (errno) {
4874 case EBUSY:
4875 ret = STMF_ERROR_BUSY;
4876 break;
4877 case EPERM:
4878 case EACCES:
4879 ret = STMF_ERROR_PERM;
4880 break;
4881 default:
4882 syslog(LOG_DEBUG,
4883 "stmfGetLogicalUnitList:"
4884 "ioctl errno(%d)", errno);
4885 ret = STMF_STATUS_ERROR;
4886 break;
4887 }
4888 goto done;
4889 }
4890 }
4891
4892 if (ret != STMF_STATUS_SUCCESS) {
4893 goto done;
4894 }
4895
4896 listCnt = stmfIoctl.stmf_obuf_nentries;
4897
4898 /*
4899 * allocate caller's buffer with the final size
4900 */
4901 *viewEntryList = (stmfViewEntryList *)calloc(1,
4902 sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
4903 if (*viewEntryList == NULL) {
4904 ret = STMF_ERROR_NOMEM;
4905 goto done;
4906 }
4907
4908 (*viewEntryList)->cnt = listCnt;
4909
4910 /* copy to caller's buffer */
4911 for (i = 0; i < listCnt; i++) {
4912 (*viewEntryList)->ve[i].veIndexValid = B_TRUE;
4913 (*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
4914 if (fVeList[i].ve_all_hosts == 1) {
4915 (*viewEntryList)->ve[i].allHosts = B_TRUE;
4916 } else {
4917 bcopy(fVeList[i].ve_host_group.name,
4918 (*viewEntryList)->ve[i].hostGroup,
4919 fVeList[i].ve_host_group.name_size);
4920 }
4921 if (fVeList[i].ve_all_targets == 1) {
4922 (*viewEntryList)->ve[i].allTargets = B_TRUE;
4923 } else {
4924 bcopy(fVeList[i].ve_target_group.name,
4925 (*viewEntryList)->ve[i].targetGroup,
4926 fVeList[i].ve_target_group.name_size);
4927 }
4928 bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
4929 sizeof ((*viewEntryList)->ve[i].luNbr));
4930 (*viewEntryList)->ve[i].luNbrValid = B_TRUE;
4931 }
4932
4933 /*
4934 * sort the list. This gives a consistent view across gets
4935 */
4936 qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
4937 sizeof (stmfViewEntry), viewEntryCompare);
4938
4939 done:
4940 (void) close(fd);
4941 /*
4942 * free internal buffers
4943 */
4944 free(fVeList);
4945 return (ret);
4946 }
4947
4948
4949 /*
4950 * loadHostGroups
4951 *
4952 * Purpose - issues the ioctl to load the host groups into stmf
4953 *
4954 * fd - file descriptor for the control node of stmf.
4955 * groupList - populated host group list
4956 */
4957 static int
4958 loadHostGroups(int fd, stmfGroupList *groupList)
4959 {
4960 int i, j;
4961 int ret = STMF_STATUS_SUCCESS;
4962 stmfGroupProperties *groupProps = NULL;
4963
4964 for (i = 0; i < groupList->cnt; i++) {
4965 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
4966 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
4967 goto out;
4968 }
4969 ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
4970 &groupProps, HOST_GROUP);
4971 for (j = 0; j < groupProps->cnt; j++) {
4972 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
4973 &(groupList->name[i]), &(groupProps->name[j])))
4974 != STMF_STATUS_SUCCESS) {
4975 goto out;
4976 }
4977 }
4978 }
4979
4980
4981 out:
4982 stmfFreeMemory(groupProps);
4983 return (ret);
4984 }
4985
4986 /*
4987 * loadTargetGroups
4988 *
4989 * Purpose - issues the ioctl to load the target groups into stmf
4990 *
4991 * fd - file descriptor for the control node of stmf.
4992 * groupList - populated target group list.
4993 */
4994 static int
4995 loadTargetGroups(int fd, stmfGroupList *groupList)
4996 {
4997 int i, j;
4998 int ret = STMF_STATUS_SUCCESS;
4999 stmfGroupProperties *groupProps = NULL;
5000
5001 for (i = 0; i < groupList->cnt; i++) {
5002 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
5003 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
5004 goto out;
5005 }
5006 ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
5007 &groupProps, TARGET_GROUP);
5008 for (j = 0; j < groupProps->cnt; j++) {
5009 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
5010 &(groupList->name[i]), &(groupProps->name[j])))
5011 != STMF_STATUS_SUCCESS) {
5012 goto out;
5013 }
5014 }
5015 }
5016
5017
5018 out:
5019 stmfFreeMemory(groupProps);
5020 return (ret);
5021 }
5022
5023
5024 /*
5025 * loadStore
5026 *
5027 * Purpose: Load the configuration data from the store
5028 *
5029 * First load the host groups and target groups, then the view entries
5030 * and finally the provider data
5031 *
5032 * fd - file descriptor of control node for stmf.
5033 */
5034 static int
5035 loadStore(int fd)
5036 {
5037 int ret;
5038 int i, j;
5039 stmfGroupList *groupList = NULL;
5040 stmfGuidList *guidList = NULL;
5041 stmfViewEntryList *viewEntryList = NULL;
5042 stmfProviderList *providerList = NULL;
5043 int providerType;
5044 nvlist_t *nvl = NULL;
5045
5046
5047
5048 /* load host groups */
5049 ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
5050 if (ret != STMF_STATUS_SUCCESS) {
5051 return (ret);
5052 }
5053 ret = loadHostGroups(fd, groupList);
5054 if (ret != STMF_STATUS_SUCCESS) {
5055 goto out;
5056 }
5057
5058 stmfFreeMemory(groupList);
5059 groupList = NULL;
5060
5061 /* load target groups */
5062 ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
5063 if (ret != STMF_STATUS_SUCCESS) {
5064 goto out;
5065 }
5066 ret = loadTargetGroups(fd, groupList);
5067 if (ret != STMF_STATUS_SUCCESS) {
5068 goto out;
5069 }
5070
5071 stmfFreeMemory(groupList);
5072 groupList = NULL;
5073
5074 /* Get the guid list */
5075 ret = psGetLogicalUnitList(&guidList);
5076 switch (ret) {
5077 case STMF_PS_SUCCESS:
5078 ret = STMF_STATUS_SUCCESS;
5079 break;
5080 case STMF_PS_ERROR_NOT_FOUND:
5081 ret = STMF_ERROR_NOT_FOUND;
5082 break;
5083 case STMF_PS_ERROR_BUSY:
5084 ret = STMF_ERROR_BUSY;
5085 break;
5086 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5087 ret = STMF_ERROR_SERVICE_NOT_FOUND;
5088 break;
5089 case STMF_PS_ERROR_VERSION_MISMATCH:
5090 ret = STMF_ERROR_SERVICE_DATA_VERSION;
5091 break;
5092 default:
5093 ret = STMF_STATUS_ERROR;
5094 break;
5095 }
5096
5097 if (ret != STMF_STATUS_SUCCESS) {
5098 goto out;
5099 }
5100
5101 /*
5102 * We have the guid list, now get the corresponding
5103 * view entries for each guid
5104 */
5105 for (i = 0; i < guidList->cnt; i++) {
5106 ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
5107 switch (ret) {
5108 case STMF_PS_SUCCESS:
5109 ret = STMF_STATUS_SUCCESS;
5110 break;
5111 case STMF_PS_ERROR_NOT_FOUND:
5112 ret = STMF_ERROR_NOT_FOUND;
5113 break;
5114 case STMF_PS_ERROR_BUSY:
5115 ret = STMF_ERROR_BUSY;
5116 break;
5117 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5118 ret = STMF_ERROR_SERVICE_NOT_FOUND;
5119 break;
5120 case STMF_PS_ERROR_VERSION_MISMATCH:
5121 ret = STMF_ERROR_SERVICE_DATA_VERSION;
5122 break;
5123 default:
5124 ret = STMF_STATUS_ERROR;
5125 break;
5126 }
5127 if (ret != STMF_STATUS_SUCCESS) {
5128 goto out;
5129 }
5130 for (j = 0; j < viewEntryList->cnt; j++) {
5131 ret = addViewEntryIoctl(fd, &guidList->guid[i],
5132 &viewEntryList->ve[j]);
5133 if (ret != STMF_STATUS_SUCCESS) {
5134 goto out;
5135 }
5136 }
5137 }
5138
5139 /* get the list of providers that have data */
5140 ret = psGetProviderDataList(&providerList);
5141 switch (ret) {
5142 case STMF_PS_SUCCESS:
5143 ret = STMF_STATUS_SUCCESS;
5144 break;
5145 case STMF_PS_ERROR_NOT_FOUND:
5146 ret = STMF_ERROR_NOT_FOUND;
5147 break;
5148 case STMF_PS_ERROR_BUSY:
5149 ret = STMF_ERROR_BUSY;
5150 break;
5151 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5152 ret = STMF_ERROR_SERVICE_NOT_FOUND;
5153 break;
5154 case STMF_PS_ERROR_VERSION_MISMATCH:
5155 ret = STMF_ERROR_SERVICE_DATA_VERSION;
5156 break;
5157 default:
5158 ret = STMF_STATUS_ERROR;
5159 break;
5160 }
5161 if (ret != STMF_STATUS_SUCCESS) {
5162 goto out;
5163 }
5164
5165 for (i = 0; i < providerList->cnt; i++) {
5166 providerType = providerList->provider[i].providerType;
5167 ret = psGetProviderData(providerList->provider[i].name,
5168 &nvl, providerType, NULL);
5169 switch (ret) {
5170 case STMF_PS_SUCCESS:
5171 ret = STMF_STATUS_SUCCESS;
5172 break;
5173 case STMF_PS_ERROR_NOT_FOUND:
5174 ret = STMF_ERROR_NOT_FOUND;
5175 break;
5176 case STMF_PS_ERROR_BUSY:
5177 ret = STMF_ERROR_BUSY;
5178 break;
5179 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5180 ret = STMF_ERROR_SERVICE_NOT_FOUND;
5181 break;
5182 case STMF_PS_ERROR_VERSION_MISMATCH:
5183 ret = STMF_ERROR_SERVICE_DATA_VERSION;
5184 break;
5185 default:
5186 ret = STMF_STATUS_ERROR;
5187 break;
5188 }
5189 if (ret != STMF_STATUS_SUCCESS) {
5190 goto out;
5191 }
5192
5193 /* call setProviderData */
5194 ret = setProviderData(fd, providerList->provider[i].name, nvl,
5195 providerType, NULL);
5196 switch (ret) {
5197 case STMF_PS_SUCCESS:
5198 ret = STMF_STATUS_SUCCESS;
5199 break;
5200 case STMF_PS_ERROR_NOT_FOUND:
5201 ret = STMF_ERROR_NOT_FOUND;
5202 break;
5203 case STMF_PS_ERROR_BUSY:
5204 ret = STMF_ERROR_BUSY;
5205 break;
5206 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5207 ret = STMF_ERROR_SERVICE_NOT_FOUND;
5208 break;
5209 case STMF_PS_ERROR_VERSION_MISMATCH:
5210 ret = STMF_ERROR_SERVICE_DATA_VERSION;
5211 break;
5212 default:
5213 ret = STMF_STATUS_ERROR;
5214 break;
5215 }
5216 if (ret != STMF_STATUS_SUCCESS) {
5217 goto out;
5218 }
5219
5220 nvlist_free(nvl);
5221 nvl = NULL;
5222 }
5223 out:
5224 if (groupList != NULL) {
5225 free(groupList);
5226 }
5227 if (guidList != NULL) {
5228 free(guidList);
5229 }
5230 if (viewEntryList != NULL) {
5231 free(viewEntryList);
5232 }
5233 if (nvl != NULL) {
5234 nvlist_free(nvl);
5235 }
5236 return (ret);
5237 }
5238
5239 /*
5240 * stmfGetAluaState
5241 *
5242 * Purpose - Get the alua state
5243 *
5244 */
5245 int
5246 stmfGetAluaState(boolean_t *enabled, uint32_t *node)
5247 {
5248 int ret = STMF_STATUS_SUCCESS;
5249 int fd;
5250 stmf_iocdata_t stmfIoctl = {0};
5251 stmf_alua_state_desc_t alua_state = {0};
5252 int ioctlRet;
5253
5254 if (enabled == NULL || node == NULL) {
5255 return (STMF_ERROR_INVALID_ARG);
5256 }
5257
5258 /*
5259 * Open control node for stmf
5260 */
5261 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5262 return (ret);
5263
5264 /*
5265 * Issue ioctl to get the stmf state
5266 */
5267 stmfIoctl.stmf_version = STMF_VERSION_1;
5268 stmfIoctl.stmf_obuf_size = sizeof (alua_state);
5269 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&alua_state;
5270 ioctlRet = ioctl(fd, STMF_IOCTL_GET_ALUA_STATE, &stmfIoctl);
5271
5272 (void) close(fd);
5273
5274 if (ioctlRet != 0) {
5275 switch (errno) {
5276 case EBUSY:
5277 ret = STMF_ERROR_BUSY;
5278 break;
5279 case EPERM:
5280 case EACCES:
5281 ret = STMF_ERROR_PERM;
5282 break;
5283 default:
5284 syslog(LOG_DEBUG,
5285 "getStmfState:ioctl errno(%d)", errno);
5286 ret = STMF_STATUS_ERROR;
5287 break;
5288 }
5289 } else {
5290 if (alua_state.alua_state == 1) {
5291 *enabled = B_TRUE;
5292 } else {
5293 *enabled = B_FALSE;
5294 }
5295 *node = alua_state.alua_node;
5296 }
5297
5298 return (ret);
5299 }
5300
5301 /*
5302 * stmfSetAluaState
5303 *
5304 * Purpose - set the alua state to enabled/disabled
5305 *
5306 */
5307 int
5308 stmfSetAluaState(boolean_t enabled, uint32_t node)
5309 {
5310 int ret = STMF_STATUS_SUCCESS;
5311 int fd;
5312 stmf_iocdata_t stmfIoctl = {0};
5313 stmf_alua_state_desc_t alua_state = {0};
5314 int ioctlRet;
5315
5316 if ((enabled != B_TRUE && enabled != B_FALSE) || (node > 1)) {
5317 return (STMF_ERROR_INVALID_ARG);
5318 }
5319
5320 if (enabled) {
5321 alua_state.alua_state = 1;
5322 }
5323
5324 alua_state.alua_node = node;
5325
5326 /*
5327 * Open control node for stmf
5328 */
5329 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5330 return (ret);
5331
5332 /*
5333 * Issue ioctl to get the stmf state
5334 */
5335 stmfIoctl.stmf_version = STMF_VERSION_1;
5336 stmfIoctl.stmf_ibuf_size = sizeof (alua_state);
5337 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&alua_state;
5338 ioctlRet = ioctl(fd, STMF_IOCTL_SET_ALUA_STATE, &stmfIoctl);
5339
5340 (void) close(fd);
5341
5342 if (ioctlRet != 0) {
5343 switch (errno) {
5344 case EBUSY:
5345 ret = STMF_ERROR_BUSY;
5346 break;
5347 case EPERM:
5348 case EACCES:
5349 ret = STMF_ERROR_PERM;
5350 break;
5351 default:
5352 syslog(LOG_DEBUG,
5353 "getStmfState:ioctl errno(%d)", errno);
5354 ret = STMF_STATUS_ERROR;
5355 break;
5356 }
5357 }
5358 if (!enabled && ret == STMF_STATUS_SUCCESS) {
5359 deleteNonActiveLus();
5360 }
5361
5362 return (ret);
5363 }
5364
5365 static void
5366 deleteNonActiveLus()
5367 {
5368 int stmfRet;
5369 int i;
5370 stmfGuidList *luList;
5371 luResource hdl = NULL;
5372 char propVal[10];
5373 size_t propValSize = sizeof (propVal);
5374
5375 stmfRet = stmfGetLogicalUnitList(&luList);
5376 if (stmfRet != STMF_STATUS_SUCCESS) {
5377 return;
5378 }
5379
5380 for (i = 0; i < luList->cnt; i++) {
5381 stmfRet = stmfGetLuResource(&luList->guid[i], &hdl);
5382 if (stmfRet != STMF_STATUS_SUCCESS) {
5383 goto err;
5384 }
5385 stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
5386 &propValSize);
5387 if (stmfRet != STMF_STATUS_SUCCESS) {
5388 goto err;
5389 }
5390 if (propVal[0] == '0') {
5391 (void) stmfFreeLuResource(hdl);
5392 hdl = NULL;
5393 continue;
5394 }
5395 (void) stmfDeleteLu(&luList->guid[i]);
5396 (void) stmfFreeLuResource(hdl);
5397 hdl = NULL;
5398 }
5399
5400 err:
5401 stmfFreeMemory(luList);
5402 (void) stmfFreeLuResource(hdl);
5403 }
5404
5405 /*
5406 * stmfLoadConfig
5407 *
5408 * Purpose - load the configuration data from smf into stmf
5409 *
5410 */
5411 int
5412 stmfLoadConfig(void)
5413 {
5414 int ret = STMF_STATUS_SUCCESS;
5415 int fd;
5416 stmf_state_desc_t stmfStateSet;
5417 stmfState state;
5418
5419 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5420 stmfStateSet.state = STMF_STATE_OFFLINE;
5421
5422 if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
5423 != STMF_STATUS_SUCCESS) {
5424 return (ret);
5425 }
5426 /*
5427 * Configuration not stored persistently; nothing to
5428 * initialize so do not set to STMF_CONFIG_INIT.
5429 */
5430 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
5431 goto done;
5432 }
5433
5434 /* Check to ensure service exists */
5435 if (psCheckService() != STMF_STATUS_SUCCESS) {
5436 return (STMF_ERROR_SERVICE_NOT_FOUND);
5437 }
5438
5439 ret = stmfGetState(&state);
5440 if (ret == STMF_STATUS_SUCCESS) {
5441 if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
5442 return (STMF_ERROR_SERVICE_ONLINE);
5443 }
5444 } else {
5445 return (STMF_STATUS_ERROR);
5446 }
5447
5448
5449 stmfStateSet.state = STMF_STATE_OFFLINE;
5450 stmfStateSet.config_state = STMF_CONFIG_INIT;
5451
5452 /*
5453 * Open control node for stmf
5454 */
5455 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5456 return (ret);
5457
5458 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
5459 if (ret != STMF_STATUS_SUCCESS) {
5460 goto done;
5461 }
5462
5463 /* Load the persistent configuration data */
5464 ret = loadStore(fd);
5465 if (ret != 0) {
5466 goto done;
5467 }
5468
5469 stmfStateSet.state = STMF_STATE_OFFLINE;
5470 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
5471
5472 done:
5473 if (ret == STMF_STATUS_SUCCESS) {
5474 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
5475 }
5476 (void) close(fd);
5477 return (ret);
5478 }
5479
5480
5481 /*
5482 * getStmfState
5483 *
5484 * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
5485 * information of the stmf service on success.
5486 */
5487 static int
5488 getStmfState(stmf_state_desc_t *stmfState)
5489 {
5490 int ret = STMF_STATUS_SUCCESS;
5491 int fd;
5492 int ioctlRet;
5493 stmf_iocdata_t stmfIoctl;
5494
5495 /*
5496 * Open control node for stmf
5497 */
5498 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5499 return (ret);
5500
5501 bzero(&stmfIoctl, sizeof (stmfIoctl));
5502 /*
5503 * Issue ioctl to get the stmf state
5504 */
5505 stmfIoctl.stmf_version = STMF_VERSION_1;
5506 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
5507 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
5508 stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
5509 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
5510 ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
5511
5512 (void) close(fd);
5513
5514 if (ioctlRet != 0) {
5515 switch (errno) {
5516 case EBUSY:
5517 ret = STMF_ERROR_BUSY;
5518 break;
5519 case EPERM:
5520 case EACCES:
5521 ret = STMF_ERROR_PERM;
5522 break;
5523 default:
5524 syslog(LOG_DEBUG,
5525 "getStmfState:ioctl errno(%d)", errno);
5526 ret = STMF_STATUS_ERROR;
5527 break;
5528 }
5529 }
5530 return (ret);
5531 }
5532
5533
5534 /*
5535 * setStmfState
5536 *
5537 * stmfState - pointer to caller set state structure
5538 * objectType - one of:
5539 * LOGICAL_UNIT_TYPE
5540 * TARGET_TYPE
5541 * STMF_SERVICE_TYPE
5542 */
5543 static int
5544 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
5545 {
5546 int ret = STMF_STATUS_SUCCESS;
5547 int ioctlRet;
5548 int cmd;
5549 stmf_iocdata_t stmfIoctl;
5550
5551 switch (objectType) {
5552 case LOGICAL_UNIT_TYPE:
5553 cmd = STMF_IOCTL_SET_LU_STATE;
5554 break;
5555 case TARGET_TYPE:
5556 cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
5557 break;
5558 case STMF_SERVICE_TYPE:
5559 cmd = STMF_IOCTL_SET_STMF_STATE;
5560 break;
5561 default:
5562 ret = STMF_STATUS_ERROR;
5563 goto done;
5564 }
5565
5566 bzero(&stmfIoctl, sizeof (stmfIoctl));
5567 /*
5568 * Issue ioctl to set the stmf state
5569 */
5570 stmfIoctl.stmf_version = STMF_VERSION_1;
5571 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
5572 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
5573 ioctlRet = ioctl(fd, cmd, &stmfIoctl);
5574 if (ioctlRet != 0) {
5575 switch (errno) {
5576 case EBUSY:
5577 ret = STMF_ERROR_BUSY;
5578 break;
5579 case EPERM:
5580 case EACCES:
5581 ret = STMF_ERROR_PERM;
5582 break;
5583 case ENOENT:
5584 ret = STMF_ERROR_NOT_FOUND;
5585 break;
5586 default:
5587 syslog(LOG_DEBUG,
5588 "setStmfState:ioctl errno(%d)", errno);
5589 ret = STMF_STATUS_ERROR;
5590 break;
5591 }
5592 }
5593 done:
5594 return (ret);
5595 }
5596 int
5597 stmfSetStmfProp(uint8_t propType, char *propVal)
5598 {
5599 int ret = STMF_STATUS_SUCCESS;
5600 switch (propType) {
5601 case STMF_DEFAULT_LU_STATE:
5602 break;
5603 case STMF_DEFAULT_TARGET_PORT_STATE:
5604 break;
5605 default:
5606 return (STMF_ERROR_INVALID_ARG);
5607 }
5608 ret = psSetStmfProp(propType, propVal);
5609 switch (ret) {
5610 case STMF_PS_SUCCESS:
5611 ret = STMF_STATUS_SUCCESS;
5612 break;
5613 case STMF_PS_ERROR_BUSY:
5614 ret = STMF_ERROR_BUSY;
5615 break;
5616 default:
5617 syslog(LOG_DEBUG,
5618 "stmfSetStmfProp:psSetStmfProp:error(%d)",
5619 ret);
5620 ret = STMF_STATUS_ERROR;
5621 break;
5622 }
5623 return (ret);
5624 }
5625
5626
5627 int
5628 stmfGetStmfProp(uint8_t propType, char *propVal, size_t *propLen)
5629 {
5630 int ret = STMF_STATUS_SUCCESS;
5631 char prop[MAXNAMELEN] = {0};
5632 size_t reqLen;
5633
5634 if (propVal == NULL || propLen == NULL) {
5635 return (STMF_ERROR_INVALID_ARG);
5636 }
5637 switch (propType) {
5638 case STMF_DEFAULT_LU_STATE:
5639 break;
5640 case STMF_DEFAULT_TARGET_PORT_STATE:
5641 break;
5642 default:
5643 return (STMF_ERROR_INVALID_ARG);
5644 }
5645 ret = psGetStmfProp(propType, prop);
5646 if ((reqLen = strlcpy(propVal, prop, *propLen)) >= *propLen) {
5647 *propLen = reqLen + 1;
5648 return (STMF_ERROR_INVALID_ARG);
5649 }
5650
5651 switch (ret) {
5652 case STMF_PS_SUCCESS:
5653 ret = STMF_STATUS_SUCCESS;
5654 break;
5655 case STMF_PS_ERROR_BUSY:
5656 ret = STMF_ERROR_BUSY;
5657 break;
5658 case STMF_PS_ERROR_NOT_FOUND:
5659 ret = STMF_ERROR_NOT_FOUND;
5660 break;
5661 default:
5662 syslog(LOG_DEBUG,
5663 "stmfGetStmfProp:psGetStmfProp:error(%d)",
5664 ret);
5665 ret = STMF_STATUS_ERROR;
5666 break;
5667 }
5668 return (ret);
5669 }
5670
5671 static int
5672 setStmfProp(stmf_set_props_t *stmf_set_props)
5673 {
5674 char propVal[MAXNAMELEN] = {0};
5675 int ret;
5676 if ((ret = psGetStmfProp(STMF_DEFAULT_LU_STATE, propVal)) ==
5677 STMF_PS_SUCCESS) {
5678 if (strncmp(propVal, "offline", strlen(propVal)) == 0) {
5679 stmf_set_props->default_lu_state_value =
5680 STMF_STATE_OFFLINE;
5681 } else {
5682 stmf_set_props->default_lu_state_value =
5683 STMF_STATE_ONLINE;
5684 }
5685 } else {
5686 syslog(LOG_DEBUG,
5687 "DefaultLuState:psSetStmfProp:error(%d)", ret);
5688 goto done;
5689 }
5690
5691 if ((ret = psGetStmfProp(STMF_DEFAULT_TARGET_PORT_STATE, propVal)) ==
5692 STMF_PS_SUCCESS) {
5693 if (strncmp(propVal, "offline", strlen(propVal)) == 0) {
5694 stmf_set_props->default_target_state_value =
5695 STMF_STATE_OFFLINE;
5696 } else {
5697 stmf_set_props->default_target_state_value =
5698 STMF_STATE_ONLINE;
5699 }
5700 } else {
5701 syslog(LOG_DEBUG,
5702 "DefaultTargetPortState:psSetStmfProp:error(%d)", ret);
5703 goto done;
5704 }
5705 done:
5706 switch (ret) {
5707 case STMF_PS_SUCCESS:
5708 ret = STMF_STATUS_SUCCESS;
5709 break;
5710 case STMF_PS_ERROR_NOT_FOUND:
5711 ret = STMF_ERROR_NOT_FOUND;
5712 break;
5713 case STMF_PS_ERROR_BUSY:
5714 ret = STMF_ERROR_BUSY;
5715 break;
5716 default:
5717 ret = STMF_STATUS_ERROR;
5718 break;
5719 }
5720 return (ret);
5721 }
5722
5723 static int
5724 loadStmfProp(int fd)
5725 {
5726 int ret = STMF_STATUS_SUCCESS;
5727 int ioctlRet;
5728 stmf_iocdata_t stmfIoctl = {0};
5729 stmf_set_props_t *stmf_set_props = NULL;
5730
5731 stmf_set_props = (stmf_set_props_t *)
5732 calloc(1, (sizeof (stmf_set_props_t)));
5733 if (stmf_set_props == NULL) {
5734 ret = STMF_ERROR_NOMEM;
5735 goto done;
5736 }
5737
5738 /* Loading the default property values from smf */
5739
5740 if ((ret = setStmfProp(stmf_set_props)) != STMF_STATUS_SUCCESS)
5741 goto done;
5742
5743 stmfIoctl.stmf_version = STMF_VERSION_1;
5744 stmfIoctl.stmf_ibuf_size = sizeof (stmf_set_props_t);
5745 stmfIoctl.stmf_ibuf =
5746 (uint64_t)(unsigned long)stmf_set_props;
5747
5748 ioctlRet = ioctl(fd, STMF_IOCTL_SET_STMF_PROPS,
5749 &stmfIoctl);
5750
5751 if (ioctlRet != 0) {
5752 switch (errno) {
5753 case EBUSY:
5754 ret = STMF_ERROR_BUSY;
5755 break;
5756 case EPERM:
5757 case EACCES:
5758 ret = STMF_ERROR_PERM;
5759 break;
5760 case ENOENT:
5761 ret = STMF_ERROR_NOT_FOUND;
5762 break;
5763 default:
5764 syslog(LOG_DEBUG,
5765 "setDefaultStmfState:"
5766 "ioctl errno(%d)", errno);
5767 ret = STMF_STATUS_ERROR;
5768 break;
5769 }
5770 }
5771 done:
5772 if (stmf_set_props != NULL) {
5773 free(stmf_set_props);
5774 }
5775 return (ret);
5776 }
5777
5778 int
5779 stmfLoadStmfProps(void)
5780 {
5781 int ret = STMF_STATUS_SUCCESS;
5782 int fd;
5783 /* open control node for stmf */
5784 if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
5785 != STMF_STATUS_SUCCESS) {
5786 goto done;
5787 }
5788 ret = loadStmfProp(fd);
5789
5790 (void) close(fd);
5791 done:
5792 if (ret != STMF_STATUS_SUCCESS) {
5793 syslog(LOG_DEBUG,
5794 "stmfLoadStmfProps:Failed");
5795 }
5796 return (ret);
5797 }
5798
5799 /*
5800 * stmfOnline
5801 *
5802 * Purpose: Online stmf service
5803 *
5804 */
5805 int
5806 stmfOnline(void)
5807 {
5808 int ret;
5809 int fd;
5810 stmfState state;
5811 stmf_state_desc_t iState;
5812
5813 ret = stmfGetState(&state);
5814 if (ret == STMF_STATUS_SUCCESS) {
5815 if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
5816 return (STMF_ERROR_SERVICE_ONLINE);
5817 }
5818 } else {
5819 return (STMF_STATUS_ERROR);
5820 }
5821 iState.state = STMF_STATE_ONLINE;
5822 iState.config_state = STMF_CONFIG_NONE;
5823 /*
5824 * Open control node for stmf
5825 * to make call to setStmfState()
5826 */
5827 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5828 return (ret);
5829 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
5830 (void) close(fd);
5831 return (ret);
5832 }
5833
5834 /*
5835 * stmfOffline
5836 *
5837 * Purpose: Offline stmf service
5838 *
5839 */
5840 int
5841 stmfOffline(void)
5842 {
5843 int ret;
5844 int fd;
5845 stmfState state;
5846 stmf_state_desc_t iState;
5847
5848 ret = stmfGetState(&state);
5849 if (ret == STMF_STATUS_SUCCESS) {
5850 if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
5851 return (STMF_ERROR_SERVICE_OFFLINE);
5852 }
5853 } else {
5854 return (STMF_STATUS_ERROR);
5855 }
5856 iState.state = STMF_STATE_OFFLINE;
5857 iState.config_state = STMF_CONFIG_NONE;
5858
5859 /*
5860 * Open control node for stmf
5861 * to make call to setStmfState()
5862 */
5863 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5864 return (ret);
5865 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
5866 (void) close(fd);
5867 return (ret);
5868 }
5869
5870
5871 /*
5872 * stmfOfflineTarget
5873 *
5874 * Purpose: Change state of target to offline
5875 *
5876 * devid - devid of the target to offline
5877 */
5878 int
5879 stmfOfflineTarget(stmfDevid *devid)
5880 {
5881 stmf_state_desc_t targetState;
5882 int ret = STMF_STATUS_SUCCESS;
5883 int fd;
5884
5885 if (devid == NULL) {
5886 return (STMF_ERROR_INVALID_ARG);
5887 }
5888 bzero(&targetState, sizeof (targetState));
5889
5890 targetState.state = STMF_STATE_OFFLINE;
5891 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
5892 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
5893 devid->identLength);
5894 /*
5895 * Open control node for stmf
5896 * to make call to setStmfState()
5897 */
5898 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5899 return (ret);
5900 ret = setStmfState(fd, &targetState, TARGET_TYPE);
5901 (void) close(fd);
5902 return (ret);
5903 }
5904
5905 /*
5906 * stmfOfflineLogicalUnit
5907 *
5908 * Purpose: Change state of logical unit to offline
5909 *
5910 * lu - guid of the logical unit to offline
5911 */
5912 int
5913 stmfOfflineLogicalUnit(stmfGuid *lu)
5914 {
5915 stmf_state_desc_t luState;
5916 int ret = STMF_STATUS_SUCCESS;
5917 int fd;
5918
5919 if (lu == NULL) {
5920 return (STMF_ERROR_INVALID_ARG);
5921 }
5922
5923 bzero(&luState, sizeof (luState));
5924
5925 luState.state = STMF_STATE_OFFLINE;
5926 bcopy(lu, &luState.ident, sizeof (stmfGuid));
5927 /*
5928 * Open control node for stmf
5929 * to make call to setStmfState()
5930 */
5931 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5932 return (ret);
5933 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
5934 (void) close(fd);
5935 return (ret);
5936 }
5937
5938 /*
5939 * stmfOnlineTarget
5940 *
5941 * Purpose: Change state of target to online
5942 *
5943 * devid - devid of the target to online
5944 */
5945 int
5946 stmfOnlineTarget(stmfDevid *devid)
5947 {
5948 stmf_state_desc_t targetState;
5949 int ret = STMF_STATUS_SUCCESS;
5950 int fd;
5951
5952 if (devid == NULL) {
5953 return (STMF_ERROR_INVALID_ARG);
5954 }
5955 bzero(&targetState, sizeof (targetState));
5956
5957 targetState.state = STMF_STATE_ONLINE;
5958 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
5959 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
5960 devid->identLength);
5961 /*
5962 * Open control node for stmf
5963 * to make call to setStmfState()
5964 */
5965 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5966 return (ret);
5967 ret = setStmfState(fd, &targetState, TARGET_TYPE);
5968 (void) close(fd);
5969 return (ret);
5970 }
5971
5972 /*
5973 * stmfOnlineLogicalUnit
5974 *
5975 * Purpose: Change state of logical unit to online
5976 *
5977 * lu - guid of the logical unit to online
5978 */
5979 int
5980 stmfOnlineLogicalUnit(stmfGuid *lu)
5981 {
5982 stmf_state_desc_t luState;
5983 int ret = STMF_STATUS_SUCCESS;
5984 int fd;
5985
5986 if (lu == NULL) {
5987 return (STMF_ERROR_INVALID_ARG);
5988 }
5989
5990 bzero(&luState, sizeof (luState));
5991
5992 luState.state = STMF_STATE_ONLINE;
5993 bcopy(lu, &luState.ident, sizeof (stmfGuid));
5994 /*
5995 * Open control node for stmf
5996 * to make call to setStmfState()
5997 */
5998 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5999 return (ret);
6000 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
6001 (void) close(fd);
6002 return (ret);
6003 }
6004
6005 /*
6006 * stmfRemoveFromHostGroup
6007 *
6008 * Purpose: Removes an initiator from an initiator group
6009 *
6010 * hostGroupName - name of an initiator group
6011 * hostName - name of host group member to remove
6012 */
6013 int
6014 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
6015 {
6016 int ret;
6017 int fd;
6018
6019 if (hostGroupName == NULL ||
6020 (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
6021 == sizeof (stmfGroupName)) || hostName == NULL) {
6022 return (STMF_ERROR_INVALID_ARG);
6023 }
6024
6025 /* call init */
6026 ret = initializeConfig();
6027 if (ret != STMF_STATUS_SUCCESS) {
6028 return (ret);
6029 }
6030
6031 /*
6032 * Open control node for stmf
6033 */
6034 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6035 return (ret);
6036
6037 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
6038 hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
6039 goto done;
6040 }
6041
6042 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
6043 goto done;
6044 }
6045
6046 ret = psRemoveHostGroupMember((char *)hostGroupName,
6047 (char *)hostName->ident);
6048 switch (ret) {
6049 case STMF_PS_SUCCESS:
6050 ret = STMF_STATUS_SUCCESS;
6051 break;
6052 case STMF_PS_ERROR_MEMBER_NOT_FOUND:
6053 ret = STMF_ERROR_MEMBER_NOT_FOUND;
6054 break;
6055 case STMF_PS_ERROR_GROUP_NOT_FOUND:
6056 ret = STMF_ERROR_GROUP_NOT_FOUND;
6057 break;
6058 case STMF_PS_ERROR_BUSY:
6059 ret = STMF_ERROR_BUSY;
6060 break;
6061 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6062 ret = STMF_ERROR_SERVICE_NOT_FOUND;
6063 break;
6064 case STMF_PS_ERROR_VERSION_MISMATCH:
6065 ret = STMF_ERROR_SERVICE_DATA_VERSION;
6066 break;
6067 default:
6068 syslog(LOG_DEBUG,
6069 "stmfRemoveFromHostGroup"
6070 "psRemoveHostGroupMember:error(%d)", ret);
6071 ret = STMF_STATUS_ERROR;
6072 break;
6073 }
6074
6075 done:
6076 (void) close(fd);
6077 return (ret);
6078 }
6079
6080 /*
6081 * stmfRemoveFromTargetGroup
6082 *
6083 * Purpose: Removes a local port from a local port group
6084 *
6085 * targetGroupName - name of a target group
6086 * targetName - name of target to remove
6087 */
6088 int
6089 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
6090 {
6091 int ret;
6092 int fd;
6093
6094 if (targetGroupName == NULL ||
6095 (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
6096 == sizeof (stmfGroupName)) || targetName == NULL) {
6097 return (STMF_ERROR_INVALID_ARG);
6098 }
6099
6100 /* call init */
6101 ret = initializeConfig();
6102 if (ret != STMF_STATUS_SUCCESS) {
6103 return (ret);
6104 }
6105
6106 /*
6107 * Open control node for stmf
6108 */
6109 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6110 return (ret);
6111
6112 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
6113 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
6114 goto done;
6115 }
6116
6117 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
6118 goto done;
6119 }
6120
6121 ret = psRemoveTargetGroupMember((char *)targetGroupName,
6122 (char *)targetName->ident);
6123 switch (ret) {
6124 case STMF_PS_SUCCESS:
6125 ret = STMF_STATUS_SUCCESS;
6126 break;
6127 case STMF_PS_ERROR_MEMBER_NOT_FOUND:
6128 ret = STMF_ERROR_MEMBER_NOT_FOUND;
6129 break;
6130 case STMF_PS_ERROR_GROUP_NOT_FOUND:
6131 ret = STMF_ERROR_GROUP_NOT_FOUND;
6132 break;
6133 case STMF_PS_ERROR_BUSY:
6134 ret = STMF_ERROR_BUSY;
6135 break;
6136 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6137 ret = STMF_ERROR_SERVICE_NOT_FOUND;
6138 break;
6139 case STMF_PS_ERROR_VERSION_MISMATCH:
6140 ret = STMF_ERROR_SERVICE_DATA_VERSION;
6141 break;
6142 default:
6143 syslog(LOG_DEBUG,
6144 "stmfRemoveFromTargetGroup"
6145 "psRemoveTargetGroupMember:error(%d)", ret);
6146 ret = STMF_STATUS_ERROR;
6147 break;
6148 }
6149
6150 done:
6151 (void) close(fd);
6152 return (ret);
6153 }
6154
6155 /*
6156 * stmfRemoveViewEntry
6157 *
6158 * Purpose: Removes a view entry from a logical unit
6159 *
6160 * lu - guid of lu for which view entry is being removed
6161 * viewEntryIndex - index of view entry to remove
6162 *
6163 */
6164 int
6165 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
6166 {
6167 int ret = STMF_STATUS_SUCCESS;
6168 int fd;
6169 int ioctlRet;
6170 stmf_iocdata_t stmfIoctl;
6171 stmf_view_op_entry_t ioctlViewEntry;
6172
6173 if (lu == NULL) {
6174 return (STMF_ERROR_INVALID_ARG);
6175 }
6176
6177 /* call init */
6178 ret = initializeConfig();
6179 if (ret != STMF_STATUS_SUCCESS) {
6180 return (ret);
6181 }
6182
6183 /*
6184 * Open control node for stmf
6185 */
6186 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6187 return (ret);
6188
6189 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
6190 ioctlViewEntry.ve_ndx_valid = B_TRUE;
6191 ioctlViewEntry.ve_ndx = viewEntryIndex;
6192 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
6193
6194 bzero(&stmfIoctl, sizeof (stmfIoctl));
6195 /*
6196 * Issue ioctl to add to the view entry
6197 */
6198 stmfIoctl.stmf_version = STMF_VERSION_1;
6199 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
6200 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6201 ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
6202 if (ioctlRet != 0) {
6203 switch (errno) {
6204 case EBUSY:
6205 ret = STMF_ERROR_BUSY;
6206 break;
6207 case EPERM:
6208 ret = STMF_ERROR_PERM;
6209 break;
6210 case EACCES:
6211 switch (stmfIoctl.stmf_error) {
6212 case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6213 ret = STMF_ERROR_CONFIG_NONE;
6214 break;
6215 default:
6216 ret = STMF_ERROR_PERM;
6217 break;
6218 }
6219 break;
6220 case ENODEV:
6221 case ENOENT:
6222 ret = STMF_ERROR_NOT_FOUND;
6223 break;
6224 default:
6225 syslog(LOG_DEBUG,
6226 "stmfRemoveViewEntry:ioctl errno(%d)",
6227 errno);
6228 ret = STMF_STATUS_ERROR;
6229 break;
6230 }
6231 goto done;
6232 }
6233
6234 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
6235 goto done;
6236 }
6237
6238 ret = psRemoveViewEntry(lu, viewEntryIndex);
6239 switch (ret) {
6240 case STMF_PS_SUCCESS:
6241 ret = STMF_STATUS_SUCCESS;
6242 break;
6243 case STMF_PS_ERROR_NOT_FOUND:
6244 ret = STMF_ERROR_NOT_FOUND;
6245 break;
6246 case STMF_PS_ERROR_BUSY:
6247 ret = STMF_ERROR_BUSY;
6248 break;
6249 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6250 ret = STMF_ERROR_SERVICE_NOT_FOUND;
6251 break;
6252 case STMF_PS_ERROR_VERSION_MISMATCH:
6253 ret = STMF_ERROR_SERVICE_DATA_VERSION;
6254 break;
6255 default:
6256 syslog(LOG_DEBUG,
6257 "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
6258 ret);
6259 ret = STMF_STATUS_ERROR;
6260 break;
6261 }
6262
6263 done:
6264 (void) close(fd);
6265 return (ret);
6266 }
6267
6268 /*
6269 * stmfSetProviderData
6270 *
6271 * Purpose: set the provider data
6272 *
6273 * providerName - unique name of provider
6274 * nvl - nvlist to set
6275 * providerType - type of provider for which to set data
6276 * STMF_LU_PROVIDER_TYPE
6277 * STMF_PORT_PROVIDER_TYPE
6278 */
6279 int
6280 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
6281 {
6282 return (stmfSetProviderDataProt(providerName, nvl, providerType,
6283 NULL));
6284 }
6285
6286 /*
6287 * stmfSetProviderDataProt
6288 *
6289 * Purpose: set the provider data
6290 *
6291 * providerName - unique name of provider
6292 * nvl - nvlist to set
6293 * providerType - type of provider for which to set data
6294 * STMF_LU_PROVIDER_TYPE
6295 * STMF_PORT_PROVIDER_TYPE
6296 * setToken - Stale data token returned in the stmfGetProviderDataProt()
6297 * call or NULL.
6298 */
6299 int
6300 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
6301 uint64_t *setToken)
6302 {
6303 int ret;
6304 int fd;
6305
6306 if (providerName == NULL || nvl == NULL) {
6307 return (STMF_ERROR_INVALID_ARG);
6308 }
6309
6310 if (providerType != STMF_LU_PROVIDER_TYPE &&
6311 providerType != STMF_PORT_PROVIDER_TYPE) {
6312 return (STMF_ERROR_INVALID_ARG);
6313 }
6314
6315 /* call init */
6316 ret = initializeConfig();
6317 if (ret != STMF_STATUS_SUCCESS) {
6318 return (ret);
6319 }
6320
6321 /*
6322 * Open control node for stmf
6323 */
6324 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6325 return (ret);
6326
6327 ret = setProviderData(fd, providerName, nvl, providerType, setToken);
6328
6329 (void) close(fd);
6330
6331 if (ret != STMF_STATUS_SUCCESS) {
6332 goto done;
6333 }
6334
6335 if (iGetPersistMethod() == STMF_PERSIST_NONE) {
6336 goto done;
6337 }
6338
6339 /* setting driver provider data successful. Now persist it */
6340 ret = psSetProviderData(providerName, nvl, providerType, NULL);
6341 switch (ret) {
6342 case STMF_PS_SUCCESS:
6343 ret = STMF_STATUS_SUCCESS;
6344 break;
6345 case STMF_PS_ERROR_EXISTS:
6346 ret = STMF_ERROR_EXISTS;
6347 break;
6348 case STMF_PS_ERROR_BUSY:
6349 ret = STMF_ERROR_BUSY;
6350 break;
6351 case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6352 ret = STMF_ERROR_SERVICE_NOT_FOUND;
6353 break;
6354 case STMF_PS_ERROR_VERSION_MISMATCH:
6355 ret = STMF_ERROR_SERVICE_DATA_VERSION;
6356 break;
6357 case STMF_PS_ERROR_PROV_DATA_STALE:
6358 ret = STMF_ERROR_PROV_DATA_STALE;
6359 break;
6360 default:
6361 syslog(LOG_DEBUG,
6362 "stmfSetProviderData"
6363 "psSetProviderData:error(%d)", ret);
6364 ret = STMF_STATUS_ERROR;
6365 break;
6366 }
6367
6368 done:
6369 return (ret);
6370 }
6371
6372 /*
6373 * getProviderData
6374 *
6375 * Purpose: set the provider data from stmf
6376 *
6377 * providerName - unique name of provider
6378 * nvl - nvlist to load/retrieve
6379 * providerType - logical unit or port provider
6380 * setToken - returned stale data token
6381 */
6382 int
6383 getProviderData(char *providerName, nvlist_t **nvl, int providerType,
6384 uint64_t *setToken)
6385 {
6386 int ret = STMF_STATUS_SUCCESS;
6387 int fd;
6388 int ioctlRet;
6389 size_t nvlistSize = ALLOC_PP_DATA_SIZE;
6390 int retryCnt = 0;
6391 int retryCntMax = MAX_PROVIDER_RETRY;
6392 stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
6393 boolean_t retry = B_TRUE;
6394 stmf_iocdata_t stmfIoctl;
6395
6396 if (providerName == NULL) {
6397 return (STMF_ERROR_INVALID_ARG);
6398 }
6399
6400 /*
6401 * Open control node for stmf
6402 */
6403 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6404 return (ret);
6405
6406 /* set provider name and provider type */
6407 if (strlcpy(ppi.ppi_name, providerName,
6408 sizeof (ppi.ppi_name)) >=
6409 sizeof (ppi.ppi_name)) {
6410 ret = STMF_ERROR_INVALID_ARG;
6411 goto done;
6412 }
6413 switch (providerType) {
6414 case STMF_LU_PROVIDER_TYPE:
6415 ppi.ppi_lu_provider = 1;
6416 break;
6417 case STMF_PORT_PROVIDER_TYPE:
6418 ppi.ppi_port_provider = 1;
6419 break;
6420 default:
6421 ret = STMF_ERROR_INVALID_ARG;
6422 goto done;
6423 }
6424
6425 do {
6426 /* allocate memory for ioctl */
6427 ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
6428 sizeof (stmf_ppioctl_data_t));
6429 if (ppi_out == NULL) {
6430 ret = STMF_ERROR_NOMEM;
6431 goto done;
6432
6433 }
6434
6435 /* set the size of the ioctl data to allocated buffer */
6436 ppi.ppi_data_size = nvlistSize;
6437
6438 bzero(&stmfIoctl, sizeof (stmfIoctl));
6439
6440 stmfIoctl.stmf_version = STMF_VERSION_1;
6441 stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
6442 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
6443 stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
6444 nvlistSize;
6445 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
6446 ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
6447 if (ioctlRet != 0) {
6448 switch (errno) {
6449 case EBUSY:
6450 ret = STMF_ERROR_BUSY;
6451 break;
6452 case EPERM:
6453 case EACCES:
6454 ret = STMF_ERROR_PERM;
6455 break;
6456 case EINVAL:
6457 if (stmfIoctl.stmf_error ==
6458 STMF_IOCERR_INSUFFICIENT_BUF) {
6459 nvlistSize =
6460 ppi_out->ppi_data_size;
6461 free(ppi_out);
6462 ppi_out = NULL;
6463 if (retryCnt++ > retryCntMax) {
6464 retry = B_FALSE;
6465 ret = STMF_ERROR_BUSY;
6466 } else {
6467 ret =
6468 STMF_STATUS_SUCCESS;
6469 }
6470 } else {
6471 syslog(LOG_DEBUG,
6472 "getProviderData:ioctl"
6473 "unable to retrieve "
6474 "nvlist");
6475 ret = STMF_STATUS_ERROR;
6476 }
6477 break;
6478 case ENOENT:
6479 ret = STMF_ERROR_NOT_FOUND;
6480 break;
6481 default:
6482 syslog(LOG_DEBUG,
6483 "getProviderData:ioctl errno(%d)",
6484 errno);
6485 ret = STMF_STATUS_ERROR;
6486 break;
6487 }
6488 if (ret != STMF_STATUS_SUCCESS)
6489 goto done;
6490 }
6491 } while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
6492
6493 if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
6494 ppi_out->ppi_data_size, nvl, 0)) != 0) {
6495 ret = STMF_STATUS_ERROR;
6496 goto done;
6497 }
6498
6499 /* caller has asked for new token */
6500 if (setToken) {
6501 *setToken = ppi_out->ppi_token;
6502 }
6503 done:
6504 free(ppi_out);
6505 (void) close(fd);
6506 return (ret);
6507 }
6508
6509 /*
6510 * setProviderData
6511 *
6512 * Purpose: set the provider data in stmf
6513 *
6514 * providerName - unique name of provider
6515 * nvl - nvlist to set
6516 * providerType - logical unit or port provider
6517 * setToken - stale data token to check if not NULL
6518 */
6519 static int
6520 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
6521 uint64_t *setToken)
6522 {
6523 int ret = STMF_STATUS_SUCCESS;
6524 int ioctlRet;
6525 size_t nvlistEncodedSize;
6526 stmf_ppioctl_data_t *ppi = NULL;
6527 uint64_t outToken;
6528 char *allocatedNvBuffer;
6529 stmf_iocdata_t stmfIoctl;
6530
6531 if (providerName == NULL) {
6532 return (STMF_ERROR_INVALID_ARG);
6533 }
6534
6535 /* get size of encoded nvlist */
6536 if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
6537 return (STMF_STATUS_ERROR);
6538 }
6539
6540 /* allocate memory for ioctl */
6541 ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
6542 sizeof (stmf_ppioctl_data_t));
6543 if (ppi == NULL) {
6544 return (STMF_ERROR_NOMEM);
6545 }
6546
6547 if (setToken) {
6548 ppi->ppi_token_valid = 1;
6549 ppi->ppi_token = *setToken;
6550 }
6551
6552 allocatedNvBuffer = (char *)&ppi->ppi_data;
6553 if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
6554 NV_ENCODE_XDR, 0) != 0) {
6555 return (STMF_STATUS_ERROR);
6556 }
6557
6558 /* set provider name and provider type */
6559 (void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
6560 switch (providerType) {
6561 case STMF_LU_PROVIDER_TYPE:
6562 ppi->ppi_lu_provider = 1;
6563 break;
6564 case STMF_PORT_PROVIDER_TYPE:
6565 ppi->ppi_port_provider = 1;
6566 break;
6567 default:
6568 return (STMF_ERROR_INVALID_ARG);
6569 }
6570
6571 /* set the size of the ioctl data to packed data size */
6572 ppi->ppi_data_size = nvlistEncodedSize;
6573
6574 bzero(&stmfIoctl, sizeof (stmfIoctl));
6575
6576 stmfIoctl.stmf_version = STMF_VERSION_1;
6577 /*
6578 * Subtracting 8 from the size as that is the size of the last member
6579 * of the structure where the packed data resides
6580 */
6581 stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
6582 sizeof (stmf_ppioctl_data_t) - 8;
6583 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
6584 stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
6585 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
6586 ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
6587 if (ioctlRet != 0) {
6588 switch (errno) {
6589 case EBUSY:
6590 ret = STMF_ERROR_BUSY;
6591 break;
6592 case EPERM:
6593 case EACCES:
6594 ret = STMF_ERROR_PERM;
6595 break;
6596 case EINVAL:
6597 if (stmfIoctl.stmf_error ==
6598 STMF_IOCERR_PPD_UPDATED) {
6599 ret = STMF_ERROR_PROV_DATA_STALE;
6600 } else {
6601 ret = STMF_STATUS_ERROR;
6602 }
6603 break;
6604 default:
6605 syslog(LOG_DEBUG,
6606 "setProviderData:ioctl errno(%d)", errno);
6607 ret = STMF_STATUS_ERROR;
6608 break;
6609 }
6610 if (ret != STMF_STATUS_SUCCESS)
6611 goto done;
6612 }
6613
6614 /* caller has asked for new token */
6615 if (setToken) {
6616 *setToken = outToken;
6617 }
6618 done:
6619 free(ppi);
6620 return (ret);
6621 }
6622
6623 /*
6624 * set the persistence method in the library only or library and service
6625 */
6626 int
6627 stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
6628 {
6629 int ret = STMF_STATUS_SUCCESS;
6630 int oldPersist;
6631
6632 (void) pthread_mutex_lock(&persistenceTypeLock);
6633 oldPersist = iPersistType;
6634 if (persistType == STMF_PERSIST_NONE ||
6635 persistType == STMF_PERSIST_SMF) {
6636 iLibSetPersist = B_TRUE;
6637 iPersistType = persistType;
6638 } else {
6639 (void) pthread_mutex_unlock(&persistenceTypeLock);
6640 return (STMF_ERROR_INVALID_ARG);
6641 }
6642 /* Is this for this library open or in SMF */
6643 if (serviceSet == B_TRUE) {
6644 ret = psSetServicePersist(persistType);
6645 if (ret != STMF_PS_SUCCESS) {
6646 ret = STMF_ERROR_PERSIST_TYPE;
6647 /* Set to old value */
6648 iPersistType = oldPersist;
6649 }
6650 }
6651 (void) pthread_mutex_unlock(&persistenceTypeLock);
6652
6653 return (ret);
6654 }
6655
6656 /*
6657 * Only returns internal state for persist. If unset, goes to ps. If that
6658 * fails, returns default setting
6659 */
6660 static uint8_t
6661 iGetPersistMethod()
6662 {
6663
6664 uint8_t persistType = 0;
6665
6666 (void) pthread_mutex_lock(&persistenceTypeLock);
6667 if (iLibSetPersist) {
6668 persistType = iPersistType;
6669 } else {
6670 int ret;
6671 ret = psGetServicePersist(&persistType);
6672 if (ret != STMF_PS_SUCCESS) {
6673 /* set to default */
6674 persistType = STMF_DEFAULT_PERSIST;
6675 }
6676 }
6677 (void) pthread_mutex_unlock(&persistenceTypeLock);
6678 return (persistType);
6679 }
6680
6681 /*
6682 * Returns either library state or persistent config state depending on
6683 * serviceState
6684 */
6685 int
6686 stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
6687 {
6688 int ret = STMF_STATUS_SUCCESS;
6689
6690 if (persistType == NULL) {
6691 return (STMF_ERROR_INVALID_ARG);
6692 }
6693 if (serviceState) {
6694 ret = psGetServicePersist(persistType);
6695 if (ret != STMF_PS_SUCCESS) {
6696 ret = STMF_ERROR_PERSIST_TYPE;
6697 }
6698 } else {
6699 (void) pthread_mutex_lock(&persistenceTypeLock);
6700 if (iLibSetPersist) {
6701 *persistType = iPersistType;
6702 } else {
6703 *persistType = STMF_DEFAULT_PERSIST;
6704 }
6705 (void) pthread_mutex_unlock(&persistenceTypeLock);
6706 }
6707
6708 return (ret);
6709 }
6710
6711 /*
6712 * stmfPostProxyMsg
6713 *
6714 * Purpose: Post a message to the proxy port provider
6715 *
6716 * buf - buffer containing message to post
6717 * buflen - buffer length
6718 */
6719 int
6720 stmfPostProxyMsg(int hdl, void *buf, uint32_t buflen)
6721 {
6722 int ret = STMF_STATUS_SUCCESS;
6723 int ioctlRet;
6724 pppt_iocdata_t ppptIoctl = {0};
6725
6726 if (buf == NULL) {
6727 return (STMF_ERROR_INVALID_ARG);
6728 }
6729
6730 /*
6731 * Issue ioctl to post the message
6732 */
6733 ppptIoctl.pppt_version = PPPT_VERSION_1;
6734 ppptIoctl.pppt_buf_size = buflen;
6735 ppptIoctl.pppt_buf = (uint64_t)(unsigned long)buf;
6736 ioctlRet = ioctl(hdl, PPPT_MESSAGE, &ppptIoctl);
6737 if (ioctlRet != 0) {
6738 switch (errno) {
6739 case EPERM:
6740 case EACCES:
6741 ret = STMF_ERROR_PERM;
6742 break;
6743 default:
6744 ret = STMF_ERROR_POST_MSG_FAILED;
6745 break;
6746 }
6747 }
6748
6749 return (ret);
6750 }
6751
6752 /*
6753 * stmfInitProxyDoor
6754 *
6755 * Purpose: Install door in proxy
6756 *
6757 * hdl - pointer to returned handle
6758 * fd - door from door_create()
6759 */
6760 int
6761 stmfInitProxyDoor(int *hdl, int door)
6762 {
6763 int ret = STMF_STATUS_SUCCESS;
6764 int ioctlRet;
6765 int fd;
6766 pppt_iocdata_t ppptIoctl = {0};
6767
6768 if (hdl == NULL) {
6769 return (STMF_ERROR_INVALID_ARG);
6770 }
6771
6772 /*
6773 * Open control node for pppt
6774 */
6775 if ((ret = openPppt(OPEN_PPPT, &fd)) != STMF_STATUS_SUCCESS) {
6776 return (ret);
6777 }
6778
6779 /*
6780 * Issue ioctl to install the door
6781 */
6782 ppptIoctl.pppt_version = PPPT_VERSION_1;
6783 ppptIoctl.pppt_door_fd = (uint32_t)door;
6784 ioctlRet = ioctl(fd, PPPT_INSTALL_DOOR, &ppptIoctl);
6785 if (ioctlRet != 0) {
6786 switch (errno) {
6787 case EPERM:
6788 case EACCES:
6789 ret = STMF_ERROR_PERM;
6790 break;
6791 case EINVAL:
6792 ret = STMF_ERROR_INVALID_ARG;
6793 break;
6794 case EBUSY:
6795 ret = STMF_ERROR_DOOR_INSTALLED;
6796 break;
6797 default:
6798 ret = STMF_STATUS_ERROR;
6799 break;
6800 }
6801 }
6802
6803 /* return driver fd to caller */
6804 *hdl = fd;
6805 return (ret);
6806 }
6807
6808 void
6809 stmfDestroyProxyDoor(int hdl)
6810 {
6811 (void) close(hdl);
6812 }
6813
6814 /*
6815 * validateLunNumIoctl
6816 *
6817 * Purpose: Issues ioctl to check and get available lun# in view entry
6818 *
6819 * viewEntry - view entry to use
6820 */
6821 static int
6822 validateLunNumIoctl(int fd, stmfViewEntry *viewEntry)
6823 {
6824 int ret = STMF_STATUS_SUCCESS;
6825 int ioctlRet;
6826 stmf_iocdata_t stmfIoctl;
6827 stmf_view_op_entry_t ioctlViewEntry;
6828
6829 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
6830 /*
6831 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
6832 * false on input
6833 */
6834 ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
6835 ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
6836 ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
6837
6838 if (viewEntry->allHosts == B_FALSE) {
6839 bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
6840 sizeof (stmfGroupName));
6841 ioctlViewEntry.ve_host_group.name_size =
6842 strlen((char *)viewEntry->hostGroup);
6843 }
6844 if (viewEntry->allTargets == B_FALSE) {
6845 bcopy(viewEntry->targetGroup,
6846 &ioctlViewEntry.ve_target_group.name,
6847 sizeof (stmfGroupName));
6848 ioctlViewEntry.ve_target_group.name_size =
6849 strlen((char *)viewEntry->targetGroup);
6850 }
6851 /* Validating the lun number */
6852 if (viewEntry->luNbrValid) {
6853 bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
6854 sizeof (ioctlViewEntry.ve_lu_nbr));
6855 }
6856
6857 bzero(&stmfIoctl, sizeof (stmfIoctl));
6858 /*
6859 * Issue ioctl to validate lun# in the view entry
6860 */
6861 stmfIoctl.stmf_version = STMF_VERSION_1;
6862 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
6863 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6864 stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
6865 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6866 ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl);
6867
6868 /* save available lun number */
6869 if (!viewEntry->luNbrValid) {
6870 bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
6871 sizeof (ioctlViewEntry.ve_lu_nbr));
6872 }
6873 if (ioctlRet != 0) {
6874 switch (errno) {
6875 case EBUSY:
6876 ret = STMF_ERROR_BUSY;
6877 break;
6878 case EPERM:
6879 ret = STMF_ERROR_PERM;
6880 break;
6881 case EACCES:
6882 switch (stmfIoctl.stmf_error) {
6883 case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6884 ret = STMF_ERROR_CONFIG_NONE;
6885 break;
6886 default:
6887 ret = STMF_ERROR_PERM;
6888 break;
6889 }
6890 break;
6891 default:
6892 switch (stmfIoctl.stmf_error) {
6893 case STMF_IOCERR_LU_NUMBER_IN_USE:
6894 ret = STMF_ERROR_LUN_IN_USE;
6895 break;
6896 case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
6897 ret = STMF_ERROR_VE_CONFLICT;
6898 break;
6899 case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6900 ret = STMF_ERROR_CONFIG_NONE;
6901 break;
6902 case STMF_IOCERR_INVALID_HG:
6903 ret = STMF_ERROR_INVALID_HG;
6904 break;
6905 case STMF_IOCERR_INVALID_TG:
6906 ret = STMF_ERROR_INVALID_TG;
6907 break;
6908 default:
6909 syslog(LOG_DEBUG,
6910 "addViewEntryIoctl"
6911 ":error(%d)",
6912 stmfIoctl.stmf_error);
6913 ret = STMF_STATUS_ERROR;
6914 break;
6915 }
6916 break;
6917 }
6918 }
6919 return (ret);
6920 }
6921
6922 /*
6923 * stmfValidateView
6924 *
6925 * Purpose: Validate or get lun # base on TG, HG of view entry
6926 *
6927 * viewEntry - view entry structure to use
6928 */
6929 int
6930 stmfValidateView(stmfViewEntry *viewEntry)
6931 {
6932 int ret;
6933 int fd;
6934 stmfViewEntry iViewEntry;
6935
6936 if (viewEntry == NULL) {
6937 return (STMF_ERROR_INVALID_ARG);
6938 }
6939
6940 /* initialize and set internal view entry */
6941 bzero(&iViewEntry, sizeof (iViewEntry));
6942
6943 if (!viewEntry->allHosts) {
6944 bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
6945 sizeof (iViewEntry.hostGroup));
6946 } else {
6947 iViewEntry.allHosts = B_TRUE;
6948 }
6949
6950 if (!viewEntry->allTargets) {
6951 bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
6952 sizeof (iViewEntry.targetGroup));
6953 } else {
6954 iViewEntry.allTargets = B_TRUE;
6955 }
6956
6957 if (viewEntry->luNbrValid) {
6958 iViewEntry.luNbrValid = B_TRUE;
6959 bcopy(viewEntry->luNbr, iViewEntry.luNbr,
6960 sizeof (iViewEntry.luNbr));
6961 }
6962
6963 /*
6964 * set users return view entry index valid flag to false
6965 * in case of failure
6966 */
6967 viewEntry->veIndexValid = B_FALSE;
6968
6969 /* Check to ensure service exists */
6970 if (psCheckService() != STMF_STATUS_SUCCESS) {
6971 return (STMF_ERROR_SERVICE_NOT_FOUND);
6972 }
6973
6974 /* call init */
6975 ret = initializeConfig();
6976 if (ret != STMF_STATUS_SUCCESS) {
6977 return (ret);
6978 }
6979
6980 /*
6981 * Open control node for stmf
6982 */
6983 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6984 return (ret);
6985
6986 /*
6987 * Validate lun# in the view entry from the driver
6988 */
6989 ret = validateLunNumIoctl(fd, &iViewEntry);
6990 (void) close(fd);
6991
6992 /* save available lun number */
6993 if (!viewEntry->luNbrValid) {
6994 bcopy(iViewEntry.luNbr, viewEntry->luNbr,
6995 sizeof (iViewEntry.luNbr));
6996 }
6997
6998 return (ret);
6999 }