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