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