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