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