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, NULL } 121 }; 122 123 struct ii_state { 124 dev_info_t *dip; 125 int instance; 126 }; 127 128 /* used for logging sysevent, gets set in _ii_attach */ 129 dev_info_t *ii_dip = NULL; 130 131 extern _ii_info_t *_ii_info_top; 132 extern _ii_lsthead_t *_ii_cluster_top; 133 extern _ii_lsthead_t *_ii_group_top; 134 extern kmutex_t _ii_cluster_mutex; 135 extern kmutex_t _ii_group_mutex; 136 137 const int dsw_major_rev = ISS_VERSION_MAJ; /* Major release number */ 138 const int dsw_minor_rev = ISS_VERSION_MIN; /* Minor release number */ 139 const int dsw_micro_rev = ISS_VERSION_MIC; /* Micro release number */ 140 const int dsw_baseline_rev = ISS_VERSION_NUM; /* Baseline revision */ 141 static void *ii_statep; 142 143 extern int _ii_init_dev(); 144 extern void _ii_deinit_dev(); 145 extern int _ii_config(intptr_t arg, int ilp32, int *rvp, int iflags); 146 extern int _ii_disable(intptr_t arg, int ilp32, int *rvp); 147 extern int _ii_suspend(intptr_t arg, int ilp32, int *rvp); 148 extern int _ii_bitmap(intptr_t arg, int ilp32, int *rvp); 149 extern int _ii_segment(intptr_t arg, int ilp32, int *rvp); 150 extern int _ii_abort(intptr_t arg, int ilp32, int *rvp); 151 extern int _ii_acopy(intptr_t arg, int ilp32, int *rvp); 152 extern int _ii_copy(intptr_t arg, int ilp32, int *rvp); 153 extern int _ii_shutdown(intptr_t arg, int *rvp); 154 extern int _ii_stat(intptr_t arg, int ilp32, int *rvp); 155 extern int _ii_version(intptr_t arg, int ilp32, int *rvp); 156 extern int _ii_wait(intptr_t arg, int ilp32, int *rvp); 157 extern int _ii_reset(intptr_t arg, int ilp32, int *rvp); 158 extern int _ii_offline(intptr_t arg, int ilp32, int *rvp); 159 extern int _ii_list(intptr_t arg, int ilp32, int *rvp); 160 extern int _ii_listlen(int cmd, int ilp32, int *rvp); 161 extern int _ii_export(intptr_t arg, int ilp32, int *rvp); 162 extern int _ii_join(intptr_t arg, int ilp32, int *rvp); 163 extern int _ii_copyparm(intptr_t arg, int ilp32, int *rvp); 164 extern int _ii_ocreate(intptr_t arg, int ilp32, int *rvp); 165 extern int _ii_oattach(intptr_t arg, int ilp32, int *rvp); 166 extern int _ii_odetach(intptr_t arg, int ilp32, int *rvp); 167 extern int _ii_olist(intptr_t arg, int ilp32, int *rvp); 168 extern int _ii_ostat(intptr_t arg, int ilp32, int *rvp, int is_iost_2); 169 extern int _ii_bitsset(intptr_t arg, int ilp32, int cmd, int *rvp); 170 extern int _ii_gc_list(intptr_t, int, int *, kmutex_t *, _ii_lsthead_t *); 171 extern int _ii_clist(intptr_t arg, int ilp32, int *rvp); 172 extern int _ii_move_grp(intptr_t arg, int ilp32, int *rvp); 173 extern int _ii_change_tag(intptr_t arg, int ilp32, int *rvp); 174 extern int ii_debug; 175 extern int ii_throttle_unit; 176 extern int ii_throttle_delay; 177 extern int ii_copy_direct; 178 extern int ii_bitmap; 179 180 int 181 _init(void) 182 { 183 int error; 184 185 error = ddi_soft_state_init(&ii_statep, sizeof (struct ii_state), 1); 186 if (!error) { 187 error = mod_install(&ii_modlinkage); 188 if (error) 189 ddi_soft_state_fini(&ii_statep); 190 } 191 192 return (error); 193 } 194 195 int 196 _fini(void) 197 { 198 int error; 199 200 error = mod_remove(&ii_modlinkage); 201 if (!error) 202 ddi_soft_state_fini(&ii_statep); 203 204 return (error); 205 } 206 207 int 208 _info(struct modinfo *modinfop) 209 { 210 int rc; 211 212 rc = mod_info(&ii_modlinkage, modinfop); 213 214 return (rc); 215 } 216 217 /* ARGSUSED */ 218 219 static int 220 iiprobe(dev_info_t *dip) 221 { 222 return (DDI_PROBE_SUCCESS); 223 } 224 225 /*ARGSUSED*/ 226 static int 227 ii_stats_update(kstat_t *ksp, int rw) 228 { 229 if (KSTAT_WRITE == rw) { 230 return (EACCES); 231 } 232 233 /* 234 * We do nothing here for now -- the kstat structure is 235 * updated in-place 236 */ 237 238 return (0); 239 } 240 241 static void 242 ii_create_kstats() 243 { 244 /* create global info structure */ 245 if (!ii_gkstat) { 246 ii_gkstat = kstat_create("ii", 0, "global", "StorEdge", 247 KSTAT_TYPE_NAMED, 248 sizeof (iigkstat) / sizeof (kstat_named_t), 249 KSTAT_FLAG_VIRTUAL); 250 if (ii_gkstat) { 251 ii_gkstat->ks_data = &iigkstat; 252 ii_gkstat->ks_update = ii_stats_update; 253 ii_gkstat->ks_private = 0; 254 kstat_install(ii_gkstat); 255 256 /* fill in immutable values */ 257 iigkstat.ii_debug.value.ul = ii_debug; 258 iigkstat.ii_bitmap.value.ul = ii_bitmap; 259 iigkstat.ii_throttle_unit.value.ul = ii_throttle_unit; 260 iigkstat.ii_throttle_delay.value.ul = 261 ii_throttle_delay; 262 iigkstat.ii_copy_direct.value.ul = ii_copy_direct; 263 } else { 264 cmn_err(CE_WARN, "!Unable to create II global stats"); 265 } 266 } 267 } 268 269 static int 270 iiattach(dev_info_t *dip, ddi_attach_cmd_t cmd) 271 { 272 struct ii_state *xsp; 273 int instance; 274 int i; 275 intptr_t flags; 276 277 if (cmd != DDI_ATTACH) { 278 return (DDI_FAILURE); 279 } 280 /* save the dev_info_t to be used in logging using ddi_log_sysevent */ 281 ii_dip = dip; 282 283 instance = ddi_get_instance(dip); 284 if (ddi_soft_state_zalloc(ii_statep, instance) != 0) { 285 cmn_err(CE_WARN, "!ii: no memory for instance %d state.", 286 instance); 287 return (DDI_FAILURE); 288 } 289 290 flags = 0; 291 xsp = ddi_get_soft_state(ii_statep, instance); 292 if (xsp == NULL) { 293 cmn_err(CE_WARN, 294 "!ii: attach: could not get state for instance %d.", 295 instance); 296 goto out; 297 } 298 299 ii_debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 300 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_debug", 0); 301 if (ii_debug != 0) { 302 #ifdef DEBUG 303 cmn_err(CE_NOTE, "!ii: initializing ii version %d.%d.%d.%d", 304 dsw_major_rev, dsw_minor_rev, 305 dsw_micro_rev, dsw_baseline_rev); 306 #else 307 if (dsw_micro_rev) { 308 cmn_err(CE_NOTE, "!ii: initializing ii vers %d.%d.%d", 309 dsw_major_rev, dsw_minor_rev, dsw_micro_rev); 310 } else { 311 cmn_err(CE_NOTE, "!ii: initializing ii version %d.%d", 312 dsw_major_rev, dsw_minor_rev); 313 } 314 #endif 315 switch (ii_debug) { 316 case 1: 317 case 2: cmn_err(CE_NOTE, 318 "!ii: ii_debug=%d is enabled.", ii_debug); 319 break; 320 default: 321 cmn_err(CE_WARN, 322 "!ii: Value of ii_debug=%d is not 0,1 or 2.", 323 ii_debug); 324 } 325 } 326 327 ii_bitmap = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 328 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_bitmap", II_WTHRU); 329 switch (ii_bitmap) { 330 case II_KMEM: 331 if (ii_debug > 0) 332 cmn_err(CE_NOTE, "!ii: ii_bitmap is in memory"); 333 break; 334 case II_FWC: 335 if (ii_debug > 0) 336 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk," 337 " no FWC"); 338 break; 339 case II_WTHRU: 340 if (ii_debug > 0) 341 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk"); 342 break; 343 default: 344 cmn_err(CE_NOTE, 345 "!ii: ii_bitmap=%d out of range; " 346 "defaulting WTHRU(%d)", ii_bitmap, II_WTHRU); 347 ii_bitmap = II_WTHRU; 348 } 349 350 /* pick up these values if in ii.conf, otherwise leave alone */ 351 i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 352 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_unit", 0); 353 if (i > 0) { 354 ii_throttle_unit = i; 355 if ((ii_throttle_unit < MIN_THROTTLE_UNIT) || 356 (ii_throttle_unit > MAX_THROTTLE_UNIT) || 357 (ii_debug > 0)) 358 cmn_err(CE_NOTE, 359 "!ii: ii_throttle_unit=%d", ii_throttle_unit); 360 } 361 362 i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 363 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_delay", 0); 364 if (i > 0) { 365 ii_throttle_delay = i; 366 if ((ii_throttle_delay < MIN_THROTTLE_DELAY) || 367 (ii_throttle_delay > MIN_THROTTLE_DELAY) || 368 (ii_debug > 0)) 369 cmn_err(CE_NOTE, 370 "!ii: ii_throttle_delay=%d", ii_throttle_delay); 371 } 372 373 ii_copy_direct = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 374 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_copy_direct", 1); 375 if (i > 0) { 376 ii_copy_direct = i; 377 if ((ii_copy_direct < 0) || (ii_copy_direct > 1)) 378 cmn_err(CE_NOTE, 379 "!ii: ii_copy_direct=%d", ii_copy_direct); 380 } 381 382 if (_ii_init_dev()) { 383 cmn_err(CE_WARN, "!ii: _ii_init_dev failed"); 384 goto out; 385 } 386 flags |= DIDINIT; 387 388 xsp->dip = dip; 389 xsp->instance = instance; 390 391 if (ddi_create_minor_node(dip, "ii", S_IFCHR, instance, DDI_PSEUDO, 0) 392 != DDI_SUCCESS) { 393 cmn_err(CE_WARN, "!ii: could not create node."); 394 goto out; 395 } 396 flags |= DIDNODES; 397 398 ddi_set_driver_private(dip, (caddr_t)flags); 399 ddi_report_dev(dip); 400 401 ii_create_kstats(); 402 403 return (DDI_SUCCESS); 404 405 out: 406 ddi_set_driver_private(dip, (caddr_t)flags); 407 (void) iidetach(dip, DDI_DETACH); 408 409 return (DDI_FAILURE); 410 } 411 412 static int 413 iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd) 414 { 415 struct ii_state *xsp; 416 int instance; 417 intptr_t flags; 418 419 if (cmd != DDI_DETACH) { 420 return (DDI_FAILURE); 421 } 422 423 if (_ii_info_top) { 424 return (DDI_FAILURE); /* busy */ 425 } 426 427 instance = ddi_get_instance(dip); 428 xsp = ddi_get_soft_state(ii_statep, instance); 429 if (xsp == NULL) { 430 cmn_err(CE_WARN, 431 "!ii: detach: could not get state for instance %d.", 432 instance); 433 return (DDI_FAILURE); 434 } 435 436 flags = (intptr_t)ddi_get_driver_private(dip); 437 if (flags & DIDNODES) 438 ddi_remove_minor_node(dip, NULL); 439 if (flags & DIDINIT) 440 _ii_deinit_dev(); 441 442 ddi_soft_state_free(ii_statep, instance); 443 444 if (ii_gkstat) { 445 kstat_delete(ii_gkstat); 446 ii_gkstat = NULL; 447 } 448 449 return (DDI_SUCCESS); 450 } 451 452 453 /* ARGSUSED */ 454 455 static int 456 iiopen(dev_t *devp, int flag, int otyp, cred_t *crp) 457 { 458 int error; 459 460 error = drv_priv(crp); 461 462 return (error); 463 } 464 465 466 /* ARGSUSED */ 467 468 static int 469 iiclose(dev_t dev, int flag, int otyp, cred_t *crp) 470 { 471 return (0); 472 } 473 474 /* ARGSUSED */ 475 476 static int 477 iiprint(dev_t dev, char *str) 478 { 479 int instance = 0; 480 481 cmn_err(CE_WARN, "!ii%d: %s", instance, str); 482 return (0); 483 } 484 485 /* ARGSUSED */ 486 487 static int 488 iiioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp) 489 { 490 int rc; 491 int ilp32; 492 493 ilp32 = (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32); 494 495 496 switch (cmd) { 497 case DSWIOC_WAIT: 498 rc = _ii_wait(arg, ilp32, rvp); 499 break; 500 501 case DSWIOC_RESET: 502 rc = _ii_reset(arg, ilp32, rvp); 503 break; 504 505 case DSWIOC_VERSION: 506 rc = _ii_version(arg, ilp32, rvp); 507 break; 508 509 case DSWIOC_ENABLE: 510 rc = _ii_config(arg, ilp32, rvp, 0); 511 break; 512 513 case DSWIOC_RESUME: 514 rc = _ii_config(arg, ilp32, rvp, II_EXISTING); 515 break; 516 517 case DSWIOC_DISABLE: 518 rc = _ii_disable(arg, ilp32, rvp); 519 break; 520 521 case DSWIOC_SUSPEND: 522 rc = _ii_suspend(arg, ilp32, rvp); 523 break; 524 525 case DSWIOC_ACOPY: 526 rc = _ii_acopy(arg, ilp32, rvp); 527 break; 528 529 case DSWIOC_COPY: 530 rc = _ii_copy(arg, ilp32, rvp); 531 break; 532 533 case DSWIOC_SHUTDOWN: 534 rc = _ii_shutdown(arg, rvp); 535 break; 536 537 case DSWIOC_STAT: 538 rc = _ii_stat(arg, ilp32, rvp); 539 break; 540 541 case DSWIOC_BITMAP: 542 rc = _ii_bitmap(arg, ilp32, rvp); 543 break; 544 545 case DSWIOC_SEGMENT: 546 rc = _ii_segment(arg, ilp32, rvp); 547 break; 548 549 case DSWIOC_ABORT: 550 rc = _ii_abort(arg, ilp32, rvp); 551 break; 552 553 case DSWIOC_OFFLINE: 554 rc = _ii_offline(arg, ilp32, rvp); 555 break; 556 557 case DSWIOC_LIST: 558 rc = _ii_list(arg, ilp32, rvp); 559 break; 560 561 case DSWIOC_LISTLEN: 562 case DSWIOC_OLISTLEN: 563 rc = _ii_listlen(cmd, ilp32, rvp); 564 break; 565 566 case DSWIOC_EXPORT: 567 rc = _ii_export(arg, ilp32, rvp); 568 break; 569 570 case DSWIOC_IMPORT: 571 rc = _ii_config(arg, ilp32, rvp, II_IMPORT); 572 break; 573 574 case DSWIOC_JOIN: 575 rc = _ii_join(arg, ilp32, rvp); 576 break; 577 578 case DSWIOC_COPYP: 579 rc = _ii_copyparm(arg, ilp32, rvp); 580 break; 581 582 case DSWIOC_OCREAT: 583 rc = _ii_ocreate(arg, ilp32, rvp); 584 break; 585 586 case DSWIOC_OATTACH: 587 rc = _ii_oattach(arg, ilp32, rvp); 588 break; 589 590 case DSWIOC_ODETACH: 591 rc = _ii_odetach(arg, ilp32, rvp); 592 break; 593 594 case DSWIOC_OLIST: 595 rc = _ii_olist(arg, ilp32, rvp); 596 break; 597 598 case DSWIOC_OSTAT: 599 rc = _ii_ostat(arg, ilp32, rvp, FALSE); 600 break; 601 602 case DSWIOC_OSTAT2: 603 rc = _ii_ostat(arg, ilp32, rvp, TRUE); 604 break; 605 606 case DSWIOC_SBITSSET: 607 case DSWIOC_CBITSSET: 608 rc = _ii_bitsset(arg, ilp32, cmd, rvp); 609 break; 610 611 case DSWIOC_CLIST: 612 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_cluster_mutex, 613 _ii_cluster_top); 614 break; 615 616 case DSWIOC_GLIST: 617 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_group_mutex, 618 _ii_group_top); 619 break; 620 621 case DSWIOC_MOVEGRP: 622 rc = _ii_move_grp(arg, ilp32, rvp); 623 break; 624 625 case DSWIOC_CHANGETAG: 626 rc = _ii_change_tag(arg, ilp32, rvp); 627 break; 628 629 default: 630 rc = EINVAL; 631 break; 632 } 633 634 return (rc); 635 } 636 637 /* 638 * dummy function 639 */ 640 641 static int 642 iistrat(struct buf *bp) 643 { 644 bp->b_error = EIO; 645 biodone(bp); 646 647 return (0); 648 } 649 650 static int 651 iiread() 652 { 653 return (EIO); 654 }