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