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