/usr/src/cmd/sbdadm/sbdadm.c
C | 752 lines | 639 code | 66 blank | 47 comment | 93 complexity | f75576494d547266f7e7514043a7b467 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, AGPL-3.0, BSD-3-Clause, GPL-3.0, LGPL-2.1, BSD-2-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, 0BSD
- /*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
- /*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- * Copyright 2012 Milan Jurik. All rights reserved.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <libintl.h>
- #include <errno.h>
- #include <string.h>
- #include <assert.h>
- #include <getopt.h>
- #include <strings.h>
- #include <ctype.h>
- #include <libnvpair.h>
- #include <locale.h>
- #include <cmdparse.h>
- #include <sys/stmf_defines.h>
- #include <libstmf.h>
- #include <sys/stmf_sbd_ioctl.h>
- #define MAX_LU_LIST 8192
- #define LU_LIST_MAX_RETRIES 3
- #define GUID_INPUT 32
- #define VERSION_STRING_MAJOR "1"
- #define VERSION_STRING_MINOR "0"
- #define VERSION_STRING_MAX_LEN 10
- char *cmdName;
- static char *getExecBasename(char *);
- int delete_lu(int argc, char *argv[], cmdOptions_t *options,
- void *callData);
- int create_lu(int argc, char *argv[], cmdOptions_t *options, void *callData);
- int list_lus(int argc, char *argv[], cmdOptions_t *options, void *callData);
- int modify_lu(int argc, char *argv[], cmdOptions_t *options, void *callData);
- int import_lu(int argc, char *argv[], cmdOptions_t *options, void *callData);
- static int callModify(char *, stmfGuid *, uint32_t, const char *, const char *);
- int print_lu_attr(stmfGuid *);
- void print_guid(uint8_t *g, FILE *f);
- void print_attr_header();
- optionTbl_t options[] = {
- { "disk-size", required_argument, 's',
- "Size with <none>/k/m/g/t/p/e modifier" },
- { "keep-views", no_arg, 'k',
- "Dont delete view entries related to the LU" },
- { NULL, 0, 0 }
- };
- subCommandProps_t subCommands[] = {
- { "create-lu", create_lu, "s", NULL, NULL,
- OPERAND_MANDATORY_SINGLE,
- "Full path of the file to initialize" },
- { "delete-lu", delete_lu, "k", NULL, NULL,
- OPERAND_MANDATORY_SINGLE, "GUID of the LU to deregister" },
- { "import-lu", import_lu, NULL, NULL, NULL,
- OPERAND_MANDATORY_SINGLE, "filename of the LU to import" },
- { "list-lu", list_lus, NULL, NULL, NULL,
- OPERAND_NONE, "List all the exported LUs" },
- { "modify-lu", modify_lu, "s", "s", NULL,
- OPERAND_MANDATORY_SINGLE,
- "Full path of the LU or GUID of a registered LU" },
- { NULL, 0, 0, NULL, 0, NULL}
- };
- /*ARGSUSED*/
- int
- create_lu(int argc, char *operands[], cmdOptions_t *options, void *callData)
- {
- luResource hdl = NULL;
- int ret = 0;
- stmfGuid createdGuid;
- ret = stmfCreateLuResource(STMF_DISK, &hdl);
- if (ret != STMF_STATUS_SUCCESS) {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("Failure to create lu resource\n"));
- return (1);
- }
- for (; options->optval; options++) {
- switch (options->optval) {
- case 's':
- ret = stmfSetLuProp(hdl, STMF_LU_PROP_SIZE,
- options->optarg);
- if (ret != STMF_STATUS_SUCCESS) {
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, options->optval,
- gettext("size param invalid"));
- (void) stmfFreeLuResource(hdl);
- return (1);
- }
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, options->optval,
- gettext("unknown option"));
- return (1);
- }
- }
- ret = stmfSetLuProp(hdl, STMF_LU_PROP_FILENAME, operands[0]);
- if (ret != STMF_STATUS_SUCCESS) {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("could not set filename"));
- return (1);
- }
- ret = stmfCreateLu(hdl, &createdGuid);
- switch (ret) {
- case STMF_STATUS_SUCCESS:
- break;
- case STMF_ERROR_BUSY:
- case STMF_ERROR_LU_BUSY:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("resource busy"));
- ret++;
- break;
- case STMF_ERROR_PERM:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("permission denied"));
- ret++;
- break;
- case STMF_ERROR_FILE_IN_USE:
- (void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
- operands[0], gettext("in use"));
- ret++;
- break;
- case STMF_ERROR_INVALID_BLKSIZE:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("invalid block size"));
- ret++;
- break;
- case STMF_ERROR_GUID_IN_USE:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("guid in use"));
- ret++;
- break;
- case STMF_ERROR_META_FILE_NAME:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("meta file error"));
- ret++;
- break;
- case STMF_ERROR_DATA_FILE_NAME:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("data file error"));
- ret++;
- break;
- case STMF_ERROR_SIZE_OUT_OF_RANGE:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("invalid size"));
- ret++;
- break;
- case STMF_ERROR_META_CREATION:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("could not create meta file"));
- ret++;
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("unknown error"));
- ret++;
- break;
- }
- if (ret != STMF_STATUS_SUCCESS) {
- goto done;
- }
- (void) printf("Created the following LU:\n");
- print_attr_header();
- ret = print_lu_attr(&createdGuid);
- done:
- (void) stmfFreeLuResource(hdl);
- return (ret);
- }
- /*ARGSUSED*/
- int
- import_lu(int argc, char *operands[], cmdOptions_t *options, void *callData)
- {
- int ret = 0;
- stmfGuid createdGuid;
- ret = stmfImportLu(STMF_DISK, operands[0], &createdGuid);
- switch (ret) {
- case STMF_STATUS_SUCCESS:
- break;
- case STMF_ERROR_BUSY:
- case STMF_ERROR_LU_BUSY:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("resource busy"));
- ret++;
- break;
- case STMF_ERROR_PERM:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("permission denied"));
- ret++;
- break;
- case STMF_ERROR_FILE_IN_USE:
- (void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
- operands[0], gettext("in use"));
- ret++;
- break;
- case STMF_ERROR_GUID_IN_USE:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("guid in use"));
- ret++;
- break;
- case STMF_ERROR_META_FILE_NAME:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("meta file error"));
- ret++;
- break;
- case STMF_ERROR_DATA_FILE_NAME:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("data file error"));
- ret++;
- break;
- case STMF_ERROR_SIZE_OUT_OF_RANGE:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("invalid size"));
- ret++;
- break;
- case STMF_ERROR_META_CREATION:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("could not create meta file"));
- ret++;
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("unknown error"));
- ret++;
- break;
- }
- if (ret != STMF_STATUS_SUCCESS) {
- goto done;
- }
- (void) printf("Imported the following LU:\n");
- print_attr_header();
- ret = print_lu_attr(&createdGuid);
- done:
- return (ret);
- }
- /*ARGSUSED*/
- int
- delete_lu(int operandLen, char *operands[], cmdOptions_t *options,
- void *callData)
- {
- int i, j;
- int ret = 0;
- int stmfRet;
- unsigned int inGuid[sizeof (stmfGuid)];
- stmfGuid delGuid;
- boolean_t keepViews = B_FALSE;
- boolean_t viewEntriesRemoved = B_FALSE;
- boolean_t noLunFound = B_FALSE;
- boolean_t views = B_FALSE;
- boolean_t notValidHexNumber = B_FALSE;
- char sGuid[GUID_INPUT + 1];
- stmfViewEntryList *viewEntryList = NULL;
- for (; options->optval; options++) {
- switch (options->optval) {
- /* Keep views for logical unit */
- case 'k':
- keepViews = B_TRUE;
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, options->optval,
- gettext("unknown option"));
- return (1);
- }
- }
- for (i = 0; i < operandLen; i++) {
- for (j = 0; j < GUID_INPUT; j++) {
- if (!isxdigit(operands[i][j])) {
- notValidHexNumber = B_TRUE;
- break;
- }
- sGuid[j] = tolower(operands[i][j]);
- }
- if ((notValidHexNumber == B_TRUE) ||
- (strlen(operands[i]) != GUID_INPUT)) {
- (void) fprintf(stderr, "%s: %s: %s%d%s\n",
- cmdName, operands[i], gettext("must be "),
- GUID_INPUT,
- gettext(" hexadecimal digits long"));
- notValidHexNumber = B_FALSE;
- ret++;
- continue;
- }
- sGuid[j] = 0;
- (void) sscanf(sGuid,
- "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
- &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
- &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
- &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
- &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
- for (j = 0; j < sizeof (stmfGuid); j++) {
- delGuid.guid[j] = inGuid[j];
- }
- stmfRet = stmfDeleteLu(&delGuid);
- switch (stmfRet) {
- case STMF_STATUS_SUCCESS:
- break;
- case STMF_ERROR_NOT_FOUND:
- noLunFound = B_TRUE;
- break;
- case STMF_ERROR_BUSY:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("resource busy"));
- ret++;
- break;
- case STMF_ERROR_PERM:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("permission denied"));
- ret++;
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("unknown error"));
- ret++;
- break;
- }
- if (!keepViews) {
- stmfRet = stmfGetViewEntryList(&delGuid,
- &viewEntryList);
- if (stmfRet == STMF_STATUS_SUCCESS) {
- for (j = 0; j < viewEntryList->cnt; j++) {
- (void) stmfRemoveViewEntry(&delGuid,
- viewEntryList->ve[j].veIndex);
- }
- /* check if viewEntryList is empty */
- if (viewEntryList->cnt != 0)
- viewEntriesRemoved = B_TRUE;
- stmfFreeMemory(viewEntryList);
- } else {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("unable to remove view entries\n"));
- ret++;
- }
- }
- if (keepViews) {
- stmfRet = stmfGetViewEntryList(&delGuid,
- &viewEntryList);
- if (stmfRet == STMF_STATUS_SUCCESS) {
- views = B_TRUE;
- stmfFreeMemory(viewEntryList);
- }
- }
- if ((!viewEntriesRemoved && noLunFound && !views) ||
- (!views && keepViews && noLunFound)) {
- (void) fprintf(stderr, "%s: %s: %s\n",
- cmdName, sGuid,
- gettext("not found"));
- ret++;
- }
- noLunFound = viewEntriesRemoved = views = B_FALSE;
- }
- return (ret);
- }
- /*ARGSUSED*/
- int
- modify_lu(int operandLen, char *operands[], cmdOptions_t *options,
- void *callData)
- {
- stmfGuid inGuid;
- unsigned int guid[sizeof (stmfGuid)];
- int ret = 0;
- int i;
- char *fname = NULL;
- char sGuid[GUID_INPUT + 1];
- boolean_t fnameUsed = B_FALSE;
- if (operands[0][0] == '/') {
- fnameUsed = B_TRUE;
- fname = operands[0];
- }
- /* check input length */
- if (!fnameUsed && strlen(operands[0]) != GUID_INPUT) {
- (void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
- gettext("must be "), GUID_INPUT,
- gettext(" hexadecimal digits"));
- return (1);
- }
- if (!fnameUsed) {
- /* convert to lower case for scan */
- for (i = 0; i < 32; i++)
- sGuid[i] = tolower(operands[0][i]);
- sGuid[i] = 0;
- (void) sscanf(sGuid,
- "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
- &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
- &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
- &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
- for (i = 0; i < sizeof (stmfGuid); i++) {
- inGuid.guid[i] = guid[i];
- }
- }
- for (; options->optval; options++) {
- switch (options->optval) {
- case 's':
- if (callModify(fname, &inGuid,
- STMF_LU_PROP_SIZE, options->optarg,
- "size") != 0) {
- return (1);
- }
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, options->optval,
- gettext("unknown option"));
- return (1);
- }
- }
- return (ret);
- }
- static int
- callModify(char *fname, stmfGuid *luGuid, uint32_t prop, const char *propVal,
- const char *propString)
- {
- int ret = 0;
- int stmfRet = 0;
- if (!fname) {
- stmfRet = stmfModifyLu(luGuid, prop, propVal);
- } else {
- stmfRet = stmfModifyLuByFname(STMF_DISK, fname, prop,
- propVal);
- }
- switch (stmfRet) {
- case STMF_STATUS_SUCCESS:
- break;
- case STMF_ERROR_BUSY:
- case STMF_ERROR_LU_BUSY:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("resource busy"));
- ret++;
- break;
- case STMF_ERROR_PERM:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("permission denied"));
- ret++;
- break;
- case STMF_ERROR_INVALID_BLKSIZE:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("invalid block size"));
- ret++;
- break;
- case STMF_ERROR_GUID_IN_USE:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("guid in use"));
- ret++;
- break;
- case STMF_ERROR_META_FILE_NAME:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("meta file error"));
- ret++;
- break;
- case STMF_ERROR_DATA_FILE_NAME:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("data file error"));
- ret++;
- break;
- case STMF_ERROR_FILE_SIZE_INVALID:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("file size invalid"));
- ret++;
- break;
- case STMF_ERROR_SIZE_OUT_OF_RANGE:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("invalid size"));
- ret++;
- break;
- case STMF_ERROR_META_CREATION:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("could not create meta file"));
- ret++;
- break;
- default:
- (void) fprintf(stderr, "%s: %s: %s: %d\n", cmdName,
- gettext("could not set property"), propString,
- stmfRet);
- ret++;
- break;
- }
- return (ret);
- }
- /*ARGSUSED*/
- int
- list_lus(int argc, char *argv[], cmdOptions_t *options, void *callData)
- {
- int stmfRet;
- stmfGuidList *luList;
- stmfLogicalUnitProperties luProps;
- int sbdLuCnt = 0;
- int i;
- if ((stmfRet = stmfGetLogicalUnitList(&luList))
- != STMF_STATUS_SUCCESS) {
- switch (stmfRet) {
- case STMF_ERROR_SERVICE_NOT_FOUND:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("STMF service not found"));
- break;
- case STMF_ERROR_BUSY:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("resource busy"));
- break;
- case STMF_ERROR_PERM:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("permission denied"));
- break;
- case STMF_ERROR_SERVICE_DATA_VERSION:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("STMF service version incorrect"));
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("list failed"));
- break;
- }
- return (1);
- }
- for (i = 0; i < luList->cnt; i++) {
- stmfRet = stmfGetLogicalUnitProperties(&luList->guid[i],
- &luProps);
- if (stmfRet != STMF_STATUS_SUCCESS) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("list failed"));
- return (1);
- }
- if (strcmp(luProps.providerName, "sbd") == 0) {
- sbdLuCnt++;
- }
- }
- if (sbdLuCnt == 0)
- return (0);
- (void) printf("\nFound %d LU(s)\n", sbdLuCnt);
- print_attr_header();
- for (i = 0; i < luList->cnt; i++) {
- stmfRet = stmfGetLogicalUnitProperties(&luList->guid[i],
- &luProps);
- if (stmfRet != STMF_STATUS_SUCCESS) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("list failed"));
- return (1);
- }
- if (strcmp(luProps.providerName, "sbd") == 0) {
- (void) print_lu_attr(&luList->guid[i]);
- }
- }
- return (0);
- }
- void
- print_attr_header()
- {
- (void) printf("\n");
- (void) printf(" GUID DATA SIZE "
- " SOURCE\n");
- (void) printf("-------------------------------- -------------------"
- " ----------------\n");
- }
- void
- print_guid(uint8_t *g, FILE *f)
- {
- int i;
- for (i = 0; i < 16; i++) {
- (void) fprintf(f, "%02x", g[i]);
- }
- }
- int
- print_lu_attr(stmfGuid *guid)
- {
- luResource hdl = NULL;
- int stmfRet = 0;
- int ret = 0;
- char propVal[MAXPATHLEN];
- size_t propValSize = sizeof (propVal);
- if ((stmfRet = stmfGetLuResource(guid, &hdl)) != STMF_STATUS_SUCCESS) {
- switch (stmfRet) {
- case STMF_ERROR_BUSY:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("resource busy"));
- break;
- case STMF_ERROR_PERM:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("permission denied"));
- break;
- case STMF_ERROR_NOT_FOUND:
- /* No error here */
- return (0);
- default:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("get extended properties failed"));
- break;
- }
- return (1);
- }
- print_guid((uint8_t *)guid, stdout);
- stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SIZE, propVal,
- &propValSize);
- if (stmfRet == STMF_STATUS_SUCCESS) {
- (void) printf(" %-19s ", propVal);
- } else if (stmfRet == STMF_ERROR_NO_PROP) {
- (void) printf("not set\n");
- } else {
- (void) printf("<error retrieving property>\n");
- ret++;
- }
- stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_FILENAME, propVal,
- &propValSize);
- if (stmfRet == STMF_STATUS_SUCCESS) {
- (void) printf("%s\n", propVal);
- } else if (stmfRet == STMF_ERROR_NO_PROP) {
- (void) printf("not set\n");
- } else {
- (void) printf("<error retrieving property>\n");
- ret++;
- }
- (void) stmfFreeLuResource(hdl);
- return (ret);
- }
- /*
- * input:
- * execFullName - exec name of program (argv[0])
- *
- * copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
- * (changed name to lowerCamelCase to keep consistent with this file)
- *
- * Returns:
- * command name portion of execFullName
- */
- static char *
- getExecBasename(char *execFullname)
- {
- char *lastSlash, *execBasename;
- /* guard against '/' at end of command invocation */
- for (;;) {
- lastSlash = strrchr(execFullname, '/');
- if (lastSlash == NULL) {
- execBasename = execFullname;
- break;
- } else {
- execBasename = lastSlash + 1;
- if (*execBasename == '\0') {
- *lastSlash = '\0';
- continue;
- }
- break;
- }
- }
- return (execBasename);
- }
- int
- main(int argc, char *argv[])
- {
- synTables_t synTables;
- char versionString[VERSION_STRING_MAX_LEN];
- int ret;
- int funcRet;
- void *subcommandArgs = NULL;
- (void) setlocale(LC_ALL, "");
- (void) textdomain(TEXT_DOMAIN);
- /* set global command name */
- cmdName = getExecBasename(argv[0]);
- (void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
- VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
- synTables.versionString = versionString;
- synTables.longOptionTbl = options;
- synTables.subCommandPropsTbl = subCommands;
- ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
- if (ret != 0) {
- return (ret);
- }
- return (funcRet);
- } /* end main */