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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 #include <stdlib.h> 26 #include <stdio.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <fcntl.h> 30 #include <unistd.h> 31 #include <libintl.h> 32 #include <errno.h> 33 #include <string.h> 34 #include <assert.h> 35 #include <getopt.h> 36 #include <strings.h> 37 #include <ctype.h> 38 #include <libnvpair.h> 39 40 #include <cmdparse.h> 41 #include <sys/stmf_defines.h> 42 #include <libstmf.h> 43 #include <sys/stmf_sbd_ioctl.h> 44 45 #define BIG_BUF_SIZE 512 46 #define MAX_LU_LIST 8192 47 #define LU_LIST_MAX_RETRIES 3 48 49 uint8_t big_buf[BIG_BUF_SIZE]; 50 51 int delete_lu(int argc, char *argv[], cmdOptions_t *options, 52 void *callData); 53 int create_lu(int argc, char *argv[], cmdOptions_t *options, void *callData); 54 int import_lu(int argc, char *argv[], cmdOptions_t *options, void *callData); 55 int list_lus(int argc, char *argv[], cmdOptions_t *options, void *callData); 56 int modify_lu(int argc, char *argv[], cmdOptions_t *options, void *callData); 57 static int persist_lu_register(char *, char *); 58 int print_lu_attr(uint64_t handle, char **s); 59 void print_guid(uint8_t *g, FILE *f); 60 void print_attr_header(); 61 62 char *rlc_ret[] = { "", "Metadata creation failed", 63 "LU is not initialized", 64 "File is already loaded", 65 "GUID in the file is already registered", 66 "Registration with framework failed", 67 "Deregistration with stmf failed", 68 "Unable to lookup file", 69 "Incorrect file type to export as LU. Only regular \n" 70 "files and raw storage devices (disks/volumes) can be exported " 71 "as LUs", 72 "Unable to open file", 73 "Unable to get file attributes", 74 "File size has to be at least 1M", 75 "File size is not a multiple of blocksize", 76 "LU size is out of range", 77 "LU size is not supported by underlying Filesystem" 78 }; 79 80 char sbdadm_ver[] = "sbdadm version 1.0"; 81 82 optionTbl_t options[] = { 83 { "disk-size", required_argument, 's', 84 "Size with <none>/k/m/g/t/p/e modifier" }, 85 { "keep-views", no_arg, 'k', 86 "Dont delete view entries related to the LU" }, 87 { NULL, 0, 0 } 88 }; 89 90 subCommandProps_t subCommands[] = { 91 { "create-lu", create_lu, "s", NULL, NULL, 92 OPERAND_MANDATORY_SINGLE, 93 "Full path of the file to initialize" }, 94 { "delete-lu", delete_lu, "k", NULL, NULL, 95 OPERAND_MANDATORY_SINGLE, "GUID of the LU to deregister" }, 96 { "import-lu", import_lu, NULL, NULL, NULL, 97 OPERAND_MANDATORY_SINGLE, "filename of the LU to import" }, 98 { "list-lu", list_lus, NULL, NULL, NULL, 99 OPERAND_NONE, "List all the exported LUs" }, 100 { "modify-lu", modify_lu, "s", "s", NULL, 101 OPERAND_MANDATORY_SINGLE, 102 "Full path of the LU or GUID of a registered LU" }, 103 { NULL, 0, 0, NULL, 0, NULL} 104 }; 105 106 int sbd_fd; 107 108 int 109 main(int argc, char *argv[]) 110 { 111 int ret, func_ret; 112 synTables_t sbdt = { sbdadm_ver, options, subCommands }; 113 114 sbd_fd = open("/devices/pseudo/stmf_sbd@0:admin", O_RDONLY); 115 if (sbd_fd < 0) { 116 if (errno == EPERM) { 117 (void) fprintf(stderr, "Not enough permissions to open " 118 "device\n"); 119 } else { 120 (void) fprintf(stderr, 121 "Unable to open device. Is the driver " 122 "attached ?\n"); 123 } 124 exit(1); 125 } 126 ret = cmdParse(argc, argv, sbdt, NULL, &func_ret); 127 128 if (ret) 129 return (ret); 130 return (func_ret); 131 } 132 133 /* 134 * Supports upto 8 Exabytes. 135 * 136 * Returns zero upon success and the size in sizep. 137 * returns 2 if the string format is invalid. 138 * returns 1 if the specified size is out of range. 139 */ 140 int 141 str_to_size(char *str, uint64_t *sizep) 142 { 143 uint64_t cur_size, m; 144 uint64_t new_cur_size; 145 int i; 146 char c; 147 148 m = 1; 149 cur_size = 0; 150 151 for (i = 0; str[i] != NULL; i++) { 152 if (m != 1) { 153 /* We should have been done after the modifier */ 154 return (2); 155 } 156 c = str[i]; 157 if (isdigit(c)) { 158 new_cur_size = (cur_size * 10) + 159 (((uint64_t)c) - '0'); 160 if (new_cur_size < cur_size) { 161 /* Overflow */ 162 return (1); 163 } 164 cur_size = new_cur_size; 165 continue; 166 } 167 if (cur_size == 0) { 168 /* Direct format modifier ?? */ 169 return (2); 170 } 171 c = toupper(c); 172 if (c == 'K') { 173 m = 1024; 174 } else if (c == 'M') { 175 m = 1024 * 1024; 176 } else if (c == 'G') { 177 m = 1024 * 1024 * 1024; 178 } else if (c == 'T') { 179 m = 1024ll * 1024 * 1024 * 1024; 180 } else if (c == 'P') { 181 m = 1024ll * 1024 * 1024 * 1024 * 1024; 182 } else if (c == 'E') { 183 m = 1024ll * 1024 * 1024 * 1024 * 1024 * 1024; 184 } else { 185 return (2); 186 } 187 } 188 189 while (m > 1) { 190 if (cur_size & 0x8000000000000000ull) { 191 /* Overflow */ 192 return (1); 193 } 194 cur_size <<= 1; 195 m >>= 1; 196 } 197 198 if (cur_size > 0x8000000000000000ull) { 199 /* We cannot allow more than 8 Exabytes */ 200 return (1); 201 } 202 203 *sizep = cur_size; 204 205 return (0); 206 } 207 208 static int 209 persist_lu_register(char *guid, char *filename) 210 { 211 int ret = 0; 212 nvlist_t *nvl = NULL; 213 uint64_t setToken; 214 boolean_t retryGetProviderData; 215 216 do { 217 retryGetProviderData = B_FALSE; 218 ret = stmfGetProviderDataProt("sbd", &nvl, 219 STMF_LU_PROVIDER_TYPE, &setToken); 220 if (ret != STMF_STATUS_SUCCESS) { 221 if (ret == STMF_ERROR_NOT_FOUND) { 222 (void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 223 } else { 224 (void) fprintf(stderr, 225 "could not access persistent store\n"); 226 ret = 1; 227 goto out; 228 } 229 } 230 231 ret = nvlist_add_string(nvl, guid, filename); 232 if (ret != 0) { 233 (void) fprintf(stderr, 234 "could not add data to nvlist\n"); 235 ret = 1; 236 goto out; 237 } 238 239 ret = stmfSetProviderDataProt("sbd", nvl, STMF_LU_PROVIDER_TYPE, 240 &setToken); 241 if (ret != STMF_STATUS_SUCCESS) { 242 if (ret == STMF_ERROR_BUSY) { 243 (void) fprintf(stderr, 244 "stmf framework resource busy\n"); 245 } else if (ret == STMF_ERROR_PROV_DATA_STALE) { 246 nvlist_free(nvl); 247 nvl = NULL; 248 retryGetProviderData = B_TRUE; 249 continue; 250 } else { 251 (void) fprintf(stderr, 252 "unable to set persistent store data\n"); 253 } 254 ret = 1; 255 goto out; 256 } 257 } while (retryGetProviderData); 258 out: 259 nvlist_free(nvl); 260 return (ret); 261 } 262 263 /*ARGSUSED*/ 264 int 265 create_lu(int argc, char *argv[], cmdOptions_t *options, void *callData) 266 { 267 register_lu_cmd_t *rlc; 268 uint32_t fl; 269 int ret = 0, err; 270 uint64_t size; 271 char guidAsciiBuf[33]; 272 273 /* Check whether this file path is absolute path */ 274 if (argv[argc - 1][0] != '/') { 275 (void) fprintf(stderr, "File name should be an absolute path" 276 " i.e. it should start with a /\n"); 277 return (1); 278 } 279 280 fl = strlen(argv[argc - 1]) + 1; 281 rlc = (register_lu_cmd_t *)malloc(sizeof (register_lu_cmd_t) + fl - 8); 282 if (rlc == NULL) { 283 (void) fprintf(stderr, "Unable to allocate memory\n"); 284 return (1); 285 } 286 bzero(rlc, sizeof (register_lu_cmd_t)); 287 rlc->total_struct_size = sizeof (register_lu_cmd_t) + fl - 8; 288 289 rlc->flags = RLC_LU_TYPE_FILEDISK | RLC_CREATE_LU | RLC_REGISTER_LU; 290 for (; options->optval; options++) { 291 if (options->optval == 's') { 292 err = str_to_size(options->optarg, &size); 293 if (err == 1) { 294 (void) fprintf(stderr, 295 "Size out of range: maximum" 296 " supported size is 9223372036854710272" 297 " (8 Exabytes - 64 Kilobytes)\n"); 298 ret = 1; 299 goto create_lu_done; 300 } else if (err == 2) { 301 (void) fprintf(stderr, 302 "Invalid size specified\n"); 303 ret = 1; 304 goto create_lu_done; 305 } 306 rlc->lu_size = size; 307 } 308 } 309 (void) strcpy(rlc->name, argv[argc-1]); 310 if ((ioctl(sbd_fd, SBD_REGISTER_LU, rlc) < 0) || 311 (rlc->return_code != 0) || (rlc->op_ret != STMF_SUCCESS)) { 312 if (rlc->return_code && (rlc->return_code < RLC_RET_MAX_VAL)) { 313 (void) fprintf(stderr, "LU Create failed : %s.\n", 314 rlc_ret[rlc->return_code]); 315 if (rlc->return_code == 316 RLC_RET_SIZE_NOT_SUPPORTED_BY_FS) { 317 (void) fprintf(stderr, "Maximum LU size on " 318 "the underlying filesystem can be %llu " 319 "bytes.\n", 320 ((((uint64_t)1) << rlc->filesize_nbits) 321 - 1 - 64 * 1024) & 0xfffffffffffffe00ull); 322 } 323 if (rlc->return_code == 324 RLC_RET_GUID_ALREADY_REGISTERED) { 325 (void) fprintf(stderr, "Registered GUID is "); 326 print_guid(rlc->guid, stderr); 327 (void) fprintf(stderr, "\n"); 328 } 329 } else { 330 (void) fprintf(stderr, "LU Create failed(%llx) : %s.\n", 331 rlc->op_ret, strerror(errno)); 332 } 333 ret = 1; 334 } else { 335 if (rlc->flags & RLC_REGISTER_LU) { 336 (void) printf("\nCreated the following LU:\n"); 337 print_attr_header(); 338 (void) print_lu_attr(rlc->lu_handle, NULL); 339 (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf), 340 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" 341 "%02x%02x%02x%02x%02x%02x", 342 rlc->guid[0], rlc->guid[1], rlc->guid[2], 343 rlc->guid[3], rlc->guid[4], rlc->guid[5], 344 rlc->guid[6], rlc->guid[7], rlc->guid[8], 345 rlc->guid[9], rlc->guid[10], rlc->guid[11], 346 rlc->guid[12], rlc->guid[13], rlc->guid[14], 347 rlc->guid[15]); 348 349 ret = persist_lu_register(guidAsciiBuf, argv[argc - 1]); 350 } 351 } 352 353 create_lu_done:; 354 free(rlc); 355 return (ret); 356 } 357 358 /*ARGSUSED*/ 359 int 360 import_lu(int argc, char *argv[], cmdOptions_t *options, void *callData) 361 { 362 register_lu_cmd_t *rlc; 363 uint32_t fl; 364 int ret = 0; 365 char guidAsciiBuf[33]; 366 367 /* Check whether this file path is absolute path */ 368 if (argv[argc - 1][0] != '/') { 369 (void) fprintf(stderr, "File name should be an absolute path" 370 " i.e. it should start with a /\n"); 371 return (1); 372 } 373 374 fl = strlen(argv[argc - 1]) + 1; 375 rlc = (register_lu_cmd_t *)malloc(sizeof (register_lu_cmd_t) + fl - 8); 376 if (rlc == NULL) { 377 (void) fprintf(stderr, "Unable to allocate memory\n"); 378 return (1); 379 } 380 bzero(rlc, sizeof (register_lu_cmd_t)); 381 rlc->total_struct_size = sizeof (register_lu_cmd_t) + fl - 8; 382 383 rlc->flags = RLC_LU_TYPE_FILEDISK | RLC_REGISTER_LU; 384 (void) strcpy(rlc->name, argv[argc-1]); 385 if ((ioctl(sbd_fd, SBD_REGISTER_LU, rlc) < 0) || 386 (rlc->return_code != 0) || (rlc->op_ret != STMF_SUCCESS)) { 387 if (rlc->return_code && (rlc->return_code < RLC_RET_MAX_VAL)) { 388 (void) fprintf(stderr, "LU import failed : %s.\n", 389 rlc_ret[rlc->return_code]); 390 if (rlc->return_code == 391 RLC_RET_SIZE_NOT_SUPPORTED_BY_FS) { 392 (void) fprintf(stderr, "Maximum LU size on " 393 "the underlying filesystem can be %llu " 394 "bytes.\n", 395 ((((uint64_t)1) << rlc->filesize_nbits) 396 - 1 - 64 * 1024) & 0xfffffffffffffe00ull); 397 } 398 if (rlc->return_code == 399 RLC_RET_GUID_ALREADY_REGISTERED) { 400 (void) fprintf(stderr, "Registered GUID is "); 401 print_guid(rlc->guid, stderr); 402 (void) fprintf(stderr, "\n"); 403 } 404 } else { 405 (void) fprintf(stderr, "LU import failed(%llx) : %s.\n", 406 rlc->op_ret, strerror(errno)); 407 } 408 ret = 1; 409 } else { 410 if (rlc->flags & RLC_REGISTER_LU) { 411 (void) printf("\nImported the following LU:\n"); 412 print_attr_header(); 413 (void) print_lu_attr(rlc->lu_handle, NULL); 414 (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf), 415 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" 416 "%02x%02x%02x%02x%02x%02x", 417 rlc->guid[0], rlc->guid[1], rlc->guid[2], 418 rlc->guid[3], rlc->guid[4], rlc->guid[5], 419 rlc->guid[6], rlc->guid[7], rlc->guid[8], 420 rlc->guid[9], rlc->guid[10], rlc->guid[11], 421 rlc->guid[12], rlc->guid[13], rlc->guid[14], 422 rlc->guid[15]); 423 424 ret = persist_lu_register(guidAsciiBuf, argv[argc - 1]); 425 } 426 } 427 428 import_lu_done:; 429 free(rlc); 430 return (ret); 431 } 432 433 /*ARGSUSED*/ 434 int 435 delete_lu(int argc, char *argv[], cmdOptions_t *options, void *callData) 436 { 437 deregister_lu_cmd_t drlc; 438 int ret = 0, i; 439 char chstr[3], *pend = NULL; 440 uint32_t ch, off = 0; 441 int exists = 0; 442 char guidAsciiBuf[33]; 443 nvlist_t *nvl = NULL; 444 445 int stmf_ret; 446 int keep_view = 0; 447 uint64_t setToken; 448 stmfGuid inGuid; 449 stmfViewEntryList *viewEntryList; 450 boolean_t retryGetProviderData; 451 452 for (; options->optval; options++) { 453 switch (options->optval) { 454 case 'k': 455 keep_view = 1; 456 break; 457 } 458 } 459 460 if (strlen(argv[argc - 1]) != 32) { 461 (void) fprintf(stderr, "GUID must be 32 characters\n"); 462 ret = 1; 463 goto delete_lu_done; 464 } 465 466 for (i = 0; i < 32; i++) { 467 guidAsciiBuf[i] = tolower(argv[argc - 1][i]); 468 } 469 470 guidAsciiBuf[i] = 0; 471 472 do { 473 retryGetProviderData = B_FALSE; 474 stmf_ret = stmfGetProviderDataProt("sbd", &nvl, 475 STMF_LU_PROVIDER_TYPE, &setToken); 476 if (stmf_ret != STMF_STATUS_SUCCESS) { 477 (void) fprintf(stderr, 478 "Could not access persistent store\n"); 479 ret = 1; 480 goto delete_lu_done; 481 } 482 ret = nvlist_remove(nvl, guidAsciiBuf, DATA_TYPE_STRING); 483 if (ret == 0) { 484 exists = 1; 485 stmf_ret = stmfSetProviderDataProt("sbd", nvl, 486 STMF_LU_PROVIDER_TYPE, &setToken); 487 if (stmf_ret != STMF_STATUS_SUCCESS) { 488 if (stmf_ret == STMF_ERROR_BUSY) { 489 (void) fprintf(stderr, 490 "stmf framework resource busy\n"); 491 } else if (stmf_ret == 492 STMF_ERROR_PROV_DATA_STALE) { 493 /* 494 * update failed, try again 495 */ 496 nvlist_free(nvl); 497 nvl = NULL; 498 retryGetProviderData = B_TRUE; 499 continue; 500 } else { 501 (void) fprintf(stderr, 502 "unable to set persistent store " 503 "data\n"); 504 } 505 ret = 1; 506 goto delete_lu_done; 507 } 508 } 509 } while (retryGetProviderData); 510 511 bzero(&drlc, sizeof (drlc)); 512 drlc.total_struct_size = sizeof (drlc); 513 drlc.flags = RLC_DEREGISTER_LU; 514 515 chstr[2] = 0; 516 i = 0; 517 while ((off + 2) <= strlen(argv[argc - 1])) { 518 bcopy(argv[argc -1] + off, chstr, 2); 519 off += 2; 520 521 if (!isxdigit(chstr[0]) || !isxdigit(chstr[1])) { 522 (void) fprintf(stderr, "Invalid LU GUID specified.\n"); 523 ret = 1; 524 goto delete_lu_done; 525 } 526 errno = 0; 527 ch = strtoul(chstr, &pend, 16); 528 if (errno != 0) { 529 (void) fprintf(stderr, "Invalid LU GUID specified.\n"); 530 ret = 1; 531 goto delete_lu_done; 532 } 533 drlc.guid[i++] = ch; 534 535 } 536 537 if (ioctl(sbd_fd, SBD_DEREGISTER_LU, &drlc) < 0) { 538 if (errno != ENODEV) { 539 (void) fprintf(stderr, 540 "Request to delete LU failed: %s\n", 541 strerror(errno)); 542 ret = 1; 543 goto delete_lu_done; 544 } 545 } else if (drlc.return_code != 0) { 546 (void) fprintf(stderr, "LU deregister failed: ret_code-%x", 547 drlc.return_code); 548 ret = 1; 549 goto delete_lu_done; 550 } else { 551 exists = 1; 552 } 553 554 if (!keep_view) { 555 for (i = 0; i < 16; i++) 556 inGuid.guid[i] = drlc.guid[i]; 557 558 if ((stmf_ret = stmfGetViewEntryList(&inGuid, 559 &viewEntryList)) == STMF_STATUS_SUCCESS) { 560 for (i = 0; i < viewEntryList->cnt; i++) { 561 (void) stmfRemoveViewEntry(&inGuid, 562 viewEntryList->ve[i].veIndex); 563 } 564 } else if (stmf_ret != STMF_ERROR_NOT_FOUND) { 565 (void) fprintf(stderr, 566 "unable to remove view entries\n"); 567 ret = 1; 568 } 569 } 570 571 if (!exists) { 572 (void) fprintf(stderr, "GUID not found.\n"); 573 ret = 1; 574 goto delete_lu_done; 575 } 576 577 delete_lu_done:; 578 return (ret); 579 } 580 581 /*ARGSUSED*/ 582 int 583 modify_lu(int argc, char *argv[], cmdOptions_t *options, void *callData) 584 { 585 modify_lu_cmd_t *mlc; 586 uint32_t fl = 0, struct_size; 587 int ret = 0, err; 588 int i = 0; 589 uint64_t size; 590 int is_filename = 0; 591 char chstr[3], *pend = NULL; 592 uint32_t ch; 593 uint32_t off = 0; 594 595 if (argv[argc - 1][0] == '/') { 596 is_filename = 1; 597 fl = strlen(argv[argc - 1]) + 1; 598 struct_size = sizeof (modify_lu_cmd_t) + fl - 8; 599 } else { 600 struct_size = sizeof (modify_lu_cmd_t); 601 } 602 mlc = (modify_lu_cmd_t *)malloc(struct_size); 603 if (mlc == NULL) { 604 (void) fprintf(stderr, "Unable to allocate memory\n"); 605 return (1); 606 } 607 bzero(mlc, sizeof (modify_lu_cmd_t)); 608 mlc->total_struct_size = struct_size; 609 610 mlc->flags = RLC_LU_TYPE_FILEDISK | RLC_CREATE_LU; 611 for (; options->optval; options++) { 612 if (options->optval == 's') { 613 err = str_to_size(options->optarg, &size); 614 if (err == 1) { 615 (void) fprintf(stderr, 616 "Size out of range: maximum" 617 " supported size is 9223372036854775808" 618 " (8 Exabytes)\n"); 619 ret = 1; 620 goto modify_lu_done; 621 } else if (err == 2) { 622 (void) fprintf(stderr, 623 "Invalid size specified\n"); 624 ret = 1; 625 goto modify_lu_done; 626 } 627 mlc->lu_size = size; 628 } 629 } 630 if (is_filename) { 631 (void) strcpy(mlc->name, argv[argc-1]); 632 (void) memset(mlc->guid, 0, 16); 633 } else { 634 if (strlen(argv[argc - 1]) != 32) { 635 (void) fprintf(stderr, 636 "Invalid device identifier or filename" 637 " specified.\nIf it is a filename, it should be an" 638 " absolute path i.e. it should start with a /\n"); 639 goto modify_lu_done; 640 } 641 chstr[2] = 0; 642 i = 0; 643 while ((off + 2) <= strlen(argv[argc - 1])) { 644 bcopy(argv[argc -1] + off, chstr, 2); 645 off += 2; 646 647 ch = strtoul(chstr, &pend, 16); 648 if (errno != 0) { 649 (void) fprintf(stderr, 650 "Invalid device identifier or" 651 " filename specified.\nIf it is a" 652 " filename, it should be an absolute path" 653 " i.e. it should start with a /\n"); 654 ret = 1; 655 goto modify_lu_done; 656 } 657 mlc->guid[i++] = ch; 658 659 } 660 mlc->name[0] = '\0'; 661 } 662 if ((ioctl(sbd_fd, SBD_MODIFY_LU, mlc) < 0) || 663 (mlc->return_code != 0) || (mlc->op_ret |= STMF_SUCCESS)) { 664 if (mlc->return_code && (mlc->return_code < RLC_RET_MAX_VAL)) { 665 (void) fprintf(stderr, "LU modify failed : %s.\n", 666 rlc_ret[mlc->return_code]); 667 if (mlc->return_code == 668 RLC_RET_SIZE_NOT_SUPPORTED_BY_FS) { 669 (void) fprintf(stderr, "Maximum LU size on " 670 "the underlying filesystem can be %llu " 671 "bytes.\n", 672 ((((uint64_t)1) << mlc->filesize_nbits) 673 - 1) & 0xfffffffffffffe00ull); 674 } else if (mlc->return_code == 675 RLC_RET_LU_NOT_INITIALIZED) { 676 (void) fprintf(stderr, "Use 'sbdadm lu-create' " 677 "to initialize the LU.\n"); 678 } 679 } else { 680 (void) fprintf(stderr, "LU modify failed(%llx) : %s.\n", 681 mlc->op_ret, strerror(errno)); 682 } 683 ret = 1; 684 } else { 685 (void) printf("LU modified Successfully.\n"); 686 } 687 688 modify_lu_done:; 689 free(mlc); 690 return (ret); 691 } 692 693 694 /*ARGSUSED*/ 695 int 696 list_lus(int argc, char *argv[], cmdOptions_t *options, void *callData) 697 { 698 sbd_lu_list_t *sll; 699 uint32_t i; 700 ssize_t list_size; 701 int retry_count = 0; 702 uint32_t lu_count_in = MAX_LU_LIST; 703 int ret; 704 nvlist_t *nvl = NULL; 705 nvpair_t *np; 706 char *s; 707 708 ret = stmfGetProviderDataProt("sbd", &nvl, STMF_LU_PROVIDER_TYPE, 709 NULL); 710 if (ret != STMF_STATUS_SUCCESS) { 711 if (ret == STMF_ERROR_NOT_FOUND) { 712 (void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 713 } else { 714 (void) fprintf(stderr, 715 "Could not access persistent store\n"); 716 return (1); 717 } 718 } 719 720 retry_get_lu_list: 721 list_size = (lu_count_in * 8) + sizeof (sbd_lu_list_t) - 8; 722 sll = (sbd_lu_list_t *)calloc(1, list_size); 723 if (sll == NULL) { 724 (void) fprintf(stderr, "Memory allocation failure\n"); 725 nvlist_free(nvl); 726 return (1); 727 } 728 729 sll->total_struct_size = list_size; 730 731 sll->count_in = lu_count_in; 732 if (ioctl(sbd_fd, SBD_GET_LU_LIST, sll) < 0) { 733 (void) fprintf(stderr, "Unable to get LU list : %s\n", 734 strerror(errno)); 735 free(sll); 736 nvlist_free(nvl); 737 return (1); 738 } 739 if (sll->count_out > sll->count_in) { 740 lu_count_in = sll->count_out; 741 free(sll); 742 if (retry_count < LU_LIST_MAX_RETRIES) { 743 retry_count++; 744 goto retry_get_lu_list; 745 } else { 746 (void) fprintf(stderr, "Unable to get LU list after %d" 747 " retries\n", retry_count); 748 nvlist_free(nvl); 749 return (1); 750 } 751 } 752 753 (void) printf("\nFound %d LU(s)\n", sll->count_out); 754 if (sll->count_out == 0) 755 goto over_print_attr; 756 757 print_attr_header(); 758 for (i = 0; i < sll->count_out; i++) { 759 if (!print_lu_attr(sll->handles[i], &s)) 760 continue; 761 if (nvlist_remove(nvl, s, DATA_TYPE_STRING) != 0) { 762 (void) fprintf(stderr, 763 "Error: GUID %s does not exist in " 764 "persistent store\n", s); 765 } 766 } 767 over_print_attr: 768 free(sll); 769 np = NULL; 770 while ((np = nvlist_next_nvpair(nvl, np)) != NULL) { 771 if (nvpair_type(np) != DATA_TYPE_STRING) 772 continue; 773 if (nvpair_value_string(np, &s) != 0) 774 continue; 775 776 (void) fprintf(stderr, "%s <Failed to load> %s\n", 777 nvpair_name(np), s); 778 } 779 nvlist_free(nvl); 780 return (0); 781 } 782 783 void 784 print_attr_header() 785 { 786 (void) printf("\n"); 787 (void) printf(" GUID DATA SIZE " 788 " SOURCE\n"); 789 (void) printf("-------------------------------- -------------------" 790 " ----------------\n"); 791 } 792 793 void 794 print_guid(uint8_t *g, FILE *f) 795 { 796 int i; 797 798 for (i = 0; i < 16; i++) { 799 (void) fprintf(f, "%02x", g[i]); 800 } 801 } 802 803 int 804 print_lu_attr(uint64_t handle, char **s) 805 { 806 sbd_lu_attr_t *sla; 807 808 sla = (sbd_lu_attr_t *)big_buf; 809 810 bzero(sla, BIG_BUF_SIZE); 811 812 sla->lu_handle = handle; 813 sla->total_struct_size = BIG_BUF_SIZE; 814 sla->max_name_length = BIG_BUF_SIZE - sizeof (*sla) + 7; 815 816 if (ioctl(sbd_fd, SBD_GET_LU_ATTR, sla) < 0) { 817 (void) fprintf(stderr, "Request to get LU attr failed: %s\n", 818 strerror(errno)); 819 return (0); 820 } 821 822 print_guid(sla->guid, stdout); 823 824 if (sla->data_size > 9999999999999ull) 825 (void) printf(" %-19llu ", sla->data_size); 826 else 827 (void) printf(" %-13llu ", sla->data_size); 828 829 if (sla->flags & RLC_LU_TYPE_MEMDISK) { 830 (void) printf("<RAM : %llu bytes>\n", sla->total_size); 831 } else { 832 (void) printf("%s\n", sla->name); 833 } 834 if (s != NULL) { 835 (void) snprintf((char *)big_buf, sizeof (big_buf), 836 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" 837 "%02x%02x%02x%02x%02x%02x", 838 sla->guid[0], sla->guid[1], sla->guid[2], 839 sla->guid[3], sla->guid[4], sla->guid[5], 840 sla->guid[6], sla->guid[7], sla->guid[8], 841 sla->guid[9], sla->guid[10], sla->guid[11], 842 sla->guid[12], sla->guid[13], sla->guid[14], 843 sla->guid[15]); 844 *s = (char *)big_buf; 845 } 846 return (1); 847 } 848