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