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 2009 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/pathname.h> 36 #include <sys/atomic.h> 37 #include <sys/nvpair.h> 38 #include <sys/fs/zfs.h> 39 #include <sys/sdt.h> 40 #include <sys/dkio.h> 41 #include <sys/zfs_ioctl.h> 42 43 #include <stmf.h> 44 #include <lpif.h> 45 #include <stmf_ioctl.h> 46 #include <stmf_sbd.h> 47 #include <sbd_impl.h> 48 #include <stmf_sbd_ioctl.h> 49 50 #define SBD_IS_ZVOL(zvol) (strncmp("/dev/zvol", zvol, 9)) 51 52 extern sbd_status_t sbd_pgr_meta_init(sbd_lu_t *sl); 53 extern sbd_status_t sbd_pgr_meta_load(sbd_lu_t *sl); 54 55 static int sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, 56 void **result); 57 static int sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 58 static int sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 59 static int sbd_open(dev_t *devp, int flag, int otype, cred_t *credp); 60 static int sbd_close(dev_t dev, int flag, int otype, cred_t *credp); 61 static int stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 62 cred_t *credp, int *rval); 63 void sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags); 64 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz, 65 uint32_t *err_ret); 66 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret, 67 int no_register, sbd_lu_t **slr); 68 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret); 69 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret); 70 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz, 71 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret); 72 char *sbd_get_zvol_name(sbd_lu_t *sl); 73 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl); 74 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl); 75 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, 76 uint64_t off); 77 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, 78 uint64_t off); 79 int sbd_is_zvol(char *path); 80 int sbd_zvolget(char *zvol_name, char **comstarprop); 81 int sbd_zvolset(char *zvol_name, char *comstarprop); 82 char sbd_ctoi(char c); 83 84 static ldi_ident_t sbd_zfs_ident; 85 static stmf_lu_provider_t *sbd_lp; 86 static sbd_lu_t *sbd_lu_list = NULL; 87 static kmutex_t sbd_lock; 88 static dev_info_t *sbd_dip; 89 static uint32_t sbd_lu_count = 0; 90 char sbd_vendor_id[] = "SUN "; 91 char sbd_product_id[] = "COMSTAR "; 92 char sbd_revision[] = "1.0 "; 93 static char sbd_name[] = "sbd"; 94 95 static struct cb_ops sbd_cb_ops = { 96 sbd_open, /* open */ 97 sbd_close, /* close */ 98 nodev, /* strategy */ 99 nodev, /* print */ 100 nodev, /* dump */ 101 nodev, /* read */ 102 nodev, /* write */ 103 stmf_sbd_ioctl, /* ioctl */ 104 nodev, /* devmap */ 105 nodev, /* mmap */ 106 nodev, /* segmap */ 107 nochpoll, /* chpoll */ 108 ddi_prop_op, /* cb_prop_op */ 109 0, /* streamtab */ 110 D_NEW | D_MP, /* cb_flag */ 111 CB_REV, /* rev */ 112 nodev, /* aread */ 113 nodev /* awrite */ 114 }; 115 116 static struct dev_ops sbd_ops = { 117 DEVO_REV, 118 0, 119 sbd_getinfo, 120 nulldev, /* identify */ 121 nulldev, /* probe */ 122 sbd_attach, 123 sbd_detach, 124 nodev, /* reset */ 125 &sbd_cb_ops, 126 NULL, /* bus_ops */ 127 NULL /* power */ 128 }; 129 130 #define SBD_NAME "COMSTAR SBD" 131 132 static struct modldrv modldrv = { 133 &mod_driverops, 134 SBD_NAME, 135 &sbd_ops 136 }; 137 138 static struct modlinkage modlinkage = { 139 MODREV_1, 140 &modldrv, 141 NULL 142 }; 143 144 int 145 _init(void) 146 { 147 int ret; 148 149 ret = mod_install(&modlinkage); 150 if (ret) 151 return (ret); 152 sbd_lp = (stmf_lu_provider_t *)stmf_alloc(STMF_STRUCT_LU_PROVIDER, 153 0, 0); 154 sbd_lp->lp_lpif_rev = LPIF_REV_1; 155 sbd_lp->lp_instance = 0; 156 sbd_lp->lp_name = sbd_name; 157 sbd_lp->lp_cb = sbd_lp_cb; 158 sbd_zfs_ident = ldi_ident_from_anon(); 159 160 if (stmf_register_lu_provider(sbd_lp) != STMF_SUCCESS) { 161 (void) mod_remove(&modlinkage); 162 stmf_free(sbd_lp); 163 return (EINVAL); 164 } 165 mutex_init(&sbd_lock, NULL, MUTEX_DRIVER, NULL); 166 return (0); 167 } 168 169 int 170 _fini(void) 171 { 172 int ret; 173 174 /* 175 * If we have registered lus, then make sure they are all offline 176 * if so then deregister them. This should drop the sbd_lu_count 177 * to zero. 178 */ 179 if (sbd_lu_count) { 180 sbd_lu_t *slu; 181 182 /* See if all of them are offline */ 183 mutex_enter(&sbd_lock); 184 for (slu = sbd_lu_list; slu != NULL; slu = slu->sl_next) { 185 if ((slu->sl_state != STMF_STATE_OFFLINE) || 186 slu->sl_state_not_acked) { 187 mutex_exit(&sbd_lock); 188 return (EBUSY); 189 } 190 } 191 mutex_exit(&sbd_lock); 192 193 #if 0 194 /* ok start deregistering them */ 195 while (sbd_lu_list) { 196 sbd_store_t *sst = sbd_lu_list->sl_sst; 197 if (sst->sst_deregister_lu(sst) != STMF_SUCCESS) 198 return (EBUSY); 199 } 200 #endif 201 return (EBUSY); 202 } 203 if (stmf_deregister_lu_provider(sbd_lp) != STMF_SUCCESS) 204 return (EBUSY); 205 ret = mod_remove(&modlinkage); 206 if (ret != 0) { 207 (void) stmf_register_lu_provider(sbd_lp); 208 return (ret); 209 } 210 stmf_free(sbd_lp); 211 mutex_destroy(&sbd_lock); 212 ldi_ident_release(sbd_zfs_ident); 213 return (0); 214 } 215 216 int 217 _info(struct modinfo *modinfop) 218 { 219 return (mod_info(&modlinkage, modinfop)); 220 } 221 222 /* ARGSUSED */ 223 static int 224 sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 225 { 226 switch (cmd) { 227 case DDI_INFO_DEVT2DEVINFO: 228 *result = sbd_dip; 229 break; 230 case DDI_INFO_DEVT2INSTANCE: 231 *result = (void *)(uintptr_t)ddi_get_instance(sbd_dip); 232 break; 233 default: 234 return (DDI_FAILURE); 235 } 236 237 return (DDI_SUCCESS); 238 } 239 240 static int 241 sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 242 { 243 switch (cmd) { 244 case DDI_ATTACH: 245 sbd_dip = dip; 246 247 if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0, 248 DDI_NT_STMF_LP, 0) != DDI_SUCCESS) { 249 break; 250 } 251 ddi_report_dev(dip); 252 return (DDI_SUCCESS); 253 } 254 255 return (DDI_FAILURE); 256 } 257 258 static int 259 sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 260 { 261 switch (cmd) { 262 case DDI_DETACH: 263 ddi_remove_minor_node(dip, 0); 264 return (DDI_SUCCESS); 265 } 266 267 return (DDI_FAILURE); 268 } 269 270 /* ARGSUSED */ 271 static int 272 sbd_open(dev_t *devp, int flag, int otype, cred_t *credp) 273 { 274 if (otype != OTYP_CHR) 275 return (EINVAL); 276 return (0); 277 } 278 279 /* ARGSUSED */ 280 static int 281 sbd_close(dev_t dev, int flag, int otype, cred_t *credp) 282 { 283 return (0); 284 } 285 286 /* ARGSUSED */ 287 static int 288 stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 289 cred_t *credp, int *rval) 290 { 291 stmf_iocdata_t *iocd; 292 void *ibuf = NULL; 293 void *obuf = NULL; 294 sbd_lu_t *nsl; 295 int i; 296 int ret; 297 298 if (drv_priv(credp) != 0) { 299 return (EPERM); 300 } 301 302 ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf); 303 if (ret) 304 return (ret); 305 iocd->stmf_error = 0; 306 307 switch (cmd) { 308 case SBD_IOCTL_CREATE_AND_REGISTER_LU: 309 if (iocd->stmf_ibuf_size < 310 (sizeof (sbd_create_and_reg_lu_t) - 8)) { 311 ret = EFAULT; 312 break; 313 } 314 if ((iocd->stmf_obuf_size == 0) || 315 (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) { 316 ret = EINVAL; 317 break; 318 } 319 ret = sbd_create_register_lu((sbd_create_and_reg_lu_t *) 320 ibuf, iocd->stmf_ibuf_size, &iocd->stmf_error); 321 bcopy(ibuf, obuf, iocd->stmf_obuf_size); 322 break; 323 case SBD_IOCTL_IMPORT_LU: 324 if (iocd->stmf_ibuf_size < 325 (sizeof (sbd_import_lu_t) - 8)) { 326 ret = EFAULT; 327 break; 328 } 329 if ((iocd->stmf_obuf_size == 0) || 330 (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) { 331 ret = EINVAL; 332 break; 333 } 334 ret = sbd_import_lu((sbd_import_lu_t *)ibuf, 335 iocd->stmf_ibuf_size, &iocd->stmf_error, 0, NULL); 336 bcopy(ibuf, obuf, iocd->stmf_obuf_size); 337 break; 338 case SBD_IOCTL_DELETE_LU: 339 if (iocd->stmf_ibuf_size < (sizeof (sbd_delete_lu_t) - 8)) { 340 ret = EFAULT; 341 break; 342 } 343 if (iocd->stmf_obuf_size) { 344 ret = EINVAL; 345 break; 346 } 347 ret = sbd_delete_lu((sbd_delete_lu_t *)ibuf, 348 iocd->stmf_ibuf_size, &iocd->stmf_error); 349 break; 350 case SBD_IOCTL_MODIFY_LU: 351 if (iocd->stmf_ibuf_size < (sizeof (sbd_modify_lu_t) - 8)) { 352 ret = EFAULT; 353 break; 354 } 355 if (iocd->stmf_obuf_size) { 356 ret = EINVAL; 357 break; 358 } 359 ret = sbd_modify_lu((sbd_modify_lu_t *)ibuf, 360 iocd->stmf_ibuf_size, &iocd->stmf_error); 361 break; 362 case SBD_IOCTL_GET_LU_PROPS: 363 if (iocd->stmf_ibuf_size < (sizeof (sbd_lu_props_t) - 8)) { 364 ret = EFAULT; 365 break; 366 } 367 if (iocd->stmf_obuf_size < sizeof (sbd_lu_props_t)) { 368 ret = EINVAL; 369 break; 370 } 371 ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf, 372 iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf, 373 iocd->stmf_obuf_size, &iocd->stmf_error); 374 break; 375 case SBD_IOCTL_GET_LU_LIST: 376 mutex_enter(&sbd_lock); 377 iocd->stmf_obuf_max_nentries = sbd_lu_count; 378 iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4), 379 sbd_lu_count); 380 for (nsl = sbd_lu_list, i = 0; nsl && 381 (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) { 382 bcopy(nsl->sl_device_id + 4, 383 &(((uint8_t *)obuf)[i << 4]), 16); 384 } 385 mutex_exit(&sbd_lock); 386 ret = 0; 387 iocd->stmf_error = 0; 388 break; 389 default: 390 ret = ENOTTY; 391 } 392 393 if (ret == 0) { 394 ret = stmf_copyout_iocdata(data, mode, iocd, obuf); 395 } else if (iocd->stmf_error) { 396 (void) stmf_copyout_iocdata(data, mode, iocd, obuf); 397 } 398 if (obuf) { 399 kmem_free(obuf, iocd->stmf_obuf_size); 400 obuf = NULL; 401 } 402 if (ibuf) { 403 kmem_free(ibuf, iocd->stmf_ibuf_size); 404 ibuf = NULL; 405 } 406 kmem_free(iocd, sizeof (stmf_iocdata_t)); 407 return (ret); 408 } 409 410 /* ARGSUSED */ 411 void 412 sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags) 413 { 414 nvpair_t *np; 415 char *s; 416 sbd_import_lu_t *ilu; 417 uint32_t ilu_sz; 418 uint32_t struct_sz; 419 uint32_t err_ret; 420 int iret; 421 422 if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) { 423 return; 424 } 425 426 if ((flags & (STMF_PCB_STMF_ONLINING | STMF_PCB_PREG_COMPLETE)) == 0) { 427 return; 428 } 429 430 np = NULL; 431 ilu_sz = 1024; 432 ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP); 433 while ((np = nvlist_next_nvpair((nvlist_t *)arg, np)) != NULL) { 434 if (nvpair_type(np) != DATA_TYPE_STRING) { 435 continue; 436 } 437 if (nvpair_value_string(np, &s) != 0) { 438 continue; 439 } 440 struct_sz = max(8, strlen(s) + 1); 441 struct_sz += sizeof (sbd_import_lu_t) - 8; 442 if (struct_sz > ilu_sz) { 443 kmem_free(ilu, ilu_sz); 444 ilu_sz = struct_sz + 32; 445 ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP); 446 } 447 ilu->ilu_struct_size = struct_sz; 448 (void) strcpy(ilu->ilu_meta_fname, s); 449 iret = sbd_import_lu(ilu, struct_sz, &err_ret, 0, NULL); 450 if (iret) { 451 stmf_trace(0, "sbd_lp_cb: import_lu failed, ret = %d, " 452 "err_ret = %d", iret, err_ret); 453 } else { 454 stmf_trace(0, "Imported the LU %s", nvpair_name(np)); 455 } 456 } 457 458 if (ilu) { 459 kmem_free(ilu, ilu_sz); 460 ilu = NULL; 461 } 462 } 463 464 sbd_status_t 465 sbd_link_lu(sbd_lu_t *sl) 466 { 467 sbd_lu_t *nsl; 468 469 mutex_enter(&sbd_lock); 470 mutex_enter(&sl->sl_lock); 471 ASSERT(sl->sl_trans_op != SL_OP_NONE); 472 473 if (sl->sl_flags & SL_LINKED) { 474 mutex_exit(&sbd_lock); 475 mutex_exit(&sl->sl_lock); 476 return (SBD_ALREADY); 477 } 478 for (nsl = sbd_lu_list; nsl; nsl = nsl->sl_next) { 479 if (strcmp(nsl->sl_name, sl->sl_name) == 0) 480 break; 481 } 482 if (nsl) { 483 mutex_exit(&sbd_lock); 484 mutex_exit(&sl->sl_lock); 485 return (SBD_ALREADY); 486 } 487 sl->sl_next = sbd_lu_list; 488 sbd_lu_list = sl; 489 sl->sl_flags |= SL_LINKED; 490 mutex_exit(&sbd_lock); 491 mutex_exit(&sl->sl_lock); 492 return (SBD_SUCCESS); 493 } 494 495 void 496 sbd_unlink_lu(sbd_lu_t *sl) 497 { 498 sbd_lu_t **ppnsl; 499 500 mutex_enter(&sbd_lock); 501 mutex_enter(&sl->sl_lock); 502 ASSERT(sl->sl_trans_op != SL_OP_NONE); 503 504 ASSERT(sl->sl_flags & SL_LINKED); 505 for (ppnsl = &sbd_lu_list; *ppnsl; ppnsl = &((*ppnsl)->sl_next)) { 506 if (*ppnsl == sl) 507 break; 508 } 509 ASSERT(*ppnsl); 510 *ppnsl = (*ppnsl)->sl_next; 511 sl->sl_flags &= ~SL_LINKED; 512 mutex_exit(&sbd_lock); 513 mutex_exit(&sl->sl_lock); 514 } 515 516 sbd_status_t 517 sbd_find_and_lock_lu(uint8_t *guid, uint8_t *meta_name, uint8_t op, 518 sbd_lu_t **ppsl) 519 { 520 sbd_lu_t *sl; 521 int found = 0; 522 sbd_status_t sret; 523 524 mutex_enter(&sbd_lock); 525 for (sl = sbd_lu_list; sl; sl = sl->sl_next) { 526 if (guid) { 527 found = bcmp(sl->sl_device_id + 4, guid, 16) == 0; 528 } else { 529 found = strcmp(sl->sl_name, (char *)meta_name) == 0; 530 } 531 if (found) 532 break; 533 } 534 if (!found) { 535 mutex_exit(&sbd_lock); 536 return (SBD_NOT_FOUND); 537 } 538 mutex_enter(&sl->sl_lock); 539 if (sl->sl_trans_op == SL_OP_NONE) { 540 sl->sl_trans_op = op; 541 *ppsl = sl; 542 sret = SBD_SUCCESS; 543 } else { 544 sret = SBD_BUSY; 545 } 546 mutex_exit(&sl->sl_lock); 547 mutex_exit(&sbd_lock); 548 return (sret); 549 } 550 551 sbd_status_t 552 sbd_read_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf) 553 { 554 uint64_t meta_align; 555 uint64_t starting_off; 556 uint64_t data_off; 557 uint64_t ending_off; 558 uint64_t io_size; 559 uint8_t *io_buf; 560 vnode_t *vp; 561 sbd_status_t ret; 562 ssize_t resid; 563 int vret; 564 565 ASSERT(sl->sl_flags & SL_META_OPENED); 566 if (sl->sl_flags & SL_SHARED_META) { 567 meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1; 568 vp = sl->sl_data_vp; 569 ASSERT(vp); 570 } else { 571 meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1; 572 if ((sl->sl_flags & SL_ZFS_META) == 0) { 573 vp = sl->sl_meta_vp; 574 ASSERT(vp); 575 } 576 } 577 starting_off = offset & ~(meta_align); 578 data_off = offset & meta_align; 579 ending_off = (offset + size + meta_align) & (~meta_align); 580 if (ending_off > sl->sl_meta_size_used) { 581 bzero(buf, size); 582 if (starting_off >= sl->sl_meta_size_used) { 583 return (SBD_SUCCESS); 584 } 585 ending_off = (sl->sl_meta_size_used + meta_align) & 586 (~meta_align); 587 if (size > (ending_off - (starting_off + data_off))) { 588 size = ending_off - (starting_off + data_off); 589 } 590 } 591 io_size = ending_off - starting_off; 592 io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP); 593 ASSERT((starting_off + io_size) <= sl->sl_total_meta_size); 594 595 if (sl->sl_flags & SL_ZFS_META) { 596 if ((ret = sbd_read_zfs_meta(sl, io_buf, io_size, 597 starting_off)) != SBD_SUCCESS) { 598 goto sbd_read_meta_failure; 599 } 600 } else { 601 vret = vn_rdwr(UIO_READ, vp, (caddr_t)io_buf, (ssize_t)io_size, 602 (offset_t)starting_off, UIO_SYSSPACE, FRSYNC, 603 RLIM64_INFINITY, CRED(), &resid); 604 605 if (vret || resid) { 606 ret = SBD_FILEIO_FAILURE | vret; 607 goto sbd_read_meta_failure; 608 } 609 } 610 611 bcopy(io_buf + data_off, buf, size); 612 ret = SBD_SUCCESS; 613 614 sbd_read_meta_failure: 615 kmem_free(io_buf, io_size); 616 return (ret); 617 } 618 619 sbd_status_t 620 sbd_write_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf) 621 { 622 uint64_t meta_align; 623 uint64_t starting_off; 624 uint64_t data_off; 625 uint64_t ending_off; 626 uint64_t io_size; 627 uint8_t *io_buf; 628 vnode_t *vp; 629 sbd_status_t ret; 630 ssize_t resid; 631 int vret; 632 633 ASSERT(sl->sl_flags & SL_META_OPENED); 634 if (sl->sl_flags & SL_SHARED_META) { 635 meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1; 636 vp = sl->sl_data_vp; 637 ASSERT(vp); 638 } else { 639 meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1; 640 if ((sl->sl_flags & SL_ZFS_META) == 0) { 641 vp = sl->sl_meta_vp; 642 ASSERT(vp); 643 } 644 } 645 starting_off = offset & ~(meta_align); 646 data_off = offset & meta_align; 647 ending_off = (offset + size + meta_align) & (~meta_align); 648 io_size = ending_off - starting_off; 649 io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP); 650 ret = sbd_read_meta(sl, starting_off, io_size, io_buf); 651 if (ret != SBD_SUCCESS) { 652 goto sbd_write_meta_failure; 653 } 654 bcopy(buf, io_buf + data_off, size); 655 if (sl->sl_flags & SL_ZFS_META) { 656 if ((ret = sbd_write_zfs_meta(sl, io_buf, io_size, 657 starting_off)) != SBD_SUCCESS) { 658 goto sbd_write_meta_failure; 659 } 660 } else { 661 vret = vn_rdwr(UIO_WRITE, vp, (caddr_t)io_buf, (ssize_t)io_size, 662 (offset_t)starting_off, UIO_SYSSPACE, FDSYNC, 663 RLIM64_INFINITY, CRED(), &resid); 664 665 if (vret || resid) { 666 ret = SBD_FILEIO_FAILURE | vret; 667 goto sbd_write_meta_failure; 668 } 669 } 670 671 ret = SBD_SUCCESS; 672 673 sbd_write_meta_failure: 674 kmem_free(io_buf, io_size); 675 return (ret); 676 } 677 678 uint8_t 679 sbd_calc_sum(uint8_t *buf, int size) 680 { 681 uint8_t s = 0; 682 683 while (size > 0) 684 s += buf[--size]; 685 686 return (s); 687 } 688 689 uint8_t 690 sbd_calc_section_sum(sm_section_hdr_t *sm, uint32_t sz) 691 { 692 uint8_t s, o; 693 694 o = sm->sms_chksum; 695 sm->sms_chksum = 0; 696 s = sbd_calc_sum((uint8_t *)sm, sz); 697 sm->sms_chksum = o; 698 699 return (s); 700 } 701 702 uint32_t 703 sbd_strlen(char *str, uint32_t maxlen) 704 { 705 uint32_t i; 706 707 for (i = 0; i < maxlen; i++) { 708 if (str[i] == 0) 709 return (i); 710 } 711 return (i); 712 } 713 714 void 715 sbd_swap_meta_start(sbd_meta_start_t *sm) 716 { 717 if (sm->sm_magic == SBD_MAGIC) 718 return; 719 sm->sm_magic = BSWAP_64(sm->sm_magic); 720 sm->sm_meta_size = BSWAP_64(sm->sm_meta_size); 721 sm->sm_meta_size_used = BSWAP_64(sm->sm_meta_size_used); 722 sm->sm_ver_major = BSWAP_16(sm->sm_ver_major); 723 sm->sm_ver_minor = BSWAP_16(sm->sm_ver_minor); 724 sm->sm_ver_subminor = BSWAP_16(sm->sm_ver_subminor); 725 } 726 727 void 728 sbd_swap_section_hdr(sm_section_hdr_t *sm) 729 { 730 if (sm->sms_data_order == SMS_DATA_ORDER) 731 return; 732 sm->sms_offset = BSWAP_64(sm->sms_offset); 733 sm->sms_size = BSWAP_32(sm->sms_size); 734 sm->sms_id = BSWAP_16(sm->sms_id); 735 sm->sms_chksum += SMS_DATA_ORDER - sm->sms_data_order; 736 sm->sms_data_order = SMS_DATA_ORDER; 737 } 738 739 void 740 sbd_swap_lu_info_1_0(sbd_lu_info_1_0_t *sli) 741 { 742 sbd_swap_section_hdr(&sli->sli_sms_header); 743 if (sli->sli_data_order == SMS_DATA_ORDER) 744 return; 745 sli->sli_sms_header.sms_chksum += SMS_DATA_ORDER - sli->sli_data_order; 746 sli->sli_data_order = SMS_DATA_ORDER; 747 sli->sli_total_store_size = BSWAP_64(sli->sli_total_store_size); 748 sli->sli_total_meta_size = BSWAP_64(sli->sli_total_meta_size); 749 sli->sli_lu_data_offset = BSWAP_64(sli->sli_lu_data_offset); 750 sli->sli_lu_data_size = BSWAP_64(sli->sli_lu_data_size); 751 sli->sli_flags = BSWAP_32(sli->sli_flags); 752 sli->sli_blocksize = BSWAP_16(sli->sli_blocksize); 753 } 754 755 void 756 sbd_swap_lu_info_1_1(sbd_lu_info_1_1_t *sli) 757 { 758 sbd_swap_section_hdr(&sli->sli_sms_header); 759 if (sli->sli_data_order == SMS_DATA_ORDER) 760 return; 761 sli->sli_sms_header.sms_chksum += SMS_DATA_ORDER - sli->sli_data_order; 762 sli->sli_data_order = SMS_DATA_ORDER; 763 sli->sli_flags = BSWAP_32(sli->sli_flags); 764 sli->sli_lu_size = BSWAP_64(sli->sli_lu_size); 765 sli->sli_meta_fname_offset = BSWAP_64(sli->sli_meta_fname_offset); 766 sli->sli_data_fname_offset = BSWAP_64(sli->sli_data_fname_offset); 767 sli->sli_serial_offset = BSWAP_64(sli->sli_serial_offset); 768 sli->sli_alias_offset = BSWAP_64(sli->sli_alias_offset); 769 } 770 771 sbd_status_t 772 sbd_load_section_hdr(sbd_lu_t *sl, sm_section_hdr_t *sms) 773 { 774 sm_section_hdr_t h; 775 uint64_t st; 776 sbd_status_t ret; 777 778 for (st = sl->sl_meta_offset + sizeof (sbd_meta_start_t); 779 st < sl->sl_meta_size_used; st += h.sms_size) { 780 if ((ret = sbd_read_meta(sl, st, sizeof (sm_section_hdr_t), 781 (uint8_t *)&h)) != SBD_SUCCESS) { 782 return (ret); 783 } 784 if (h.sms_data_order != SMS_DATA_ORDER) { 785 sbd_swap_section_hdr(&h); 786 } 787 if ((h.sms_data_order != SMS_DATA_ORDER) || 788 (h.sms_offset != st) || (h.sms_size < sizeof (h)) || 789 ((st + h.sms_size) > sl->sl_meta_size_used)) { 790 return (SBD_META_CORRUPTED); 791 } 792 if (h.sms_id == sms->sms_id) { 793 bcopy(&h, sms, sizeof (h)); 794 return (SBD_SUCCESS); 795 } 796 } 797 798 return (SBD_NOT_FOUND); 799 } 800 801 sbd_status_t 802 sbd_load_meta_start(sbd_lu_t *sl) 803 { 804 sbd_meta_start_t *sm; 805 sbd_status_t ret; 806 807 /* Fake meta params initially */ 808 sl->sl_total_meta_size = (uint64_t)-1; 809 sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t); 810 811 sm = kmem_zalloc(sizeof (*sm), KM_SLEEP); 812 ret = sbd_read_meta(sl, sl->sl_meta_offset, sizeof (*sm), 813 (uint8_t *)sm); 814 if (ret != SBD_SUCCESS) { 815 goto load_meta_start_failed; 816 } 817 818 if (sm->sm_magic != SBD_MAGIC) { 819 sbd_swap_meta_start(sm); 820 } 821 822 if ((sm->sm_magic != SBD_MAGIC) || (sbd_calc_sum((uint8_t *)sm, 823 sizeof (*sm) - 1) != sm->sm_chksum)) { 824 ret = SBD_META_CORRUPTED; 825 goto load_meta_start_failed; 826 } 827 828 if (sm->sm_ver_major != SBD_VER_MAJOR) { 829 ret = SBD_NOT_SUPPORTED; 830 goto load_meta_start_failed; 831 } 832 833 sl->sl_total_meta_size = sm->sm_meta_size; 834 sl->sl_meta_size_used = sm->sm_meta_size_used; 835 ret = SBD_SUCCESS; 836 837 load_meta_start_failed: 838 kmem_free(sm, sizeof (*sm)); 839 return (ret); 840 } 841 842 sbd_status_t 843 sbd_write_meta_start(sbd_lu_t *sl, uint64_t meta_size, uint64_t meta_size_used) 844 { 845 sbd_meta_start_t *sm; 846 sbd_status_t ret; 847 848 sm = (sbd_meta_start_t *)kmem_zalloc(sizeof (sbd_meta_start_t), 849 KM_SLEEP); 850 851 sm->sm_magic = SBD_MAGIC; 852 sm->sm_meta_size = meta_size; 853 sm->sm_meta_size_used = meta_size_used; 854 sm->sm_ver_major = SBD_VER_MAJOR; 855 sm->sm_ver_minor = SBD_VER_MINOR; 856 sm->sm_ver_subminor = SBD_VER_SUBMINOR; 857 sm->sm_chksum = sbd_calc_sum((uint8_t *)sm, sizeof (*sm) - 1); 858 859 ret = sbd_write_meta(sl, sl->sl_meta_offset, sizeof (*sm), 860 (uint8_t *)sm); 861 kmem_free(sm, sizeof (*sm)); 862 863 return (ret); 864 } 865 866 sbd_status_t 867 sbd_read_meta_section(sbd_lu_t *sl, sm_section_hdr_t **ppsms, uint16_t sms_id) 868 { 869 sbd_status_t ret; 870 sm_section_hdr_t sms; 871 int alloced = 0; 872 873 mutex_enter(&sl->sl_metadata_lock); 874 if (((*ppsms) == NULL) || ((*ppsms)->sms_offset == 0)) { 875 bzero(&sms, sizeof (sm_section_hdr_t)); 876 sms.sms_id = sms_id; 877 if ((ret = sbd_load_section_hdr(sl, &sms)) != SBD_SUCCESS) { 878 mutex_exit(&sl->sl_metadata_lock); 879 return (ret); 880 } else { 881 if ((*ppsms) == NULL) { 882 *ppsms = (sm_section_hdr_t *)kmem_zalloc( 883 sms.sms_size, KM_SLEEP); 884 alloced = 1; 885 } 886 bcopy(&sms, *ppsms, sizeof (sm_section_hdr_t)); 887 } 888 } 889 890 ret = sbd_read_meta(sl, (*ppsms)->sms_offset, (*ppsms)->sms_size, 891 (uint8_t *)(*ppsms)); 892 if (ret == SBD_SUCCESS) { 893 uint8_t s; 894 if ((*ppsms)->sms_data_order != SMS_DATA_ORDER) 895 sbd_swap_section_hdr(*ppsms); 896 if ((*ppsms)->sms_id != SMS_ID_UNUSED) { 897 s = sbd_calc_section_sum(*ppsms, (*ppsms)->sms_size); 898 if (s != (*ppsms)->sms_chksum) 899 ret = SBD_META_CORRUPTED; 900 } 901 } 902 mutex_exit(&sl->sl_metadata_lock); 903 904 if ((ret != SBD_SUCCESS) && alloced) 905 kmem_free(*ppsms, sms.sms_size); 906 return (ret); 907 } 908 909 sbd_status_t 910 sbd_load_section_hdr_unbuffered(sbd_lu_t *sl, sm_section_hdr_t *sms) 911 { 912 sbd_status_t ret; 913 914 /* 915 * Bypass buffering and re-read the meta data from permanent storage. 916 */ 917 if (sl->sl_flags & SL_ZFS_META) { 918 if ((ret = sbd_open_zfs_meta(sl)) != SBD_SUCCESS) { 919 return (ret); 920 } 921 } 922 /* Re-get the meta sizes into sl */ 923 if ((ret = sbd_load_meta_start(sl)) != SBD_SUCCESS) { 924 return (ret); 925 } 926 return (sbd_load_section_hdr(sl, sms)); 927 } 928 929 sbd_status_t 930 sbd_write_meta_section(sbd_lu_t *sl, sm_section_hdr_t *sms) 931 { 932 sm_section_hdr_t t; 933 uint64_t off, s; 934 uint64_t unused_start; 935 sbd_status_t ret; 936 sbd_status_t write_meta_ret = SBD_SUCCESS; 937 uint8_t *cb; 938 int meta_size_changed = 0; 939 sm_section_hdr_t sms_before_unused = {0}; 940 941 mutex_enter(&sl->sl_metadata_lock); 942 write_meta_section_again: 943 if (sms->sms_offset) { 944 /* 945 * If the section already exists and the size is the 946 * same as this new data then overwrite in place. If 947 * the sizes are different then mark the existing as 948 * unused and look for free space. 949 */ 950 ret = sbd_read_meta(sl, sms->sms_offset, sizeof (t), 951 (uint8_t *)&t); 952 if (ret != SBD_SUCCESS) { 953 mutex_exit(&sl->sl_metadata_lock); 954 return (ret); 955 } 956 if (t.sms_data_order != SMS_DATA_ORDER) { 957 sbd_swap_section_hdr(&t); 958 } 959 if (t.sms_id != sms->sms_id) { 960 mutex_exit(&sl->sl_metadata_lock); 961 return (SBD_INVALID_ARG); 962 } 963 if (t.sms_size == sms->sms_size) { 964 ret = sbd_write_meta(sl, sms->sms_offset, 965 sms->sms_size, (uint8_t *)sms); 966 mutex_exit(&sl->sl_metadata_lock); 967 return (ret); 968 } 969 sms_before_unused = t; 970 971 t.sms_id = SMS_ID_UNUSED; 972 /* 973 * For unused sections we only use chksum of the header. for 974 * all other sections, the chksum is for the entire section. 975 */ 976 t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t)); 977 ret = sbd_write_meta(sl, t.sms_offset, sizeof (t), 978 (uint8_t *)&t); 979 if (ret != SBD_SUCCESS) { 980 mutex_exit(&sl->sl_metadata_lock); 981 return (ret); 982 } 983 sms->sms_offset = 0; 984 } else { 985 /* Section location is unknown, search for it. */ 986 t.sms_id = sms->sms_id; 987 t.sms_data_order = SMS_DATA_ORDER; 988 ret = sbd_load_section_hdr(sl, &t); 989 if (ret == SBD_SUCCESS) { 990 sms->sms_offset = t.sms_offset; 991 sms->sms_chksum = 992 sbd_calc_section_sum(sms, sms->sms_size); 993 goto write_meta_section_again; 994 } else if (ret != SBD_NOT_FOUND) { 995 mutex_exit(&sl->sl_metadata_lock); 996 return (ret); 997 } 998 } 999 1000 /* 1001 * At this point we know that section does not already exist. 1002 * Find space large enough to hold the section or grow meta if 1003 * possible. 1004 */ 1005 unused_start = 0; 1006 s = 0; /* size of space found */ 1007 1008 /* 1009 * Search all sections for unused space of sufficient size. 1010 * The first one found is taken. Contiguous unused sections 1011 * will be combined. 1012 */ 1013 for (off = sl->sl_meta_offset + sizeof (sbd_meta_start_t); 1014 off < sl->sl_meta_size_used; off += t.sms_size) { 1015 ret = sbd_read_meta(sl, off, sizeof (t), (uint8_t *)&t); 1016 if (ret != SBD_SUCCESS) { 1017 mutex_exit(&sl->sl_metadata_lock); 1018 return (ret); 1019 } 1020 if (t.sms_data_order != SMS_DATA_ORDER) 1021 sbd_swap_section_hdr(&t); 1022 if (t.sms_size == 0) { 1023 mutex_exit(&sl->sl_metadata_lock); 1024 return (SBD_META_CORRUPTED); 1025 } 1026 if (t.sms_id == SMS_ID_UNUSED) { 1027 if (unused_start == 0) 1028 unused_start = off; 1029 /* 1030 * Calculate size of the unused space, break out 1031 * if it satisfies the requirement. 1032 */ 1033 s = t.sms_size - unused_start + off; 1034 if ((s == sms->sms_size) || (s >= (sms->sms_size + 1035 sizeof (t)))) { 1036 break; 1037 } else { 1038 s = 0; 1039 } 1040 } else { 1041 unused_start = 0; 1042 } 1043 } 1044 1045 off = (unused_start == 0) ? sl->sl_meta_size_used : unused_start; 1046 /* 1047 * If none found, how much room is at the end? 1048 * See if the data can be expanded. 1049 */ 1050 if (s == 0) { 1051 s = sl->sl_total_meta_size - off; 1052 if (s >= sms->sms_size || !(sl->sl_flags & SL_SHARED_META)) { 1053 s = sms->sms_size; 1054 meta_size_changed = 1; 1055 } else { 1056 s = 0; 1057 } 1058 } 1059 1060 if (s == 0) { 1061 mutex_exit(&sl->sl_metadata_lock); 1062 return (SBD_ALLOC_FAILURE); 1063 } 1064 1065 sms->sms_offset = off; 1066 sms->sms_chksum = sbd_calc_section_sum(sms, sms->sms_size); 1067 /* 1068 * Since we may have to write more than one section (current + 1069 * any unused), use a combined buffer. 1070 */ 1071 cb = kmem_zalloc(s, KM_SLEEP); 1072 bcopy(sms, cb, sms->sms_size); 1073 if (s > sms->sms_size) { 1074 t.sms_offset = off + sms->sms_size; 1075 t.sms_size = s - sms->sms_size; 1076 t.sms_id = SMS_ID_UNUSED; 1077 t.sms_data_order = SMS_DATA_ORDER; 1078 t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t)); 1079 bcopy(&t, cb + sms->sms_size, sizeof (t)); 1080 } 1081 /* 1082 * Two write events & statuses take place. Failure writing the 1083 * meta section takes precedence, can possibly be rolled back, 1084 * & gets reported. Else return status from writing the meta start. 1085 */ 1086 ret = SBD_SUCCESS; /* Set a default, it's not always loaded below. */ 1087 if (meta_size_changed) { 1088 uint64_t old_meta_size; 1089 uint64_t old_sz_used = sl->sl_meta_size_used; /* save a copy */ 1090 old_meta_size = sl->sl_total_meta_size; /* save a copy */ 1091 1092 write_meta_ret = sbd_write_meta(sl, off, s, cb); 1093 if (write_meta_ret == SBD_SUCCESS) { 1094 sl->sl_meta_size_used = off + s; 1095 if (sl->sl_total_meta_size < sl->sl_meta_size_used) { 1096 uint64_t meta_align = 1097 (((uint64_t)1) << 1098 sl->sl_meta_blocksize_shift) - 1; 1099 sl->sl_total_meta_size = 1100 (sl->sl_meta_size_used + meta_align) & 1101 (~meta_align); 1102 } 1103 ret = sbd_write_meta_start(sl, sl->sl_total_meta_size, 1104 sl->sl_meta_size_used); 1105 if (ret != SBD_SUCCESS) { 1106 sl->sl_meta_size_used = old_sz_used; 1107 sl->sl_total_meta_size = old_meta_size; 1108 } 1109 } else { 1110 sl->sl_meta_size_used = old_sz_used; 1111 sl->sl_total_meta_size = old_meta_size; 1112 } 1113 } else { 1114 write_meta_ret = sbd_write_meta(sl, off, s, cb); 1115 } 1116 if ((write_meta_ret != SBD_SUCCESS) && 1117 (sms_before_unused.sms_offset != 0)) { 1118 sm_section_hdr_t new_sms; 1119 sm_section_hdr_t *unused_sms; 1120 /* 1121 * On failure writing the meta section attempt to undo 1122 * the change to unused. 1123 * Re-read the meta data from permanent storage. 1124 * The section id can't exist for undo to be possible. 1125 * Read what should be the entire old section data and 1126 * insure the old data's still present by validating 1127 * against it's old checksum. 1128 */ 1129 new_sms.sms_id = sms->sms_id; 1130 new_sms.sms_data_order = SMS_DATA_ORDER; 1131 if (sbd_load_section_hdr_unbuffered(sl, &new_sms) != 1132 SBD_NOT_FOUND) { 1133 goto done; 1134 } 1135 unused_sms = kmem_zalloc(sms_before_unused.sms_size, KM_SLEEP); 1136 if (sbd_read_meta(sl, sms_before_unused.sms_offset, 1137 sms_before_unused.sms_size, 1138 (uint8_t *)unused_sms) != SBD_SUCCESS) { 1139 goto done; 1140 } 1141 if (unused_sms->sms_data_order != SMS_DATA_ORDER) { 1142 sbd_swap_section_hdr(unused_sms); 1143 } 1144 if (unused_sms->sms_id != SMS_ID_UNUSED) { 1145 goto done; 1146 } 1147 if (unused_sms->sms_offset != sms_before_unused.sms_offset) { 1148 goto done; 1149 } 1150 if (unused_sms->sms_size != sms_before_unused.sms_size) { 1151 goto done; 1152 } 1153 unused_sms->sms_id = sms_before_unused.sms_id; 1154 if (sbd_calc_section_sum(unused_sms, 1155 sizeof (sm_section_hdr_t)) != 1156 sbd_calc_section_sum(&sms_before_unused, 1157 sizeof (sm_section_hdr_t))) { 1158 goto done; 1159 } 1160 unused_sms->sms_chksum = 1161 sbd_calc_section_sum(unused_sms, unused_sms->sms_size); 1162 if (unused_sms->sms_chksum != sms_before_unused.sms_chksum) { 1163 goto done; 1164 } 1165 (void) sbd_write_meta(sl, unused_sms->sms_offset, 1166 sizeof (sm_section_hdr_t), (uint8_t *)unused_sms); 1167 } 1168 done: 1169 mutex_exit(&sl->sl_metadata_lock); 1170 kmem_free(cb, s); 1171 if (write_meta_ret != SBD_SUCCESS) { 1172 return (write_meta_ret); 1173 } 1174 return (ret); 1175 } 1176 1177 sbd_status_t 1178 sbd_write_lu_info(sbd_lu_t *sl) 1179 { 1180 sbd_lu_info_1_1_t *sli; 1181 int s; 1182 uint8_t *p; 1183 char *zvol_name = NULL; 1184 sbd_status_t ret; 1185 1186 mutex_enter(&sl->sl_lock); 1187 1188 s = sl->sl_serial_no_size; 1189 if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) { 1190 if (sl->sl_data_filename) { 1191 s += strlen(sl->sl_data_filename) + 1; 1192 } 1193 } 1194 if (sl->sl_flags & SL_ZFS_META) { 1195 zvol_name = sbd_get_zvol_name(sl); 1196 s += strlen(zvol_name) + 1; 1197 } 1198 if (sl->sl_alias) { 1199 s += strlen(sl->sl_alias) + 1; 1200 } 1201 if (sl->sl_mgmt_url) { 1202 s += strlen(sl->sl_mgmt_url) + 1; 1203 } 1204 sli = (sbd_lu_info_1_1_t *)kmem_zalloc(sizeof (*sli) + s, KM_SLEEP); 1205 p = sli->sli_buf; 1206 if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) { 1207 sli->sli_flags |= SLI_SEPARATE_META; 1208 (void) strcpy((char *)p, sl->sl_data_filename); 1209 sli->sli_data_fname_offset = 1210 (uintptr_t)p - (uintptr_t)sli->sli_buf; 1211 sli->sli_flags |= SLI_DATA_FNAME_VALID; 1212 p += strlen(sl->sl_data_filename) + 1; 1213 } 1214 if (sl->sl_flags & SL_ZFS_META) { 1215 (void) strcpy((char *)p, zvol_name); 1216 sli->sli_meta_fname_offset = 1217 (uintptr_t)p - (uintptr_t)sli->sli_buf; 1218 sli->sli_flags |= SLI_META_FNAME_VALID | SLI_ZFS_META; 1219 p += strlen(zvol_name) + 1; 1220 kmem_free(zvol_name, strlen(zvol_name) + 1); 1221 zvol_name = NULL; 1222 } 1223 if (sl->sl_alias) { 1224 (void) strcpy((char *)p, sl->sl_alias); 1225 sli->sli_alias_offset = 1226 (uintptr_t)p - (uintptr_t)sli->sli_buf; 1227 sli->sli_flags |= SLI_ALIAS_VALID; 1228 p += strlen(sl->sl_alias) + 1; 1229 } 1230 if (sl->sl_mgmt_url) { 1231 (void) strcpy((char *)p, sl->sl_mgmt_url); 1232 sli->sli_mgmt_url_offset = 1233 (uintptr_t)p - (uintptr_t)sli->sli_buf; 1234 sli->sli_flags |= SLI_MGMT_URL_VALID; 1235 p += strlen(sl->sl_mgmt_url) + 1; 1236 } 1237 if (sl->sl_flags & SL_WRITE_PROTECTED) { 1238 sli->sli_flags |= SLI_WRITE_PROTECTED; 1239 } 1240 if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) { 1241 sli->sli_flags |= SLI_WRITEBACK_CACHE_DISABLE; 1242 } 1243 if (sl->sl_flags & SL_VID_VALID) { 1244 bcopy(sl->sl_vendor_id, sli->sli_vid, 8); 1245 sli->sli_flags |= SLI_VID_VALID; 1246 } 1247 if (sl->sl_flags & SL_PID_VALID) { 1248 bcopy(sl->sl_product_id, sli->sli_pid, 16); 1249 sli->sli_flags |= SLI_PID_VALID; 1250 } 1251 if (sl->sl_flags & SL_REV_VALID) { 1252 bcopy(sl->sl_revision, sli->sli_rev, 4); 1253 sli->sli_flags |= SLI_REV_VALID; 1254 } 1255 if (sl->sl_serial_no_size) { 1256 bcopy(sl->sl_serial_no, p, sl->sl_serial_no_size); 1257 sli->sli_serial_size = sl->sl_serial_no_size; 1258 sli->sli_serial_offset = 1259 (uintptr_t)p - (uintptr_t)sli->sli_buf; 1260 sli->sli_flags |= SLI_SERIAL_VALID; 1261 p += sli->sli_serial_size; 1262 } 1263 sli->sli_lu_size = sl->sl_lu_size; 1264 sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift; 1265 sli->sli_data_order = SMS_DATA_ORDER; 1266 bcopy(sl->sl_device_id, sli->sli_device_id, 20); 1267 1268 sli->sli_sms_header.sms_size = sizeof (*sli) + s; 1269 sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1; 1270 sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER; 1271 1272 mutex_exit(&sl->sl_lock); 1273 ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli); 1274 kmem_free(sli, sizeof (*sli) + s); 1275 return (ret); 1276 } 1277 1278 int 1279 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret) 1280 { 1281 stmf_lu_t *lu = sl->sl_lu; 1282 stmf_status_t ret; 1283 1284 lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id; 1285 if (sl->sl_alias) { 1286 lu->lu_alias = sl->sl_alias; 1287 } else { 1288 lu->lu_alias = sl->sl_name; 1289 } 1290 lu->lu_lp = sbd_lp; 1291 lu->lu_task_alloc = sbd_task_alloc; 1292 lu->lu_new_task = sbd_new_task; 1293 lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done; 1294 lu->lu_send_status_done = sbd_send_status_done; 1295 lu->lu_task_free = sbd_task_free; 1296 lu->lu_abort = sbd_abort; 1297 lu->lu_ctl = sbd_ctl; 1298 lu->lu_info = sbd_info; 1299 sl->sl_state = STMF_STATE_OFFLINE; 1300 1301 if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) { 1302 stmf_trace(0, "Failed to register with framework, ret=%llx", 1303 ret); 1304 if (ret == STMF_ALREADY) { 1305 *err_ret = SBD_RET_GUID_ALREADY_REGISTERED; 1306 } 1307 return (EIO); 1308 } 1309 1310 *err_ret = 0; 1311 return (0); 1312 } 1313 1314 int 1315 sbd_open_data_file(sbd_lu_t *sl, uint32_t *err_ret, int lu_size_valid, 1316 int vp_valid, int keep_open) 1317 { 1318 int ret; 1319 int flag; 1320 ulong_t nbits; 1321 uint64_t supported_size; 1322 vattr_t vattr; 1323 enum vtype vt; 1324 1325 mutex_enter(&sl->sl_lock); 1326 if (vp_valid) { 1327 goto odf_over_open; 1328 } 1329 if (sl->sl_data_filename[0] != '/') { 1330 *err_ret = SBD_RET_DATA_PATH_NOT_ABSOLUTE; 1331 mutex_exit(&sl->sl_lock); 1332 return (EINVAL); 1333 } 1334 if ((ret = lookupname(sl->sl_data_filename, UIO_SYSSPACE, FOLLOW, 1335 NULLVPP, &sl->sl_data_vp)) != 0) { 1336 *err_ret = SBD_RET_DATA_FILE_LOOKUP_FAILED; 1337 mutex_exit(&sl->sl_lock); 1338 return (ret); 1339 } 1340 sl->sl_data_vtype = vt = sl->sl_data_vp->v_type; 1341 VN_RELE(sl->sl_data_vp); 1342 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) { 1343 *err_ret = SBD_RET_WRONG_DATA_FILE_TYPE; 1344 mutex_exit(&sl->sl_lock); 1345 return (EINVAL); 1346 } 1347 if (sl->sl_flags & SL_WRITE_PROTECTED) { 1348 flag = FREAD | FOFFMAX; 1349 } else { 1350 flag = FREAD | FWRITE | FOFFMAX | FEXCL; 1351 } 1352 if ((ret = vn_open(sl->sl_data_filename, UIO_SYSSPACE, flag, 0, 1353 &sl->sl_data_vp, 0, 0)) != 0) { 1354 *err_ret = SBD_RET_DATA_FILE_OPEN_FAILED; 1355 mutex_exit(&sl->sl_lock); 1356 return (ret); 1357 } 1358 odf_over_open: 1359 vattr.va_mask = AT_SIZE; 1360 if ((ret = VOP_GETATTR(sl->sl_data_vp, &vattr, 0, CRED(), NULL)) != 0) { 1361 *err_ret = SBD_RET_DATA_FILE_GETATTR_FAILED; 1362 goto odf_close_data_and_exit; 1363 } 1364 if ((vt != VREG) && (vattr.va_size == 0)) { 1365 /* 1366 * Its a zero byte block or char device. This cannot be 1367 * a raw disk. 1368 */ 1369 *err_ret = SBD_RET_WRONG_DATA_FILE_TYPE; 1370 ret = EINVAL; 1371 goto odf_close_data_and_exit; 1372 } 1373 /* sl_data_readable size includes any metadata. */ 1374 sl->sl_data_readable_size = vattr.va_size; 1375 if (VOP_PATHCONF(sl->sl_data_vp, _PC_FILESIZEBITS, &nbits, 1376 CRED(), NULL) != 0) { 1377 nbits = 0; 1378 } 1379 /* nbits cannot be greater than 64 */ 1380 sl->sl_data_fs_nbits = (uint8_t)nbits; 1381 if (lu_size_valid) { 1382 sl->sl_total_data_size = sl->sl_lu_size; 1383 if (sl->sl_flags & SL_SHARED_META) { 1384 sl->sl_total_data_size += SHARED_META_DATA_SIZE; 1385 } 1386 if ((nbits > 0) && (nbits < 64)) { 1387 /* 1388 * The expression below is correct only if nbits is 1389 * positive and less than 64. 1390 */ 1391 supported_size = (((uint64_t)1) << nbits) - 1; 1392 if (sl->sl_total_data_size > supported_size) { 1393 *err_ret = SBD_RET_SIZE_NOT_SUPPORTED_BY_FS; 1394 ret = EINVAL; 1395 goto odf_close_data_and_exit; 1396 } 1397 } 1398 } else { 1399 sl->sl_total_data_size = vattr.va_size; 1400 if (sl->sl_flags & SL_SHARED_META) { 1401 if (vattr.va_size > SHARED_META_DATA_SIZE) { 1402 sl->sl_lu_size = vattr.va_size - 1403 SHARED_META_DATA_SIZE; 1404 } else { 1405 *err_ret = SBD_RET_FILE_SIZE_ERROR; 1406 ret = EINVAL; 1407 goto odf_close_data_and_exit; 1408 } 1409 } else { 1410 sl->sl_lu_size = vattr.va_size; 1411 } 1412 } 1413 if (sl->sl_lu_size < SBD_MIN_LU_SIZE) { 1414 *err_ret = SBD_RET_FILE_SIZE_ERROR; 1415 ret = EINVAL; 1416 goto odf_close_data_and_exit; 1417 } 1418 if (sl->sl_lu_size & 1419 ((((uint64_t)1) << sl->sl_data_blocksize_shift) - 1)) { 1420 *err_ret = SBD_RET_FILE_ALIGN_ERROR; 1421 ret = EINVAL; 1422 goto odf_close_data_and_exit; 1423 } 1424 sl->sl_flags |= SL_MEDIA_LOADED; 1425 mutex_exit(&sl->sl_lock); 1426 return (0); 1427 1428 odf_close_data_and_exit: 1429 if (!keep_open) { 1430 (void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL); 1431 VN_RELE(sl->sl_data_vp); 1432 } 1433 mutex_exit(&sl->sl_lock); 1434 return (ret); 1435 } 1436 1437 int 1438 sbd_close_delete_lu(sbd_lu_t *sl, int ret) 1439 { 1440 int flag; 1441 1442 if (((sl->sl_flags & SL_SHARED_META) == 0) && 1443 (sl->sl_flags & SL_META_OPENED)) { 1444 if (sl->sl_flags & SL_ZFS_META) { 1445 rw_destroy(&sl->sl_zfs_meta_lock); 1446 if (sl->sl_zfs_meta) { 1447 kmem_free(sl->sl_zfs_meta, ZAP_MAXVALUELEN / 2); 1448 } 1449 } else { 1450 flag = FREAD | FWRITE | FOFFMAX | FEXCL; 1451 (void) VOP_CLOSE(sl->sl_meta_vp, flag, 1, 0, 1452 CRED(), NULL); 1453 VN_RELE(sl->sl_meta_vp); 1454 } 1455 sl->sl_flags &= ~SL_META_OPENED; 1456 } 1457 if (sl->sl_flags & SL_MEDIA_LOADED) { 1458 if (sl->sl_flags & SL_WRITE_PROTECTED) { 1459 flag = FREAD | FOFFMAX; 1460 } else { 1461 flag = FREAD | FWRITE | FOFFMAX | FEXCL; 1462 } 1463 (void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL); 1464 VN_RELE(sl->sl_data_vp); 1465 sl->sl_flags &= ~SL_MEDIA_LOADED; 1466 if (sl->sl_flags & SL_SHARED_META) { 1467 sl->sl_flags &= ~SL_META_OPENED; 1468 } 1469 } 1470 if (sl->sl_flags & SL_LINKED) 1471 sbd_unlink_lu(sl); 1472 mutex_destroy(&sl->sl_metadata_lock); 1473 mutex_destroy(&sl->sl_lock); 1474 rw_destroy(&sl->sl_pgr->pgr_lock); 1475 if (sl->sl_serial_no_alloc_size) { 1476 kmem_free(sl->sl_serial_no, sl->sl_serial_no_alloc_size); 1477 } 1478 if (sl->sl_data_fname_alloc_size) { 1479 kmem_free(sl->sl_data_filename, sl->sl_data_fname_alloc_size); 1480 } 1481 if (sl->sl_alias_alloc_size) { 1482 kmem_free(sl->sl_alias, sl->sl_alias_alloc_size); 1483 } 1484 if (sl->sl_mgmt_url_alloc_size) { 1485 kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size); 1486 } 1487 stmf_free(sl->sl_lu); 1488 return (ret); 1489 } 1490 1491 int 1492 sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz, 1493 uint32_t *err_ret) 1494 { 1495 char *namebuf; 1496 sbd_lu_t *sl; 1497 stmf_lu_t *lu; 1498 sbd_status_t sret; 1499 char *p; 1500 int sz; 1501 int alloc_sz; 1502 int ret = EIO; 1503 int flag; 1504 int wcd = 0; 1505 enum vtype vt; 1506 1507 sz = struct_sz - sizeof (sbd_create_and_reg_lu_t) + 8 + 1; 1508 1509 *err_ret = 0; 1510 1511 /* Lets validate various offsets */ 1512 if (((slu->slu_meta_fname_valid) && 1513 (slu->slu_meta_fname_off >= sz)) || 1514 (slu->slu_data_fname_off >= sz) || 1515 ((slu->slu_alias_valid) && 1516 (slu->slu_alias_off >= sz)) || 1517 ((slu->slu_mgmt_url_valid) && 1518 (slu->slu_mgmt_url_off >= sz)) || 1519 ((slu->slu_serial_valid) && 1520 ((slu->slu_serial_off + slu->slu_serial_size) >= sz))) { 1521 return (EINVAL); 1522 } 1523 1524 namebuf = kmem_zalloc(sz, KM_SLEEP); 1525 bcopy(slu->slu_buf, namebuf, sz - 1); 1526 namebuf[sz - 1] = 0; 1527 1528 alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t); 1529 if (slu->slu_meta_fname_valid) { 1530 alloc_sz += strlen(namebuf + slu->slu_meta_fname_off) + 1; 1531 } 1532 alloc_sz += strlen(namebuf + slu->slu_data_fname_off) + 1; 1533 if (slu->slu_alias_valid) { 1534 alloc_sz += strlen(namebuf + slu->slu_alias_off) + 1; 1535 } 1536 if (slu->slu_mgmt_url_valid) { 1537 alloc_sz += strlen(namebuf + slu->slu_mgmt_url_off) + 1; 1538 } 1539 if (slu->slu_serial_valid) { 1540 alloc_sz += slu->slu_serial_size; 1541 } 1542 1543 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0); 1544 if (lu == NULL) { 1545 kmem_free(namebuf, sz); 1546 return (ENOMEM); 1547 } 1548 sl = (sbd_lu_t *)lu->lu_provider_private; 1549 bzero(sl, alloc_sz); 1550 sl->sl_lu = lu; 1551 sl->sl_alloc_size = alloc_sz; 1552 sl->sl_pgr = (sbd_pgr_t *)(sl + 1); 1553 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL); 1554 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL); 1555 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL); 1556 p = ((char *)sl) + sizeof (sbd_lu_t) + sizeof (sbd_pgr_t); 1557 sl->sl_data_filename = p; 1558 (void) strcpy(sl->sl_data_filename, namebuf + slu->slu_data_fname_off); 1559 p += strlen(sl->sl_data_filename) + 1; 1560 sl->sl_meta_offset = SBD_META_OFFSET; 1561 if (slu->slu_meta_fname_valid) { 1562 sl->sl_alias = sl->sl_name = sl->sl_meta_filename = p; 1563 (void) strcpy(sl->sl_meta_filename, namebuf + 1564 slu->slu_meta_fname_off); 1565 p += strlen(sl->sl_meta_filename) + 1; 1566 } else { 1567 sl->sl_alias = sl->sl_name = sl->sl_data_filename; 1568 if (sbd_is_zvol(sl->sl_data_filename)) { 1569 sl->sl_flags |= SL_ZFS_META; 1570 sl->sl_meta_offset = 0; 1571 } else { 1572 sl->sl_flags |= SL_SHARED_META; 1573 sl->sl_data_offset = SHARED_META_DATA_SIZE; 1574 sl->sl_total_meta_size = SHARED_META_DATA_SIZE; 1575 sl->sl_meta_size_used = 0; 1576 } 1577 } 1578 if (slu->slu_alias_valid) { 1579 sl->sl_alias = p; 1580 (void) strcpy(p, namebuf + slu->slu_alias_off); 1581 p += strlen(sl->sl_alias) + 1; 1582 } 1583 if (slu->slu_mgmt_url_valid) { 1584 sl->sl_mgmt_url = p; 1585 (void) strcpy(p, namebuf + slu->slu_mgmt_url_off); 1586 p += strlen(sl->sl_mgmt_url) + 1; 1587 } 1588 if (slu->slu_serial_valid) { 1589 sl->sl_serial_no = (uint8_t *)p; 1590 bcopy(namebuf + slu->slu_serial_off, sl->sl_serial_no, 1591 slu->slu_serial_size); 1592 sl->sl_serial_no_size = slu->slu_serial_size; 1593 p += slu->slu_serial_size; 1594 } 1595 kmem_free(namebuf, sz); 1596 if (slu->slu_vid_valid) { 1597 bcopy(slu->slu_vid, sl->sl_vendor_id, 8); 1598 sl->sl_flags |= SL_VID_VALID; 1599 } 1600 if (slu->slu_pid_valid) { 1601 bcopy(slu->slu_pid, sl->sl_product_id, 16); 1602 sl->sl_flags |= SL_PID_VALID; 1603 } 1604 if (slu->slu_rev_valid) { 1605 bcopy(slu->slu_rev, sl->sl_revision, 4); 1606 sl->sl_flags |= SL_REV_VALID; 1607 } 1608 if (slu->slu_write_protected) { 1609 sl->sl_flags |= SL_WRITE_PROTECTED; 1610 } 1611 if (slu->slu_writeback_cache_disable) { 1612 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE | 1613 SL_SAVED_WRITE_CACHE_DISABLE; 1614 } 1615 1616 if (slu->slu_blksize_valid) { 1617 if ((slu->slu_blksize & (slu->slu_blksize - 1)) || 1618 (slu->slu_blksize > (32 * 1024)) || 1619 (slu->slu_blksize == 0)) { 1620 *err_ret = SBD_RET_INVALID_BLKSIZE; 1621 ret = EINVAL; 1622 goto scm_err_out; 1623 } 1624 while ((1 << sl->sl_data_blocksize_shift) != slu->slu_blksize) { 1625 sl->sl_data_blocksize_shift++; 1626 } 1627 } else { 1628 sl->sl_data_blocksize_shift = 9; /* 512 by default */ 1629 slu->slu_blksize = 512; 1630 } 1631 1632 /* Now lets start creating meta */ 1633 sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU; 1634 if (sbd_link_lu(sl) != SBD_SUCCESS) { 1635 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED; 1636 ret = EALREADY; 1637 goto scm_err_out; 1638 } 1639 1640 /* 1st focus on the data store */ 1641 if (slu->slu_lu_size_valid) { 1642 sl->sl_lu_size = slu->slu_lu_size; 1643 } 1644 ret = sbd_open_data_file(sl, err_ret, slu->slu_lu_size_valid, 0, 0); 1645 slu->slu_ret_filesize_nbits = sl->sl_data_fs_nbits; 1646 slu->slu_lu_size = sl->sl_lu_size; 1647 if (ret) { 1648 goto scm_err_out; 1649 } 1650 1651 /* 1652 * set write cache disable on the device 1653 * if it fails, we'll support it using sync/flush 1654 */ 1655 if (slu->slu_writeback_cache_disable) { 1656 (void) sbd_wcd_set(1, sl); 1657 wcd = 1; 1658 /* 1659 * Attempt to set it to enable, if that fails and it was explicitly set 1660 * return an error, otherwise get the current setting and use that 1661 */ 1662 } else { 1663 sret = sbd_wcd_set(0, sl); 1664 if (slu->slu_writeback_cache_disable_valid && 1665 sret != SBD_SUCCESS) { 1666 *err_ret = SBD_RET_WRITE_CACHE_SET_FAILED; 1667 ret = EFAULT; 1668 goto scm_err_out; 1669 } 1670 if (sret != SBD_SUCCESS) { 1671 sbd_wcd_get(&wcd, sl); 1672 } 1673 } 1674 1675 if (wcd) { 1676 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE | 1677 SL_SAVED_WRITE_CACHE_DISABLE; 1678 } 1679 1680 if (sl->sl_flags & SL_SHARED_META) { 1681 goto over_meta_open; 1682 } 1683 if (sl->sl_flags & SL_ZFS_META) { 1684 if (sbd_create_zfs_meta_object(sl) != SBD_SUCCESS) { 1685 *err_ret = SBD_RET_ZFS_META_CREATE_FAILED; 1686 ret = ENOMEM; 1687 goto scm_err_out; 1688 } 1689 sl->sl_meta_blocksize_shift = 0; 1690 goto over_meta_create; 1691 } 1692 if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW, 1693 NULLVPP, &sl->sl_meta_vp)) != 0) { 1694 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED; 1695 goto scm_err_out; 1696 } 1697 sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type; 1698 VN_RELE(sl->sl_meta_vp); 1699 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) { 1700 *err_ret = SBD_RET_WRONG_META_FILE_TYPE; 1701 ret = EINVAL; 1702 goto scm_err_out; 1703 } 1704 if (vt == VREG) { 1705 sl->sl_meta_blocksize_shift = 0; 1706 } else { 1707 sl->sl_meta_blocksize_shift = 9; 1708 } 1709 flag = FREAD | FWRITE | FOFFMAX | FEXCL; 1710 if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0, 1711 &sl->sl_meta_vp, 0, 0)) != 0) { 1712 *err_ret = SBD_RET_META_FILE_OPEN_FAILED; 1713 goto scm_err_out; 1714 } 1715 over_meta_create: 1716 sl->sl_total_meta_size = sl->sl_meta_offset + sizeof (sbd_meta_start_t); 1717 sl->sl_total_meta_size += 1718 (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1; 1719 sl->sl_total_meta_size &= 1720 ~((((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1); 1721 sl->sl_meta_size_used = 0; 1722 over_meta_open: 1723 sl->sl_flags |= SL_META_OPENED; 1724 1725 sl->sl_device_id[3] = 16; 1726 if (slu->slu_guid_valid) { 1727 sl->sl_device_id[0] = 0xf1; 1728 sl->sl_device_id[1] = 3; 1729 sl->sl_device_id[2] = 0; 1730 bcopy(slu->slu_guid, sl->sl_device_id + 4, 16); 1731 } else { 1732 if (!slu->slu_company_id_valid) 1733 slu->slu_company_id = COMPANY_ID_SUN; 1734 if (stmf_scsilib_uniq_lu_id(slu->slu_company_id, 1735 (scsi_devid_desc_t *)&sl->sl_device_id[0]) != 1736 STMF_SUCCESS) { 1737 *err_ret = SBD_RET_META_CREATION_FAILED; 1738 ret = EIO; 1739 goto scm_err_out; 1740 } 1741 bcopy(sl->sl_device_id + 4, slu->slu_guid, 16); 1742 } 1743 1744 /* Lets create the meta now */ 1745 mutex_enter(&sl->sl_metadata_lock); 1746 if (sbd_write_meta_start(sl, sl->sl_total_meta_size, 1747 sizeof (sbd_meta_start_t)) != SBD_SUCCESS) { 1748 mutex_exit(&sl->sl_metadata_lock); 1749 *err_ret = SBD_RET_META_CREATION_FAILED; 1750 ret = EIO; 1751 goto scm_err_out; 1752 } 1753 mutex_exit(&sl->sl_metadata_lock); 1754 sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t); 1755 1756 if (sbd_write_lu_info(sl) != SBD_SUCCESS) { 1757 *err_ret = SBD_RET_META_CREATION_FAILED; 1758 ret = EIO; 1759 goto scm_err_out; 1760 } 1761 1762 if (sbd_pgr_meta_init(sl) != SBD_SUCCESS) { 1763 *err_ret = SBD_RET_META_CREATION_FAILED; 1764 ret = EIO; 1765 goto scm_err_out; 1766 } 1767 1768 ret = sbd_populate_and_register_lu(sl, err_ret); 1769 if (ret) { 1770 goto scm_err_out; 1771 } 1772 1773 sl->sl_trans_op = SL_OP_NONE; 1774 atomic_add_32(&sbd_lu_count, 1); 1775 return (0); 1776 1777 scm_err_out: 1778 return (sbd_close_delete_lu(sl, ret)); 1779 } 1780 1781 int 1782 sbd_load_sli_1_0(sbd_lu_t *sl, uint32_t *err_ret) 1783 { 1784 sbd_lu_info_1_0_t *sli = NULL; 1785 sbd_status_t sret; 1786 1787 sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli, 1788 SMS_ID_LU_INFO_1_0); 1789 1790 if (sret != SBD_SUCCESS) { 1791 *err_ret = SBD_RET_NO_META; 1792 return (EIO); 1793 } 1794 if (sli->sli_data_order != SMS_DATA_ORDER) { 1795 sbd_swap_lu_info_1_0(sli); 1796 if (sli->sli_data_order != SMS_DATA_ORDER) { 1797 kmem_free(sli, sli->sli_sms_header.sms_size); 1798 *err_ret = SBD_RET_NO_META; 1799 return (EIO); 1800 } 1801 } 1802 1803 sl->sl_flags |= SL_SHARED_META; 1804 sl->sl_data_blocksize_shift = 9; 1805 sl->sl_data_offset = SHARED_META_DATA_SIZE; 1806 sl->sl_lu_size = sli->sli_total_store_size - SHARED_META_DATA_SIZE; 1807 sl->sl_total_data_size = SHARED_META_DATA_SIZE + sl->sl_lu_size; 1808 bcopy(sli->sli_lu_devid, sl->sl_device_id, 20); 1809 1810 kmem_free(sli, sli->sli_sms_header.sms_size); 1811 return (0); 1812 } 1813 1814 int 1815 sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret, 1816 int no_register, sbd_lu_t **slr) 1817 { 1818 stmf_lu_t *lu; 1819 sbd_lu_t *sl; 1820 sbd_lu_info_1_1_t *sli = NULL; 1821 int asz; 1822 int ret = 0; 1823 int flag; 1824 int wcd = 0; 1825 int data_opened; 1826 uint16_t sli_buf_sz; 1827 uint8_t *sli_buf_copy = NULL; 1828 enum vtype vt; 1829 sbd_status_t sret; 1830 1831 if (no_register && slr == NULL) { 1832 return (EINVAL); 1833 } 1834 ilu->ilu_meta_fname[struct_sz - sizeof (*ilu) + 8 - 1] = 0; 1835 asz = strlen(ilu->ilu_meta_fname) + 1; 1836 1837 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, 1838 sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) + asz, 0); 1839 if (lu == NULL) { 1840 return (ENOMEM); 1841 } 1842 sl = (sbd_lu_t *)lu->lu_provider_private; 1843 bzero(sl, sizeof (*sl)); 1844 sl->sl_lu = lu; 1845 sl->sl_pgr = (sbd_pgr_t *)(sl + 1); 1846 sl->sl_meta_filename = ((char *)sl) + sizeof (*sl) + sizeof (sbd_pgr_t); 1847 (void) strcpy(sl->sl_meta_filename, ilu->ilu_meta_fname); 1848 sl->sl_name = sl->sl_meta_filename; 1849 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL); 1850 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL); 1851 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL); 1852 sl->sl_trans_op = SL_OP_IMPORT_LU; 1853 /* we're only loading the metadata */ 1854 if (!no_register) { 1855 if (sbd_link_lu(sl) != SBD_SUCCESS) { 1856 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED; 1857 ret = EALREADY; 1858 goto sim_err_out; 1859 } 1860 } 1861 if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW, 1862 NULLVPP, &sl->sl_meta_vp)) != 0) { 1863 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED; 1864 goto sim_err_out; 1865 } 1866 if (sbd_is_zvol(sl->sl_meta_filename)) { 1867 sl->sl_flags |= SL_ZFS_META; 1868 sl->sl_data_filename = sl->sl_meta_filename; 1869 } 1870 sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type; 1871 VN_RELE(sl->sl_meta_vp); 1872 if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) { 1873 *err_ret = SBD_RET_WRONG_META_FILE_TYPE; 1874 ret = EINVAL; 1875 goto sim_err_out; 1876 } 1877 if (sl->sl_flags & SL_ZFS_META) { 1878 if (sbd_open_zfs_meta(sl) != SBD_SUCCESS) { 1879 /* let see if metadata is in the 64k block */ 1880 sl->sl_flags &= ~SL_ZFS_META; 1881 } 1882 } 1883 if (!(sl->sl_flags & SL_ZFS_META)) { 1884 /* metadata is always writable */ 1885 flag = FREAD | FWRITE | FOFFMAX | FEXCL; 1886 if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0, 1887 &sl->sl_meta_vp, 0, 0)) != 0) { 1888 *err_ret = SBD_RET_META_FILE_OPEN_FAILED; 1889 goto sim_err_out; 1890 } 1891 } 1892 if ((sl->sl_flags & SL_ZFS_META) || (vt == VREG)) { 1893 sl->sl_meta_blocksize_shift = 0; 1894 } else { 1895 sl->sl_meta_blocksize_shift = 9; 1896 } 1897 sl->sl_meta_offset = (sl->sl_flags & SL_ZFS_META) ? 0 : SBD_META_OFFSET; 1898 sl->sl_flags |= SL_META_OPENED; 1899 1900 mutex_enter(&sl->sl_metadata_lock); 1901 sret = sbd_load_meta_start(sl); 1902 mutex_exit(&sl->sl_metadata_lock); 1903 if (sret != SBD_SUCCESS) { 1904 if (sret == SBD_META_CORRUPTED) { 1905 *err_ret = SBD_RET_NO_META; 1906 } else if (sret == SBD_NOT_SUPPORTED) { 1907 *err_ret = SBD_RET_VERSION_NOT_SUPPORTED; 1908 } else { 1909 *err_ret = SBD_RET_NO_META; 1910 } 1911 ret = EINVAL; 1912 goto sim_err_out; 1913 } 1914 1915 /* Now lets see if we can read the most recent LU info */ 1916 sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli, 1917 SMS_ID_LU_INFO_1_1); 1918 if ((sret == SBD_NOT_FOUND) && ((sl->sl_flags & SL_ZFS_META) == 0)) { 1919 ret = sbd_load_sli_1_0(sl, err_ret); 1920 if (ret) 1921 goto sim_err_out; 1922 goto sim_sli_loaded; 1923 } 1924 if (sret != SBD_SUCCESS) { 1925 *err_ret = SBD_RET_NO_META; 1926 ret = EIO; 1927 goto sim_err_out; 1928 } 1929 /* load sli 1.1 */ 1930 if (sli->sli_data_order != SMS_DATA_ORDER) { 1931 sbd_swap_lu_info_1_1(sli); 1932 if (sli->sli_data_order != SMS_DATA_ORDER) { 1933 *err_ret = SBD_RET_NO_META; 1934 ret = EIO; 1935 goto sim_err_out; 1936 } 1937 } 1938 1939 sli_buf_sz = sli->sli_sms_header.sms_size - 1940 sizeof (sbd_lu_info_1_1_t) + 8; 1941 sli_buf_copy = kmem_alloc(sli_buf_sz + 1, KM_SLEEP); 1942 bcopy(sli->sli_buf, sli_buf_copy, sli_buf_sz); 1943 sli_buf_copy[sli_buf_sz] = 0; 1944 1945 /* Make sure all the offsets are within limits */ 1946 if (((sli->sli_flags & SLI_META_FNAME_VALID) && 1947 (sli->sli_meta_fname_offset > sli_buf_sz)) || 1948 ((sli->sli_flags & SLI_DATA_FNAME_VALID) && 1949 (sli->sli_data_fname_offset > sli_buf_sz)) || 1950 ((sli->sli_flags & SLI_MGMT_URL_VALID) && 1951 (sli->sli_mgmt_url_offset > sli_buf_sz)) || 1952 ((sli->sli_flags & SLI_SERIAL_VALID) && 1953 ((sli->sli_serial_offset + sli->sli_serial_size) > sli_buf_sz)) || 1954 ((sli->sli_flags & SLI_ALIAS_VALID) && 1955 (sli->sli_alias_offset > sli_buf_sz))) { 1956 *err_ret = SBD_RET_NO_META; 1957 ret = EIO; 1958 goto sim_err_out; 1959 } 1960 1961 sl->sl_lu_size = sli->sli_lu_size; 1962 sl->sl_data_blocksize_shift = sli->sli_data_blocksize_shift; 1963 bcopy(sli->sli_device_id, sl->sl_device_id, 20); 1964 if (sli->sli_flags & SLI_SERIAL_VALID) { 1965 sl->sl_serial_no_size = sl->sl_serial_no_alloc_size = 1966 sli->sli_serial_size; 1967 sl->sl_serial_no = kmem_zalloc(sli->sli_serial_size, KM_SLEEP); 1968 bcopy(sli_buf_copy + sli->sli_serial_offset, sl->sl_serial_no, 1969 sl->sl_serial_no_size); 1970 } 1971 if (sli->sli_flags & SLI_SEPARATE_META) { 1972 sl->sl_total_data_size = sl->sl_lu_size; 1973 if (sli->sli_flags & SLI_DATA_FNAME_VALID) { 1974 sl->sl_data_fname_alloc_size = strlen((char *) 1975 sli_buf_copy + sli->sli_data_fname_offset) + 1; 1976 sl->sl_data_filename = kmem_zalloc( 1977 sl->sl_data_fname_alloc_size, KM_SLEEP); 1978 (void) strcpy(sl->sl_data_filename, 1979 (char *)sli_buf_copy + sli->sli_data_fname_offset); 1980 } 1981 } else { 1982 if (sl->sl_flags & SL_ZFS_META) { 1983 sl->sl_total_data_size = sl->sl_lu_size; 1984 sl->sl_data_offset = 0; 1985 } else { 1986 sl->sl_total_data_size = 1987 sl->sl_lu_size + SHARED_META_DATA_SIZE; 1988 sl->sl_data_offset = SHARED_META_DATA_SIZE; 1989 sl->sl_flags |= SL_SHARED_META; 1990 } 1991 } 1992 if (sli->sli_flags & SLI_ALIAS_VALID) { 1993 sl->sl_alias_alloc_size = strlen((char *)sli_buf_copy + 1994 sli->sli_alias_offset) + 1; 1995 sl->sl_alias = kmem_alloc(sl->sl_alias_alloc_size, KM_SLEEP); 1996 (void) strcpy(sl->sl_alias, (char *)sli_buf_copy + 1997 sli->sli_alias_offset); 1998 } 1999 if (sli->sli_flags & SLI_MGMT_URL_VALID) { 2000 sl->sl_mgmt_url_alloc_size = strlen((char *)sli_buf_copy + 2001 sli->sli_mgmt_url_offset) + 1; 2002 sl->sl_mgmt_url = kmem_alloc(sl->sl_mgmt_url_alloc_size, 2003 KM_SLEEP); 2004 (void) strcpy(sl->sl_mgmt_url, (char *)sli_buf_copy + 2005 sli->sli_mgmt_url_offset); 2006 } 2007 if (sli->sli_flags & SLI_WRITE_PROTECTED) { 2008 sl->sl_flags |= SL_WRITE_PROTECTED; 2009 } 2010 if (sli->sli_flags & SLI_VID_VALID) { 2011 sl->sl_flags |= SL_VID_VALID; 2012 bcopy(sli->sli_vid, sl->sl_vendor_id, 8); 2013 } 2014 if (sli->sli_flags & SLI_PID_VALID) { 2015 sl->sl_flags |= SL_PID_VALID; 2016 bcopy(sli->sli_pid, sl->sl_product_id, 16); 2017 } 2018 if (sli->sli_flags & SLI_REV_VALID) { 2019 sl->sl_flags |= SL_REV_VALID; 2020 bcopy(sli->sli_rev, sl->sl_revision, 4); 2021 } 2022 if (sli->sli_flags & SLI_WRITEBACK_CACHE_DISABLE) { 2023 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE; 2024 } 2025 sim_sli_loaded: 2026 if ((sl->sl_flags & SL_SHARED_META) == 0) { 2027 data_opened = 0; 2028 } else { 2029 data_opened = 1; 2030 sl->sl_data_filename = sl->sl_meta_filename; 2031 sl->sl_data_vp = sl->sl_meta_vp; 2032 sl->sl_data_vtype = sl->sl_meta_vtype; 2033 } 2034 2035 sret = sbd_pgr_meta_load(sl); 2036 if (sret != SBD_SUCCESS) { 2037 *err_ret = SBD_RET_NO_META; 2038 ret = EIO; 2039 goto sim_err_out; 2040 } 2041 2042 ret = sbd_open_data_file(sl, err_ret, 1, data_opened, 0); 2043 if (ret) 2044 goto sim_err_out; 2045 2046 /* 2047 * set write cache disable on the device 2048 * Note: this shouldn't fail on import unless the cache capabilities 2049 * of the device changed. If that happened, modify will need to 2050 * be used to set the cache flag appropriately after import is done. 2051 */ 2052 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) { 2053 (void) sbd_wcd_set(1, sl); 2054 wcd = 1; 2055 /* 2056 * if not explicitly set, attempt to set it to enable, if that fails 2057 * get the current setting and use that 2058 */ 2059 } else { 2060 sret = sbd_wcd_set(0, sl); 2061 if (sret != SBD_SUCCESS) { 2062 sbd_wcd_get(&wcd, sl); 2063 } 2064 } 2065 2066 if (wcd) { 2067 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE | 2068 SL_SAVED_WRITE_CACHE_DISABLE; 2069 } 2070 2071 /* we're only loading the metadata */ 2072 if (!no_register) { 2073 ret = sbd_populate_and_register_lu(sl, err_ret); 2074 if (ret) 2075 goto sim_err_out; 2076 atomic_add_32(&sbd_lu_count, 1); 2077 } 2078 2079 bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16); 2080 sl->sl_trans_op = SL_OP_NONE; 2081 if (sli) { 2082 kmem_free(sli, sli->sli_sms_header.sms_size); 2083 sli = NULL; 2084 } 2085 if (sli_buf_copy) { 2086 kmem_free(sli_buf_copy, sli_buf_sz + 1); 2087 sli_buf_copy = NULL; 2088 } 2089 if (no_register) { 2090 *slr = sl; 2091 } 2092 return (0); 2093 2094 sim_err_out: 2095 if (sli) { 2096 kmem_free(sli, sli->sli_sms_header.sms_size); 2097 sli = NULL; 2098 } 2099 if (sli_buf_copy) { 2100 kmem_free(sli_buf_copy, sli_buf_sz + 1); 2101 sli_buf_copy = NULL; 2102 } 2103 return (sbd_close_delete_lu(sl, ret)); 2104 } 2105 2106 int 2107 sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret) 2108 { 2109 sbd_lu_t *sl = NULL; 2110 uint16_t alias_sz; 2111 int ret = 0; 2112 sbd_it_data_t *it; 2113 sbd_status_t sret; 2114 uint64_t old_size; 2115 int modify_unregistered = 0; 2116 int ua = 0; 2117 sbd_import_lu_t *ilu; 2118 stmf_lu_t *lu; 2119 uint32_t ilu_sz; 2120 uint32_t sz; 2121 2122 sz = struct_sz - sizeof (*mlu) + 8 + 1; 2123 2124 /* if there is data in the buf, null terminate it */ 2125 if (struct_sz > sizeof (*mlu)) { 2126 mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0; 2127 } 2128 2129 *err_ret = 0; 2130 2131 /* Lets validate offsets */ 2132 if (((mlu->mlu_alias_valid) && 2133 (mlu->mlu_alias_off >= sz)) || 2134 ((mlu->mlu_mgmt_url_valid) && 2135 (mlu->mlu_mgmt_url_off >= sz)) || 2136 (mlu->mlu_by_fname) && 2137 (mlu->mlu_fname_off >= sz)) { 2138 return (EINVAL); 2139 } 2140 2141 /* 2142 * We'll look for the device but if we don't find it registered, 2143 * we'll still try to modify the unregistered device. 2144 */ 2145 if (mlu->mlu_by_guid) { 2146 sret = sbd_find_and_lock_lu(mlu->mlu_input_guid, NULL, 2147 SL_OP_MODIFY_LU, &sl); 2148 } else if (mlu->mlu_by_fname) { 2149 sret = sbd_find_and_lock_lu(NULL, 2150 (uint8_t *)&(mlu->mlu_buf[mlu->mlu_fname_off]), 2151 SL_OP_MODIFY_LU, &sl); 2152 } else { 2153 return (EINVAL); 2154 } 2155 2156 2157 if (sret != SBD_SUCCESS) { 2158 if (sret == SBD_BUSY) { 2159 *err_ret = SBD_RET_LU_BUSY; 2160 return (EBUSY); 2161 } else if (sret != SBD_NOT_FOUND) { 2162 return (EIO); 2163 } else if (!mlu->mlu_by_fname) { 2164 return (EINVAL); 2165 } 2166 /* Okay, try to import the device */ 2167 struct_sz = max(8, strlen(&(mlu->mlu_buf[mlu->mlu_fname_off])) 2168 + 1); 2169 struct_sz += sizeof (sbd_import_lu_t) - 8; 2170 ilu_sz = struct_sz; 2171 ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP); 2172 ilu->ilu_struct_size = struct_sz; 2173 (void) strcpy(ilu->ilu_meta_fname, 2174 &(mlu->mlu_buf[mlu->mlu_fname_off])); 2175 ret = sbd_import_lu(ilu, struct_sz, err_ret, 1, &sl); 2176 kmem_free(ilu, ilu_sz); 2177 if (ret != SBD_SUCCESS) { 2178 return (ENOENT); 2179 } 2180 modify_unregistered = 1; 2181 } 2182 2183 /* check for write cache change */ 2184 if (mlu->mlu_writeback_cache_disable_valid) { 2185 /* set wce on device */ 2186 sret = sbd_wcd_set(mlu->mlu_writeback_cache_disable, sl); 2187 if (!mlu->mlu_writeback_cache_disable && sret != SBD_SUCCESS) { 2188 *err_ret = SBD_RET_WRITE_CACHE_SET_FAILED; 2189 ret = EFAULT; 2190 goto smm_err_out; 2191 } 2192 mutex_enter(&sl->sl_lock); 2193 if (!mlu->mlu_writeback_cache_disable) { 2194 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) { 2195 ua = 1; 2196 sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE; 2197 sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE; 2198 } 2199 } else { 2200 if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) { 2201 ua = 1; 2202 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE; 2203 sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE; 2204 } 2205 } 2206 for (it = sl->sl_it_list; ua && it != NULL; 2207 it = it->sbd_it_next) { 2208 it->sbd_it_ua_conditions |= 2209 SBD_UA_MODE_PARAMETERS_CHANGED; 2210 } 2211 mutex_exit(&sl->sl_lock); 2212 } 2213 ua = 0; 2214 2215 if (mlu->mlu_alias_valid) { 2216 alias_sz = strlen((char *)mlu->mlu_buf + 2217 mlu->mlu_alias_off) + 1; 2218 /* 2219 * Use the allocated buffer or alloc a new one. 2220 * Don't copy into sl_alias if sl_alias_alloc_size is 0 2221 * otherwise or you'll be writing over the data/metadata 2222 * filename. 2223 */ 2224 mutex_enter(&sl->sl_lock); 2225 if (sl->sl_alias_alloc_size > 0 && 2226 sl->sl_alias_alloc_size < alias_sz) { 2227 kmem_free(sl->sl_alias, 2228 sl->sl_alias_alloc_size); 2229 sl->sl_alias_alloc_size = 0; 2230 } 2231 if (sl->sl_alias_alloc_size == 0) { 2232 sl->sl_alias = kmem_alloc(alias_sz, KM_SLEEP); 2233 sl->sl_alias_alloc_size = alias_sz; 2234 } 2235 (void) strcpy(sl->sl_alias, (char *)mlu->mlu_buf + 2236 mlu->mlu_alias_off); 2237 lu = sl->sl_lu; 2238 lu->lu_alias = sl->sl_alias; 2239 mutex_exit(&sl->sl_lock); 2240 } 2241 2242 if (mlu->mlu_mgmt_url_valid) { 2243 uint16_t url_sz; 2244 2245 url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off); 2246 if (url_sz > 0) 2247 url_sz++; 2248 2249 mutex_enter(&sl->sl_lock); 2250 if (sl->sl_mgmt_url_alloc_size > 0 && 2251 (url_sz == 0 || sl->sl_mgmt_url_alloc_size < url_sz)) { 2252 kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size); 2253 sl->sl_mgmt_url = NULL; 2254 sl->sl_mgmt_url_alloc_size = 0; 2255 } 2256 if (url_sz > 0) { 2257 if (sl->sl_mgmt_url_alloc_size == 0) { 2258 sl->sl_mgmt_url = kmem_alloc(url_sz, KM_SLEEP); 2259 sl->sl_mgmt_url_alloc_size = url_sz; 2260 } 2261 (void) strcpy(sl->sl_mgmt_url, (char *)mlu->mlu_buf + 2262 mlu->mlu_mgmt_url_off); 2263 } 2264 for (it = sl->sl_it_list; it != NULL; 2265 it = it->sbd_it_next) { 2266 it->sbd_it_ua_conditions |= 2267 SBD_UA_MODE_PARAMETERS_CHANGED; 2268 } 2269 mutex_exit(&sl->sl_lock); 2270 } 2271 2272 if (mlu->mlu_write_protected_valid) { 2273 mutex_enter(&sl->sl_lock); 2274 if (mlu->mlu_write_protected) { 2275 if ((sl->sl_flags & SL_WRITE_PROTECTED) == 0) { 2276 ua = 1; 2277 sl->sl_flags |= SL_WRITE_PROTECTED; 2278 } 2279 } else { 2280 if (sl->sl_flags & SL_WRITE_PROTECTED) { 2281 ua = 1; 2282 sl->sl_flags &= ~SL_WRITE_PROTECTED; 2283 } 2284 } 2285 for (it = sl->sl_it_list; ua && it != NULL; 2286 it = it->sbd_it_next) { 2287 it->sbd_it_ua_conditions |= 2288 SBD_UA_MODE_PARAMETERS_CHANGED; 2289 } 2290 mutex_exit(&sl->sl_lock); 2291 } 2292 2293 if (mlu->mlu_lu_size_valid) { 2294 /* 2295 * validate lu size and set 2296 * For open file only (registered lu) 2297 */ 2298 mutex_enter(&sl->sl_lock); 2299 old_size = sl->sl_lu_size; 2300 sl->sl_lu_size = mlu->mlu_lu_size; 2301 mutex_exit(&sl->sl_lock); 2302 ret = sbd_open_data_file(sl, err_ret, 1, 1, 1); 2303 if (ret) { 2304 mutex_enter(&sl->sl_lock); 2305 sl->sl_lu_size = old_size; 2306 mutex_exit(&sl->sl_lock); 2307 goto smm_err_out; 2308 } 2309 if (old_size != mlu->mlu_lu_size) { 2310 mutex_enter(&sl->sl_lock); 2311 for (it = sl->sl_it_list; it != NULL; 2312 it = it->sbd_it_next) { 2313 it->sbd_it_ua_conditions |= 2314 SBD_UA_CAPACITY_CHANGED; 2315 } 2316 mutex_exit(&sl->sl_lock); 2317 } 2318 } 2319 2320 if (sbd_write_lu_info(sl) != SBD_SUCCESS) { 2321 *err_ret = SBD_RET_META_CREATION_FAILED; 2322 ret = EIO; 2323 } 2324 2325 smm_err_out: 2326 if (modify_unregistered) { 2327 (void) sbd_close_delete_lu(sl, 0); 2328 } else { 2329 sl->sl_trans_op = SL_OP_NONE; 2330 } 2331 return (ret); 2332 } 2333 2334 /* ARGSUSED */ 2335 int 2336 sbd_delete_locked_lu(sbd_lu_t *sl, uint32_t *err_ret, 2337 stmf_state_change_info_t *ssi) 2338 { 2339 int i; 2340 2341 if ((sl->sl_state == STMF_STATE_OFFLINE) && 2342 !sl->sl_state_not_acked) { 2343 goto sdl_do_dereg; 2344 } 2345 2346 if ((sl->sl_state != STMF_STATE_ONLINE) || 2347 sl->sl_state_not_acked) { 2348 return (EBUSY); 2349 } 2350 if (stmf_ctl(STMF_CMD_LU_OFFLINE, sl->sl_lu, ssi) != STMF_SUCCESS) { 2351 return (EBUSY); 2352 } 2353 2354 for (i = 0; i < 500; i++) { 2355 if (sl->sl_state == STMF_STATE_OFFLINE) 2356 break; 2357 delay(drv_usectohz(10000)); 2358 } 2359 2360 if ((sl->sl_state == STMF_STATE_OFFLINE) && 2361 !sl->sl_state_not_acked) { 2362 goto sdl_do_dereg; 2363 } 2364 2365 return (EBUSY); 2366 sdl_do_dereg:; 2367 if (stmf_deregister_lu(sl->sl_lu) != STMF_SUCCESS) 2368 return (EBUSY); 2369 atomic_add_32(&sbd_lu_count, -1); 2370 2371 return (sbd_close_delete_lu(sl, 0)); 2372 } 2373 2374 int 2375 sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret) 2376 { 2377 sbd_lu_t *sl; 2378 sbd_status_t sret; 2379 stmf_state_change_info_t ssi; 2380 int ret; 2381 2382 if (dlu->dlu_by_meta_name) { 2383 ((char *)dlu)[struct_sz - 1] = 0; 2384 sret = sbd_find_and_lock_lu(NULL, dlu->dlu_meta_name, 2385 SL_OP_DELETE_LU, &sl); 2386 } else { 2387 sret = sbd_find_and_lock_lu(dlu->dlu_guid, NULL, 2388 SL_OP_DELETE_LU, &sl); 2389 } 2390 if (sret != SBD_SUCCESS) { 2391 if (sret == SBD_BUSY) { 2392 *err_ret = SBD_RET_LU_BUSY; 2393 return (EBUSY); 2394 } else if (sret == SBD_NOT_FOUND) { 2395 *err_ret = SBD_RET_NOT_FOUND; 2396 return (ENOENT); 2397 } 2398 return (EIO); 2399 } 2400 2401 ssi.st_rflags = STMF_RFLAG_USER_REQUEST; 2402 ssi.st_additional_info = "sbd_delete_lu call (ioctl)"; 2403 ret = sbd_delete_locked_lu(sl, err_ret, &ssi); 2404 2405 if (ret) { 2406 /* Once its locked, no need to grab mutex again */ 2407 sl->sl_trans_op = SL_OP_NONE; 2408 } 2409 return (ret); 2410 } 2411 2412 sbd_status_t 2413 sbd_data_read(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf) 2414 { 2415 int ret; 2416 long resid; 2417 2418 if ((offset + size) > sl->sl_lu_size) { 2419 return (SBD_IO_PAST_EOF); 2420 } 2421 2422 offset += sl->sl_data_offset; 2423 2424 if ((offset + size) > sl->sl_data_readable_size) { 2425 uint64_t store_end; 2426 if (offset > sl->sl_data_readable_size) { 2427 bzero(buf, size); 2428 return (SBD_SUCCESS); 2429 } 2430 store_end = sl->sl_data_readable_size - offset; 2431 bzero(buf + store_end, size - store_end); 2432 size = store_end; 2433 } 2434 2435 DTRACE_PROBE4(backing__store__read__start, sbd_lu_t *, sl, 2436 uint8_t *, buf, uint64_t, size, uint64_t, offset); 2437 2438 ret = vn_rdwr(UIO_READ, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size, 2439 (offset_t)offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, CRED(), 2440 &resid); 2441 2442 DTRACE_PROBE5(backing__store__read__end, sbd_lu_t *, sl, 2443 uint8_t *, buf, uint64_t, size, uint64_t, offset, 2444 int, ret); 2445 2446 over_sl_data_read: 2447 if (ret || resid) { 2448 stmf_trace(0, "UIO_READ failed, ret = %d, resid = %d", ret, 2449 resid); 2450 return (SBD_FAILURE); 2451 } 2452 2453 return (SBD_SUCCESS); 2454 } 2455 2456 sbd_status_t 2457 sbd_data_write(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf) 2458 { 2459 int ret; 2460 long resid; 2461 sbd_status_t sret = SBD_SUCCESS; 2462 int ioflag; 2463 2464 if ((offset + size) > sl->sl_lu_size) { 2465 return (SBD_IO_PAST_EOF); 2466 } 2467 2468 offset += sl->sl_data_offset; 2469 2470 if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) && 2471 (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) { 2472 ioflag = FSYNC; 2473 } else { 2474 ioflag = 0; 2475 } 2476 2477 DTRACE_PROBE4(backing__store__write__start, sbd_lu_t *, sl, 2478 uint8_t *, buf, uint64_t, size, uint64_t, offset); 2479 2480 ret = vn_rdwr(UIO_WRITE, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size, 2481 (offset_t)offset, UIO_SYSSPACE, ioflag, RLIM64_INFINITY, CRED(), 2482 &resid); 2483 2484 DTRACE_PROBE5(backing__store__write__end, sbd_lu_t *, sl, 2485 uint8_t *, buf, uint64_t, size, uint64_t, offset, 2486 int, ret); 2487 2488 if ((ret == 0) && (resid == 0) && 2489 (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) && 2490 (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) { 2491 sret = sbd_flush_data_cache(sl, 1); 2492 } 2493 over_sl_data_write: 2494 2495 if ((ret || resid) || (sret != SBD_SUCCESS)) { 2496 return (SBD_FAILURE); 2497 } else if ((offset + size) > sl->sl_data_readable_size) { 2498 uint64_t old_size, new_size; 2499 2500 do { 2501 old_size = sl->sl_data_readable_size; 2502 if ((offset + size) <= old_size) 2503 break; 2504 new_size = offset + size; 2505 } while (atomic_cas_64(&sl->sl_data_readable_size, old_size, 2506 new_size) != old_size); 2507 } 2508 2509 return (SBD_SUCCESS); 2510 } 2511 2512 int 2513 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz, 2514 sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret) 2515 { 2516 sbd_status_t sret; 2517 sbd_lu_t *sl = NULL; 2518 uint32_t sz; 2519 uint16_t off; 2520 2521 if (islp->slp_input_guid) { 2522 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL, 2523 SL_OP_LU_PROPS, &sl); 2524 } else { 2525 ((char *)islp)[islp_sz - 1] = 0; 2526 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf, 2527 SL_OP_LU_PROPS, &sl); 2528 } 2529 if (sret != SBD_SUCCESS) { 2530 if (sret == SBD_BUSY) { 2531 *err_ret = SBD_RET_LU_BUSY; 2532 return (EBUSY); 2533 } else if (sret == SBD_NOT_FOUND) { 2534 *err_ret = SBD_RET_NOT_FOUND; 2535 return (ENOENT); 2536 } 2537 return (EIO); 2538 } 2539 2540 sz = strlen(sl->sl_name) + 1; 2541 if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) { 2542 if (sl->sl_data_filename) { 2543 sz += strlen(sl->sl_data_filename) + 1; 2544 } 2545 } 2546 sz += sl->sl_serial_no_size; 2547 if (sl->sl_alias) { 2548 sz += strlen(sl->sl_alias) + 1; 2549 } 2550 2551 if (sl->sl_mgmt_url) { 2552 sz += strlen(sl->sl_mgmt_url) + 1; 2553 } 2554 bzero(oslp, sizeof (*oslp) - 8); 2555 oslp->slp_buf_size_needed = sz; 2556 2557 if (sz > (oslp_sz - sizeof (*oslp) + 8)) { 2558 sl->sl_trans_op = SL_OP_NONE; 2559 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE; 2560 return (ENOMEM); 2561 } 2562 2563 off = 0; 2564 (void) strcpy((char *)oslp->slp_buf, sl->sl_name); 2565 oslp->slp_meta_fname_off = off; 2566 off += strlen(sl->sl_name) + 1; 2567 if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) { 2568 oslp->slp_meta_fname_valid = 1; 2569 oslp->slp_separate_meta = 1; 2570 if (sl->sl_data_filename) { 2571 oslp->slp_data_fname_valid = 1; 2572 oslp->slp_data_fname_off = off; 2573 (void) strcpy((char *)&oslp->slp_buf[off], 2574 sl->sl_data_filename); 2575 off += strlen(sl->sl_data_filename) + 1; 2576 } 2577 } else { 2578 oslp->slp_data_fname_valid = 1; 2579 oslp->slp_data_fname_off = oslp->slp_meta_fname_off; 2580 if (sl->sl_flags & SL_ZFS_META) { 2581 oslp->slp_zfs_meta = 1; 2582 } 2583 } 2584 if (sl->sl_alias) { 2585 oslp->slp_alias_valid = 1; 2586 oslp->slp_alias_off = off; 2587 (void) strcpy((char *)&oslp->slp_buf[off], sl->sl_alias); 2588 off += strlen(sl->sl_alias) + 1; 2589 } 2590 if (sl->sl_mgmt_url) { 2591 oslp->slp_mgmt_url_valid = 1; 2592 oslp->slp_mgmt_url_off = off; 2593 (void) strcpy((char *)&oslp->slp_buf[off], sl->sl_mgmt_url); 2594 off += strlen(sl->sl_mgmt_url) + 1; 2595 } 2596 if (sl->sl_serial_no_size) { 2597 oslp->slp_serial_off = off; 2598 bcopy(sl->sl_serial_no, &oslp->slp_buf[off], 2599 sl->sl_serial_no_size); 2600 oslp->slp_serial_size = sl->sl_serial_no_size; 2601 oslp->slp_serial_valid = 1; 2602 off += sl->sl_serial_no_size; 2603 } 2604 2605 oslp->slp_lu_size = sl->sl_lu_size; 2606 oslp->slp_blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift; 2607 2608 if (sl->sl_flags & SL_VID_VALID) { 2609 oslp->slp_lu_vid = 1; 2610 bcopy(sl->sl_vendor_id, oslp->slp_vid, 8); 2611 } else { 2612 bcopy(sbd_vendor_id, oslp->slp_vid, 8); 2613 } 2614 if (sl->sl_flags & SL_PID_VALID) { 2615 oslp->slp_lu_pid = 1; 2616 bcopy(sl->sl_product_id, oslp->slp_pid, 16); 2617 } else { 2618 bcopy(sbd_product_id, oslp->slp_pid, 16); 2619 } 2620 if (sl->sl_flags & SL_REV_VALID) { 2621 oslp->slp_lu_rev = 1; 2622 bcopy(sl->sl_revision, oslp->slp_rev, 4); 2623 } else { 2624 bcopy(sbd_revision, oslp->slp_rev, 4); 2625 } 2626 bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16); 2627 2628 if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) 2629 oslp->slp_writeback_cache_disable_cur = 1; 2630 if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) 2631 oslp->slp_writeback_cache_disable_saved = 1; 2632 if (sl->sl_flags & SL_WRITE_PROTECTED) 2633 oslp->slp_write_protected = 1; 2634 2635 sl->sl_trans_op = SL_OP_NONE; 2636 2637 return (0); 2638 } 2639 2640 char * 2641 sbd_get_zvol_name(sbd_lu_t *sl) 2642 { 2643 char *src; 2644 char *p; 2645 2646 if (sl->sl_data_filename) 2647 src = sl->sl_data_filename; 2648 else 2649 src = sl->sl_meta_filename; 2650 /* There has to be a better way */ 2651 if (SBD_IS_ZVOL(src) != 0) { 2652 ASSERT(0); 2653 } 2654 src += 14; 2655 if (*src == '/') 2656 src++; 2657 p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP); 2658 (void) strcpy(p, src); 2659 return (p); 2660 } 2661 2662 /* 2663 * this function creates a local metadata zvol property 2664 */ 2665 sbd_status_t 2666 sbd_create_zfs_meta_object(sbd_lu_t *sl) 2667 { 2668 /* 2669 * -allocate 1/2 the property size, the zfs property 2670 * is 8k in size and stored as ascii hex string, all 2671 * we needed is 4k buffer to store the binary data. 2672 * -initialize reader/write lock 2673 */ 2674 if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP)) 2675 == NULL) 2676 return (SBD_FAILURE); 2677 rw_init(&sl->sl_zfs_meta_lock, NULL, RW_DRIVER, NULL); 2678 return (SBD_SUCCESS); 2679 } 2680 2681 char 2682 sbd_ctoi(char c) 2683 { 2684 if ((c >= '0') && (c <= '9')) 2685 c -= '0'; 2686 else if ((c >= 'A') && (c <= 'F')) 2687 c = c - 'A' + 10; 2688 else if ((c >= 'a') && (c <= 'f')) 2689 c = c - 'a' + 10; 2690 else 2691 c = -1; 2692 return (c); 2693 } 2694 2695 /* 2696 * read zvol property and convert to binary 2697 */ 2698 sbd_status_t 2699 sbd_open_zfs_meta(sbd_lu_t *sl) 2700 { 2701 char *meta = NULL, cl, ch; 2702 int i; 2703 char *tmp, *ptr; 2704 uint64_t rc = SBD_SUCCESS; 2705 int len; 2706 char *file; 2707 2708 if (sl->sl_zfs_meta == NULL) { 2709 if (sbd_create_zfs_meta_object(sl) == SBD_FAILURE) 2710 return (SBD_FAILURE); 2711 } else { 2712 bzero(sl->sl_zfs_meta, (ZAP_MAXVALUELEN / 2)); 2713 } 2714 2715 rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER); 2716 file = sbd_get_zvol_name(sl); 2717 if (sbd_zvolget(file, &meta)) { 2718 rc = SBD_FAILURE; 2719 goto done; 2720 } 2721 tmp = meta; 2722 /* convert ascii hex to binary meta */ 2723 len = strlen(meta); 2724 ptr = sl->sl_zfs_meta; 2725 for (i = 0; i < len; i += 2) { 2726 ch = sbd_ctoi(*tmp++); 2727 cl = sbd_ctoi(*tmp++); 2728 if (ch == -1 || cl == -1) { 2729 rc = SBD_FAILURE; 2730 break; 2731 } 2732 *ptr++ = (ch << 4) + cl; 2733 } 2734 done: 2735 rw_exit(&sl->sl_zfs_meta_lock); 2736 if (meta) 2737 kmem_free(meta, len + 1); 2738 kmem_free(file, strlen(file) + 1); 2739 return (rc); 2740 } 2741 2742 sbd_status_t 2743 sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off) 2744 { 2745 ASSERT(sl->sl_zfs_meta); 2746 rw_enter(&sl->sl_zfs_meta_lock, RW_READER); 2747 bcopy(&sl->sl_zfs_meta[off], buf, sz); 2748 rw_exit(&sl->sl_zfs_meta_lock); 2749 return (SBD_SUCCESS); 2750 } 2751 2752 sbd_status_t 2753 sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off) 2754 { 2755 char *ptr, *ah_meta; 2756 char *dp = NULL; 2757 int i, num; 2758 char *file; 2759 2760 ASSERT(sl->sl_zfs_meta); 2761 if ((off + sz) > (ZAP_MAXVALUELEN / 2 - 1)) { 2762 return (SBD_META_CORRUPTED); 2763 } 2764 if ((off + sz) > sl->sl_meta_size_used) { 2765 sl->sl_meta_size_used = off + sz; 2766 if (sl->sl_total_meta_size < sl->sl_meta_size_used) { 2767 uint64_t meta_align = 2768 (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1; 2769 sl->sl_total_meta_size = (sl->sl_meta_size_used + 2770 meta_align) & (~meta_align); 2771 } 2772 } 2773 ptr = ah_meta = kmem_zalloc(ZAP_MAXVALUELEN, KM_SLEEP); 2774 rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER); 2775 bcopy(buf, &sl->sl_zfs_meta[off], sz); 2776 /* convert local copy to ascii hex */ 2777 dp = sl->sl_zfs_meta; 2778 for (i = 0; i < sl->sl_total_meta_size; i++, dp++) { 2779 num = ((*dp) >> 4) & 0xF; 2780 *ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10)); 2781 num = (*dp) & 0xF; 2782 *ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10)); 2783 } 2784 *ah_meta = NULL; 2785 file = sbd_get_zvol_name(sl); 2786 if (sbd_zvolset(file, (char *)ptr)) { 2787 rw_exit(&sl->sl_zfs_meta_lock); 2788 kmem_free(ptr, ZAP_MAXVALUELEN); 2789 kmem_free(file, strlen(file) + 1); 2790 return (SBD_META_CORRUPTED); 2791 } 2792 rw_exit(&sl->sl_zfs_meta_lock); 2793 kmem_free(ptr, ZAP_MAXVALUELEN); 2794 kmem_free(file, strlen(file) + 1); 2795 return (SBD_SUCCESS); 2796 } 2797 2798 int 2799 sbd_is_zvol(char *path) 2800 { 2801 int is_zfs = 0; 2802 2803 if (SBD_IS_ZVOL(path) == 0) 2804 is_zfs = 1; 2805 2806 return (is_zfs); 2807 } 2808 2809 /* 2810 * set write cache disable 2811 * wcd - 1 = disable, 0 = enable 2812 */ 2813 sbd_status_t 2814 sbd_wcd_set(int wcd, sbd_lu_t *sl) 2815 { 2816 /* translate to wce bit */ 2817 int wce = wcd ? 0 : 1; 2818 int ret; 2819 sbd_status_t sret = SBD_SUCCESS; 2820 2821 mutex_enter(&sl->sl_lock); 2822 sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED; 2823 2824 if (sl->sl_data_vp->v_type == VREG) { 2825 sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE; 2826 goto done; 2827 } 2828 2829 ret = VOP_IOCTL(sl->sl_data_vp, DKIOCSETWCE, (intptr_t)&wce, FKIOCTL, 2830 kcred, NULL, NULL); 2831 if (ret == 0) { 2832 sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED; 2833 sl->sl_flags &= ~SL_FLUSH_ON_DISABLED_WRITECACHE; 2834 } else { 2835 sl->sl_flags |= SL_WRITEBACK_CACHE_SET_UNSUPPORTED; 2836 sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE; 2837 sret = SBD_FAILURE; 2838 goto done; 2839 } 2840 2841 done: 2842 mutex_exit(&sl->sl_lock); 2843 return (sret); 2844 } 2845 2846 /* 2847 * get write cache disable 2848 * wcd - 1 = disable, 0 = enable 2849 */ 2850 void 2851 sbd_wcd_get(int *wcd, sbd_lu_t *sl) 2852 { 2853 int wce; 2854 int ret; 2855 2856 if (sl->sl_data_vp->v_type == VREG) { 2857 *wcd = 0; 2858 return; 2859 } 2860 2861 ret = VOP_IOCTL(sl->sl_data_vp, DKIOCGETWCE, (intptr_t)&wce, FKIOCTL, 2862 kcred, NULL, NULL); 2863 /* if write cache get failed, assume disabled */ 2864 if (ret) { 2865 *wcd = 1; 2866 } else { 2867 /* translate to wcd bit */ 2868 *wcd = wce ? 0 : 1; 2869 } 2870 } 2871 2872 int 2873 sbd_zvolget(char *zvol_name, char **comstarprop) 2874 { 2875 ldi_handle_t zfs_lh; 2876 nvlist_t *nv = NULL, *nv2; 2877 zfs_cmd_t *zc; 2878 char *ptr; 2879 int size = 1024; 2880 int unused; 2881 int rc; 2882 2883 if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred, 2884 &zfs_lh, sbd_zfs_ident)) != 0) { 2885 cmn_err(CE_WARN, "ldi_open %d", rc); 2886 return (ENXIO); 2887 } 2888 2889 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2890 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name)); 2891 again: 2892 zc->zc_nvlist_dst = (uint64_t)(intptr_t)kmem_alloc(size, 2893 KM_SLEEP); 2894 zc->zc_nvlist_dst_size = size; 2895 rc = ldi_ioctl(zfs_lh, ZFS_IOC_OBJSET_STATS, (intptr_t)zc, 2896 FKIOCTL, kcred, &unused); 2897 /* 2898 * ENOMEM means the list is larger than what we've allocated 2899 * ldi_ioctl will fail with ENOMEM only once 2900 */ 2901 if (rc == ENOMEM) { 2902 int newsize; 2903 newsize = zc->zc_nvlist_dst_size; 2904 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size); 2905 size = newsize; 2906 goto again; 2907 } else if (rc != 0) { 2908 goto out; 2909 } 2910 rc = nvlist_unpack((char *)(uintptr_t)zc->zc_nvlist_dst, 2911 zc->zc_nvlist_dst_size, &nv, 0); 2912 ASSERT(rc == 0); /* nvlist_unpack should not fail */ 2913 if ((rc = nvlist_lookup_nvlist(nv, "stmf_sbd_lu", &nv2)) == 0) { 2914 rc = nvlist_lookup_string(nv2, ZPROP_VALUE, &ptr); 2915 if (rc != 0) { 2916 cmn_err(CE_WARN, "couldn't get value"); 2917 } else { 2918 *comstarprop = kmem_alloc(strlen(ptr) + 1, 2919 KM_SLEEP); 2920 (void) strcpy(*comstarprop, ptr); 2921 } 2922 } 2923 out: 2924 if (nv != NULL) 2925 nvlist_free(nv); 2926 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size); 2927 kmem_free(zc, sizeof (zfs_cmd_t)); 2928 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred); 2929 2930 return (rc); 2931 } 2932 2933 int 2934 sbd_zvolset(char *zvol_name, char *comstarprop) 2935 { 2936 ldi_handle_t zfs_lh; 2937 nvlist_t *nv; 2938 char *packed = NULL; 2939 size_t len; 2940 zfs_cmd_t *zc; 2941 int unused; 2942 int rc; 2943 2944 if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred, 2945 &zfs_lh, sbd_zfs_ident)) != 0) { 2946 cmn_err(CE_WARN, "ldi_open %d", rc); 2947 return (ENXIO); 2948 } 2949 (void) nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP); 2950 (void) nvlist_add_string(nv, "stmf_sbd_lu", comstarprop); 2951 if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) { 2952 goto out; 2953 } 2954 2955 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2956 (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name)); 2957 zc->zc_nvlist_src = (uint64_t)(intptr_t)packed; 2958 zc->zc_nvlist_src_size = len; 2959 rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc, 2960 FKIOCTL, kcred, &unused); 2961 if (rc != 0) { 2962 cmn_err(CE_NOTE, "ioctl failed %d", rc); 2963 } 2964 kmem_free(zc, sizeof (zfs_cmd_t)); 2965 if (packed) 2966 kmem_free(packed, len); 2967 out: 2968 nvlist_free(nv); 2969 (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred); 2970 return (rc); 2971 } 2972