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