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