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 26 #include <sys/conf.h> 27 #include <sys/file.h> 28 #include <sys/ddi.h> 29 #include <sys/sunddi.h> 30 #include <sys/modctl.h> 31 #include <sys/scsi/scsi.h> 32 #include <sys/scsi/impl/scsi_reset_notify.h> 33 #include <sys/disp.h> 34 #include <sys/byteorder.h> 35 #include <sys/atomic.h> 36 #include <sys/nvpair.h> 37 38 #include <stmf.h> 39 #include <lpif.h> 40 #include <stmf_ioctl.h> 41 #include <stmf_sbd.h> 42 #include <sbd_impl.h> 43 #include <stmf_sbd_ioctl.h> 44 45 static int sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 46 static int sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 47 static int sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, 48 void **result); 49 static int sbd_open(dev_t *devp, int flag, int otype, cred_t *credp); 50 static int sbd_close(dev_t dev, int flag, int otype, cred_t *credp); 51 static int stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 52 cred_t *credp, int *rval); 53 void sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags); 54 uint8_t sbd_calc_sum(uint8_t *buf, int size); 55 void sbd_swap_meta_start(sbd_meta_start_t *sm); 56 void sbd_swap_section_hdr(sm_section_hdr_t *h, uint8_t data_order); 57 void sbd_swap_sli_fields(sbd_lu_info_t *sli, uint8_t data_order); 58 int sbd_migrate_meta_from_v0_to_v1(sbd_store_t *sst); 59 60 extern struct mod_ops mod_driverops; 61 62 static stmf_lu_provider_t *sbd_lp; 63 static dev_info_t *sbd_dip; 64 static kmutex_t sbd_lock; 65 sbd_lu_t *sbd_lu_list = NULL; 66 static int sbd_lu_count = 0; 67 static char sbd_name[] = "sbd"; 68 static uint64_t sbd_meta_offset = 4096; /* offset to skip label */ 69 70 static struct cb_ops sbd_cb_ops = { 71 sbd_open, /* open */ 72 sbd_close, /* close */ 73 nodev, /* strategy */ 74 nodev, /* print */ 75 nodev, /* dump */ 76 nodev, /* read */ 77 nodev, /* write */ 78 stmf_sbd_ioctl, /* ioctl */ 79 nodev, /* devmap */ 80 nodev, /* mmap */ 81 nodev, /* segmap */ 82 nochpoll, /* chpoll */ 83 ddi_prop_op, /* cb_prop_op */ 84 0, /* streamtab */ 85 D_NEW | D_MP, /* cb_flag */ 86 CB_REV, /* rev */ 87 nodev, /* aread */ 88 nodev /* awrite */ 89 }; 90 91 static struct dev_ops sbd_ops = { 92 DEVO_REV, 93 0, 94 sbd_getinfo, 95 nulldev, /* identify */ 96 nulldev, /* probe */ 97 sbd_attach, 98 sbd_detach, 99 nodev, /* reset */ 100 &sbd_cb_ops, 101 NULL, /* bus_ops */ 102 NULL /* power */ 103 }; 104 105 #define SBD_NAME "COMSTAR SBD" 106 107 static struct modldrv modldrv = { 108 &mod_driverops, 109 SBD_NAME, 110 &sbd_ops 111 }; 112 113 static struct modlinkage modlinkage = { 114 MODREV_1, 115 &modldrv, 116 NULL 117 }; 118 119 int 120 _init(void) 121 { 122 int ret; 123 124 ret = mod_install(&modlinkage); 125 if (ret) 126 return (ret); 127 sbd_lp = (stmf_lu_provider_t *)stmf_alloc(STMF_STRUCT_LU_PROVIDER, 128 0, 0); 129 sbd_lp->lp_lpif_rev = LPIF_REV_1; 130 sbd_lp->lp_instance = 0; 131 sbd_lp->lp_name = sbd_name; 132 sbd_lp->lp_cb = sbd_lp_cb; 133 134 if (stmf_register_lu_provider(sbd_lp) != STMF_SUCCESS) { 135 (void) mod_remove(&modlinkage); 136 stmf_free(sbd_lp); 137 return (DDI_FAILURE); 138 } 139 mutex_init(&sbd_lock, NULL, MUTEX_DRIVER, NULL); 140 return (0); 141 } 142 143 int 144 _fini(void) 145 { 146 int ret; 147 148 /* 149 * If we have registered lus, then make sure they are all offline 150 * if so then deregister them. This should drop the sbd_lu_count 151 * to zero. 152 */ 153 if (sbd_lu_count) { 154 sbd_lu_t *slu; 155 156 /* See if all of them are offline */ 157 mutex_enter(&sbd_lock); 158 for (slu = sbd_lu_list; slu != NULL; slu = slu->sl_next) { 159 if ((slu->sl_state != STMF_STATE_OFFLINE) || 160 slu->sl_state_not_acked) { 161 mutex_exit(&sbd_lock); 162 return (EBUSY); 163 } 164 } 165 mutex_exit(&sbd_lock); 166 167 /* ok start deregistering them */ 168 while (sbd_lu_list) { 169 sbd_store_t *sst = sbd_lu_list->sl_sst; 170 if (sst->sst_deregister_lu(sst) != STMF_SUCCESS) 171 return (EBUSY); 172 } 173 } 174 ASSERT(sbd_lu_count == 0); 175 if (stmf_deregister_lu_provider(sbd_lp) != STMF_SUCCESS) 176 return (EBUSY); 177 ret = mod_remove(&modlinkage); 178 if (ret != 0) { 179 (void) stmf_register_lu_provider(sbd_lp); 180 return (ret); 181 } 182 stmf_free(sbd_lp); 183 mutex_destroy(&sbd_lock); 184 return (0); 185 } 186 187 int 188 _info(struct modinfo *modinfop) 189 { 190 return (mod_info(&modlinkage, modinfop)); 191 } 192 193 /* ARGSUSED */ 194 static int 195 sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 196 { 197 switch (cmd) { 198 case DDI_INFO_DEVT2DEVINFO: 199 *result = sbd_dip; 200 break; 201 case DDI_INFO_DEVT2INSTANCE: 202 *result = (void *)(uintptr_t)ddi_get_instance(dip); 203 break; 204 default: 205 return (DDI_FAILURE); 206 } 207 208 return (DDI_SUCCESS); 209 } 210 211 static int 212 sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 213 { 214 switch (cmd) { 215 case DDI_ATTACH: 216 sbd_dip = dip; 217 218 if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0, 219 DDI_NT_STMF_LP, 0) != DDI_SUCCESS) { 220 break; 221 } 222 ddi_report_dev(dip); 223 return (DDI_SUCCESS); 224 } 225 226 return (DDI_FAILURE); 227 } 228 229 static int 230 sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 231 { 232 switch (cmd) { 233 case DDI_DETACH: 234 ddi_remove_minor_node(dip, 0); 235 return (DDI_SUCCESS); 236 } 237 238 return (DDI_FAILURE); 239 } 240 241 /* ARGSUSED */ 242 static int 243 sbd_open(dev_t *devp, int flag, int otype, cred_t *credp) 244 { 245 if (otype != OTYP_CHR) 246 return (EINVAL); 247 return (0); 248 } 249 250 /* ARGSUSED */ 251 static int 252 sbd_close(dev_t dev, int flag, int otype, cred_t *credp) 253 { 254 return (0); 255 } 256 257 /* 258 * The ioctl code will be re written once the lun mapping and masking 259 * has been implemented and ioctl definitions have been cleanned up. 260 */ 261 void * 262 sbd_ioctl_read_struct(intptr_t data, int mode) 263 { 264 void *ptr; 265 uint32_t s; 266 267 if (ddi_copyin((void *)data, &s, 4, mode)) 268 return (NULL); 269 ptr = kmem_alloc(s, KM_SLEEP); 270 if (ddi_copyin((void *)data, ptr, s, mode)) 271 return (NULL); 272 return (ptr); 273 } 274 275 int 276 sbd_ioctl_write_struct(intptr_t data, int mode, void *ptr) 277 { 278 int *s = (int *)ptr; 279 int ret = 0; 280 281 if (ddi_copyout(ptr, (void *)data, *s, mode)) { 282 ret = EFAULT; 283 } 284 285 kmem_free(ptr, *s); 286 return (ret); 287 } 288 289 /* ARGSUSED */ 290 static int 291 stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 292 cred_t *credp, int *rval) 293 { 294 register_lu_cmd_t *rlc; 295 deregister_lu_cmd_t *drlc; 296 sbd_lu_list_t *sll; 297 sbd_lu_attr_t *sla; 298 sbd_lu_t *slul; 299 void *p; 300 int ret = 0; 301 int ret1; 302 int cnt; 303 int max_times, idx; 304 stmf_state_change_info_t ssi; 305 306 if (drv_priv(credp) != 0) { 307 return (EPERM); 308 } 309 310 ssi.st_rflags = STMF_RFLAG_USER_REQUEST; 311 ssi.st_additional_info = NULL; 312 if ((cmd != SBD_REGISTER_LU) && (cmd != SBD_GET_LU_ATTR) && 313 (cmd != SBD_GET_LU_LIST) && (cmd != SBD_DEREGISTER_LU) && 314 (cmd != SBD_MODIFY_LU)) { 315 return (EINVAL); 316 } 317 if ((p = sbd_ioctl_read_struct(data, mode)) == NULL) 318 return (EFAULT); 319 320 switch (cmd) { 321 case SBD_REGISTER_LU: 322 rlc = (register_lu_cmd_t *)p; 323 ((char *)p)[rlc->total_struct_size - 1] = 0; 324 if (rlc->flags & RLC_LU_TYPE_MEMDISK) { 325 if ((rlc->op_ret = memdisk_register_lu(rlc)) != 326 STMF_SUCCESS) { 327 ret = EIO; 328 } 329 } else if (rlc->flags & RLC_LU_TYPE_FILEDISK) { 330 if ((rlc->op_ret = filedisk_register_lu(rlc)) != 331 STMF_SUCCESS) { 332 ret = EIO; 333 } 334 } else { 335 ret = EINVAL; 336 break; 337 } 338 break; 339 case SBD_MODIFY_LU: { 340 modify_lu_cmd_t *mlc = (modify_lu_cmd_t *)p; 341 sbd_lu_t *slu; 342 sbd_store_t *sst = NULL; 343 if ((mlc->flags & RLC_LU_TYPE_FILEDISK) == 0) { 344 ret = EINVAL; 345 break; 346 } 347 if (mlc->name[0] != '\0') { 348 mutex_enter(&sbd_lock); 349 for (slu = sbd_lu_list; slu != NULL; 350 slu = slu->sl_next) { 351 if (strcmp(slu->sl_sst->sst_alias, 352 mlc->name) == 0) 353 break; 354 } 355 mutex_exit(&sbd_lock); 356 if (slu == NULL) { 357 /* not registered */ 358 sst = NULL; 359 } else { 360 sst = slu->sl_sst; 361 } 362 } else { 363 mutex_enter(&sbd_lock); 364 for (slu = sbd_lu_list; slu != NULL; 365 slu = slu->sl_next) { 366 if (bcmp(slu->sl_lu->lu_id->ident, 367 mlc->guid, 16) == 0) 368 break; 369 } 370 mutex_exit(&sbd_lock); 371 if (slu == NULL) { 372 /* not registered, this is not allowed */ 373 ret = ENODEV; 374 break; 375 } 376 sst = slu->sl_sst; 377 } 378 379 mlc->op_ret = filedisk_modify_lu(sst, mlc); 380 if (mlc->op_ret != STMF_SUCCESS) { 381 ret = EIO; 382 } 383 } 384 break; 385 386 case SBD_DEREGISTER_LU: 387 drlc = (deregister_lu_cmd_t *)p; 388 389 mutex_enter(&sbd_lock); 390 for (slul = sbd_lu_list; slul != NULL; slul = slul->sl_next) { 391 ret1 = bcmp(drlc->guid, slul->sl_lu->lu_id->ident, 16); 392 if (ret1 == 0) { 393 break; 394 } 395 } 396 397 if (slul == NULL) { 398 mutex_exit(&sbd_lock); 399 400 stmf_trace(0, "sbd_ioctl: can't find specified LU"); 401 ret = ENODEV; 402 break; 403 } 404 405 if ((slul->sl_state == STMF_STATE_OFFLINE) && 406 !slul->sl_state_not_acked) { 407 mutex_exit(&sbd_lock); 408 409 goto do_lu_dereg; 410 } 411 412 if (slul->sl_state != STMF_STATE_ONLINE) { 413 mutex_exit(&sbd_lock); 414 415 ret = EBUSY; 416 break; 417 } 418 mutex_exit(&sbd_lock); 419 420 ssi.st_additional_info = "DEREGLU offline LU now"; 421 (void) stmf_ctl(STMF_CMD_LU_OFFLINE, slul->sl_lu, &ssi); 422 max_times = 50; 423 424 mutex_enter(&sbd_lock); 425 for (idx = 0; idx < max_times; idx++) { 426 if ((slul->sl_state == STMF_STATE_OFFLINE) && 427 !slul->sl_state_not_acked) { 428 break; 429 } 430 mutex_exit(&sbd_lock); 431 432 delay(drv_usectohz(100000)); 433 434 mutex_enter(&sbd_lock); 435 } 436 mutex_exit(&sbd_lock); 437 438 if (idx == max_times) { 439 stmf_trace(0, "sbd_ioctl: LU-%p can't go off", slul); 440 ret = ETIMEDOUT; 441 } else { 442 do_lu_dereg: 443 if (slul->sl_sst->sst_deregister_lu(slul->sl_sst) != 444 STMF_SUCCESS) { 445 stmf_trace(0, "sbd_ioctl: sst_degregister_lu " 446 "sst-%p failed", slul->sl_sst); 447 ret = ENOTSUP; 448 } 449 } 450 break; 451 452 case SBD_GET_LU_LIST: 453 sll = (sbd_lu_list_t *)p; 454 cnt = sll->total_struct_size - sizeof (sbd_lu_list_t); 455 if (cnt < 0) { 456 ret = EINVAL; 457 break; 458 } 459 cnt = (cnt >> 3) + 1; 460 if (sll->count_in > cnt) { 461 ret = EFAULT; 462 break; 463 } 464 mutex_enter(&sbd_lock); 465 sll->count_out = 0; 466 for (slul = sbd_lu_list; slul != NULL; slul = slul->sl_next) { 467 if (sll->count_out < sll->count_in) { 468 sll->handles[sll->count_out] = 469 (uint64_t)(unsigned long)slul; 470 } 471 sll->count_out++; 472 } 473 mutex_exit(&sbd_lock); 474 break; 475 case SBD_GET_LU_ATTR: 476 sla = (sbd_lu_attr_t *)p; 477 if (sla->total_struct_size < 478 (sizeof (sbd_lu_attr_t) + sla->max_name_length - 7)) { 479 ret = EFAULT; 480 break; 481 } 482 mutex_enter(&sbd_lock); 483 for (slul = sbd_lu_list; slul != NULL; slul = slul->sl_next) { 484 if (sla->lu_handle == (uint64_t)(unsigned long)slul) 485 break; 486 } 487 if (slul != NULL) { 488 filedisk_fillout_attr(slul->sl_sst, sla); 489 memdisk_fillout_attr(slul->sl_sst, sla); 490 sla->total_size = slul->sl_sli->sli_total_store_size; 491 sla->data_size = slul->sl_sli->sli_lu_data_size; 492 bcopy(slul->sl_lu->lu_id->ident, sla->guid, 16); 493 } else { 494 ret = EINVAL; 495 } 496 mutex_exit(&sbd_lock); 497 break; 498 499 default: 500 return (ENOTTY); 501 } 502 503 ret1 = sbd_ioctl_write_struct(data, mode, p); 504 if (!ret) 505 ret = ret1; 506 return (ret); 507 } 508 509 /* ARGSUSED */ 510 void 511 sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags) 512 { 513 nvpair_t *np; 514 register_lu_cmd_t *rlc = NULL; 515 char *s; 516 int rlc_size = 0; 517 int sn; 518 519 if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) { 520 return; 521 } 522 523 if ((flags & (STMF_PCB_STMF_ONLINING | STMF_PCB_PREG_COMPLETE)) == 0) { 524 return; 525 } 526 527 np = NULL; 528 while ((np = nvlist_next_nvpair((nvlist_t *)arg, np)) != NULL) { 529 if (nvpair_type(np) != DATA_TYPE_STRING) { 530 continue; 531 } 532 if (nvpair_value_string(np, &s) != 0) { 533 continue; 534 } 535 sn = sizeof (register_lu_cmd_t) - 8 + strlen(s) + 1; 536 if (sn > rlc_size) { 537 if (rlc_size) { 538 kmem_free(rlc, rlc_size); 539 } 540 rlc_size = sn + 32; /* Make it a little bigger */ 541 rlc = (register_lu_cmd_t *)kmem_zalloc(rlc_size, 542 KM_SLEEP); 543 } 544 bzero(rlc, rlc_size); 545 rlc->total_struct_size = rlc_size; 546 rlc->flags = RLC_LU_TYPE_FILEDISK | RLC_REGISTER_LU; 547 (void) strcpy(rlc->name, s); 548 (void) filedisk_register_lu(rlc); 549 } 550 551 if (rlc) { 552 kmem_free(rlc, rlc_size); 553 } 554 } 555 556 /* ARGSUSED */ 557 sbd_store_t * 558 sbd_sst_alloc(uint32_t additional_size, uint32_t flags) 559 { 560 uint32_t total_as; 561 sbd_store_t *sst; 562 stmf_lu_t *lu; 563 sbd_lu_t *slu; 564 565 total_as = GET_STRUCT_SIZE(sbd_store_t) + GET_STRUCT_SIZE(sbd_lu_t) + 566 ((additional_size + 7) & ~7); 567 568 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, total_as, 0); 569 if (lu == NULL) 570 return (NULL); 571 sst = (sbd_store_t *)lu->lu_provider_private; 572 sst->sst_sbd_private = GET_BYTE_OFFSET(sst, 573 GET_STRUCT_SIZE(sbd_store_t)); 574 sst->sst_store_private = GET_BYTE_OFFSET(sst->sst_sbd_private, 575 GET_STRUCT_SIZE(sbd_lu_t)); 576 slu = (sbd_lu_t *)sst->sst_sbd_private; 577 slu->sl_sst = sst; 578 slu->sl_lu = lu; 579 slu->sl_total_allocation_size = total_as; 580 mutex_init(&slu->sl_it_list_lock, NULL, MUTEX_DRIVER, NULL); 581 582 return (sst); 583 } 584 585 void 586 sbd_sst_free(sbd_store_t *sst) 587 { 588 sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private; 589 590 mutex_destroy(&slu->sl_it_list_lock); 591 stmf_free(slu->sl_lu); 592 } 593 594 #define DATA_ALIGNMENT 0xfffffffffffff000 595 #define DATA_BLOCK_SIZE 4 * 1024 596 597 stmf_status_t 598 sbd_aligned_meta_write(struct sbd_store *sst, uint64_t offset, 599 uint64_t size, uint8_t *buf) 600 { 601 uint64_t starting_off = offset & DATA_ALIGNMENT; 602 uint64_t off_from_starting = offset & (~DATA_ALIGNMENT); 603 uint64_t ending_off = 604 (offset + size + DATA_BLOCK_SIZE) & DATA_ALIGNMENT; 605 uint64_t op_size = ending_off - starting_off; 606 uint8_t *op_buf = (uint8_t *)kmem_zalloc(op_size, KM_SLEEP); 607 stmf_status_t ret; 608 609 /* we should read first to avoid overwrite other data */ 610 if (sst->sst_meta_read) { 611 ret = sst->sst_meta_read(sst, starting_off, 612 op_size, (uint8_t *)op_buf); 613 } else { 614 ret = sst->sst_data_read(sst, starting_off, 615 op_size, (uint8_t *)op_buf); 616 } 617 if (ret != STMF_SUCCESS) 618 goto aligned_write_ret; 619 620 bcopy(buf, op_buf + off_from_starting, size); 621 622 if (sst->sst_meta_write) { 623 ret = sst->sst_meta_write(sst, starting_off, 624 op_size, (uint8_t *)op_buf); 625 } else { 626 ret = sst->sst_data_write(sst, starting_off, 627 op_size, (uint8_t *)op_buf); 628 } 629 630 aligned_write_ret: 631 if (op_buf) 632 kmem_free(op_buf, op_size); 633 return (ret); 634 } 635 636 stmf_status_t 637 sbd_aligned_meta_read(struct sbd_store *sst, uint64_t offset, 638 uint64_t size, uint8_t *buf) 639 { 640 uint64_t starting_off = offset & DATA_ALIGNMENT; 641 uint64_t off_from_starting = offset & (~DATA_ALIGNMENT); 642 uint64_t ending_off = 643 (offset + size + DATA_BLOCK_SIZE) & DATA_ALIGNMENT; 644 uint64_t op_size = ending_off - starting_off; 645 uint8_t *op_buf = (uint8_t *)kmem_zalloc(op_size, KM_SLEEP); 646 stmf_status_t ret; 647 648 if (sst->sst_meta_read) { 649 ret = sst->sst_meta_read(sst, starting_off, 650 op_size, (uint8_t *)op_buf); 651 } else { 652 ret = sst->sst_data_read(sst, starting_off, 653 op_size, (uint8_t *)op_buf); 654 } 655 if (ret != STMF_SUCCESS) 656 goto aligned_read_ret; 657 bcopy(op_buf + off_from_starting, buf, size); 658 659 aligned_read_ret: 660 if (op_buf) 661 kmem_free(op_buf, op_size); 662 return (ret); 663 } 664 665 uint8_t 666 sbd_calc_sum(uint8_t *buf, int size) 667 { 668 uint8_t s = 0; 669 670 while (size > 0) 671 s += buf[--size]; 672 673 return (s); 674 } 675 676 void 677 sbd_swap_meta_start(sbd_meta_start_t *sm) 678 { 679 sm->sm_magic = BSWAP_64(sm->sm_magic); 680 sm->sm_meta_size = BSWAP_64(sm->sm_meta_size); 681 sm->sm_meta_size_used = BSWAP_64(sm->sm_meta_size_used); 682 sm->sm_ver_major = BSWAP_16(sm->sm_ver_major); 683 sm->sm_ver_minor = BSWAP_16(sm->sm_ver_minor); 684 sm->sm_ver_subminor = BSWAP_16(sm->sm_ver_subminor); 685 } 686 687 void 688 sbd_swap_section_hdr(sm_section_hdr_t *h, uint8_t data_order) 689 { 690 h->sms_offset = BSWAP_64(h->sms_offset); 691 h->sms_size = BSWAP_32(h->sms_size); 692 h->sms_id = BSWAP_16(h->sms_id); 693 h->sms_data_order = data_order; 694 } 695 696 void 697 sbd_swap_sli_fields(sbd_lu_info_t *sli, uint8_t data_order) 698 { 699 sli->sli_total_store_size = BSWAP_64(sli->sli_total_store_size); 700 sli->sli_total_meta_size = BSWAP_64(sli->sli_total_meta_size); 701 sli->sli_lu_data_offset = BSWAP_64(sli->sli_lu_data_offset); 702 sli->sli_lu_data_size = BSWAP_64(sli->sli_lu_data_size); 703 sli->sli_flags = BSWAP_32(sli->sli_flags); 704 sli->sli_blocksize = BSWAP_16(sli->sli_blocksize); 705 sli->sli_data_order = data_order; 706 } 707 708 /* 709 * will not modify sms. 710 */ 711 uint64_t 712 sbd_find_section_offset(sbd_store_t *sst, sm_section_hdr_t *sms) 713 { 714 stmf_status_t ret; 715 sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private; 716 uint64_t ssize; 717 uint64_t meta_end; 718 sm_section_hdr_t smsh; 719 720 if (slu->sl_sm.sm_magic != SBD_MAGIC) { 721 cmn_err(CE_PANIC, "sbd_find section called without reading the" 722 " header first."); 723 } 724 725 ssize = slu->sl_meta_offset + sizeof (sbd_meta_start_t); 726 meta_end = slu->sl_sm.sm_meta_size_used; 727 while (ssize < meta_end) { 728 ret = sbd_aligned_meta_read(sst, ssize, 729 sizeof (sm_section_hdr_t), (uint8_t *)&smsh); 730 if (ret != STMF_SUCCESS) 731 return (0); 732 if (smsh.sms_data_order != sms->sms_data_order) { 733 sbd_swap_section_hdr(&smsh, sms->sms_data_order); 734 } 735 if (smsh.sms_id == sms->sms_id) 736 return (smsh.sms_offset); 737 ssize += smsh.sms_size; 738 } 739 740 return (0); 741 } 742 743 stmf_status_t 744 sbd_read_section(sbd_store_t *sst, sm_section_hdr_t *sms) 745 { 746 stmf_status_t ret; 747 uint32_t sz; 748 uint8_t osum, nsum; 749 750 if (sms->sms_offset == 0) { 751 sms->sms_offset = sbd_find_section_offset(sst, sms); 752 if (sms->sms_offset == 0) 753 return (STMF_FAILURE); 754 } 755 sz = sms->sms_size; 756 757 ret = sbd_aligned_meta_read(sst, sms->sms_offset, 758 sms->sms_size, (uint8_t *)sms); 759 if (ret != STMF_SUCCESS) 760 return (ret); 761 762 osum = sms->sms_chksum; 763 sms->sms_chksum = 0; 764 nsum = sbd_calc_sum((uint8_t *)sms, sz); 765 sms->sms_chksum = osum; 766 if (osum != nsum) { 767 return (STMF_FAILURE); 768 } 769 if (sms->sms_data_order != SMS_DATA_ORDER) { 770 /* Adjust byte order of the header */ 771 sbd_swap_section_hdr(sms, SMS_DATA_ORDER); 772 } 773 774 return (STMF_SUCCESS); 775 } 776 777 stmf_status_t 778 sbd_write_section(sbd_store_t *sst, sm_section_hdr_t *sms) 779 { 780 stmf_status_t ret; 781 sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private; 782 sbd_lu_info_t *sli = slu->sl_sli; 783 784 if (sms->sms_offset == 0) { 785 sms->sms_offset = sbd_find_section_offset(sst, sms); 786 if (sms->sms_offset == 0) { 787 if (sli->sli_total_meta_size < 788 (slu->sl_sm.sm_meta_size_used + sms->sms_size)) { 789 return (STMF_FAILURE); 790 } 791 sms->sms_offset = slu->sl_sm.sm_meta_size_used; 792 slu->sl_sm.sm_meta_size_used += sms->sms_size; 793 slu->sl_sm.sm_chksum = 0; 794 slu->sl_sm.sm_chksum = sbd_calc_sum((uint8_t *) 795 &slu->sl_sm, sizeof (sbd_meta_start_t)); 796 ret = sbd_aligned_meta_write(sst, slu->sl_meta_offset, 797 sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm); 798 if (ret != STMF_SUCCESS) { 799 slu->sl_sm.sm_meta_size_used -= sms->sms_size; 800 slu->sl_sm.sm_chksum = 0; 801 slu->sl_sm.sm_chksum = sbd_calc_sum((uint8_t *) 802 &slu->sl_sm, sizeof (sbd_meta_start_t)); 803 return (STMF_FAILURE); 804 } 805 } 806 } 807 808 sms->sms_chksum = 0; 809 sms->sms_chksum = sbd_calc_sum((uint8_t *)sms, sms->sms_size); 810 ret = sbd_aligned_meta_write(sst, sms->sms_offset, 811 sms->sms_size, (uint8_t *)sms); 812 813 return (ret); 814 } 815 816 stmf_status_t 817 sbd_create_meta(sbd_store_t *sst, sst_init_data_t *sst_idata) 818 { 819 sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private; 820 sbd_lu_info_t *sli; 821 sm_section_hdr_t *h; 822 stmf_status_t ret; 823 uint64_t meta_size; 824 uint64_t lu_data_offset; 825 uint64_t lu_data_size; 826 uint16_t b; 827 828 /* Blocksize should be a non-zero power of 2 */ 829 b = sst_idata->sst_blocksize; 830 if ((b < 2) || ((b & (b - 1)) != 0)) { 831 return (STMF_INVALID_ARG); 832 } 833 834 /* Store size should be nonzero multiple of blocksize */ 835 if ((sst_idata->sst_store_size == 0) || 836 ((sst_idata->sst_store_size % b) != 0)) { 837 return (STMF_INVALID_ARG); 838 } 839 840 /* 841 * Total metadata size is size of metadata headers + size of 842 * sbd_lu_info_t + any space needed by the store implementation 843 * itself. We should also keep enough space for future expansions. 844 * Also metadat size should be rounded off to blocksize. 845 */ 846 /* 847 * meta_size = sizeof (sbd_meta_start_t ) + sizeof (sbd_lu_info_t) + 848 * sst_idata->sst_store_meta_data_size; 849 */ 850 /* 851 * for now keep a static 64K for metasize. This should be enough to 852 * store metadata as well as any persistent reservations and keys. 853 */ 854 meta_size = 64 * 1024; 855 meta_size = (meta_size + (uint64_t)(b - 1)); 856 meta_size /= (uint64_t)b; 857 meta_size *= (uint64_t)b; 858 859 /* 860 * If metadata is not separate from user data then store size 861 * should be large enough to hold metadata. Also effective data 862 * size should be adjusted. 863 */ 864 if (sst->sst_meta_write == NULL) { 865 if (meta_size >= sst_idata->sst_store_size) 866 return (STMF_INVALID_ARG); 867 lu_data_offset = meta_size; 868 lu_data_size = sst_idata->sst_store_size - meta_size; 869 } 870 871 /* Initialize the header and write it */ 872 bzero(&slu->sl_sm, sizeof (sbd_meta_start_t)); 873 slu->sl_sm.sm_magic = SBD_MAGIC; 874 slu->sl_sm.sm_meta_size = meta_size; 875 /* 876 * Note that we already included the size for sli even though 877 * it is going to be written in next step. 878 */ 879 slu->sl_sm.sm_meta_size_used = sbd_meta_offset + 880 sizeof (sbd_meta_start_t) + sizeof (sbd_lu_info_t); 881 slu->sl_sm.sm_ver_major = 1; 882 slu->sl_sm.sm_chksum = sbd_calc_sum((uint8_t *)&slu->sl_sm, 883 sizeof (sbd_meta_start_t)); 884 885 ret = sbd_aligned_meta_write(sst, sbd_meta_offset, 886 sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm); 887 if (ret != STMF_SUCCESS) 888 return (ret); 889 890 slu->sl_meta_offset = sbd_meta_offset; 891 slu->sl_sli = (sbd_lu_info_t *)kmem_zalloc(sizeof (sbd_lu_info_t), 892 KM_SLEEP); 893 sli = slu->sl_sli; 894 h = &sli->sli_sms_header; 895 h->sms_offset = sbd_meta_offset + sizeof (sbd_meta_start_t); 896 h->sms_size = sizeof (sbd_lu_info_t); 897 h->sms_id = SMS_ID_LU_INFO; 898 h->sms_data_order = SMS_DATA_ORDER; 899 sli->sli_total_store_size = sst_idata->sst_store_size; 900 sli->sli_total_meta_size = meta_size; 901 sli->sli_lu_data_offset = lu_data_offset; 902 sli->sli_lu_data_size = lu_data_size; 903 sli->sli_blocksize = sst_idata->sst_blocksize; 904 sli->sli_data_order = SMS_DATA_ORDER; 905 sli->sli_lu_devid[3] = 16; 906 ret = stmf_scsilib_uniq_lu_id(COMPANY_ID_SUN, (scsi_devid_desc_t *) 907 &sli->sli_lu_devid[0]); 908 909 if (ret == STMF_SUCCESS) { 910 bcopy(&sli->sli_lu_devid[4], sst_idata->sst_guid, 16); 911 ret = sbd_write_section(sst, (sm_section_hdr_t *)slu->sl_sli); 912 if (ret != STMF_SUCCESS) 913 cmn_err(CE_NOTE, "write section failed"); 914 } else { 915 cmn_err(CE_NOTE, "scsilib failed %llx", 916 (unsigned long long)ret); 917 } 918 919 kmem_free(slu->sl_sli, sizeof (sbd_lu_info_t)); 920 slu->sl_sli = NULL; 921 922 return (ret); 923 } 924 925 /* 926 * Used to modify the total store size in meta for a LUN, We only 927 * check sst_idata->sst_store_size here. 928 * For LUN not registered, we will read meta data first 929 */ 930 stmf_status_t 931 sbd_modify_meta(sbd_store_t *sst, sst_init_data_t *sst_idata) 932 { 933 sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private; 934 sbd_lu_info_t *sli; 935 stmf_status_t ret; 936 /* uint64_t meta_size; */ 937 uint64_t lu_data_size; 938 sbd_it_data_t *sid = NULL; 939 uint64_t meta_offset; 940 941 942 if (sst->sst_meta_write == NULL) { 943 if (slu->sl_sm.sm_meta_size >= sst_idata->sst_store_size) 944 return (STMF_INVALID_ARG); 945 lu_data_size = sst_idata->sst_store_size - 946 slu->sl_sm.sm_meta_size; 947 } 948 949 /* 950 * use a copy here in order not to change anything if 951 * sbd_write_section() failed 952 */ 953 sli = (sbd_lu_info_t *)kmem_zalloc(sizeof (sbd_lu_info_t), KM_SLEEP); 954 if (slu->sl_sli) 955 bcopy(slu->sl_sli, sli, sizeof (sbd_lu_info_t)); 956 else { /* not registered, have to read meta data */ 957 meta_offset = sbd_meta_offset; 958 read_meta_header: 959 ret = sbd_aligned_meta_read(sst, meta_offset, 960 sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm); 961 if (ret != STMF_SUCCESS) { 962 goto exit_modify_lu; 963 } 964 if (slu->sl_sm.sm_magic != SBD_MAGIC) { 965 if (BSWAP_64(slu->sl_sm.sm_magic) != SBD_MAGIC) { 966 if (!sbd_migrate_meta_from_v0_to_v1(sst)) { 967 ret = STMF_INVALID_ARG; 968 goto exit_modify_lu; 969 } 970 goto read_meta_header; 971 } 972 sbd_swap_meta_start(&slu->sl_sm); 973 } 974 slu->sl_meta_offset = meta_offset; 975 976 sli->sli_sms_header.sms_size = sizeof (sbd_lu_info_t); 977 sli->sli_sms_header.sms_id = SMS_ID_LU_INFO; 978 sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER; 979 980 ret = sbd_read_section(sst, (sm_section_hdr_t *)sli); 981 982 if (ret != STMF_SUCCESS) 983 goto exit_modify_lu; 984 if (sli->sli_data_order != SMS_DATA_ORDER) { 985 sbd_swap_sli_fields(sli, SMS_DATA_ORDER); 986 } 987 } 988 989 sli->sli_total_store_size = sst_idata->sst_store_size; 990 sli->sli_lu_data_size = lu_data_size; 991 bcopy(&sli->sli_lu_devid[4], sst_idata->sst_guid, 16); 992 993 ret = sbd_write_section(sst, (sm_section_hdr_t *)sli); 994 if (ret != STMF_SUCCESS) 995 cmn_err(CE_NOTE, "write section failed"); 996 else if (slu->sl_sli) { 997 /* for registered LU */ 998 slu->sl_sli->sli_total_store_size = sli->sli_total_store_size; 999 slu->sl_sli->sli_lu_data_size = sli->sli_lu_data_size; 1000 mutex_enter(&slu->sl_it_list_lock); 1001 for (sid = slu->sl_it_list; sid; sid = sid->sbd_it_next) { 1002 sid->sbd_it_ua_conditions |= SBD_UA_CAPACITY_CHANGED; 1003 } 1004 mutex_exit(&slu->sl_it_list_lock); 1005 } 1006 exit_modify_lu: 1007 kmem_free(sli, sizeof (sbd_lu_info_t)); 1008 1009 return (ret); 1010 } 1011 1012 /* 1013 * Added sst_idata here because with dynamic LUN, we can only get the 1014 * LUN size from meta data if we are registering LUN 1015 */ 1016 stmf_status_t 1017 sbd_register_sst(sbd_store_t *sst, sst_init_data_t *sst_idata) 1018 { 1019 sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private; 1020 sbd_lu_info_t *sli; 1021 stmf_lu_t *lu; 1022 stmf_status_t ret; 1023 uint16_t b; 1024 uint64_t meta_offset = sbd_meta_offset; 1025 1026 if (slu->sl_sli) { 1027 cmn_err(CE_PANIC, "sbd_register_sst called with active data " 1028 " from an existing store"); 1029 } 1030 read_meta_header: 1031 ret = sbd_aligned_meta_read(sst, meta_offset, 1032 sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm); 1033 if (ret != STMF_SUCCESS) { 1034 return (ret); 1035 } 1036 if (slu->sl_sm.sm_magic != SBD_MAGIC) { 1037 if (BSWAP_64(slu->sl_sm.sm_magic) != SBD_MAGIC) { 1038 if (!sbd_migrate_meta_from_v0_to_v1(sst)) 1039 return (STMF_INVALID_ARG); 1040 goto read_meta_header; 1041 } 1042 sbd_swap_meta_start(&slu->sl_sm); 1043 ret = sbd_aligned_meta_write(sst, meta_offset, 1044 sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm); 1045 if (ret != STMF_SUCCESS) 1046 return (ret); 1047 } 1048 slu->sl_meta_offset = meta_offset; 1049 1050 sli = (sbd_lu_info_t *)kmem_zalloc(sizeof (sbd_lu_info_t), 1051 KM_SLEEP); 1052 slu->sl_sli = sli; 1053 sli->sli_sms_header.sms_size = sizeof (sbd_lu_info_t); 1054 sli->sli_sms_header.sms_id = SMS_ID_LU_INFO; 1055 sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER; 1056 1057 ret = sbd_read_section(sst, (sm_section_hdr_t *)sli); 1058 1059 if (ret != STMF_SUCCESS) { 1060 goto exit_store_online; 1061 } 1062 1063 if (sli->sli_data_order != SMS_DATA_ORDER) { 1064 sbd_swap_sli_fields(sli, SMS_DATA_ORDER); 1065 } 1066 bcopy(&sli->sli_lu_devid[4], sst_idata->sst_guid, 16); 1067 b = sli->sli_blocksize; 1068 1069 /* Calculate shift factor to convert LBA to a linear offset */ 1070 for (slu->sl_shift_count = 0; b != 1; slu->sl_shift_count++) 1071 b >>= 1; 1072 1073 /* Initialize LU and register it */ 1074 lu = slu->sl_lu; 1075 lu->lu_id = (scsi_devid_desc_t *)&sli->sli_lu_devid[0]; 1076 lu->lu_alias = sst->sst_alias; 1077 lu->lu_lp = sbd_lp; 1078 lu->lu_task_alloc = sbd_task_alloc; 1079 lu->lu_new_task = sbd_new_task; 1080 lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done; 1081 lu->lu_send_status_done = sbd_send_status_done; 1082 lu->lu_task_free = sbd_task_free; 1083 lu->lu_abort = sbd_abort; 1084 lu->lu_ctl = sbd_ctl; 1085 lu->lu_info = sbd_info; 1086 slu->sl_state = STMF_STATE_OFFLINE; 1087 1088 if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) { 1089 stmf_trace(0, "Failed to register with framework, ret=%llx", 1090 ret); 1091 goto exit_store_online; 1092 } 1093 1094 mutex_enter(&sbd_lock); 1095 slu->sl_next = sbd_lu_list; 1096 sbd_lu_list = slu; 1097 sbd_lu_count++; 1098 mutex_exit(&sbd_lock); 1099 1100 if (sst_idata) { 1101 sst_idata->sst_store_size = sli->sli_total_store_size; 1102 sst_idata->sst_blocksize = sli->sli_blocksize; 1103 } 1104 1105 return (STMF_SUCCESS); 1106 exit_store_online:; 1107 kmem_free(slu->sl_sli, sizeof (sbd_lu_info_t)); 1108 slu->sl_sli = NULL; 1109 return (ret); 1110 } 1111 1112 stmf_status_t 1113 sbd_deregister_sst(sbd_store_t *sst) 1114 { 1115 sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private; 1116 sbd_lu_t **ppslu; 1117 1118 if (slu->sl_state != STMF_STATE_OFFLINE) 1119 return (STMF_BUSY); 1120 1121 if (stmf_deregister_lu(slu->sl_lu) != STMF_SUCCESS) 1122 return (STMF_BUSY); 1123 1124 mutex_enter(&sbd_lock); 1125 for (ppslu = &sbd_lu_list; (*ppslu) != NULL; 1126 ppslu = &((*ppslu)->sl_next)) { 1127 if ((*ppslu) == slu) { 1128 *ppslu = (*ppslu)->sl_next; 1129 sbd_lu_count--; 1130 break; 1131 } 1132 } 1133 mutex_exit(&sbd_lock); 1134 if (slu->sl_sli) { 1135 kmem_free(slu->sl_sli, sizeof (sbd_lu_info_t)); 1136 slu->sl_sli = NULL; 1137 } 1138 return (STMF_SUCCESS); 1139 } 1140 1141 1142 /* 1143 * Version 0 format of metadata was never integrated into solaris. It 1144 * was the format used by early opensolaris release until feb. 2008. 1145 * Subsequent opensolaris releases used version 1 and thats what 1146 * was integrated into solaris as well. At some point V0 stuff should be 1147 * completely removed. 1148 */ 1149 int 1150 sbd_is_meta_v0(sbd_store_t *sst, uint64_t *meta_size, uint64_t *meta_offset) 1151 { 1152 sbd_v0_meta_start_t m; 1153 1154 *meta_offset = 4096; 1155 v0_check:; 1156 if (sbd_aligned_meta_read(sst, *meta_offset, 16, (uint8_t *)&m) != 1157 STMF_SUCCESS) { 1158 return (0); 1159 } 1160 1161 if (m.sm_magic != SBD_V0_MAGIC) { 1162 m.sm_magic = BSWAP_64(m.sm_magic); 1163 if (m.sm_magic != SBD_V0_MAGIC) { 1164 if (*meta_offset == 4096) { 1165 *meta_offset = 0; 1166 goto v0_check; 1167 } 1168 return (0); 1169 } 1170 m.sm_meta_size = BSWAP_64(m.sm_meta_size); 1171 } 1172 1173 *meta_size = m.sm_meta_size; 1174 1175 return (1); 1176 } 1177 1178 int 1179 sbd_migrate_meta_from_v0_to_v1(sbd_store_t *sst) 1180 { 1181 uint64_t v0_meta_size; 1182 uint64_t v0_meta_offset; 1183 sbd_v0_lu_info_t *v0sli; 1184 sbd_lu_info_t *sli; 1185 sbd_meta_start_t *sm; 1186 sm_section_hdr_t *h; 1187 int ret = 0; 1188 1189 if (!sbd_is_meta_v0(sst, &v0_meta_size, &v0_meta_offset)) 1190 return (0); 1191 1192 v0sli = kmem_zalloc(sizeof (*v0sli), KM_SLEEP); 1193 sm = kmem_zalloc(sizeof (*sm) + sizeof (*sli), KM_SLEEP); 1194 sli = (sbd_lu_info_t *)(((uint8_t *)sm) + sizeof (*sm)); 1195 if (sbd_aligned_meta_read(sst, v0_meta_offset + 16, sizeof (*v0sli), 1196 (uint8_t *)v0sli) != STMF_SUCCESS) { 1197 goto mv0v1_exit; 1198 } 1199 sm->sm_magic = SBD_MAGIC; 1200 sm->sm_meta_size = v0_meta_size; 1201 sm->sm_meta_size_used = sbd_meta_offset + sizeof (*sm) + sizeof (*sli); 1202 sm->sm_ver_major = 1; 1203 sm->sm_chksum = sbd_calc_sum((uint8_t *)sm, sizeof (sbd_meta_start_t)); 1204 1205 h = &sli->sli_sms_header; 1206 h->sms_offset = sbd_meta_offset + sizeof (*sm); 1207 h->sms_size = sizeof (*sli); 1208 h->sms_id = SMS_ID_LU_INFO; 1209 h->sms_data_order = SMS_DATA_ORDER; 1210 if (v0sli->sli_sms_header.sms_payload_data_order == SMS_DATA_ORDER) { 1211 sli->sli_total_store_size = v0sli->sli_total_store_size; 1212 sli->sli_total_meta_size = v0sli->sli_total_meta_size; 1213 sli->sli_lu_data_offset = v0sli->sli_lu_data_offset; 1214 sli->sli_lu_data_size = v0sli->sli_lu_data_size; 1215 } else { 1216 sli->sli_total_store_size = 1217 BSWAP_64(v0sli->sli_total_store_size); 1218 sli->sli_total_meta_size = 1219 BSWAP_64(v0sli->sli_total_meta_size); 1220 sli->sli_lu_data_offset = 1221 BSWAP_64(v0sli->sli_lu_data_offset); 1222 sli->sli_lu_data_size = 1223 BSWAP_64(v0sli->sli_lu_data_size); 1224 } 1225 /* sli_flags were not used in v0 */ 1226 sli->sli_blocksize = 512; 1227 sli->sli_data_order = SMS_DATA_ORDER; 1228 bcopy(v0sli->sli_lu_devid, sli->sli_lu_devid, 20); 1229 h->sms_chksum = sbd_calc_sum((uint8_t *)h, h->sms_size); 1230 1231 if (sbd_aligned_meta_write(sst, sbd_meta_offset, 1232 sizeof (*sm) + sizeof (*sli), (uint8_t *)sm) != STMF_SUCCESS) { 1233 goto mv0v1_exit; 1234 } 1235 1236 ret = 1; 1237 mv0v1_exit: 1238 kmem_free(v0sli, sizeof (*v0sli)); 1239 kmem_free(sm, sizeof (*sm) + sizeof (*sli)); 1240 1241 return (ret); 1242 } 1243