1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #define _DSW_ 27 28 #include <sys/types.h> 29 #include <sys/ksynch.h> 30 #include <sys/kmem.h> 31 #include <sys/errno.h> 32 #include <sys/conf.h> 33 #include <sys/cmn_err.h> 34 #include <sys/modctl.h> 35 #include <sys/cred.h> 36 #include <sys/file.h> 37 #include <sys/ddi.h> 38 #include <sys/unistat/spcs_s.h> 39 #include <sys/dkio.h> 40 41 #ifdef DS_DDICT 42 #include "../contract.h" 43 #endif 44 45 #include <sys/nsctl/nsctl.h> 46 #include <sys/nsctl/nsvers.h> 47 48 #include <sys/sdt.h> /* dtrace is S10 or later */ 49 50 #include "dsw.h" 51 #include "dsw_dev.h" 52 53 #define DIDINIT 0x01 54 #define DIDNODES 0x02 55 56 57 static int iiopen(dev_t *devp, int flag, int otyp, cred_t *crp); 58 static int iiclose(dev_t dev, int flag, int otyp, cred_t *crp); 59 static int iiprint(dev_t dev, char *str); 60 static int iiioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, 61 int *rvp); 62 static int iiprobe(dev_info_t *dip); 63 static int iiattach(dev_info_t *dip, ddi_attach_cmd_t cmd); 64 static int iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd); 65 static int iistrat(struct buf *); 66 static int iiread(); 67 68 69 static kstat_t *ii_gkstat = NULL; 70 iigkstat_t iigkstat = { 71 { "ii_debug", KSTAT_DATA_ULONG }, 72 { "ii_bitmap", KSTAT_DATA_ULONG }, 73 { "ii_throttle_unit", KSTAT_DATA_ULONG }, 74 { "ii_throttle_delay", KSTAT_DATA_ULONG }, 75 { "ii_copy_direct", KSTAT_DATA_ULONG }, 76 { "num-sets", KSTAT_DATA_ULONG }, 77 { "assoc-over", KSTAT_DATA_ULONG }, 78 { "spilled-over", KSTAT_DATA_ULONG }, 79 }; 80 81 static struct cb_ops ii_cb_ops = { 82 iiopen, 83 iiclose, 84 iistrat, /* dummy strategy */ 85 iiprint, 86 nodev, /* no dump */ 87 iiread, /* dummy read */ 88 nodev, /* no write */ 89 iiioctl, 90 nodev, /* no devmap */ 91 nodev, /* no mmap */ 92 nodev, /* no segmap */ 93 nochpoll, 94 ddi_prop_op, 95 NULL, /* not STREAMS */ 96 D_NEW | D_MP 97 }; 98 99 static struct dev_ops ii_ops = { 100 DEVO_REV, 101 0, 102 nodev, /* no getinfo */ 103 nulldev, 104 iiprobe, 105 iiattach, 106 iidetach, 107 nodev, /* no reset */ 108 &ii_cb_ops, 109 (struct bus_ops *)NULL 110 }; 111 112 static struct modldrv ii_ldrv = { 113 &mod_driverops, 114 "nws:Point-in-Time:" ISS_VERSION_STR, 115 &ii_ops 116 }; 117 118 static struct modlinkage ii_modlinkage = { 119 MODREV_1, 120 &ii_ldrv, 121 NULL 122 }; 123 124 struct ii_state { 125 dev_info_t *dip; 126 int instance; 127 }; 128 129 /* used for logging sysevent, gets set in _ii_attach */ 130 dev_info_t *ii_dip = NULL; 131 132 extern _ii_info_t *_ii_info_top; 133 extern _ii_lsthead_t *_ii_cluster_top; 134 extern _ii_lsthead_t *_ii_group_top; 135 extern kmutex_t _ii_cluster_mutex; 136 extern kmutex_t _ii_group_mutex; 137 138 const int dsw_major_rev = ISS_VERSION_MAJ; /* Major release number */ 139 const int dsw_minor_rev = ISS_VERSION_MIN; /* Minor release number */ 140 const int dsw_micro_rev = ISS_VERSION_MIC; /* Micro release number */ 141 const int dsw_baseline_rev = ISS_VERSION_NUM; /* Baseline revision */ 142 static void *ii_statep; 143 144 extern int _ii_init_dev(); 145 extern void _ii_deinit_dev(); 146 extern int _ii_config(intptr_t arg, int ilp32, int *rvp, int iflags); 147 extern int _ii_disable(intptr_t arg, int ilp32, int *rvp); 148 extern int _ii_suspend(intptr_t arg, int ilp32, int *rvp); 149 extern int _ii_bitmap(intptr_t arg, int ilp32, int *rvp); 150 extern int _ii_segment(intptr_t arg, int ilp32, int *rvp); 151 extern int _ii_abort(intptr_t arg, int ilp32, int *rvp); 152 extern int _ii_acopy(intptr_t arg, int ilp32, int *rvp); 153 extern int _ii_copy(intptr_t arg, int ilp32, int *rvp); 154 extern int _ii_shutdown(intptr_t arg, int *rvp); 155 extern int _ii_stat(intptr_t arg, int ilp32, int *rvp); 156 extern int _ii_version(intptr_t arg, int ilp32, int *rvp); 157 extern int _ii_wait(intptr_t arg, int ilp32, int *rvp); 158 extern int _ii_reset(intptr_t arg, int ilp32, int *rvp); 159 extern int _ii_offline(intptr_t arg, int ilp32, int *rvp); 160 extern int _ii_list(intptr_t arg, int ilp32, int *rvp); 161 extern int _ii_listlen(int cmd, int ilp32, int *rvp); 162 extern int _ii_export(intptr_t arg, int ilp32, int *rvp); 163 extern int _ii_join(intptr_t arg, int ilp32, int *rvp); 164 extern int _ii_copyparm(intptr_t arg, int ilp32, int *rvp); 165 extern int _ii_ocreate(intptr_t arg, int ilp32, int *rvp); 166 extern int _ii_oattach(intptr_t arg, int ilp32, int *rvp); 167 extern int _ii_odetach(intptr_t arg, int ilp32, int *rvp); 168 extern int _ii_olist(intptr_t arg, int ilp32, int *rvp); 169 extern int _ii_ostat(intptr_t arg, int ilp32, int *rvp, int is_iost_2); 170 extern int _ii_bitsset(intptr_t arg, int ilp32, int cmd, int *rvp); 171 extern int _ii_gc_list(intptr_t, int, int *, kmutex_t *, _ii_lsthead_t *); 172 extern int _ii_clist(intptr_t arg, int ilp32, int *rvp); 173 extern int _ii_move_grp(intptr_t arg, int ilp32, int *rvp); 174 extern int _ii_change_tag(intptr_t arg, int ilp32, int *rvp); 175 extern int ii_debug; 176 extern int ii_throttle_unit; 177 extern int ii_throttle_delay; 178 extern int ii_copy_direct; 179 extern int ii_bitmap; 180 181 int 182 _init(void) 183 { 184 int error; 185 186 error = ddi_soft_state_init(&ii_statep, sizeof (struct ii_state), 1); 187 if (!error) { 188 error = mod_install(&ii_modlinkage); 189 if (error) 190 ddi_soft_state_fini(&ii_statep); 191 } 192 193 return (error); 194 } 195 196 int 197 _fini(void) 198 { 199 int error; 200 201 error = mod_remove(&ii_modlinkage); 202 if (!error) 203 ddi_soft_state_fini(&ii_statep); 204 205 return (error); 206 } 207 208 int 209 _info(struct modinfo *modinfop) 210 { 211 int rc; 212 213 rc = mod_info(&ii_modlinkage, modinfop); 214 215 return (rc); 216 } 217 218 /* ARGSUSED */ 219 220 static int 221 iiprobe(dev_info_t *dip) 222 { 223 return (DDI_PROBE_SUCCESS); 224 } 225 226 /*ARGSUSED*/ 227 static int 228 ii_stats_update(kstat_t *ksp, int rw) 229 { 230 if (KSTAT_WRITE == rw) { 231 return (EACCES); 232 } 233 234 /* 235 * We do nothing here for now -- the kstat structure is 236 * updated in-place 237 */ 238 239 return (0); 240 } 241 242 static void 243 ii_create_kstats() 244 { 245 /* create global info structure */ 246 if (!ii_gkstat) { 247 ii_gkstat = kstat_create("ii", 0, "global", "StorEdge", 248 KSTAT_TYPE_NAMED, 249 sizeof (iigkstat) / sizeof (kstat_named_t), 250 KSTAT_FLAG_VIRTUAL); 251 if (ii_gkstat) { 252 ii_gkstat->ks_data = &iigkstat; 253 ii_gkstat->ks_update = ii_stats_update; 254 ii_gkstat->ks_private = 0; 255 kstat_install(ii_gkstat); 256 257 /* fill in immutable values */ 258 iigkstat.ii_debug.value.ul = ii_debug; 259 iigkstat.ii_bitmap.value.ul = ii_bitmap; 260 iigkstat.ii_throttle_unit.value.ul = ii_throttle_unit; 261 iigkstat.ii_throttle_delay.value.ul = 262 ii_throttle_delay; 263 iigkstat.ii_copy_direct.value.ul = ii_copy_direct; 264 } else { 265 cmn_err(CE_WARN, "!Unable to create II global stats"); 266 } 267 } 268 } 269 270 static int 271 iiattach(dev_info_t *dip, ddi_attach_cmd_t cmd) 272 { 273 struct ii_state *xsp; 274 int instance; 275 int i; 276 intptr_t flags; 277 278 if (cmd != DDI_ATTACH) { 279 return (DDI_FAILURE); 280 } 281 /* save the dev_info_t to be used in logging using ddi_log_sysevent */ 282 ii_dip = dip; 283 284 instance = ddi_get_instance(dip); 285 if (ddi_soft_state_zalloc(ii_statep, instance) != 0) { 286 cmn_err(CE_WARN, "!ii: no memory for instance %d state.", 287 instance); 288 return (DDI_FAILURE); 289 } 290 291 flags = 0; 292 xsp = ddi_get_soft_state(ii_statep, instance); 293 if (xsp == NULL) { 294 cmn_err(CE_WARN, 295 "!ii: attach: could not get state for instance %d.", 296 instance); 297 goto out; 298 } 299 300 ii_debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 301 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_debug", 0); 302 if (ii_debug != 0) { 303 #ifdef DEBUG 304 cmn_err(CE_NOTE, "!ii: initializing ii version %d.%d.%d.%d", 305 dsw_major_rev, dsw_minor_rev, 306 dsw_micro_rev, dsw_baseline_rev); 307 #else 308 if (dsw_micro_rev) { 309 cmn_err(CE_NOTE, "!ii: initializing ii vers %d.%d.%d", 310 dsw_major_rev, dsw_minor_rev, dsw_micro_rev); 311 } else { 312 cmn_err(CE_NOTE, "!ii: initializing ii version %d.%d", 313 dsw_major_rev, dsw_minor_rev); 314 } 315 #endif 316 switch (ii_debug) { 317 case 1: 318 case 2: cmn_err(CE_NOTE, 319 "!ii: ii_debug=%d is enabled.", ii_debug); 320 break; 321 default: 322 cmn_err(CE_WARN, 323 "!ii: Value of ii_debug=%d is not 0,1 or 2.", 324 ii_debug); 325 } 326 } 327 328 ii_bitmap = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 329 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_bitmap", II_WTHRU); 330 switch (ii_bitmap) { 331 case II_KMEM: 332 if (ii_debug > 0) 333 cmn_err(CE_NOTE, "!ii: ii_bitmap is in memory"); 334 break; 335 case II_FWC: 336 if (ii_debug > 0) 337 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk," 338 " no FWC"); 339 break; 340 case II_WTHRU: 341 if (ii_debug > 0) 342 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk"); 343 break; 344 default: 345 cmn_err(CE_NOTE, 346 "!ii: ii_bitmap=%d out of range; " 347 "defaulting WTHRU(%d)", ii_bitmap, II_WTHRU); 348 ii_bitmap = II_WTHRU; 349 } 350 351 /* pick up these values if in ii.conf, otherwise leave alone */ 352 i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 353 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_unit", 0); 354 if (i > 0) { 355 ii_throttle_unit = i; 356 if ((ii_throttle_unit < MIN_THROTTLE_UNIT) || 357 (ii_throttle_unit > MAX_THROTTLE_UNIT) || 358 (ii_debug > 0)) 359 cmn_err(CE_NOTE, 360 "!ii: ii_throttle_unit=%d", ii_throttle_unit); 361 } 362 363 i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 364 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_delay", 0); 365 if (i > 0) { 366 ii_throttle_delay = i; 367 if ((ii_throttle_delay < MIN_THROTTLE_DELAY) || 368 (ii_throttle_delay > MIN_THROTTLE_DELAY) || 369 (ii_debug > 0)) 370 cmn_err(CE_NOTE, 371 "!ii: ii_throttle_delay=%d", ii_throttle_delay); 372 } 373 374 ii_copy_direct = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 375 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_copy_direct", 1); 376 if (i > 0) { 377 ii_copy_direct = i; 378 if ((ii_copy_direct < 0) || (ii_copy_direct > 1)) 379 cmn_err(CE_NOTE, 380 "!ii: ii_copy_direct=%d", ii_copy_direct); 381 } 382 383 if (_ii_init_dev()) { 384 cmn_err(CE_WARN, "!ii: _ii_init_dev failed"); 385 goto out; 386 } 387 flags |= DIDINIT; 388 389 xsp->dip = dip; 390 xsp->instance = instance; 391 392 if (ddi_create_minor_node(dip, "ii", S_IFCHR, instance, DDI_PSEUDO, 0) 393 != DDI_SUCCESS) { 394 cmn_err(CE_WARN, "!ii: could not create node."); 395 goto out; 396 } 397 flags |= DIDNODES; 398 399 ddi_set_driver_private(dip, (caddr_t)flags); 400 ddi_report_dev(dip); 401 402 ii_create_kstats(); 403 404 return (DDI_SUCCESS); 405 406 out: 407 ddi_set_driver_private(dip, (caddr_t)flags); 408 (void) iidetach(dip, DDI_DETACH); 409 410 return (DDI_FAILURE); 411 } 412 413 static int 414 iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd) 415 { 416 struct ii_state *xsp; 417 int instance; 418 intptr_t flags; 419 420 if (cmd != DDI_DETACH) { 421 return (DDI_FAILURE); 422 } 423 424 if (_ii_info_top) { 425 return (DDI_FAILURE); /* busy */ 426 } 427 428 instance = ddi_get_instance(dip); 429 xsp = ddi_get_soft_state(ii_statep, instance); 430 if (xsp == NULL) { 431 cmn_err(CE_WARN, 432 "!ii: detach: could not get state for instance %d.", 433 instance); 434 return (DDI_FAILURE); 435 } 436 437 flags = (intptr_t)ddi_get_driver_private(dip); 438 if (flags & DIDNODES) 439 ddi_remove_minor_node(dip, NULL); 440 if (flags & DIDINIT) 441 _ii_deinit_dev(); 442 443 ddi_soft_state_free(ii_statep, instance); 444 445 if (ii_gkstat) { 446 kstat_delete(ii_gkstat); 447 ii_gkstat = NULL; 448 } 449 450 return (DDI_SUCCESS); 451 } 452 453 454 /* ARGSUSED */ 455 456 static int 457 iiopen(dev_t *devp, int flag, int otyp, cred_t *crp) 458 { 459 int error; 460 461 error = drv_priv(crp); 462 463 return (error); 464 } 465 466 467 /* ARGSUSED */ 468 469 static int 470 iiclose(dev_t dev, int flag, int otyp, cred_t *crp) 471 { 472 return (0); 473 } 474 475 /* ARGSUSED */ 476 477 static int 478 iiprint(dev_t dev, char *str) 479 { 480 int instance = 0; 481 482 cmn_err(CE_WARN, "!ii%d: %s", instance, str); 483 return (0); 484 } 485 486 /* ARGSUSED */ 487 488 static int 489 iiioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp) 490 { 491 int rc; 492 int ilp32; 493 494 ilp32 = (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32); 495 496 497 switch (cmd) { 498 case DSWIOC_WAIT: 499 rc = _ii_wait(arg, ilp32, rvp); 500 break; 501 502 case DSWIOC_RESET: 503 rc = _ii_reset(arg, ilp32, rvp); 504 break; 505 506 case DSWIOC_VERSION: 507 rc = _ii_version(arg, ilp32, rvp); 508 break; 509 510 case DSWIOC_ENABLE: 511 rc = _ii_config(arg, ilp32, rvp, 0); 512 break; 513 514 case DSWIOC_RESUME: 515 rc = _ii_config(arg, ilp32, rvp, II_EXISTING); 516 break; 517 518 case DSWIOC_DISABLE: 519 rc = _ii_disable(arg, ilp32, rvp); 520 break; 521 522 case DSWIOC_SUSPEND: 523 rc = _ii_suspend(arg, ilp32, rvp); 524 break; 525 526 case DSWIOC_ACOPY: 527 rc = _ii_acopy(arg, ilp32, rvp); 528 break; 529 530 case DSWIOC_COPY: 531 rc = _ii_copy(arg, ilp32, rvp); 532 break; 533 534 case DSWIOC_SHUTDOWN: 535 rc = _ii_shutdown(arg, rvp); 536 break; 537 538 case DSWIOC_STAT: 539 rc = _ii_stat(arg, ilp32, rvp); 540 break; 541 542 case DSWIOC_BITMAP: 543 rc = _ii_bitmap(arg, ilp32, rvp); 544 break; 545 546 case DSWIOC_SEGMENT: 547 rc = _ii_segment(arg, ilp32, rvp); 548 break; 549 550 case DSWIOC_ABORT: 551 rc = _ii_abort(arg, ilp32, rvp); 552 break; 553 554 case DSWIOC_OFFLINE: 555 rc = _ii_offline(arg, ilp32, rvp); 556 break; 557 558 case DSWIOC_LIST: 559 rc = _ii_list(arg, ilp32, rvp); 560 break; 561 562 case DSWIOC_LISTLEN: 563 case DSWIOC_OLISTLEN: 564 rc = _ii_listlen(cmd, ilp32, rvp); 565 break; 566 567 case DSWIOC_EXPORT: 568 rc = _ii_export(arg, ilp32, rvp); 569 break; 570 571 case DSWIOC_IMPORT: 572 rc = _ii_config(arg, ilp32, rvp, II_IMPORT); 573 break; 574 575 case DSWIOC_JOIN: 576 rc = _ii_join(arg, ilp32, rvp); 577 break; 578 579 case DSWIOC_COPYP: 580 rc = _ii_copyparm(arg, ilp32, rvp); 581 break; 582 583 case DSWIOC_OCREAT: 584 rc = _ii_ocreate(arg, ilp32, rvp); 585 break; 586 587 case DSWIOC_OATTACH: 588 rc = _ii_oattach(arg, ilp32, rvp); 589 break; 590 591 case DSWIOC_ODETACH: 592 rc = _ii_odetach(arg, ilp32, rvp); 593 break; 594 595 case DSWIOC_OLIST: 596 rc = _ii_olist(arg, ilp32, rvp); 597 break; 598 599 case DSWIOC_OSTAT: 600 rc = _ii_ostat(arg, ilp32, rvp, FALSE); 601 break; 602 603 case DSWIOC_OSTAT2: 604 rc = _ii_ostat(arg, ilp32, rvp, TRUE); 605 break; 606 607 case DSWIOC_SBITSSET: 608 case DSWIOC_CBITSSET: 609 rc = _ii_bitsset(arg, ilp32, cmd, rvp); 610 break; 611 612 case DSWIOC_CLIST: 613 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_cluster_mutex, 614 _ii_cluster_top); 615 break; 616 617 case DSWIOC_GLIST: 618 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_group_mutex, 619 _ii_group_top); 620 break; 621 622 case DSWIOC_MOVEGRP: 623 rc = _ii_move_grp(arg, ilp32, rvp); 624 break; 625 626 case DSWIOC_CHANGETAG: 627 rc = _ii_change_tag(arg, ilp32, rvp); 628 break; 629 630 default: 631 rc = EINVAL; 632 break; 633 } 634 635 return (rc); 636 } 637 638 /* 639 * dummy function 640 */ 641 642 static int 643 iistrat(struct buf *bp) 644 { 645 bp->b_error = EIO; 646 biodone(bp); 647 648 return (0); 649 } 650 651 static int 652 iiread() 653 { 654 return (EIO); 655 } 656