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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
28 #include <sys/types.h>
39 #include <libnvpair.h>
43 #include <sys/stmf_defines.h>
45 #include <sys/stmf_sbd_ioctl.h>
47 #define MAX_LU_LIST 8192
48 #define LU_LIST_MAX_RETRIES 3
51 #define VERSION_STRING_MAJOR "1"
52 #define VERSION_STRING_MINOR "0"
53 #define VERSION_STRING_MAX_LEN 10
58 static char *getExecBasename(char *);
59 int delete_lu(int argc
, char *argv
[], cmdOptions_t
*options
,
61 int create_lu(int argc
, char *argv
[], cmdOptions_t
*options
, void *callData
);
62 int list_lus(int argc
, char *argv
[], cmdOptions_t
*options
, void *callData
);
63 int modify_lu(int argc
, char *argv
[], cmdOptions_t
*options
, void *callData
);
64 int import_lu(int argc
, char *argv
[], cmdOptions_t
*options
, void *callData
);
65 static int callModify(char *, stmfGuid
*, uint32_t, const char *, const char *);
66 int print_lu_attr(stmfGuid
*);
67 void print_guid(uint8_t *g
, FILE *f
);
68 void print_attr_header();
70 optionTbl_t options
[] = {
71 { "disk-size", required_argument
, 's',
72 "Size with <none>/k/m/g/t/p/e modifier" },
73 { "keep-views", no_arg
, 'k',
74 "Dont delete view entries related to the LU" },
78 subCommandProps_t subCommands
[] = {
79 { "create-lu", create_lu
, "s", NULL
, NULL
,
80 OPERAND_MANDATORY_SINGLE
,
81 "Full path of the file to initialize" },
82 { "delete-lu", delete_lu
, "k", NULL
, NULL
,
83 OPERAND_MANDATORY_SINGLE
, "GUID of the LU to deregister" },
84 { "import-lu", import_lu
, NULL
, NULL
, NULL
,
85 OPERAND_MANDATORY_SINGLE
, "filename of the LU to import" },
86 { "list-lu", list_lus
, NULL
, NULL
, NULL
,
87 OPERAND_NONE
, "List all the exported LUs" },
88 { "modify-lu", modify_lu
, "s", "s", NULL
,
89 OPERAND_MANDATORY_SINGLE
,
90 "Full path of the LU or GUID of a registered LU" },
91 { NULL
, 0, NULL
, NULL
, NULL
, 0, NULL
}
96 create_lu(int argc
, char *operands
[], cmdOptions_t
*options
, void *callData
)
98 luResource hdl
= NULL
;
100 stmfGuid createdGuid
;
102 ret
= stmfCreateLuResource(STMF_DISK
, &hdl
);
104 if (ret
!= STMF_STATUS_SUCCESS
) {
105 (void) fprintf(stderr
, "%s: %s\n",
106 cmdName
, gettext("Failure to create lu resource\n"));
110 for (; options
->optval
; options
++) {
111 switch (options
->optval
) {
113 ret
= stmfSetLuProp(hdl
, STMF_LU_PROP_SIZE
,
115 if (ret
!= STMF_STATUS_SUCCESS
) {
116 (void) fprintf(stderr
, "%s: %c: %s\n",
117 cmdName
, options
->optval
,
118 gettext("size param invalid"));
119 (void) stmfFreeLuResource(hdl
);
124 (void) fprintf(stderr
, "%s: %c: %s\n",
125 cmdName
, options
->optval
,
126 gettext("unknown option"));
131 ret
= stmfSetLuProp(hdl
, STMF_LU_PROP_FILENAME
, operands
[0]);
133 if (ret
!= STMF_STATUS_SUCCESS
) {
134 (void) fprintf(stderr
, "%s: %s\n",
135 cmdName
, gettext("could not set filename"));
139 ret
= stmfCreateLu(hdl
, &createdGuid
);
141 case STMF_STATUS_SUCCESS
:
143 case STMF_ERROR_BUSY
:
144 case STMF_ERROR_LU_BUSY
:
145 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
146 gettext("resource busy"));
149 case STMF_ERROR_PERM
:
150 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
151 gettext("permission denied"));
154 case STMF_ERROR_FILE_IN_USE
:
155 (void) fprintf(stderr
, "%s: filename %s: %s\n", cmdName
,
156 operands
[0], gettext("in use"));
159 case STMF_ERROR_INVALID_BLKSIZE
:
160 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
161 gettext("invalid block size"));
164 case STMF_ERROR_GUID_IN_USE
:
165 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
166 gettext("guid in use"));
169 case STMF_ERROR_META_FILE_NAME
:
170 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
171 gettext("meta file error"));
174 case STMF_ERROR_DATA_FILE_NAME
:
175 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
176 gettext("data file error"));
179 case STMF_ERROR_SIZE_OUT_OF_RANGE
:
180 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
181 gettext("invalid size"));
184 case STMF_ERROR_META_CREATION
:
185 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
186 gettext("could not create meta file"));
190 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
191 gettext("unknown error"));
196 if (ret
!= STMF_STATUS_SUCCESS
) {
200 (void) printf("Created the following LU:\n");
202 ret
= print_lu_attr(&createdGuid
);
205 (void) stmfFreeLuResource(hdl
);
211 import_lu(int argc
, char *operands
[], cmdOptions_t
*options
, void *callData
)
214 stmfGuid createdGuid
;
216 ret
= stmfImportLu(STMF_DISK
, operands
[0], &createdGuid
);
218 case STMF_STATUS_SUCCESS
:
220 case STMF_ERROR_BUSY
:
221 case STMF_ERROR_LU_BUSY
:
222 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
223 gettext("resource busy"));
226 case STMF_ERROR_PERM
:
227 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
228 gettext("permission denied"));
231 case STMF_ERROR_FILE_IN_USE
:
232 (void) fprintf(stderr
, "%s: filename %s: %s\n", cmdName
,
233 operands
[0], gettext("in use"));
236 case STMF_ERROR_GUID_IN_USE
:
237 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
238 gettext("guid in use"));
241 case STMF_ERROR_META_FILE_NAME
:
242 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
243 gettext("meta file error"));
246 case STMF_ERROR_DATA_FILE_NAME
:
247 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
248 gettext("data file error"));
251 case STMF_ERROR_SIZE_OUT_OF_RANGE
:
252 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
253 gettext("invalid size"));
256 case STMF_ERROR_META_CREATION
:
257 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
258 gettext("could not create meta file"));
262 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
263 gettext("unknown error"));
268 if (ret
!= STMF_STATUS_SUCCESS
) {
272 (void) printf("Imported the following LU:\n");
274 ret
= print_lu_attr(&createdGuid
);
282 delete_lu(int operandLen
, char *operands
[], cmdOptions_t
*options
,
288 unsigned int inGuid
[sizeof (stmfGuid
)];
290 boolean_t keepViews
= B_FALSE
;
291 boolean_t viewEntriesRemoved
= B_FALSE
;
292 boolean_t noLunFound
= B_FALSE
;
293 boolean_t views
= B_FALSE
;
294 boolean_t notValidHexNumber
= B_FALSE
;
295 char sGuid
[GUID_INPUT
+ 1];
296 stmfViewEntryList
*viewEntryList
= NULL
;
298 for (; options
->optval
; options
++) {
299 switch (options
->optval
) {
300 /* Keep views for logical unit */
305 (void) fprintf(stderr
, "%s: %c: %s\n",
306 cmdName
, options
->optval
,
307 gettext("unknown option"));
313 for (i
= 0; i
< operandLen
; i
++) {
314 for (j
= 0; j
< GUID_INPUT
; j
++) {
315 if (!isxdigit(operands
[i
][j
])) {
316 notValidHexNumber
= B_TRUE
;
319 sGuid
[j
] = tolower(operands
[i
][j
]);
321 if ((notValidHexNumber
== B_TRUE
) ||
322 (strlen(operands
[i
]) != GUID_INPUT
)) {
323 (void) fprintf(stderr
, "%s: %s: %s%d%s\n",
324 cmdName
, operands
[i
], gettext("must be "),
326 gettext(" hexadecimal digits long"));
327 notValidHexNumber
= B_FALSE
;
335 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
336 &inGuid
[0], &inGuid
[1], &inGuid
[2], &inGuid
[3],
337 &inGuid
[4], &inGuid
[5], &inGuid
[6], &inGuid
[7],
338 &inGuid
[8], &inGuid
[9], &inGuid
[10], &inGuid
[11],
339 &inGuid
[12], &inGuid
[13], &inGuid
[14], &inGuid
[15]);
341 for (j
= 0; j
< sizeof (stmfGuid
); j
++) {
342 delGuid
.guid
[j
] = inGuid
[j
];
345 stmfRet
= stmfDeleteLu(&delGuid
);
347 case STMF_STATUS_SUCCESS
:
349 case STMF_ERROR_NOT_FOUND
:
352 case STMF_ERROR_BUSY
:
353 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
354 gettext("resource busy"));
357 case STMF_ERROR_PERM
:
358 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
359 gettext("permission denied"));
363 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
364 gettext("unknown error"));
370 stmfRet
= stmfGetViewEntryList(&delGuid
,
372 if (stmfRet
== STMF_STATUS_SUCCESS
) {
373 for (j
= 0; j
< viewEntryList
->cnt
; j
++) {
374 (void) stmfRemoveViewEntry(&delGuid
,
375 viewEntryList
->ve
[j
].veIndex
);
377 /* check if viewEntryList is empty */
378 if (viewEntryList
->cnt
!= 0)
379 viewEntriesRemoved
= B_TRUE
;
380 stmfFreeMemory(viewEntryList
);
382 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
383 gettext("unable to remove view entries\n"));
388 stmfRet
= stmfGetViewEntryList(&delGuid
,
390 if (stmfRet
== STMF_STATUS_SUCCESS
) {
392 stmfFreeMemory(viewEntryList
);
396 if ((!viewEntriesRemoved
&& noLunFound
&& !views
) ||
397 (!views
&& keepViews
&& noLunFound
)) {
398 (void) fprintf(stderr
, "%s: %s: %s\n",
400 gettext("not found"));
403 noLunFound
= viewEntriesRemoved
= views
= B_FALSE
;
410 modify_lu(int operandLen
, char *operands
[], cmdOptions_t
*options
,
414 unsigned int guid
[sizeof (stmfGuid
)];
418 char sGuid
[GUID_INPUT
+ 1];
419 boolean_t fnameUsed
= B_FALSE
;
421 if (operands
[0][0] == '/') {
426 /* check input length */
427 if (!fnameUsed
&& strlen(operands
[0]) != GUID_INPUT
) {
428 (void) fprintf(stderr
, "%s: %s: %s%d%s\n", cmdName
, operands
[0],
429 gettext("must be "), GUID_INPUT
,
430 gettext(" hexadecimal digits"));
435 /* convert to lower case for scan */
436 for (i
= 0; i
< 32; i
++)
437 sGuid
[i
] = tolower(operands
[0][i
]);
440 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
441 &guid
[0], &guid
[1], &guid
[2], &guid
[3], &guid
[4], &guid
[5],
442 &guid
[6], &guid
[7], &guid
[8], &guid
[9], &guid
[10],
443 &guid
[11], &guid
[12], &guid
[13], &guid
[14], &guid
[15]);
445 for (i
= 0; i
< sizeof (stmfGuid
); i
++) {
446 inGuid
.guid
[i
] = guid
[i
];
450 for (; options
->optval
; options
++) {
451 switch (options
->optval
) {
453 if (callModify(fname
, &inGuid
,
454 STMF_LU_PROP_SIZE
, options
->optarg
,
460 (void) fprintf(stderr
, "%s: %c: %s\n",
461 cmdName
, options
->optval
,
462 gettext("unknown option"));
470 callModify(char *fname
, stmfGuid
*luGuid
, uint32_t prop
, const char *propVal
,
471 const char *propString
)
477 stmfRet
= stmfModifyLu(luGuid
, prop
, propVal
);
479 stmfRet
= stmfModifyLuByFname(STMF_DISK
, fname
, prop
,
483 case STMF_STATUS_SUCCESS
:
485 case STMF_ERROR_BUSY
:
486 case STMF_ERROR_LU_BUSY
:
487 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
488 gettext("resource busy"));
491 case STMF_ERROR_PERM
:
492 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
493 gettext("permission denied"));
496 case STMF_ERROR_INVALID_BLKSIZE
:
497 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
498 gettext("invalid block size"));
501 case STMF_ERROR_GUID_IN_USE
:
502 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
503 gettext("guid in use"));
506 case STMF_ERROR_META_FILE_NAME
:
507 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
508 gettext("meta file error"));
511 case STMF_ERROR_DATA_FILE_NAME
:
512 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
513 gettext("data file error"));
516 case STMF_ERROR_FILE_SIZE_INVALID
:
517 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
518 gettext("file size invalid"));
521 case STMF_ERROR_SIZE_OUT_OF_RANGE
:
522 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
523 gettext("invalid size"));
526 case STMF_ERROR_META_CREATION
:
527 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
528 gettext("could not create meta file"));
532 (void) fprintf(stderr
, "%s: %s: %s: %d\n", cmdName
,
533 gettext("could not set property"), propString
,
545 list_lus(int argc
, char *argv
[], cmdOptions_t
*options
, void *callData
)
548 stmfGuidList
*luList
;
549 stmfLogicalUnitProperties luProps
;
553 if ((stmfRet
= stmfGetLogicalUnitList(&luList
))
554 != STMF_STATUS_SUCCESS
) {
556 case STMF_ERROR_SERVICE_NOT_FOUND
:
557 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
558 gettext("STMF service not found"));
560 case STMF_ERROR_BUSY
:
561 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
562 gettext("resource busy"));
564 case STMF_ERROR_PERM
:
565 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
566 gettext("permission denied"));
568 case STMF_ERROR_SERVICE_DATA_VERSION
:
569 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
570 gettext("STMF service version incorrect"));
573 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
574 gettext("list failed"));
580 for (i
= 0; i
< luList
->cnt
; i
++) {
581 stmfRet
= stmfGetLogicalUnitProperties(&luList
->guid
[i
],
583 if (stmfRet
!= STMF_STATUS_SUCCESS
) {
584 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
585 gettext("list failed"));
588 if (strcmp(luProps
.providerName
, "sbd") == 0) {
597 (void) printf("\nFound %d LU(s)\n", sbdLuCnt
);
600 for (i
= 0; i
< luList
->cnt
; i
++) {
601 stmfRet
= stmfGetLogicalUnitProperties(&luList
->guid
[i
],
603 if (stmfRet
!= STMF_STATUS_SUCCESS
) {
604 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
605 gettext("list failed"));
608 if (strcmp(luProps
.providerName
, "sbd") == 0) {
609 (void) print_lu_attr(&luList
->guid
[i
]);
619 (void) printf(" GUID DATA SIZE "
621 (void) printf("-------------------------------- -------------------"
622 " ----------------\n");
626 print_guid(uint8_t *g
, FILE *f
)
630 for (i
= 0; i
< 16; i
++) {
631 (void) fprintf(f
, "%02x", g
[i
]);
636 print_lu_attr(stmfGuid
*guid
)
638 luResource hdl
= NULL
;
641 char propVal
[MAXPATHLEN
];
642 size_t propValSize
= sizeof (propVal
);
644 if ((stmfRet
= stmfGetLuResource(guid
, &hdl
)) != STMF_STATUS_SUCCESS
) {
646 case STMF_ERROR_BUSY
:
647 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
648 gettext("resource busy"));
650 case STMF_ERROR_PERM
:
651 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
652 gettext("permission denied"));
654 case STMF_ERROR_NOT_FOUND
:
658 (void) fprintf(stderr
, "%s: %s\n", cmdName
,
659 gettext("get extended properties failed"));
665 print_guid((uint8_t *)guid
, stdout
);
667 stmfRet
= stmfGetLuProp(hdl
, STMF_LU_PROP_SIZE
, propVal
,
669 if (stmfRet
== STMF_STATUS_SUCCESS
) {
670 (void) printf(" %-19s ", propVal
);
671 } else if (stmfRet
== STMF_ERROR_NO_PROP
) {
672 (void) printf("not set\n");
674 (void) printf("<error retrieving property>\n");
678 stmfRet
= stmfGetLuProp(hdl
, STMF_LU_PROP_FILENAME
, propVal
,
680 if (stmfRet
== STMF_STATUS_SUCCESS
) {
681 (void) printf("%s\n", propVal
);
682 } else if (stmfRet
== STMF_ERROR_NO_PROP
) {
683 (void) printf("not set\n");
685 (void) printf("<error retrieving property>\n");
690 (void) stmfFreeLuResource(hdl
);
696 * execFullName - exec name of program (argv[0])
698 * copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
699 * (changed name to lowerCamelCase to keep consistent with this file)
702 * command name portion of execFullName
705 getExecBasename(char *execFullname
)
707 char *lastSlash
, *execBasename
;
709 /* guard against '/' at end of command invocation */
711 lastSlash
= strrchr(execFullname
, '/');
712 if (lastSlash
== NULL
) {
713 execBasename
= execFullname
;
716 execBasename
= lastSlash
+ 1;
717 if (*execBasename
== '\0') {
724 return (execBasename
);
727 main(int argc
, char *argv
[])
729 synTables_t synTables
;
730 char versionString
[VERSION_STRING_MAX_LEN
];
733 void *subcommandArgs
= NULL
;
735 (void) setlocale(LC_ALL
, "");
736 (void) textdomain(TEXT_DOMAIN
);
737 /* set global command name */
738 cmdName
= getExecBasename(argv
[0]);
740 (void) snprintf(versionString
, VERSION_STRING_MAX_LEN
, "%s.%s",
741 VERSION_STRING_MAJOR
, VERSION_STRING_MINOR
);
742 synTables
.versionString
= versionString
;
743 synTables
.longOptionTbl
= options
;
744 synTables
.subCommandPropsTbl
= subCommands
;
746 ret
= cmdParse(argc
, argv
, synTables
, subcommandArgs
, &funcRet
);