PageRenderTime 208ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 1ms

/usr/src/lib/libstmf/common/store.c

https://bitbucket.org/nexenta/illumos-nexenta
C | 5385 lines | 3545 code | 513 blank | 1327 comment | 1281 complexity | 72cecf98ef8b788f39a4e83302e0ed76 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, AGPL-1.0, GPL-3.0, LGPL-3.0, BSD-2-Clause, AGPL-3.0, BSD-3-Clause, GPL-2.0, LGPL-2.1, 0BSD

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23. * Copyright 2012 Milan Jurik. All rights reserved.
  24. */
  25. #include <libscf.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <errno.h>
  29. #include <assert.h>
  30. #include <strings.h>
  31. #include <libstmf.h>
  32. #include <store.h>
  33. #include <syslog.h>
  34. #include <signal.h>
  35. #include <pthread.h>
  36. #include <libnvpair.h>
  37. #include <limits.h>
  38. #include <unistd.h>
  39. /*
  40. * This file's functions are responsible for all store and retrieve operations
  41. * against the STMF smf(5) database. The following shows the currently defined
  42. * schema for the STMF database:
  43. *
  44. * Description of property groups for service: svc:/system/stmf
  45. *
  46. * Stability: Volatile
  47. *
  48. * 1. Property Group: host_groups
  49. * Properties: group_name-<N> where <N> is an unsigned integer
  50. * type: ustring
  51. * contains: group name
  52. * group_name-<N>-member_list where <N> is an unsigned
  53. * integer matching a group_name-<N> property.
  54. * type: ustring
  55. * contains: list of members
  56. *
  57. * Description:
  58. * Contains the host group names as well as the host group members
  59. * for each host group.
  60. *
  61. * 2. Property Group: target_groups
  62. * Properties: group_name-<N> where <N> is an unsigned integer
  63. * type: ustring
  64. * contains: group name
  65. * group_name-<N>-member_list where <N> is an unsigned
  66. * integer matching a group_name-<N> property.
  67. * type: ustring
  68. * contains: list of members
  69. *
  70. * Description:
  71. * Contains the target group names as well as the target group
  72. * members for each target group.
  73. *
  74. * 3. Property Group: lu-<GUID>
  75. * where <GUID> is a 32 character hexadecimal string.
  76. * Properties: ve_cnt
  77. * type: count
  78. * contains: the number of current view entries
  79. * view-entry-<N>-<GUID> where <N> is an unsigned integer
  80. * type: ustring
  81. * contains: nothing. Used as reference to the view
  82. * entry property group
  83. *
  84. * Description:
  85. * Contains the references to each view entry. One lu-<GUID>
  86. * property group will exist for each logical unit with 1 or more
  87. * view entries.
  88. * Potentially can hold any other data that can be managed on a per
  89. * logical unit basis.
  90. *
  91. * 4. Property Group: view_entry-<N>-<GUID> (matches property in lu-<GUID>
  92. * property group)
  93. * Properties: all_hosts
  94. * type: boolean
  95. * contains: when true, the value of host_group is
  96. * ignored
  97. * all_targets
  98. * type: boolean
  99. * contains: when true, the value of target_group is
  100. * ignored
  101. * host_group
  102. * type: ustring
  103. * contains: host group for logical unit mapping and
  104. * masking purposes
  105. * target_group
  106. * type: ustring
  107. * contains: target group for logical unit mapping and
  108. * masking purposes
  109. * lu_nbr
  110. * type: opaque
  111. * contains: the 8-byte SCSI logical unit number for
  112. * mapping and masking purposes
  113. * Description:
  114. * One "view_entry-<N>-<GUID>" property group will exist for each
  115. * view entry in the system. This property group name maps
  116. * directly to the "lu-<GUID>" property group with a matching
  117. * <GUID>.
  118. *
  119. * 5. Property Group: provider_data_pg_<provider-name>
  120. * where <provider-name> is the name of the provider
  121. * registered with stmf.
  122. * Properties: provider_data_prop-<N>
  123. * where <N> is a sequential identifier for the data
  124. * chunk.
  125. * type: opaque
  126. * contains: up to STMF_PROVIDER_DATA_PROP_SIZE bytes
  127. * of nvlist packed data.
  128. * provider_data_count
  129. * type: count
  130. * contains: the number of provider data chunks
  131. * provider_data_type
  132. * type: integer
  133. * contains: STMF_PORT_PROVIDER_TYPE or
  134. * STMF_LU_PROVIDER_TYPE
  135. *
  136. * Description:
  137. * Holds the nvlist packed provider data set via
  138. * stmfSetProviderData and retrieved via stmfGetProviderData. Data
  139. * is stored in STMF_PROVIDER_DATA_PROP_SIZE chunks. On retrieve,
  140. * these chunks are reassembled and unpacked.
  141. *
  142. */
  143. static int iPsInit(scf_handle_t **, scf_service_t **);
  144. static int iPsCreateDeleteGroup(char *, char *, int);
  145. static int iPsAddRemoveGroupMember(char *, char *, char *, int);
  146. static int iPsGetGroupList(char *, stmfGroupList **);
  147. static int iPsGetGroupMemberList(char *, char *, stmfGroupProperties **);
  148. static int iPsAddViewEntry(char *, char *, stmfViewEntry *);
  149. static int iPsAddRemoveLuViewEntry(char *, char *, int);
  150. static int iPsGetViewEntry(char *, stmfViewEntry *);
  151. static int iPsGetActualGroupName(char *, char *, char *);
  152. static int iPsGetServiceVersion(uint64_t *, scf_handle_t *, scf_service_t *);
  153. static int iPsGetSetPersistType(uint8_t *, scf_handle_t *, scf_service_t *,
  154. int);
  155. static int iPsGetSetStmfProp(int, char *, int);
  156. static int viewEntryCompare(const void *, const void *);
  157. static int holdSignal(sigset_t *);
  158. static int releaseSignal(sigset_t *);
  159. static void sigHandler();
  160. static pthread_mutex_t sigSetLock = PTHREAD_MUTEX_INITIALIZER;
  161. sigset_t sigSet;
  162. sigset_t signalsCaught;
  163. struct sigaction currentActionQuit;
  164. struct sigaction currentActionTerm;
  165. struct sigaction currentActionInt;
  166. boolean_t actionSet = B_FALSE;
  167. /*
  168. * Version info for the SMF schema
  169. */
  170. #define STMF_SMF_VERSION 1
  171. /*
  172. * Note: Do not change these property names and size values.
  173. * They represent fields in the persistent config and once modified
  174. * will have a nasty side effect of invalidating the existing store.
  175. * If you do need to change them, you'll need to use the versioning above
  176. * to retain backward compatiblity with the previous configuration schema.
  177. */
  178. /* BEGIN STORE PROPERTY DEFINITIONS */
  179. /*
  180. * Property Group Names and prefixes
  181. */
  182. #define STMF_HOST_GROUPS "host_groups"
  183. #define STMF_TARGET_GROUPS "target_groups"
  184. #define STMF_VE_PREFIX "view_entry"
  185. #define STMF_LU_PREFIX "lu"
  186. #define STMF_DATA_GROUP "stmf_data"
  187. /*
  188. * Property names and prefix for logical unit property group
  189. */
  190. #define STMF_VE_CNT "ve_cnt"
  191. #define STMF_GROUP_PREFIX "group_name"
  192. #define STMF_MEMBER_LIST_SUFFIX "member_list"
  193. #define STMF_VERSION_NAME "version_name"
  194. #define STMF_PERSIST_TYPE "persist_method"
  195. /* Property names for stmf properties */
  196. #define DEFAULT_LU_STATE "default_lu_state"
  197. #define DEFAULT_TARGET_PORT_STATE "default_target_state"
  198. /*
  199. * Property names for view entry
  200. */
  201. #define STMF_VE_ALLHOSTS "all_hosts"
  202. #define STMF_VE_HOSTGROUP "host_group"
  203. #define STMF_VE_ALLTARGETS "all_targets"
  204. #define STMF_VE_TARGETGROUP "target_group"
  205. #define STMF_VE_LUNBR "lu_nbr"
  206. /* Property group suffix for provider data */
  207. #define STMF_PROVIDER_DATA_PREFIX "provider_data_pg_"
  208. #define STMF_PROVIDER_DATA_PROP_PREFIX "provider_data_prop"
  209. #define STMF_PROVIDER_DATA_PROP_NAME_SIZE 256
  210. #define STMF_PROVIDER_DATA_PROP_TYPE "provider_type"
  211. #define STMF_PROVIDER_DATA_PROP_SET_COUNT "provider_data_set_cnt"
  212. #define STMF_PROVIDER_DATA_PROP_COUNT "provider_data_cnt"
  213. #define STMF_SMF_READ_ATTR "solaris.smf.read.stmf"
  214. #define STMF_PS_PERSIST_NONE "none"
  215. #define STMF_PS_PERSIST_SMF "smf"
  216. #define STMF_PROVIDER_DATA_PROP_SIZE 4000
  217. #define STMF_PS_LU_ONLINE "default_lu_online"
  218. #define STMF_PS_LU_OFFLINE "default_lu_offline"
  219. #define STMF_PS_TARGET_PORT_ONLINE "default_target_online"
  220. #define STMF_PS_TARGET_PORT_OFFLINE "default_target_offline"
  221. /* END STORE PROPERTY DEFINITIONS */
  222. /* service name */
  223. #define STMF_SERVICE "system/stmf"
  224. /* limits and flag values */
  225. #define GROUP_MEMBER_ALLOC 100
  226. #define VIEW_ENTRY_STRUCT_CNT 6
  227. #define VIEW_ENTRY_PG_SIZE 256
  228. #define LOGICAL_UNIT_PG_SIZE 256
  229. #define VIEW_ENTRY_MAX UINT32_MAX
  230. #define GROUP_MAX UINT64_MAX
  231. #define ADD 0
  232. #define REMOVE 1
  233. #define GET 0
  234. #define SET 1
  235. /*
  236. * sigHandler
  237. *
  238. * Catch the signal and set the global signalsCaught to the signal received
  239. *
  240. * signalsCaught will be used by releaseSignal to raise this signal when
  241. * we're done processing our critical code.
  242. *
  243. */
  244. static void
  245. sigHandler(int sig)
  246. {
  247. (void) sigaddset(&signalsCaught, sig);
  248. }
  249. /*
  250. * iPsAddRemoveGroupMember
  251. *
  252. * Add or remove a member for a given group
  253. *
  254. * pgName - Property group name
  255. * groupName - group name to which the member is added/removed
  256. * memberName - member to be added/removed
  257. * addRemoveFlag - ADD/REMOVE
  258. *
  259. * returns:
  260. * STMF_PS_SUCCESS on success
  261. * STMF_PS_ERROR_* on failure
  262. */
  263. static int
  264. iPsAddRemoveGroupMember(char *pgName, char *groupName, char *memberName,
  265. int addRemoveFlag)
  266. {
  267. scf_handle_t *handle = NULL;
  268. scf_service_t *svc = NULL;
  269. scf_propertygroup_t *pg = NULL;
  270. scf_property_t *prop = NULL;
  271. scf_value_t *valueLookup = NULL;
  272. scf_value_t **valueSet = NULL;
  273. scf_iter_t *valueIter = NULL;
  274. scf_transaction_t *tran = NULL;
  275. scf_transaction_entry_t *entry = NULL;
  276. int i = 0;
  277. int lastAlloc;
  278. int valueArraySize = 0;
  279. int ret = STMF_PS_SUCCESS;
  280. char buf[STMF_IDENT_LENGTH];
  281. int commitRet;
  282. boolean_t found = B_FALSE;
  283. assert(pgName != NULL && groupName != NULL && memberName != NULL);
  284. /*
  285. * Init the service handle
  286. */
  287. ret = iPsInit(&handle, &svc);
  288. if (ret != STMF_PS_SUCCESS) {
  289. goto out;
  290. }
  291. /*
  292. * Allocate scf resources
  293. */
  294. if (((pg = scf_pg_create(handle)) == NULL) ||
  295. ((tran = scf_transaction_create(handle)) == NULL) ||
  296. ((entry = scf_entry_create(handle)) == NULL) ||
  297. ((prop = scf_property_create(handle)) == NULL) ||
  298. ((valueIter = scf_iter_create(handle)) == NULL)) {
  299. syslog(LOG_ERR, "scf alloc resource failed - %s",
  300. scf_strerror(scf_error()));
  301. ret = STMF_PS_ERROR;
  302. goto out;
  303. }
  304. /*
  305. * Get the service property group handle
  306. */
  307. if (scf_service_get_pg(svc, pgName, pg) == -1) {
  308. if (scf_error() == SCF_ERROR_NOT_FOUND) {
  309. ret = STMF_PS_ERROR_NOT_FOUND;
  310. } else {
  311. ret = STMF_PS_ERROR;
  312. }
  313. syslog(LOG_ERR, "get pg %s failed - %s",
  314. pgName, scf_strerror(scf_error()));
  315. goto out;
  316. }
  317. /*
  318. * Begin the transaction
  319. */
  320. if (scf_transaction_start(tran, pg) == -1) {
  321. syslog(LOG_ERR, "start transaction for %s failed - %s",
  322. pgName, scf_strerror(scf_error()));
  323. ret = STMF_PS_ERROR;
  324. goto out;
  325. }
  326. /*
  327. * We're changing an existing property by adding a propval
  328. * There are no add semantics in libscf for a property value. We'll
  329. * need to read in the current properties and apply them all to the
  330. * set and then add the one we were asked to add or omit the one
  331. * we were asked to remove.
  332. */
  333. if (scf_transaction_property_change(tran, entry, groupName,
  334. SCF_TYPE_USTRING) == -1) {
  335. if (scf_error() == SCF_ERROR_NOT_FOUND) {
  336. ret = STMF_PS_ERROR_GROUP_NOT_FOUND;
  337. } else {
  338. ret = STMF_PS_ERROR;
  339. syslog(LOG_ERR, "tran property change %s/%s "
  340. "failed - %s", pgName, groupName,
  341. scf_strerror(scf_error()));
  342. }
  343. goto out;
  344. }
  345. /*
  346. * Get the property handle
  347. */
  348. if (scf_pg_get_property(pg, groupName, prop) == -1) {
  349. syslog(LOG_ERR, "get property %s/%s failed - %s",
  350. pgName, groupName, scf_strerror(scf_error()));
  351. ret = STMF_PS_ERROR;
  352. goto out;
  353. }
  354. /*
  355. * Value lookup is used to lookup the existing values
  356. */
  357. valueLookup = scf_value_create(handle);
  358. if (valueLookup == NULL) {
  359. syslog(LOG_ERR, "scf value alloc for %s failed - %s",
  360. pgName, scf_strerror(scf_error()));
  361. ret = STMF_PS_ERROR;
  362. goto out;
  363. }
  364. /*
  365. * valueIter is the iterator handle, create the resource
  366. */
  367. if (scf_iter_property_values(valueIter, prop) == -1) {
  368. syslog(LOG_ERR, "iter values for %s/%s failed - %s",
  369. pgName, groupName, scf_strerror(scf_error()));
  370. ret = STMF_PS_ERROR;
  371. goto out;
  372. }
  373. /*
  374. * Allocate value resource pointers.
  375. * We need a value resource for each value as value pointers passed
  376. * to libscf cannot be destroyed until the commit or destroy on the
  377. * transaction is done.
  378. *
  379. * We're using GROUP_MEMBER_ALLOC initially. If it's not large
  380. * enough, we'll realloc on the fly
  381. */
  382. valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet)
  383. * (lastAlloc = GROUP_MEMBER_ALLOC));
  384. if (valueSet == NULL) {
  385. ret = STMF_PS_ERROR_NOMEM;
  386. goto out;
  387. }
  388. /*
  389. * Iterate through the existing values
  390. */
  391. while (scf_iter_next_value(valueIter, valueLookup) == 1) {
  392. bzero(buf, sizeof (buf));
  393. if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) {
  394. syslog(LOG_ERR, "iter %s/%s value failed - %s",
  395. pgName, groupName, scf_strerror(scf_error()));
  396. ret = STMF_PS_ERROR;
  397. break;
  398. }
  399. /*
  400. * Check for existing
  401. * If we're adding, it's an error
  402. * If we're removing, we skip it and simply not
  403. * add it to the set. Subtraction by omission.
  404. */
  405. if ((strlen(buf) == strlen(memberName)) &&
  406. bcmp(buf, memberName, strlen(buf)) == 0) {
  407. if (addRemoveFlag == ADD) {
  408. ret = STMF_PS_ERROR_EXISTS;
  409. break;
  410. } else {
  411. found = B_TRUE;
  412. continue;
  413. }
  414. }
  415. /*
  416. * Create the value resource for this iteration
  417. */
  418. valueSet[i] = scf_value_create(handle);
  419. if (valueSet[i] == NULL) {
  420. syslog(LOG_ERR, "scf value alloc for %s failed - %s",
  421. pgName, scf_strerror(scf_error()));
  422. ret = STMF_PS_ERROR;
  423. break;
  424. }
  425. /*
  426. * Set the value
  427. */
  428. if (scf_value_set_ustring(valueSet[i], buf) == -1) {
  429. syslog(LOG_ERR, "set value for %s/%s failed - %s",
  430. pgName, groupName, scf_strerror(scf_error()));
  431. ret = STMF_PS_ERROR;
  432. break;
  433. }
  434. /*
  435. * Now add the value
  436. */
  437. if (scf_entry_add_value(entry, valueSet[i]) == -1) {
  438. syslog(LOG_ERR, "add value for %s/%s failed - %s",
  439. pgName, groupName, scf_strerror(scf_error()));
  440. ret = STMF_PS_ERROR;
  441. break;
  442. }
  443. i++;
  444. /*
  445. * realloc if we've hit the previous alloc size
  446. */
  447. if (i >= lastAlloc) {
  448. lastAlloc += GROUP_MEMBER_ALLOC;
  449. valueSet = realloc(valueSet,
  450. sizeof (*valueSet) * lastAlloc);
  451. if (valueSet == NULL) {
  452. ret = STMF_PS_ERROR;
  453. break;
  454. }
  455. }
  456. }
  457. /*
  458. * set valueArraySize to final allocated length
  459. * so we can use it to destroy the resources correctly
  460. */
  461. valueArraySize = i;
  462. if (!found && (addRemoveFlag == REMOVE)) {
  463. ret = STMF_PS_ERROR_MEMBER_NOT_FOUND;
  464. }
  465. if (ret != STMF_PS_SUCCESS) {
  466. goto out;
  467. }
  468. /*
  469. * If we're adding, we have one more step. Add the member to the
  470. * propval list
  471. */
  472. if (addRemoveFlag == ADD) {
  473. /*
  474. * Now create the new entry
  475. */
  476. valueSet[i] = scf_value_create(handle);
  477. if (valueSet[i] == NULL) {
  478. syslog(LOG_ERR, "scf value alloc for %s/%s failed - %s",
  479. pgName, groupName, scf_strerror(scf_error()));
  480. ret = STMF_PS_ERROR;
  481. goto out;
  482. } else {
  483. valueArraySize++;
  484. }
  485. /*
  486. * Set the new member name
  487. */
  488. if (scf_value_set_ustring(valueSet[i], memberName) == -1) {
  489. syslog(LOG_ERR, "set value for %s/%s failed - %s",
  490. pgName, groupName, scf_strerror(scf_error()));
  491. ret = STMF_PS_ERROR;
  492. goto out;
  493. }
  494. /*
  495. * Add the new member
  496. */
  497. if (scf_entry_add_value(entry, valueSet[i]) == -1) {
  498. syslog(LOG_ERR, "add value for %s/%s failed - %s",
  499. pgName, groupName, scf_strerror(scf_error()));
  500. ret = STMF_PS_ERROR;
  501. goto out;
  502. }
  503. }
  504. /*
  505. * Yes, we're finally done. We actually added or removed one entry
  506. * from the list.
  507. * Woohoo!
  508. */
  509. if ((commitRet = scf_transaction_commit(tran)) != 1) {
  510. syslog(LOG_ERR, "transaction commit for %s failed - %s",
  511. pgName, scf_strerror(scf_error()));
  512. if (commitRet == 0) {
  513. ret = STMF_PS_ERROR_BUSY;
  514. } else {
  515. ret = STMF_PS_ERROR;
  516. }
  517. goto out;
  518. }
  519. out:
  520. /*
  521. * Free resources
  522. */
  523. if (handle != NULL) {
  524. scf_handle_destroy(handle);
  525. }
  526. if (svc != NULL) {
  527. scf_service_destroy(svc);
  528. }
  529. if (pg != NULL) {
  530. scf_pg_destroy(pg);
  531. }
  532. if (tran != NULL) {
  533. scf_transaction_destroy(tran);
  534. }
  535. if (entry != NULL) {
  536. scf_entry_destroy(entry);
  537. }
  538. if (prop != NULL) {
  539. scf_property_destroy(prop);
  540. }
  541. if (valueLookup != NULL) {
  542. scf_value_destroy(valueLookup);
  543. }
  544. if (valueIter != NULL) {
  545. scf_iter_destroy(valueIter);
  546. }
  547. /*
  548. * Free valueSet scf resources
  549. */
  550. if (valueArraySize > 0) {
  551. for (i = 0; i < valueArraySize; i++) {
  552. scf_value_destroy(valueSet[i]);
  553. }
  554. }
  555. /*
  556. * Now free the pointer array to the resources
  557. */
  558. if (valueSet != NULL) {
  559. free(valueSet);
  560. }
  561. return (ret);
  562. }
  563. /*
  564. * iPsAddRemoveLuViewEntry
  565. *
  566. * Adds or removes a view entry name property for a given logical unit
  567. * property group. There is one logical unit property group for every logical
  568. * unit that has one or more associated view entries.
  569. *
  570. * luPgName - Property group name of logical unit
  571. * viewEntryPgName - Property group name of view entry
  572. * addRemoveFlag - ADD_VE/REMOVE_VE
  573. *
  574. * returns:
  575. * STMF_PS_SUCCESS on success
  576. * STMF_PS_ERROR_* on failure
  577. */
  578. static int
  579. iPsAddRemoveLuViewEntry(char *luPgName, char *viewEntryPgName,
  580. int addRemoveFlag)
  581. {
  582. scf_handle_t *handle = NULL;
  583. scf_service_t *svc = NULL;
  584. scf_propertygroup_t *pg = NULL;
  585. scf_property_t *prop = NULL;
  586. scf_value_t *value = NULL;
  587. scf_transaction_t *tran = NULL;
  588. scf_transaction_entry_t *entry = NULL;
  589. scf_transaction_entry_t *entryVeName = NULL;
  590. boolean_t createVeCnt = B_FALSE;
  591. uint64_t veCnt = 0;
  592. int ret = STMF_PS_SUCCESS;
  593. int commitRet;
  594. assert(luPgName != NULL || viewEntryPgName != NULL);
  595. assert(!(addRemoveFlag != ADD && addRemoveFlag != REMOVE));
  596. /*
  597. * Init the service handle
  598. */
  599. ret = iPsInit(&handle, &svc);
  600. if (ret != STMF_PS_SUCCESS) {
  601. goto out;
  602. }
  603. /*
  604. * Allocate scf resources
  605. */
  606. if (((pg = scf_pg_create(handle)) == NULL) ||
  607. ((tran = scf_transaction_create(handle)) == NULL) ||
  608. ((entry = scf_entry_create(handle)) == NULL) ||
  609. ((prop = scf_property_create(handle)) == NULL) ||
  610. ((value = scf_value_create(handle)) == NULL)) {
  611. syslog(LOG_ERR, "scf alloc resource failed - %s",
  612. scf_strerror(scf_error()));
  613. ret = STMF_PS_ERROR;
  614. goto out;
  615. }
  616. /* get the LU property group */
  617. if (scf_service_get_pg(svc, luPgName, pg) == -1) {
  618. if (scf_error() == SCF_ERROR_NOT_FOUND &&
  619. addRemoveFlag == ADD) {
  620. /* if it doesn't exist, create it */
  621. if (scf_service_add_pg(svc, luPgName,
  622. SCF_GROUP_APPLICATION, 0, pg) == -1) {
  623. syslog(LOG_ERR, "add pg %s failed - %s",
  624. luPgName, scf_strerror(scf_error()));
  625. ret = STMF_PS_ERROR;
  626. } else {
  627. /* we need to create the VE_CNT property */
  628. createVeCnt = B_TRUE;
  629. ret = STMF_PS_SUCCESS;
  630. }
  631. } else if (scf_error() == SCF_ERROR_NOT_FOUND) {
  632. ret = STMF_PS_ERROR_NOT_FOUND;
  633. } else {
  634. syslog(LOG_ERR, "get lu pg %s failed - %s",
  635. luPgName, scf_strerror(scf_error()));
  636. ret = STMF_PS_ERROR;
  637. }
  638. if (ret != STMF_PS_SUCCESS) {
  639. goto out;
  640. }
  641. }
  642. /*
  643. * Begin the transaction
  644. */
  645. if (scf_transaction_start(tran, pg) == -1) {
  646. syslog(LOG_ERR, "start transaction for %s failed - %s",
  647. luPgName, scf_strerror(scf_error()));
  648. ret = STMF_PS_ERROR;
  649. goto out;
  650. }
  651. if (createVeCnt) {
  652. /*
  653. * Create the STMF_VE_CNT property. This will keep the current
  654. * total view entries for this logical unit.
  655. */
  656. if (scf_transaction_property_new(tran, entry, STMF_VE_CNT,
  657. SCF_TYPE_COUNT) == -1) {
  658. if (scf_error() == SCF_ERROR_EXISTS) {
  659. ret = STMF_PS_ERROR_EXISTS;
  660. } else {
  661. syslog(LOG_ERR,
  662. "transaction property new %s/%s "
  663. "failed - %s", luPgName, STMF_VE_CNT,
  664. scf_strerror(scf_error()));
  665. ret = STMF_PS_ERROR;
  666. }
  667. goto out;
  668. }
  669. } else {
  670. /*
  671. * The STMF_VE_CNT property already exists. Just update
  672. * it.
  673. */
  674. if (scf_transaction_property_change(tran, entry,
  675. STMF_VE_CNT, SCF_TYPE_COUNT) == -1) {
  676. syslog(LOG_ERR, "transaction property %s/%s change "
  677. "failed - %s", luPgName, STMF_VE_CNT,
  678. scf_strerror(scf_error()));
  679. ret = STMF_PS_ERROR;
  680. goto out;
  681. }
  682. /*
  683. * Get the STMF_VE_CNT property
  684. */
  685. if (scf_pg_get_property(pg, STMF_VE_CNT, prop) == -1) {
  686. syslog(LOG_ERR, "get property %s/%s failed - %s",
  687. luPgName, STMF_VE_CNT, scf_strerror(scf_error()));
  688. ret = STMF_PS_ERROR;
  689. goto out;
  690. }
  691. /*
  692. * Get the STMF_VE_CNT value
  693. */
  694. if (scf_property_get_value(prop, value) == -1) {
  695. syslog(LOG_ERR, "get property %s/%s value failed - %s",
  696. luPgName, STMF_VE_CNT, scf_strerror(scf_error()));
  697. ret = STMF_PS_ERROR;
  698. goto out;
  699. }
  700. /*
  701. * Now get the actual value from the value handle
  702. */
  703. if (scf_value_get_count(value, &veCnt) == -1) {
  704. syslog(LOG_ERR, "get count value %s/%s failed - %s",
  705. luPgName, STMF_VE_CNT, scf_strerror(scf_error()));
  706. ret = STMF_PS_ERROR;
  707. goto out;
  708. }
  709. /*
  710. * Reset the value resource as it is used below
  711. */
  712. scf_value_reset(value);
  713. }
  714. if (addRemoveFlag == ADD) {
  715. veCnt++;
  716. } else {
  717. /* Check if this is the last one being removed */
  718. if (veCnt == 1) {
  719. /*
  720. * Delete the pg and get out if this is the last
  721. * view entry
  722. */
  723. if (scf_pg_delete(pg) == -1) {
  724. syslog(LOG_ERR, "delete pg %s failed - %s",
  725. luPgName, scf_strerror(scf_error()));
  726. ret = STMF_PS_ERROR;
  727. }
  728. goto out;
  729. } else {
  730. veCnt--;
  731. }
  732. }
  733. /*
  734. * Set the view entry count
  735. */
  736. scf_value_set_count(value, veCnt);
  737. /*
  738. * Add the value to the transaction entry
  739. */
  740. if (scf_entry_add_value(entry, value) == -1) {
  741. syslog(LOG_ERR, "add value %s/%s failed - %s",
  742. luPgName, STMF_VE_CNT, scf_strerror(scf_error()));
  743. ret = STMF_PS_ERROR;
  744. goto out;
  745. }
  746. /*
  747. * Create a transaction entry resource for the view entry name
  748. */
  749. entryVeName = scf_entry_create(handle);
  750. if (entryVeName == NULL) {
  751. syslog(LOG_ERR, "scf transaction entry alloc %s/%s failed - %s",
  752. luPgName, viewEntryPgName, scf_strerror(scf_error()));
  753. ret = STMF_PS_ERROR;
  754. goto out;
  755. }
  756. if (addRemoveFlag == ADD) {
  757. /*
  758. * If adding, create a property with the view entry name
  759. */
  760. if (scf_transaction_property_new(tran, entryVeName,
  761. viewEntryPgName, SCF_TYPE_USTRING) == -1) {
  762. if (scf_error() == SCF_ERROR_EXISTS) {
  763. ret = STMF_PS_ERROR_EXISTS;
  764. } else {
  765. syslog(LOG_ERR,
  766. "transaction property new %s/%s "
  767. "failed - %s", luPgName, viewEntryPgName,
  768. scf_strerror(scf_error()));
  769. ret = STMF_PS_ERROR;
  770. }
  771. goto out;
  772. }
  773. } else {
  774. /*
  775. * If removing, delete the existing property with the view
  776. * entry name
  777. */
  778. if (scf_transaction_property_delete(tran, entryVeName,
  779. viewEntryPgName) == -1) {
  780. if (scf_error() == SCF_ERROR_NOT_FOUND) {
  781. ret = STMF_PS_ERROR_NOT_FOUND;
  782. } else {
  783. syslog(LOG_ERR,
  784. "transaction property delete %s/%s "
  785. "failed - %s", luPgName, viewEntryPgName,
  786. scf_strerror(scf_error()));
  787. ret = STMF_PS_ERROR;
  788. }
  789. goto out;
  790. }
  791. }
  792. /*
  793. * Commit property transaction
  794. */
  795. if ((commitRet = scf_transaction_commit(tran)) != 1) {
  796. syslog(LOG_ERR, "transaction commit for %s failed - %s",
  797. luPgName, scf_strerror(scf_error()));
  798. if (commitRet == 0) {
  799. ret = STMF_PS_ERROR_BUSY;
  800. } else {
  801. ret = STMF_PS_ERROR;
  802. }
  803. goto out;
  804. }
  805. out:
  806. /*
  807. * Free resources
  808. */
  809. if (handle != NULL) {
  810. scf_handle_destroy(handle);
  811. }
  812. if (svc != NULL) {
  813. scf_service_destroy(svc);
  814. }
  815. if (pg != NULL) {
  816. scf_pg_destroy(pg);
  817. }
  818. if (tran != NULL) {
  819. scf_transaction_destroy(tran);
  820. }
  821. if (entry != NULL) {
  822. scf_entry_destroy(entry);
  823. }
  824. if (entryVeName != NULL) {
  825. scf_entry_destroy(entryVeName);
  826. }
  827. if (prop != NULL) {
  828. scf_property_destroy(prop);
  829. }
  830. if (value != NULL) {
  831. scf_value_destroy(value);
  832. }
  833. return (ret);
  834. }
  835. /*
  836. * iPsAddViewEntry
  837. *
  838. * Add a view entry property group and optionally, a logical unit property
  839. * group if it does not exist.
  840. *
  841. * luName - ascii hexadecimal logical unit identifier
  842. * viewEntryName - name of view entry (VIEW_ENTRY_nn)
  843. * viewEntry - pointer to stmfViewEntry structure
  844. */
  845. static int
  846. iPsAddViewEntry(char *luPgName, char *viewEntryPgName, stmfViewEntry *viewEntry)
  847. {
  848. scf_handle_t *handle = NULL;
  849. scf_service_t *svc = NULL;
  850. scf_propertygroup_t *pg = NULL;
  851. scf_value_t *value[VIEW_ENTRY_STRUCT_CNT];
  852. scf_transaction_t *tran = NULL;
  853. scf_transaction_entry_t *entry[VIEW_ENTRY_STRUCT_CNT];
  854. int i = 0;
  855. int j = 0;
  856. int ret;
  857. uint8_t scfBool;
  858. boolean_t createdVePg = B_FALSE;
  859. int backoutRet;
  860. int commitRet;
  861. assert(luPgName != NULL || viewEntryPgName != NULL ||
  862. viewEntry == NULL);
  863. bzero(value, sizeof (value));
  864. bzero(entry, sizeof (entry));
  865. /*
  866. * Init the service handle
  867. */
  868. ret = iPsInit(&handle, &svc);
  869. if (ret != STMF_PS_SUCCESS) {
  870. goto out;
  871. }
  872. /*
  873. * Allocate scf resources
  874. */
  875. if (((pg = scf_pg_create(handle)) == NULL) ||
  876. ((tran = scf_transaction_create(handle)) == NULL)) {
  877. syslog(LOG_ERR, "scf alloc resource failed - %s",
  878. scf_strerror(scf_error()));
  879. ret = STMF_PS_ERROR;
  880. goto out;
  881. }
  882. /*
  883. * allocate value and entry resources for scf
  884. */
  885. for (i = 0; i < VIEW_ENTRY_STRUCT_CNT; i++) {
  886. if (((value[i] = scf_value_create(handle)) == NULL) ||
  887. ((entry[i] = scf_entry_create(handle)) == NULL)) {
  888. syslog(LOG_ERR, "scf alloc resource failed - %s",
  889. scf_strerror(scf_error()));
  890. ret = STMF_PS_ERROR;
  891. goto out;
  892. }
  893. }
  894. i = 0;
  895. /*
  896. * Create the View Entry property group
  897. */
  898. if (scf_service_add_pg(svc, viewEntryPgName, SCF_GROUP_APPLICATION,
  899. 0, pg) == -1) {
  900. if (scf_error() == SCF_ERROR_EXISTS) {
  901. ret = STMF_PS_ERROR_EXISTS;
  902. } else {
  903. syslog(LOG_ERR, "add pg %s failed - %s",
  904. viewEntryPgName, scf_strerror(scf_error()));
  905. ret = STMF_PS_ERROR;
  906. }
  907. goto out;
  908. }
  909. createdVePg = B_TRUE;
  910. /*
  911. * Add the view entry as properties on the view entry group
  912. */
  913. /*
  914. * Begin property update transaction
  915. */
  916. if (scf_transaction_start(tran, pg) == -1) {
  917. syslog(LOG_ERR, "start transaction for add %s failed - %s",
  918. viewEntryPgName, scf_strerror(scf_error()));
  919. ret = STMF_PS_ERROR;
  920. goto out;
  921. }
  922. /*
  923. * Add allHosts property
  924. */
  925. if (scf_transaction_property_new(tran, entry[i],
  926. STMF_VE_ALLHOSTS, SCF_TYPE_BOOLEAN) == -1) {
  927. if (scf_error() == SCF_ERROR_EXISTS) {
  928. ret = STMF_PS_ERROR_EXISTS;
  929. } else {
  930. syslog(LOG_ERR, "transaction property new %s/%s "
  931. "failed - %s", viewEntryPgName, STMF_VE_ALLHOSTS,
  932. scf_strerror(scf_error()));
  933. ret = STMF_PS_ERROR;
  934. }
  935. goto out;
  936. }
  937. /* Set the allHosts value */
  938. scfBool = viewEntry->allHosts;
  939. scf_value_set_boolean(value[i], scfBool);
  940. /*
  941. * Add the allHosts value to the transaction
  942. */
  943. if (scf_entry_add_value(entry[i], value[i]) == -1) {
  944. syslog(LOG_ERR, "add value %s/%s failed - %s",
  945. viewEntryPgName, STMF_VE_ALLHOSTS,
  946. scf_strerror(scf_error()));
  947. ret = STMF_PS_ERROR;
  948. goto out;
  949. }
  950. i++;
  951. /*
  952. * Create hostGroup property
  953. */
  954. if (scf_transaction_property_new(tran, entry[i],
  955. STMF_VE_HOSTGROUP, SCF_TYPE_USTRING) == -1) {
  956. if (scf_error() == SCF_ERROR_EXISTS) {
  957. ret = STMF_PS_ERROR_EXISTS;
  958. } else {
  959. syslog(LOG_ERR, "transaction property new %s/%s "
  960. "failed - %s", viewEntryPgName, STMF_VE_HOSTGROUP,
  961. scf_strerror(scf_error()));
  962. ret = STMF_PS_ERROR;
  963. }
  964. goto out;
  965. }
  966. /*
  967. * Set the value for hostGroup
  968. */
  969. if (scf_value_set_ustring(value[i], viewEntry->hostGroup) == -1) {
  970. syslog(LOG_ERR, "set value %s/%s failed - %s",
  971. viewEntryPgName, STMF_VE_HOSTGROUP,
  972. scf_strerror(scf_error()));
  973. ret = STMF_PS_ERROR;
  974. goto out;
  975. }
  976. /*
  977. * Add the hostGroup value to the transaction entry
  978. */
  979. if (scf_entry_add_value(entry[i], value[i]) == -1) {
  980. syslog(LOG_ERR, "add value %s/%s failed - %s",
  981. viewEntryPgName, STMF_VE_HOSTGROUP,
  982. scf_strerror(scf_error()));
  983. ret = STMF_PS_ERROR;
  984. goto out;
  985. }
  986. i++;
  987. /*
  988. * Create the allTargets property
  989. */
  990. if (scf_transaction_property_new(tran, entry[i],
  991. STMF_VE_ALLTARGETS, SCF_TYPE_BOOLEAN) == -1) {
  992. if (scf_error() == SCF_ERROR_EXISTS) {
  993. ret = STMF_PS_ERROR_EXISTS;
  994. } else {
  995. syslog(LOG_ERR, "transaction property new %s/%s "
  996. "failed - %s", viewEntryPgName, STMF_VE_ALLTARGETS,
  997. scf_strerror(scf_error()));
  998. ret = STMF_PS_ERROR;
  999. }
  1000. goto out;
  1001. }
  1002. /*
  1003. * Set the allTargets value
  1004. */
  1005. scfBool = viewEntry->allTargets;
  1006. scf_value_set_boolean(value[i], scfBool);
  1007. /*
  1008. * Add the allTargets value to the transaction
  1009. */
  1010. if (scf_entry_add_value(entry[i], value[i]) == -1) {
  1011. syslog(LOG_ERR, "add value %s/%s failed - %s",
  1012. viewEntryPgName, STMF_VE_ALLTARGETS,
  1013. scf_strerror(scf_error()));
  1014. ret = STMF_PS_ERROR;
  1015. goto out;
  1016. }
  1017. i++;
  1018. /*
  1019. * Create targetGroup property
  1020. */
  1021. if (scf_transaction_property_new(tran, entry[i],
  1022. STMF_VE_TARGETGROUP, SCF_TYPE_USTRING) == -1) {
  1023. if (scf_error() == SCF_ERROR_EXISTS) {
  1024. ret = STMF_PS_ERROR_EXISTS;
  1025. } else {
  1026. syslog(LOG_ERR, "transaction property new %s/%s "
  1027. "failed - %s", viewEntryPgName,
  1028. STMF_VE_TARGETGROUP, scf_strerror(scf_error()));
  1029. ret = STMF_PS_ERROR;
  1030. }
  1031. goto out;
  1032. }
  1033. /*
  1034. * Set the value for targetGroup
  1035. */
  1036. if (scf_value_set_ustring(value[i], viewEntry->targetGroup) == -1) {
  1037. syslog(LOG_ERR, "set value %s/%s failed - %s",
  1038. viewEntryPgName, STMF_VE_TARGETGROUP,
  1039. scf_strerror(scf_error()));
  1040. ret = STMF_PS_ERROR;
  1041. goto out;
  1042. }
  1043. /*
  1044. * Add targetGroup value to the transaction
  1045. */
  1046. if (scf_entry_add_value(entry[i], value[i]) == -1) {
  1047. syslog(LOG_ERR, "add value %s/%s failed - %s",
  1048. viewEntryPgName, STMF_VE_TARGETGROUP,
  1049. scf_strerror(scf_error()));
  1050. ret = STMF_PS_ERROR;
  1051. goto out;
  1052. }
  1053. i++;
  1054. /*
  1055. * Create the luNbr property
  1056. */
  1057. if (scf_transaction_property_new(tran, entry[i], STMF_VE_LUNBR,
  1058. SCF_TYPE_OPAQUE) == -1) {
  1059. if (scf_error() == SCF_ERROR_EXISTS) {
  1060. ret = STMF_PS_ERROR_EXISTS;
  1061. } else {
  1062. syslog(LOG_ERR, "transaction property new %s/%s "
  1063. "failed - %s", viewEntryPgName, STMF_VE_LUNBR,
  1064. scf_strerror(scf_error()));
  1065. ret = STMF_PS_ERROR;
  1066. }
  1067. goto out;
  1068. }
  1069. /*
  1070. * Set the luNbr
  1071. */
  1072. if (scf_value_set_opaque(value[i], (char *)viewEntry->luNbr,
  1073. sizeof (viewEntry->luNbr)) == -1) {
  1074. syslog(LOG_ERR, "set value %s/%s failed - %s",
  1075. viewEntryPgName, STMF_VE_LUNBR, scf_strerror(scf_error()));
  1076. ret = STMF_PS_ERROR;
  1077. goto out;
  1078. }
  1079. /*
  1080. * Add luNbr to the transaction entry
  1081. */
  1082. if (scf_entry_add_value(entry[i], value[i]) == -1) {
  1083. syslog(LOG_ERR, "add value %s/%s failed - %s",
  1084. viewEntryPgName, STMF_VE_LUNBR, scf_strerror(scf_error()));
  1085. ret = STMF_PS_ERROR;
  1086. goto out;
  1087. }
  1088. /*
  1089. * Now that we've successfully added the view entry,
  1090. * update the logical unit property group or create
  1091. * it if it does not exist
  1092. */
  1093. ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName, ADD);
  1094. /*
  1095. * If we did not add the view entry name to the logical unit,
  1096. * make sure we do not commit the transaction
  1097. */
  1098. if (ret != STMF_PS_SUCCESS) {
  1099. goto out;
  1100. }
  1101. /*
  1102. * Commit property transaction
  1103. */
  1104. if ((commitRet = scf_transaction_commit(tran)) != 1) {
  1105. syslog(LOG_ERR, "transaction commit for add %s failed - %s",
  1106. viewEntryPgName, scf_strerror(scf_error()));
  1107. if (commitRet == 0) {
  1108. ret = STMF_PS_ERROR_BUSY;
  1109. } else {
  1110. ret = STMF_PS_ERROR;
  1111. }
  1112. }
  1113. if (ret != STMF_PS_SUCCESS) {
  1114. /*
  1115. * If we did not commit, try to remove the view entry name
  1116. * from the logical unit.
  1117. * If that fails, we're now inconsistent.
  1118. */
  1119. backoutRet = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName,
  1120. REMOVE);
  1121. if (backoutRet != STMF_PS_SUCCESS) {
  1122. syslog(LOG_ERR, "remove lu view entry %s failed"
  1123. "possible inconsistency - %s", luPgName,
  1124. scf_strerror(scf_error()));
  1125. }
  1126. /*
  1127. * We are still in an error scenario even though the remove
  1128. * lu view entry succeeded.
  1129. */
  1130. goto out;
  1131. }
  1132. out:
  1133. /*
  1134. * Free resources
  1135. */
  1136. if (handle != NULL) {
  1137. scf_handle_destroy(handle);
  1138. }
  1139. if (svc != NULL) {
  1140. scf_service_destroy(svc);
  1141. }
  1142. /* if there was an error, delete the created pg if one was created */
  1143. if ((ret != STMF_PS_SUCCESS) && createdVePg) {
  1144. if (scf_pg_delete(pg) == -1) {
  1145. syslog(LOG_ERR, "delete VE pg %s failed - %s",
  1146. viewEntryPgName, scf_strerror(scf_error()));
  1147. }
  1148. }
  1149. if (pg != NULL) {
  1150. scf_pg_destroy(pg);
  1151. }
  1152. if (tran != NULL) {
  1153. scf_transaction_destroy(tran);
  1154. }
  1155. /*
  1156. * Free value and entry scf resources
  1157. */
  1158. if (i > 0) {
  1159. for (j = 0; j < VIEW_ENTRY_STRUCT_CNT; j++) {
  1160. if (value[j] != NULL)
  1161. scf_value_destroy(value[j]);
  1162. if (entry[j] != NULL)
  1163. scf_entry_destroy(entry[j]);
  1164. }
  1165. }
  1166. return (ret);
  1167. }
  1168. /*
  1169. * psClearProviderData
  1170. *
  1171. * providerName - name of provider data to clear
  1172. */
  1173. int
  1174. psClearProviderData(char *providerName, int providerType)
  1175. {
  1176. scf_handle_t *handle = NULL;
  1177. scf_service_t *svc = NULL;
  1178. scf_propertygroup_t *pg = NULL;
  1179. char pgName[MAXPATHLEN];
  1180. int ret = STMF_PS_SUCCESS;
  1181. boolean_t pgNotFound = B_FALSE;
  1182. if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE &&
  1183. providerType != STMF_PORT_PROVIDER_TYPE)) {
  1184. ret = STMF_PS_ERROR_INVALID_ARG;
  1185. goto out;
  1186. }
  1187. ret = iPsInit(&handle, &svc);
  1188. if (ret != STMF_PS_SUCCESS) {
  1189. goto out;
  1190. }
  1191. /*
  1192. * Allocate scf resources
  1193. */
  1194. if ((pg = scf_pg_create(handle)) == NULL) {
  1195. syslog(LOG_ERR, "scf alloc resource failed - %s",
  1196. scf_strerror(scf_error()));
  1197. ret = STMF_PS_ERROR;
  1198. goto out;
  1199. }
  1200. /*
  1201. * create the property group name
  1202. */
  1203. (void) snprintf(pgName, sizeof (pgName), "%s%s",
  1204. STMF_PROVIDER_DATA_PREFIX, providerName);
  1205. /*
  1206. * delete provider property group
  1207. */
  1208. if (scf_service_get_pg(svc, pgName, pg) == -1) {
  1209. if (scf_error() != SCF_ERROR_NOT_FOUND) {
  1210. syslog(LOG_ERR, "get pg %s failed - %s",
  1211. pgName, scf_strerror(scf_error()));
  1212. ret = STMF_PS_ERROR;
  1213. goto out;
  1214. } else {
  1215. pgNotFound = B_TRUE;
  1216. }
  1217. }
  1218. if (!pgNotFound && (scf_pg_delete(pg) == -1)) {
  1219. syslog(LOG_ERR, "delete pg %s failed - %s",
  1220. pgName, scf_strerror(scf_error()));
  1221. ret = STMF_PS_ERROR;
  1222. goto out;
  1223. }
  1224. if (pgNotFound) {
  1225. ret = STMF_PS_ERROR_NOT_FOUND;
  1226. }
  1227. out:
  1228. /*
  1229. * Free resources
  1230. */
  1231. if (handle != NULL) {
  1232. scf_handle_destroy(handle);
  1233. }
  1234. if (svc != NULL) {
  1235. scf_service_destroy(svc);
  1236. }
  1237. if (pg != NULL) {
  1238. scf_pg_destroy(pg);
  1239. }
  1240. return (ret);
  1241. }
  1242. /*
  1243. * iPsCreateDeleteGroup
  1244. *
  1245. * Creates or deletes a group (target or host)
  1246. *
  1247. * When creating a group, two properties are created. One to hold the group
  1248. * name and the other to hold the group members.
  1249. *
  1250. * pgName - Property group name
  1251. * groupName - group name to create
  1252. * addRemoveFlag - ADD_GROUP/REMOVE_GROUP
  1253. *
  1254. * returns:
  1255. * STMF_PS_SUCCESS on success
  1256. * STMF_PS_ERROR_* on failure
  1257. */
  1258. static int
  1259. iPsCreateDeleteGroup(char *pgRefName, char *groupName, int addRemoveFlag)
  1260. {
  1261. scf_handle_t *handle = NULL;
  1262. scf_service_t *svc = NULL;
  1263. scf_propertygroup_t *pg = NULL;
  1264. scf_property_t *prop = NULL;
  1265. scf_iter_t *propIter = NULL;
  1266. scf_transaction_t *tran = NULL;
  1267. scf_transaction_entry_t *entry1 = NULL;
  1268. scf_transaction_entry_t *entry2 = NULL;
  1269. scf_value_t *value = NULL;
  1270. uint64_t groupIdx;
  1271. char buf1[MAXNAMELEN];
  1272. char buf2[MAXNAMELEN];
  1273. char tmpbuf[MAXNAMELEN];
  1274. boolean_t found = B_FALSE;
  1275. int ret = STMF_PS_SUCCESS;
  1276. int commitRet;
  1277. assert(groupName != NULL);
  1278. ret = iPsInit(&handle, &svc);
  1279. if (ret != STMF_PS_SUCCESS) {
  1280. goto out;
  1281. }
  1282. /*
  1283. * Allocate scf resources
  1284. */
  1285. if (((pg = scf_pg_create(handle)) == NULL) ||
  1286. ((tran = scf_transaction_create(handle)) == NULL) ||
  1287. ((entry1 = scf_entry_create(handle)) == NULL) ||
  1288. ((entry2 = scf_entry_create(handle)) == NULL) ||
  1289. ((prop = scf_property_create(handle)) == NULL) ||
  1290. ((propIter = scf_iter_create(handle)) == NULL) ||
  1291. ((value = scf_value_create(handle)) == NULL)) {
  1292. syslog(LOG_ERR, "scf alloc resource failed - %s",
  1293. scf_strerror(scf_error()));
  1294. ret = STMF_PS_ERROR;
  1295. goto out;
  1296. }
  1297. /*
  1298. * Get the property group being modified
  1299. */
  1300. if (scf_service_get_pg(svc, pgRefName, pg) == -1) {
  1301. if (scf_error() == SCF_ERROR_NOT_FOUND &&
  1302. addRemoveFlag == ADD) {
  1303. if (scf_service_add_pg(svc, pgRefName,
  1304. SCF_GROUP_APPLICATION, 0, pg) == -1) {
  1305. syslog(LOG_ERR, "add pg %s failed - %s",
  1306. pgRefName, scf_strerror(scf_error()));
  1307. ret = STMF_PS_ERROR;
  1308. }
  1309. } else if (scf_error() == SCF_ERROR_NOT_FOUND) {
  1310. syslog(LOG_ERR, "get pg %s failed - %s",
  1311. pgRefName, scf_strerror(scf_error()));
  1312. ret = STMF_PS_ERROR_NOT_FOUND;
  1313. } else {
  1314. syslog(LOG_ERR, "get pg %s failed - %s",
  1315. pgRefName, scf_strerror(scf_error()));
  1316. ret = STMF_PS_ERROR;
  1317. }
  1318. if (ret != STMF_PS_SUCCESS) {
  1319. goto out;
  1320. }
  1321. }
  1322. /*
  1323. * propIter is the iterator handle
  1324. */
  1325. if (scf_iter_pg_properties(propIter, pg) == -1) {
  1326. syslog(LOG_ERR, "iter properties for %s failed - %s",
  1327. pgRefName, scf_strerror(scf_error()));
  1328. ret = STMF_PS_ERROR;
  1329. goto out;
  1330. }
  1331. /*
  1332. * Iterate through the group names.
  1333. * If we find it in the list, it's an error when addRemoveFlag == ADD.
  1334. */
  1335. while (scf_iter_next_property(propIter, prop) == 1) {
  1336. if (scf_property_get_name(prop, buf1, sizeof (buf1)) == -1) {
  1337. syslog(LOG_ERR, "get name from %s iter failed - %s",
  1338. pgRefName, scf_strerror(scf_error()));
  1339. ret = STMF_PS_ERROR;
  1340. break;
  1341. }
  1342. /*
  1343. * Skip over member list properties
  1344. */
  1345. if (strstr(buf1, STMF_MEMBER_LIST_SUFFIX)) {
  1346. continue;
  1347. }
  1348. if (scf_property_get_value(prop, value) == -1) {
  1349. syslog(LOG_ERR, "get property value %s/%s failed - %s",
  1350. pgRefName, buf1, scf_strerror(scf_error()));
  1351. ret = STMF_PS_ERROR;
  1352. break;
  1353. }
  1354. if (scf_value_get_ustring(value, tmpbuf,
  1355. sizeof (tmpbuf)) == -1) {
  1356. syslog(LOG_ERR, "get ustring %s/%s failed - %s",
  1357. pgRefName, buf1, scf_strerror(scf_error()));
  1358. ret = STMF_PS_ERROR;
  1359. break;
  1360. }
  1361. if ((strlen(tmpbuf) == strlen(groupName)) &&
  1362. bcmp(tmpbuf, groupName, strlen(tmpbuf)) == 0) {
  1363. if (addRemoveFlag == ADD) {
  1364. ret = STMF_PS_ERROR_EXISTS;
  1365. }
  1366. found = B_TRUE;
  1367. /*
  1368. * buf1 contains the name for REMOVE
  1369. */
  1370. break;
  1371. }
  1372. }
  1373. if (ret != STMF_PS_SUCCESS) {
  1374. goto out;
  1375. }
  1376. scf_value_reset(value);
  1377. if (!found && addRemoveFlag == REMOVE) {
  1378. ret = STMF_PS_ERROR_NOT_FOUND;
  1379. goto out;
  1380. }
  1381. /*
  1382. * If we're adding, we need to create a new property name for the
  1383. * new group
  1384. */
  1385. if (addRemoveFlag == ADD) {
  1386. for (groupIdx = 0; groupIdx < GROUP_MAX; groupIdx++) {
  1387. if (snprintf(buf1, sizeof (buf1), "%s-%lld",
  1388. STMF_GROUP_PREFIX, groupIdx) > sizeof (buf1)) {
  1389. syslog(LOG_ERR,
  1390. "buffer overflow on property name %s",
  1391. buf1);
  1392. ret = STMF_PS_ERROR;
  1393. break;
  1394. }
  1395. if (scf_pg_get_property(pg, buf1, prop) == -1) {
  1396. if (scf_error() != SCF_ERROR_NOT_FOUND) {
  1397. syslog(LOG_ERR, "get property %s/%s "
  1398. "failed - %s", pgRefName, buf1,
  1399. scf_strerror(scf_error()));
  1400. ret = STMF_PS_ERROR;
  1401. }
  1402. break;
  1403. }
  1404. }
  1405. }
  1406. /*
  1407. * Now create the new member list property for the new group
  1408. */
  1409. if (snprintf(buf2, sizeof (buf2), "%s-%s", buf1,
  1410. STMF_MEMBER_LIST_SUFFIX) > sizeof (buf2)) {
  1411. syslog(LOG_ERR, "buffer overflow on property name %s",
  1412. buf1);
  1413. ret = STMF_PS_ERROR;
  1414. goto out;
  1415. }
  1416. /*
  1417. * buf1 now contains the name of the property if it was found in the
  1418. * list in the case of delete or the next available property name
  1419. * in the case of create
  1420. *
  1421. * buf2 now contains the member list property name
  1422. */
  1423. if (scf_transaction_start(tran, pg) == -1) {
  1424. syslog(LOG_ERR, "start transaction for %s failed - %s",
  1425. pgRefName, scf_strerror(scf_error()));
  1426. ret = STMF_PS_ERROR;
  1427. goto out;
  1428. }
  1429. if (addRemoveFlag == ADD) {
  1430. /*
  1431. * Create the property 'group name'
  1432. * This is the container for the group name
  1433. */
  1434. if (scf_transaction_property_new(tran, entry1, buf1,
  1435. SCF_TYPE_USTRING) == -1) {
  1436. syslog(LOG_ERR, "transaction property new %s/%s "
  1437. "failed - %s", pgRefName, buf1,
  1438. scf_strerror(scf_error()));
  1439. ret = STMF_PS_ERROR;
  1440. goto out;
  1441. }
  1442. if (scf_value_set_ustring(value, groupName) == -1) {
  1443. syslog(LOG_ERR, "set ustring %s/%s failed - %s",
  1444. pgRefName, buf1, scf_strerror(scf_error()));
  1445. ret = STMF_PS_ERROR;
  1446. goto out;
  1447. }
  1448. if (scf_entry_add_value(entry1, value) == -1) {
  1449. syslog(LOG_ERR, "add value %s/%s failed - %s",
  1450. pgRefName, buf1, scf_strerror(scf_error()));
  1451. ret = STMF_PS_ERROR;
  1452. goto out;
  1453. }
  1454. /*
  1455. * Create the property 'group list'
  1456. * This is the container for the group members
  1457. */
  1458. if (scf_transaction_property_new(tran, entry2, buf2,
  1459. SCF_TYPE_USTRING) == -1) {
  1460. syslog(LOG_ERR, "transaction property new %s/%s "
  1461. "failed - %s", pgRefName, buf2,
  1462. scf_strerror(scf_error()));
  1463. ret = STMF_PS_ERROR;
  1464. goto out;
  1465. }
  1466. } else {
  1467. /*
  1468. * Delete the property 'group name'
  1469. */
  1470. if (scf_transaction_property_delete(tran, entry1, buf1)
  1471. == -1) {
  1472. syslog(LOG_ERR,
  1473. "transaction property delete %s/%s failed - %s",
  1474. pgRefName, buf1, scf_strerror(scf_error()));
  1475. ret = STMF_PS_ERROR;
  1476. goto out;
  1477. }
  1478. /*
  1479. * Delete the property 'group list'
  1480. */
  1481. if (scf_transaction_property_delete(tran, entry2, buf2)
  1482. == -1) {
  1483. syslog(LOG_ERR, "transaction property delete %s/%s "
  1484. "failed - %s", pgRefName, buf2,
  1485. scf_strerror(scf_error()));
  1486. ret = STMF_PS_ERROR;
  1487. goto out;
  1488. }
  1489. }
  1490. if (ret != STMF_PS_SUCCESS) {
  1491. goto out;
  1492. }
  1493. if ((commitRet = scf_transaction_commit(tran)) != 1) {
  1494. syslog(LOG_ERR, "transaction commit for %s failed - %s",
  1495. pgRefName, scf_strerror(scf_error()));
  1496. if (commitRet == 0) {
  1497. ret = STMF_PS_ERROR_BUSY;
  1498. } else {
  1499. ret = STMF_PS_ERROR;
  1500. }
  1501. }
  1502. out:
  1503. /*
  1504. * Free resources
  1505. */
  1506. if (handle != NULL) {
  1507. scf_handle_destroy(handle);
  1508. }
  1509. if (svc != NULL) {
  1510. scf_service_destroy(svc);
  1511. }
  1512. if (pg != NULL) {
  1513. scf_pg_destroy(pg);
  1514. }
  1515. if (tran != NULL) {
  1516. scf_transaction_destroy(tran);
  1517. }
  1518. if (entry1 != NULL) {
  1519. scf_entry_destroy(entry1);
  1520. }
  1521. if (entry2 != NULL) {
  1522. scf_entry_destroy(entry2);
  1523. }
  1524. if (prop != NULL) {
  1525. scf_property_destroy(prop);
  1526. }
  1527. if (propIter != NULL) {
  1528. scf_iter_destroy(propIter);
  1529. }
  1530. if (value != NULL) {
  1531. scf_value_destroy(value);
  1532. }
  1533. return (ret);
  1534. }
  1535. /*
  1536. * iPsGetGroupList
  1537. *
  1538. * pgName - Property group name
  1539. * groupList - pointer to pointer to stmfGroupList structure. On success,
  1540. * contains the list of groups
  1541. *
  1542. * returns:
  1543. * STMF_PS_SUCCESS on success
  1544. * STMF_PS_ERROR_* on failure
  1545. */
  1546. static int
  1547. iPsGetGroupList(char *pgName, stmfGroupList **groupList)
  1548. {
  1549. scf_handle_t *handle = NULL;
  1550. scf_service_t *svc = NULL;
  1551. scf_propertygroup_t *pg = NULL;
  1552. scf_property_t *prop = NULL;
  1553. scf_iter_t *propIter = NULL;
  1554. scf_value_t *value = NULL;
  1555. char buf[MAXNAMELEN];
  1556. int memberCnt = 0;
  1557. int i = 0;
  1558. int ret = STMF_PS_SUCCESS;
  1559. assert(groupList != NULL);
  1560. ret = iPsInit(&handle, &svc);
  1561. if (ret != STMF_PS_SUCCESS) {
  1562. goto out;
  1563. }
  1564. /*
  1565. * Allocate scf resources
  1566. */
  1567. if (((pg = scf_pg_create(handle)) == NULL) ||
  1568. ((prop = scf_property_create(handle)) == NULL) ||
  1569. ((propIter = scf_iter_create(handle)) == NULL) ||
  1570. ((value = scf_value_create(handle)) == NULL)) {
  1571. syslog(LOG_ERR, "scf alloc resource failed - %s",
  1572. scf_strerror(scf_error()));
  1573. ret = STMF_PS_ERROR;
  1574. goto out;
  1575. }
  1576. if (scf_service_get_pg(svc, pgName, pg) == -1) {
  1577. if (scf_error() == SCF_ERROR_NOT_FOUND) {
  1578. syslog(LOG_ERR, "get pg %s failed - %s",
  1579. pgName, scf_strerror(scf_error()));
  1580. ret = STMF_PS_ERROR_NOT_FOUND;
  1581. } else {
  1582. syslog(LOG_ERR, "get pg %s failed - %s",
  1583. pgName, scf_strerror(scf_error()));
  1584. ret = STMF_PS_ERROR;
  1585. }
  1586. goto out;
  1587. }
  1588. /*
  1589. * propIter is the iterator handle
  1590. */
  1591. if (scf_iter_pg_properties(propIter, pg) == -1) {
  1592. syslog(LOG_ERR, "iter properties for %s failed - %s",
  1593. pgName, scf_strerror(scf_error()));
  1594. ret = STMF_PS_ERROR;
  1595. goto out;
  1596. }
  1597. while (scf_iter_next_property(propIter, prop) == 1) {
  1598. if (scf_property_get_name(prop, buf, sizeof (buf)) == -1) {
  1599. syslog(LOG_ERR, "get name from %s iter failed - %s",
  1600. pgName, scf_strerror(scf_error()));
  1601. ret = STMF_PS_ERROR;
  1602. break;
  1603. }
  1604. /*
  1605. * Skip over member list properties
  1606. */
  1607. if (strstr(buf, STMF_MEMBER_LIST_SUFFIX)) {
  1608. continue;
  1609. }
  1610. memberCnt++;
  1611. }
  1612. /*
  1613. * propIter is the iterator handle
  1614. */
  1615. if (scf_iter_pg_properties(propIter, pg) == -1) {
  1616. syslog(LOG_ERR, "iter properties for %s failed - %s",
  1617. pgName, scf_strerror(scf_error()));
  1618. ret = STMF_PS_ERROR;
  1619. goto out;
  1620. }
  1621. *groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
  1622. memberCnt * sizeof (stmfGroupName));
  1623. if (*groupList == NULL) {
  1624. ret = STMF_PS_ERROR_NOMEM;
  1625. goto out;
  1626. }
  1627. /*
  1628. * In order to get a list of groups, simply get all of the
  1629. * properties that are not member list properties, i.e. the group
  1630. * name properties.
  1631. * It's possible for this list to grow beyond what was originally
  1632. * read so just ensure we're not writing beyond our allocated buffer
  1633. * by ensuring i < memberCnt
  1634. */
  1635. while ((scf_iter_next_property(propIter, prop) == 1) &&
  1636. (i < memberCnt)) {
  1637. if (scf_property_get_name(prop, buf, sizeof (buf)) == -1) {
  1638. syslog(LOG_ERR, "get name from %s iter failed - %s",
  1639. pgName, scf_strerror(scf_error()));
  1640. ret = STMF_PS_ERROR;
  1641. break;
  1642. }
  1643. /*
  1644. * Skip over member list properties
  1645. */
  1646. if (strstr(buf, STMF_MEMBER_LIST_SUFFIX)) {
  1647. continue;
  1648. }
  1649. if (scf_property_get_value(prop, value) == -1) {
  1650. syslog(LOG_ERR, "get property value %s/%s failed - %s",
  1651. pgName, buf, scf_strerror(scf_error()));
  1652. ret = STMF_PS_ERROR;
  1653. break;
  1654. }
  1655. if (scf_value_get_ustring(value, buf, sizeof (buf)) == -1) {
  1656. syslog(LOG_ERR, "get ustring %s/%s failed - %s",
  1657. pgName, buf, scf_strerror(scf_error()));
  1658. ret = STMF_PS_ERROR;
  1659. break;
  1660. }
  1661. bcopy(buf, (*groupList)->name[i++], strlen(buf));
  1662. (*groupList)->cnt++;
  1663. }
  1664. if (ret != STMF_PS_SUCCESS) {
  1665. free(*groupList);
  1666. goto out;
  1667. }
  1668. out:
  1669. /*
  1670. * Free resources
  1671. */
  1672. if (handle != NULL) {
  1673. scf_handle_destroy(handle);
  1674. }
  1675. if (svc != NULL) {
  1676. scf_service_destroy(svc);
  1677. }
  1678. if (pg != NULL) {
  1679. scf_pg_destroy(pg);
  1680. }
  1681. if (propIter != NULL) {
  1682. scf_iter_destroy(propIter);
  1683. }
  1684. if (prop != NULL) {
  1685. scf_property_destroy(prop);
  1686. }
  1687. if (value != NULL) {
  1688. scf_value_destroy(value);
  1689. }
  1690. return (ret);
  1691. }
  1692. /*
  1693. * iPsGetGroupMemberList
  1694. *
  1695. * pgName - Property group name
  1696. * groupName - group name (host group or target group)
  1697. * groupMemberList - pointer to pointer to stmfGroupProperties structure. On
  1698. * success, contains the list of group members
  1699. *
  1700. * returns:
  1701. * STMF_PS_SUCCESS on success
  1702. * STMF_PS_ERROR_* on failure
  1703. */
  1704. static int
  1705. iPsGetGroupMemberList(char *pgName, char *groupName,
  1706. stmfGroupProperties **groupMemberList)
  1707. {
  1708. scf_handle_t *handle = NULL;
  1709. scf_service_t *svc = NULL;
  1710. scf_propertygroup_t *pg = NULL;
  1711. scf_property_t *prop = NULL;
  1712. scf_value_t *valueLookup = NULL;
  1713. scf_iter_t *valueIter = NULL;
  1714. int i = 0;
  1715. int memberCnt;
  1716. int len;
  1717. int ret = STMF_PS_SUCCESS;
  1718. char buf[MAXNAMELEN];
  1719. assert(pgName != NULL && groupName != NULL);
  1720. /*
  1721. * init the service handle
  1722. */
  1723. ret = iPsInit(&handle, &svc);
  1724. if (ret != STMF_PS_SUCCESS) {
  1725. goto out;
  1726. }
  1727. /*
  1728. * Allocate scf resources
  1729. */
  1730. if (((pg = scf_pg_create(handle)) == NULL) ||
  1731. ((prop = scf_property_create(handle)) == NULL) ||
  1732. ((valueIter = scf_iter_create(handle)) == NULL) ||
  1733. ((valueLookup = scf_value_create(handle)) == NULL)) {
  1734. syslog(LOG_ERR, "scf alloc resource failed - %s",
  1735. scf_strerror(scf_error()));
  1736. ret = STMF_PS_ERROR;
  1737. goto out;
  1738. }
  1739. /*
  1740. * get the service property group handle
  1741. */
  1742. if (scf_service_get_pg(svc, pgName, pg) == -1) {
  1743. if (scf_error() == SCF_ERROR_NOT_FOUND) {
  1744. ret = STMF_PS_ERROR_NOT_FOUND;
  1745. } else {
  1746. ret = STMF_PS_ERROR;
  1747. }
  1748. syslog(LOG_ERR, "get pg %s failed - %s",
  1749. pgName, scf_strerror(scf_error()));
  1750. goto out;
  1751. }
  1752. /*
  1753. * Get the property handle
  1754. * based on the target or host group name
  1755. */
  1756. if (scf_pg_get_property(pg, groupName, prop) == -1) {
  1757. syslog(LOG_ERR, "get property %s/%s failed - %s",
  1758. pgName, groupName, scf_strerror(scf_error()));
  1759. ret = STMF_PS_ERROR;
  1760. goto out;
  1761. }
  1762. /*
  1763. * valueIter is the iterator handle
  1764. */
  1765. if (scf_iter_property_values(valueIter, prop) == -1) {
  1766. syslog(LOG_ERR, "iter value %s/%s failed - %s",
  1767. pgName, groupName, scf_strerror(scf_error()));
  1768. ret = STMF_PS_ERROR;
  1769. goto out;
  1770. }
  1771. while (scf_iter_next_value(valueIter, valueLookup) == 1) {
  1772. if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) {
  1773. syslog(LOG_ERR, "iter value %s/%s failed - %s",
  1774. pgName, groupName, scf_strerror(scf_error()));
  1775. ret = STMF_PS_ERROR;
  1776. break;
  1777. }
  1778. i++;
  1779. }
  1780. /*
  1781. * valueIter is the iterator handle
  1782. */
  1783. if (scf_iter_

Large files files are truncated, but you can click here to view the full file