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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #define _RDC_ 27 #include <sys/types.h> 28 #include <sys/ksynch.h> 29 #include <sys/kmem.h> 30 #include <sys/errno.h> 31 #include <sys/conf.h> 32 #include <sys/cmn_err.h> 33 #include <sys/modctl.h> 34 #include <sys/cred.h> 35 #include <sys/ddi.h> 36 #include <sys/unistat/spcs_s.h> 37 #include <sys/unistat/spcs_s_k.h> 38 #include <sys/unistat/spcs_errors.h> 39 40 #include <sys/nsc_thread.h> 41 #ifdef DS_DDICT 42 #include "../contract.h" 43 #endif 44 #include <sys/nsctl/nsctl.h> 45 #include <sys/nsctl/nsvers.h> 46 47 #include <sys/sdt.h> /* dtrace is S10 or later */ 48 49 #include "rdc.h" 50 #include "rdc_io.h" 51 #include "rdc_bitmap.h" 52 #include "rdc_ioctl.h" 53 #include "rdcsrv.h" 54 #include "rdc_diskq.h" 55 56 #define DIDINIT 0x01 57 #define DIDNODES 0x02 58 #define DIDCONFIG 0x04 59 60 static int rdcopen(dev_t *devp, int flag, int otyp, cred_t *crp); 61 static int rdcclose(dev_t dev, int flag, int otyp, cred_t *crp); 62 static int rdcprint(dev_t dev, char *str); 63 static int rdcioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, 64 int *rvp); 65 static int rdcattach(dev_info_t *dip, ddi_attach_cmd_t cmd); 66 static int rdcdetach(dev_info_t *dip, ddi_detach_cmd_t cmd); 67 static int rdcgetinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 68 void **result); 69 #ifdef DEBUG 70 static int rdc_clrkstat(void *); 71 #endif 72 73 /* 74 * kstat interface 75 */ 76 static kstat_t *sndr_kstats; 77 78 int sndr_info_stats_update(kstat_t *ksp, int rw); 79 80 static sndr_m_stats_t sndr_info_stats = { 81 {RDC_MKSTAT_MAXSETS, KSTAT_DATA_ULONG}, 82 {RDC_MKSTAT_MAXFBAS, KSTAT_DATA_ULONG}, 83 {RDC_MKSTAT_RPC_TIMEOUT, KSTAT_DATA_ULONG}, 84 {RDC_MKSTAT_HEALTH_THRES, KSTAT_DATA_ULONG}, 85 {RDC_MKSTAT_BITMAP_WRITES, KSTAT_DATA_ULONG}, 86 {RDC_MKSTAT_CLNT_COTS_CALLS, KSTAT_DATA_ULONG}, 87 {RDC_MKSTAT_CLNT_CLTS_CALLS, KSTAT_DATA_ULONG}, 88 {RDC_MKSTAT_SVC_COTS_CALLS, KSTAT_DATA_ULONG}, 89 {RDC_MKSTAT_SVC_CLTS_CALLS, KSTAT_DATA_ULONG}, 90 {RDC_MKSTAT_BITMAP_REF_DELAY, KSTAT_DATA_ULONG} 91 }; 92 93 int rdc_info_stats_update(kstat_t *ksp, int rw); 94 95 static rdc_info_stats_t rdc_info_stats = { 96 {RDC_IKSTAT_FLAGS, KSTAT_DATA_ULONG}, 97 {RDC_IKSTAT_SYNCFLAGS, KSTAT_DATA_ULONG}, 98 {RDC_IKSTAT_BMPFLAGS, KSTAT_DATA_ULONG}, 99 {RDC_IKSTAT_SYNCPOS, KSTAT_DATA_ULONG}, 100 {RDC_IKSTAT_VOLSIZE, KSTAT_DATA_ULONG}, 101 {RDC_IKSTAT_BITSSET, KSTAT_DATA_ULONG}, 102 {RDC_IKSTAT_AUTOSYNC, KSTAT_DATA_ULONG}, 103 {RDC_IKSTAT_MAXQFBAS, KSTAT_DATA_ULONG}, 104 {RDC_IKSTAT_MAXQITEMS, KSTAT_DATA_ULONG}, 105 {RDC_IKSTAT_FILE, KSTAT_DATA_STRING}, 106 {RDC_IKSTAT_SECFILE, KSTAT_DATA_STRING}, 107 {RDC_IKSTAT_BITMAP, KSTAT_DATA_STRING}, 108 {RDC_IKSTAT_PRIMARY_HOST, KSTAT_DATA_STRING}, 109 {RDC_IKSTAT_SECONDARY_HOST, KSTAT_DATA_STRING}, 110 {RDC_IKSTAT_TYPE_FLAG, KSTAT_DATA_ULONG}, 111 {RDC_IKSTAT_BMP_SIZE, KSTAT_DATA_ULONG}, 112 {RDC_IKSTAT_DISK_STATUS, KSTAT_DATA_ULONG}, 113 {RDC_IKSTAT_IF_DOWN, KSTAT_DATA_ULONG}, 114 {RDC_IKSTAT_IF_RPC_VERSION, KSTAT_DATA_ULONG}, 115 {RDC_IKSTAT_ASYNC_BLOCK_HWM, KSTAT_DATA_ULONG}, 116 {RDC_IKSTAT_ASYNC_ITEM_HWM, KSTAT_DATA_ULONG}, 117 {RDC_IKSTAT_ASYNC_THROTTLE_DELAY, KSTAT_DATA_ULONG}, 118 {RDC_IKSTAT_ASYNC_ITEMS, KSTAT_DATA_ULONG}, 119 {RDC_IKSTAT_ASYNC_BLOCKS, KSTAT_DATA_ULONG}, 120 {RDC_IKSTAT_QUEUE_TYPE, KSTAT_DATA_CHAR} 121 }; 122 123 static struct cb_ops rdc_cb_ops = { 124 rdcopen, 125 rdcclose, 126 nulldev, /* no strategy */ 127 rdcprint, 128 nodev, /* no dump */ 129 nodev, /* no read */ 130 nodev, /* no write */ 131 rdcioctl, 132 nodev, /* no devmap */ 133 nodev, /* no mmap */ 134 nodev, /* no segmap */ 135 nochpoll, 136 ddi_prop_op, 137 NULL, /* not STREAMS */ 138 D_NEW | D_MP | D_64BIT, 139 CB_REV, 140 nodev, /* no aread */ 141 nodev, /* no awrite */ 142 }; 143 144 static struct dev_ops rdc_ops = { 145 DEVO_REV, 146 0, 147 rdcgetinfo, 148 nulldev, /* identify */ 149 nulldev, /* probe */ 150 rdcattach, 151 rdcdetach, 152 nodev, /* no reset */ 153 &rdc_cb_ops, 154 (struct bus_ops *)NULL 155 }; 156 157 static struct modldrv rdc_ldrv = { 158 &mod_driverops, 159 "nws:Remote Mirror:" ISS_VERSION_STR, 160 &rdc_ops 161 }; 162 163 static struct modlinkage rdc_modlinkage = { 164 MODREV_1, 165 &rdc_ldrv, 166 NULL 167 }; 168 169 const int sndr_major_rev = ISS_VERSION_MAJ; 170 const int sndr_minor_rev = ISS_VERSION_MIN; 171 const int sndr_micro_rev = ISS_VERSION_MIC; 172 const int sndr_baseline_rev = ISS_VERSION_NUM; 173 static char sndr_version[16]; 174 175 static void *rdc_dip; 176 177 extern int _rdc_init_dev(); 178 extern void _rdc_deinit_dev(); 179 extern void rdc_link_down_free(); 180 181 int rdc_bitmap_mode; 182 int rdc_auto_sync; 183 int rdc_max_sets; 184 extern int rdc_health_thres; 185 186 static const char rdc_built[] = "@(#) rdc: built " __TIME__ " " __DATE__; 187 188 kmutex_t rdc_sync_mutex; 189 rdc_sync_event_t rdc_sync_event; 190 clock_t rdc_sync_event_timeout; 191 192 static void 193 rdc_sync_event_init() 194 { 195 mutex_init(&rdc_sync_mutex, NULL, MUTEX_DRIVER, NULL); 196 mutex_init(&rdc_sync_event.mutex, NULL, MUTEX_DRIVER, NULL); 197 cv_init(&rdc_sync_event.cv, NULL, CV_DRIVER, NULL); 198 cv_init(&rdc_sync_event.done_cv, NULL, CV_DRIVER, NULL); 199 rdc_sync_event.master[0] = 0; 200 rdc_sync_event.lbolt = (clock_t)0; 201 rdc_sync_event_timeout = RDC_SYNC_EVENT_TIMEOUT; 202 } 203 204 205 static void 206 rdc_sync_event_destroy() 207 { 208 mutex_destroy(&rdc_sync_mutex); 209 mutex_destroy(&rdc_sync_event.mutex); 210 cv_destroy(&rdc_sync_event.cv); 211 cv_destroy(&rdc_sync_event.done_cv); 212 } 213 214 215 216 int 217 _init(void) 218 { 219 return (mod_install(&rdc_modlinkage)); 220 } 221 222 int 223 _fini(void) 224 { 225 return (mod_remove(&rdc_modlinkage)); 226 } 227 228 int 229 _info(struct modinfo *modinfop) 230 { 231 return (mod_info(&rdc_modlinkage, modinfop)); 232 } 233 234 static int 235 rdcattach(dev_info_t *dip, ddi_attach_cmd_t cmd) 236 { 237 intptr_t flags; 238 int instance; 239 int i; 240 241 /*CONSTCOND*/ 242 ASSERT(sizeof (u_longlong_t) == 8); 243 244 if (cmd != DDI_ATTACH) 245 return (DDI_FAILURE); 246 247 cmn_err(CE_CONT, "!%s\n", rdc_built); 248 249 (void) strncpy(sndr_version, _VERSION_, sizeof (sndr_version)); 250 251 #ifdef DEBUG 252 cmn_err(CE_NOTE, "SNDR: initializing version %d.%d %s", sndr_major_rev, 253 sndr_minor_rev, sndr_version); 254 #endif 255 instance = ddi_get_instance(dip); 256 rdc_dip = dip; 257 258 flags = 0; 259 260 rdc_sync_event_init(); 261 262 /* 263 * rdc_max_sets must be set before calling _rdc_load(). 264 */ 265 266 rdc_max_sets = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 267 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "rdc_max_sets", 64); 268 269 if (_rdc_init_dev()) { 270 cmn_err(CE_WARN, "rdc: _rdc_init_dev failed"); 271 goto out; 272 } 273 flags |= DIDINIT; 274 275 if (_rdc_load() != 0) { 276 cmn_err(CE_WARN, "rdc: _rdc_load failed"); 277 goto out; 278 } 279 280 if (_rdc_configure()) { 281 cmn_err(CE_WARN, "rdc: _rdc_configure failed"); 282 goto out; 283 } 284 flags |= DIDCONFIG; 285 286 if (ddi_create_minor_node(dip, "rdc", S_IFCHR, instance, DDI_PSEUDO, 0) 287 != DDI_SUCCESS) { 288 cmn_err(CE_WARN, "rdc: could not create node."); 289 goto out; 290 } 291 flags |= DIDNODES; 292 293 rdc_bitmap_mode = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 294 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 295 "rdc_bitmap_mode", 0); 296 297 switch (rdc_bitmap_mode) { 298 case RDC_BMP_AUTO: /* 0 */ 299 break; 300 case RDC_BMP_ALWAYS: /* 1 */ 301 #ifdef DEBUG 302 cmn_err(CE_NOTE, "SNDR bitmap mode override"); 303 cmn_err(CE_CONT, 304 "SNDR: bitmaps will be written for every write I/O\n"); 305 #endif 306 break; 307 case RDC_BMP_NEVER: /* 2 */ 308 cmn_err(CE_NOTE, "SNDR bitmap mode override"); 309 cmn_err(CE_CONT, 310 "SNDR: bitmaps will only be written on shutdown\n"); 311 break; 312 default: /* unknown */ 313 cmn_err(CE_NOTE, 314 "SNDR: unknown bitmap mode %d - autodetecting mode", 315 rdc_bitmap_mode); 316 rdc_bitmap_mode = RDC_BMP_AUTO; 317 break; 318 } 319 320 rdc_bitmap_init(); 321 322 rdc_auto_sync = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 323 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 324 "rdc_auto_sync", 0); 325 326 i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 327 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 328 "rdc_health_thres", RDC_HEALTH_THRESHOLD); 329 if (i >= RDC_MIN_HEALTH_THRES) 330 rdc_health_thres = i; 331 else 332 cmn_err(CE_WARN, "value rdc_heath_thres from rdc.conf ignored " 333 "as it is smaller than the min value of %d", 334 RDC_MIN_HEALTH_THRES); 335 336 ddi_set_driver_private(dip, (caddr_t)flags); 337 ddi_report_dev(dip); 338 339 sndr_kstats = kstat_create(RDC_KSTAT_MODULE, 0, 340 RDC_KSTAT_MINFO, RDC_KSTAT_CLASS, KSTAT_TYPE_NAMED, 341 sizeof (sndr_m_stats_t) / sizeof (kstat_named_t), 342 KSTAT_FLAG_VIRTUAL); 343 344 if (sndr_kstats) { 345 sndr_kstats->ks_data = &sndr_info_stats; 346 sndr_kstats->ks_update = sndr_info_stats_update; 347 sndr_kstats->ks_private = &rdc_k_info[0]; 348 kstat_install(sndr_kstats); 349 } else 350 cmn_err(CE_WARN, "SNDR: module kstats failed"); 351 352 return (DDI_SUCCESS); 353 354 out: 355 DTRACE_PROBE(rdc_attach_failed); 356 ddi_set_driver_private(dip, (caddr_t)flags); 357 (void) rdcdetach(dip, DDI_DETACH); 358 return (DDI_FAILURE); 359 } 360 361 static int 362 rdcdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) 363 { 364 rdc_k_info_t *krdc; 365 rdc_u_info_t *urdc; 366 int rdcd; 367 intptr_t flags; 368 369 370 if (cmd != DDI_DETACH) { 371 DTRACE_PROBE(rdc_detach_unknown_cmd); 372 return (DDI_FAILURE); 373 } 374 375 if (rdc_k_info == NULL || rdc_u_info == NULL) 376 goto cleanup; 377 378 mutex_enter(&rdc_conf_lock); 379 380 for (rdcd = 0; rdcd < rdc_max_sets; rdcd++) { 381 krdc = &rdc_k_info[rdcd]; 382 urdc = &rdc_u_info[rdcd]; 383 384 if (IS_ENABLED(urdc) || krdc->devices) { 385 #ifdef DEBUG 386 cmn_err(CE_WARN, 387 "!rdc: cannot detach, rdcd %d still in use", rdcd); 388 #endif 389 mutex_exit(&rdc_conf_lock); 390 DTRACE_PROBE(rdc_detach_err_busy); 391 return (DDI_FAILURE); 392 } 393 } 394 395 mutex_exit(&rdc_conf_lock); 396 397 cleanup: 398 flags = (intptr_t)ddi_get_driver_private(dip); 399 400 if (flags & DIDNODES) 401 ddi_remove_minor_node(dip, NULL); 402 403 if (sndr_kstats) { 404 kstat_delete(sndr_kstats); 405 } 406 if (flags & DIDINIT) 407 _rdc_deinit_dev(); 408 409 if (flags & DIDCONFIG) { 410 (void) _rdc_deconfigure(); 411 (void) _rdc_unload(); 412 rdcsrv_unload(); 413 } 414 415 rdc_sync_event_destroy(); 416 rdc_link_down_free(); 417 418 rdc_dip = NULL; 419 return (DDI_SUCCESS); 420 } 421 422 /* ARGSUSED */ 423 static int 424 rdcgetinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 425 { 426 int rc = DDI_FAILURE; 427 428 switch (infocmd) { 429 430 case DDI_INFO_DEVT2DEVINFO: 431 *result = rdc_dip; 432 rc = DDI_SUCCESS; 433 break; 434 435 case DDI_INFO_DEVT2INSTANCE: 436 /* We only have a single instance */ 437 *result = 0; 438 rc = DDI_SUCCESS; 439 break; 440 441 default: 442 break; 443 } 444 445 return (rc); 446 } 447 448 449 /* ARGSUSED */ 450 451 static int 452 rdcopen(dev_t *devp, int flag, int otyp, cred_t *crp) 453 { 454 return (0); 455 } 456 457 458 /* ARGSUSED */ 459 460 static int 461 rdcclose(dev_t dev, int flag, int otyp, cred_t *crp) 462 { 463 return (0); 464 } 465 466 /* ARGSUSED */ 467 468 static int 469 rdcprint(dev_t dev, char *str) 470 { 471 int instance = 0; 472 473 cmn_err(CE_WARN, "rdc%d: %s", instance, str); 474 return (0); 475 } 476 477 478 static int 479 convert_ioctl_args(int cmd, intptr_t arg, int mode, _rdc_ioctl_t *args) 480 { 481 _rdc_ioctl32_t args32; 482 483 if (ddi_copyin((void *)arg, &args32, sizeof (_rdc_ioctl32_t), mode)) 484 return (EFAULT); 485 486 bzero((void *)args, sizeof (_rdc_ioctl_t)); 487 488 switch (cmd) { 489 case RDC_CONFIG: 490 args->arg0 = (uint32_t)args32.arg0; /* _rdc_config_t * */ 491 args->arg1 = (uint32_t)args32.arg1; /* pointer */ 492 args->arg2 = (uint32_t)args32.arg2; /* size */ 493 args->ustatus = (spcs_s_info_t)args32.ustatus; 494 break; 495 496 case RDC_STATUS: 497 args->arg0 = (uint32_t)args32.arg0; /* pointer */ 498 args->ustatus = (spcs_s_info_t)args32.ustatus; 499 break; 500 501 case RDC_ENABLE_SVR: 502 args->arg0 = (uint32_t)args32.arg0; /* _rdc_svc_args * */ 503 break; 504 505 case RDC_VERSION: 506 args->arg0 = (uint32_t)args32.arg0; /* _rdc_version_t * */ 507 args->ustatus = (spcs_s_info_t)args32.ustatus; 508 break; 509 510 case RDC_SYNC_EVENT: 511 args->arg0 = (uint32_t)args32.arg0; /* char * */ 512 args->arg1 = (uint32_t)args32.arg1; /* char * */ 513 args->ustatus = (spcs_s_info_t)args32.ustatus; 514 break; 515 516 case RDC_LINK_DOWN: 517 args->arg0 = (uint32_t)args32.arg0; /* char * */ 518 args->ustatus = (spcs_s_info_t)args32.ustatus; 519 break; 520 case RDC_POOL_CREATE: 521 args->arg0 = (uint32_t)args32.arg0; /* svcpool_args * */ 522 break; 523 case RDC_POOL_WAIT: 524 args->arg0 = (uint32_t)args32.arg0; /* int */ 525 break; 526 case RDC_POOL_RUN: 527 args->arg0 = (uint32_t)args32.arg0; /* int */ 528 break; 529 530 default: 531 return (EINVAL); 532 } 533 534 return (0); 535 } 536 537 538 /* 539 * Yet another standard thing that is not standard ... 540 */ 541 #ifndef offsetof 542 #define offsetof(s, m) ((size_t)(&((s *)0)->m)) 543 #endif 544 545 /* 546 * Build a 32bit rdc_set structure and copyout to the user level. 547 */ 548 int 549 rdc_status_copy32(const void *arg, void *usetp, size_t size, int mode) 550 { 551 rdc_u_info_t *urdc = (rdc_u_info_t *)arg; 552 struct rdc_set32 set32; 553 size_t tailsize; 554 #ifdef DEBUG 555 size_t tailsize32; 556 #endif 557 558 bzero(&set32, sizeof (set32)); 559 560 tailsize = sizeof (struct rdc_addr32) - 561 offsetof(struct rdc_addr32, intf); 562 563 /* primary address structure, avoiding netbuf */ 564 bcopy(&urdc->primary.intf[0], &set32.primary.intf[0], tailsize); 565 566 /* secondary address structure, avoiding netbuf */ 567 bcopy(&urdc->secondary.intf[0], &set32.secondary.intf[0], tailsize); 568 569 /* 570 * the rest, avoiding netconfig 571 * note: the tail must be the same size in both structures 572 */ 573 tailsize = sizeof (struct rdc_set) - offsetof(struct rdc_set, flags); 574 #ifdef DEBUG 575 /* 576 * ASSERT is calling for debug reason, and tailsize32 is only declared 577 * for ASSERT, put them under debug to avoid lint warning. 578 */ 579 tailsize32 = sizeof (struct rdc_set32) - 580 offsetof(struct rdc_set32, flags); 581 ASSERT(tailsize == tailsize32); 582 #endif 583 584 bcopy(&urdc->flags, &set32.flags, tailsize); 585 586 /* copyout to user level */ 587 return (ddi_copyout(&set32, usetp, size, mode)); 588 } 589 590 591 /* 592 * Status ioctl. 593 */ 594 static int 595 rdcstatus(_rdc_ioctl_t *args, int mode) 596 { 597 int (*copyout)(const void *, void *, size_t, int); 598 rdc_u_info_t *urdc; 599 rdc_k_info_t *krdc; 600 disk_queue *dqp; 601 char *usetp; /* pointer to user rdc_set structure */ 602 size_t size; /* sizeof user rdc_set structure */ 603 int32_t *maxsetsp; /* address of status->maxsets; */ 604 int nset, max, i, j; 605 606 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 607 struct rdc_status32 status32; 608 609 if (ddi_copyin((void *)args->arg0, &status32, 610 sizeof (status32), mode)) { 611 return (EFAULT); 612 } 613 614 usetp = ((char *)args->arg0) + 615 offsetof(struct rdc_status32, rdc_set); 616 maxsetsp = (int32_t *)((char *)args->arg0 + 617 offsetof(struct rdc_status32, maxsets)); 618 nset = status32.nset; 619 620 size = sizeof (struct rdc_set32); 621 copyout = rdc_status_copy32; 622 } else { 623 struct rdc_status status; 624 625 if (ddi_copyin((void *)args->arg0, &status, 626 sizeof (status), mode)) { 627 return (EFAULT); 628 } 629 630 usetp = ((char *)args->arg0) + 631 offsetof(struct rdc_status, rdc_set); 632 maxsetsp = (int32_t *)((char *)args->arg0 + 633 offsetof(struct rdc_status, maxsets)); 634 nset = status.nset; 635 636 size = sizeof (struct rdc_set); 637 copyout = ddi_copyout; 638 } 639 640 max = min(nset, rdc_max_sets); 641 642 for (i = 0, j = 0; i < max; i++) { 643 urdc = &rdc_u_info[i]; 644 krdc = &rdc_k_info[i]; 645 646 if (!IS_ENABLED(urdc)) 647 continue; 648 649 /* 650 * sneak out qstate in urdc->flags 651 * this is harmless because it's value is not used 652 * in urdc->flags. the real qstate is kept in 653 * group->diskq->disk_hdr.h.state 654 */ 655 if (RDC_IS_DISKQ(krdc->group)) { 656 dqp = &krdc->group->diskq; 657 if (IS_QSTATE(dqp, RDC_QNOBLOCK)) 658 urdc->flags |= RDC_QNOBLOCK; 659 } 660 661 j++; 662 if ((*copyout)(urdc, usetp, size, mode) != 0) 663 return (EFAULT); 664 665 urdc->flags &= ~RDC_QNOBLOCK; /* clear qstate */ 666 usetp += size; 667 } 668 669 /* copyout rdc_max_sets value */ 670 671 if (ddi_copyout(&rdc_max_sets, maxsetsp, sizeof (*maxsetsp), mode) != 0) 672 return (EFAULT); 673 674 /* copyout number of sets manipulated */ 675 676 /*CONSTCOND*/ 677 ASSERT(offsetof(struct rdc_status32, nset) == 0); 678 /*CONSTCOND*/ 679 ASSERT(offsetof(struct rdc_status, nset) == 0); 680 681 return (ddi_copyout(&j, (void *)args->arg0, sizeof (int), mode)); 682 } 683 684 685 /* ARGSUSED */ 686 687 static int 688 rdcioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp) 689 { 690 spcs_s_info_t kstatus = NULL; 691 _rdc_ioctl_t args; 692 int error; 693 int rc = 0; 694 695 if (cmd != RDC_STATUS) { 696 if ((error = drv_priv(crp)) != 0) 697 return (error); 698 } 699 #ifdef DEBUG 700 if (cmd == RDC_ASYNC6) { 701 rc = rdc_async6((void *)arg, mode, rvp); 702 return (rc); 703 } 704 705 if (cmd == RDC_CLRKSTAT) { 706 rc = rdc_clrkstat((void *)arg); 707 return (rc); 708 } 709 710 if (cmd == RDC_STALL0) { 711 if (((int)arg > 1) || ((int)arg < 0)) 712 return (EINVAL); 713 rdc_stallzero((int)arg); 714 return (0); 715 } 716 if (cmd == RDC_READGEN) { 717 rc = rdc_readgen((void *)arg, mode, rvp); 718 return (rc); 719 } 720 #endif 721 if (cmd == RDC_BITMAPOP) { 722 rdc_bitmap_op_t bmop; 723 rdc_bitmap_op32_t bmop32; 724 725 if (ddi_model_convert_from(mode & FMODELS) 726 == DDI_MODEL_ILP32) { 727 if (ddi_copyin((void *)arg, &bmop32, sizeof (bmop32), 728 mode)) 729 return (EFAULT); 730 bmop.offset = bmop32.offset; 731 bmop.op = bmop32.op; 732 (void) strncpy(bmop.sechost, bmop32.sechost, 733 MAX_RDC_HOST_SIZE); 734 (void) strncpy(bmop.secfile, bmop32.secfile, 735 NSC_MAXPATH); 736 bmop.len = bmop32.len; 737 bmop.addr = (unsigned long)bmop32.addr; 738 } else { 739 if (ddi_copyin((void *)arg, &bmop, sizeof (bmop), 740 mode)) 741 return (EFAULT); 742 } 743 rc = rdc_bitmapset(bmop.op, bmop.sechost, bmop.secfile, 744 (void *)bmop.addr, bmop.len, bmop.offset, mode); 745 return (rc); 746 } 747 748 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 749 if ((rc = convert_ioctl_args(cmd, arg, mode, &args)) != 0) 750 return (rc); 751 } else { 752 if (ddi_copyin((void *)arg, &args, 753 sizeof (_rdc_ioctl_t), mode)) { 754 return (EFAULT); 755 } 756 } 757 758 kstatus = spcs_s_kcreate(); 759 if (!kstatus) { 760 return (ENOMEM); 761 } 762 763 764 switch (cmd) { 765 766 case RDC_POOL_CREATE: { 767 struct svcpool_args p; 768 769 if (ddi_copyin((void *)arg, &p, sizeof (p), mode)) { 770 spcs_s_kfree(kstatus); 771 return (EFAULT); 772 } 773 error = svc_pool_create(&p); 774 775 break; 776 } 777 case RDC_POOL_WAIT: { 778 int id; 779 780 if (ddi_copyin((void *)arg, &id, sizeof (id), mode)) { 781 spcs_s_kfree(kstatus); 782 return (EFAULT); 783 } 784 785 error = svc_wait(id); 786 break; 787 } 788 case RDC_POOL_RUN: { 789 int id; 790 791 if (ddi_copyin((void *)arg, &id, sizeof (id), mode)) { 792 spcs_s_kfree(kstatus); 793 return (EFAULT); 794 } 795 error = svc_do_run(id); 796 break; 797 } 798 case RDC_ENABLE_SVR: 799 { 800 STRUCT_DECL(rdc_svc_args, parms); 801 802 STRUCT_INIT(parms, mode); 803 /* Only used by sndrd which does not use unistat */ 804 805 if (ddi_copyin((void *)args.arg0, STRUCT_BUF(parms), 806 STRUCT_SIZE(parms), mode)) { 807 spcs_s_kfree(kstatus); 808 return (EFAULT); 809 } 810 rc = rdc_start_server(STRUCT_BUF(parms), mode); 811 } 812 break; 813 814 case RDC_STATUS: 815 rc = rdcstatus(&args, mode); 816 break; 817 818 case RDC_CONFIG: 819 rc = _rdc_config((void *)args.arg0, mode, kstatus, rvp); 820 spcs_s_copyoutf(&kstatus, args.ustatus); 821 return (rc); 822 823 case RDC_VERSION: 824 { 825 STRUCT_DECL(rdc_version, parms); 826 827 STRUCT_INIT(parms, mode); 828 829 STRUCT_FSET(parms, major, sndr_major_rev); 830 STRUCT_FSET(parms, minor, sndr_minor_rev); 831 STRUCT_FSET(parms, micro, sndr_micro_rev); 832 STRUCT_FSET(parms, baseline, sndr_baseline_rev); 833 834 if (ddi_copyout(STRUCT_BUF(parms), (void *)args.arg0, 835 STRUCT_SIZE(parms), mode)) { 836 spcs_s_kfree(kstatus); 837 return (EFAULT); 838 } 839 break; 840 } 841 842 case RDC_LINK_DOWN: 843 /* char *host from user */ 844 rc = _rdc_link_down((void *)args.arg0, mode, kstatus, rvp); 845 spcs_s_copyoutf(&kstatus, args.ustatus); 846 847 return (rc); 848 849 case RDC_SYNC_EVENT: 850 rc = _rdc_sync_event_wait((void *)args.arg0, (void *)args.arg1, 851 mode, kstatus, rvp); 852 spcs_s_copyoutf(&kstatus, args.ustatus); 853 854 return (rc); 855 856 857 default: 858 rc = EINVAL; 859 break; 860 } 861 862 spcs_s_kfree(kstatus); 863 return (rc); 864 } 865 866 int 867 sndr_info_stats_update(kstat_t *ksp, int rw) 868 { 869 extern int rdc_rpc_tmout; 870 extern int rdc_health_thres; 871 extern int rdc_bitmap_delay; 872 extern long rdc_clnt_count; 873 extern long rdc_svc_count; 874 sndr_m_stats_t *info_stats; 875 rdc_k_info_t *krdc; 876 877 info_stats = (sndr_m_stats_t *)(ksp->ks_data); 878 krdc = (rdc_k_info_t *)(ksp->ks_private); 879 880 /* no writes currently allowed */ 881 882 if (rw == KSTAT_WRITE) { 883 return (EACCES); 884 } 885 886 /* default to READ */ 887 info_stats->m_maxsets.value.ul = rdc_max_sets; 888 info_stats->m_maxfbas.value.ul = krdc->maxfbas; 889 info_stats->m_rpc_timeout.value.ul = rdc_rpc_tmout; 890 info_stats->m_health_thres.value.ul = rdc_health_thres; 891 info_stats->m_bitmap_writes.value.ul = krdc->bitmap_write; 892 info_stats->m_bitmap_ref_delay.value.ul = rdc_bitmap_delay; 893 894 /* clts counters not implemented yet */ 895 info_stats->m_clnt_cots_calls.value.ul = rdc_clnt_count; 896 info_stats->m_clnt_clts_calls.value.ul = 0; 897 info_stats->m_svc_cots_calls.value.ul = rdc_svc_count; 898 info_stats->m_svc_clts_calls.value.ul = 0; 899 900 return (0); 901 } 902 903 /* 904 * copy tailsize-1 bytes of tail of s to s1. 905 */ 906 void 907 rdc_str_tail_cpy(char *s1, char *s, size_t tailsize) 908 { 909 /* To avoid un-terminated string, max size is 16 - 1 */ 910 ssize_t offset = strlen(s) - (tailsize - 1); 911 912 offset = (offset > 0) ? offset : 0; 913 914 /* ensure it's null terminated */ 915 (void) strlcpy(s1, (const char *)(s + offset), tailsize); 916 } 917 918 int 919 rdc_info_stats_update(kstat_t *ksp, int rw) 920 { 921 rdc_info_stats_t *rdc_info_stats; 922 rdc_k_info_t *krdc; 923 rdc_u_info_t *urdc; 924 925 rdc_info_stats = (rdc_info_stats_t *)(ksp->ks_data); 926 krdc = (rdc_k_info_t *)(ksp->ks_private); 927 urdc = &rdc_u_info[krdc->index]; 928 929 /* no writes currently allowed */ 930 931 if (rw == KSTAT_WRITE) { 932 return (EACCES); 933 } 934 935 /* default to READ */ 936 rdc_info_stats->s_flags.value.ul = urdc->flags; 937 rdc_info_stats->s_syncflags.value.ul = 938 urdc->sync_flags; 939 rdc_info_stats->s_bmpflags.value.ul = 940 urdc->bmap_flags; 941 rdc_info_stats->s_syncpos.value.ul = 942 urdc->sync_pos; 943 rdc_info_stats->s_volsize.value.ul = 944 urdc->volume_size; 945 rdc_info_stats->s_bits_set.value.ul = 946 urdc->bits_set; 947 rdc_info_stats->s_autosync.value.ul = 948 urdc->autosync; 949 rdc_info_stats->s_maxqfbas.value.ul = 950 urdc->maxqfbas; 951 rdc_info_stats->s_maxqitems.value.ul = 952 urdc->maxqitems; 953 954 kstat_named_setstr(&rdc_info_stats->s_primary_vol, 955 urdc->primary.file); 956 957 kstat_named_setstr(&rdc_info_stats->s_secondary_vol, 958 urdc->secondary.file); 959 960 if (rdc_get_vflags(urdc) & RDC_PRIMARY) { 961 kstat_named_setstr(&rdc_info_stats->s_bitmap, 962 urdc->primary.bitmap); 963 } else { 964 kstat_named_setstr(&rdc_info_stats->s_bitmap, 965 urdc->secondary.bitmap); 966 } 967 968 kstat_named_setstr(&rdc_info_stats->s_primary_intf, 969 urdc->primary.intf); 970 971 kstat_named_setstr(&rdc_info_stats->s_secondary_intf, 972 urdc->secondary.intf); 973 974 rdc_info_stats->s_type_flag.value.ul = krdc->type_flag; 975 rdc_info_stats->s_bitmap_size.value.ul = krdc->bitmap_size; 976 rdc_info_stats->s_disk_status.value.ul = krdc->disk_status; 977 978 if (krdc->intf) { 979 rdc_info_stats->s_if_if_down.value.ul = krdc->intf->if_down; 980 rdc_info_stats->s_if_rpc_version.value.ul = 981 krdc->intf->rpc_version; 982 } 983 984 /* the type can change without disable/re-enable so... */ 985 bzero(rdc_info_stats->s_aqueue_type.value.c, KSTAT_DATA_CHAR_LEN); 986 if (RDC_IS_MEMQ(krdc->group)) { 987 (void) strcpy(rdc_info_stats->s_aqueue_type.value.c, "memory"); 988 rdc_info_stats->s_aqueue_blk_hwm.value.ul = 989 krdc->group->ra_queue.blocks_hwm; 990 rdc_info_stats->s_aqueue_itm_hwm.value.ul = 991 krdc->group->ra_queue.nitems_hwm; 992 rdc_info_stats->s_aqueue_throttle.value.ul = 993 krdc->group->ra_queue.throttle_delay; 994 rdc_info_stats->s_aqueue_items.value.ul = 995 krdc->group->ra_queue.nitems; 996 rdc_info_stats->s_aqueue_blocks.value.ul = 997 krdc->group->ra_queue.blocks; 998 999 } else if (RDC_IS_DISKQ(krdc->group)) { 1000 disk_queue *q = &krdc->group->diskq; 1001 rdc_info_stats->s_aqueue_blk_hwm.value.ul = 1002 krdc->group->diskq.blocks_hwm; 1003 rdc_info_stats->s_aqueue_itm_hwm.value.ul = 1004 krdc->group->diskq.nitems_hwm; 1005 rdc_info_stats->s_aqueue_throttle.value.ul = 1006 krdc->group->diskq.throttle_delay; 1007 rdc_info_stats->s_aqueue_items.value.ul = QNITEMS(q); 1008 rdc_info_stats->s_aqueue_blocks.value.ul = QBLOCKS(q); 1009 (void) strcpy(rdc_info_stats->s_aqueue_type.value.c, "disk"); 1010 } 1011 1012 return (0); 1013 } 1014 1015 void 1016 rdc_kstat_create(int index) 1017 { 1018 int j = index; 1019 rdc_k_info_t *krdc = &rdc_k_info[index]; 1020 rdc_u_info_t *urdc = &rdc_u_info[krdc->index]; 1021 size_t varsize; 1022 1023 if (!krdc->set_kstats) { 1024 krdc->set_kstats = kstat_create(RDC_KSTAT_MODULE, j, 1025 RDC_KSTAT_INFO, RDC_KSTAT_CLASS, KSTAT_TYPE_NAMED, 1026 sizeof (rdc_info_stats_t) / sizeof (kstat_named_t), 1027 KSTAT_FLAG_VIRTUAL); 1028 #ifdef DEBUG 1029 if (!krdc->set_kstats) 1030 cmn_err(CE_NOTE, "krdc:u_kstat null"); 1031 #endif 1032 1033 if (krdc->set_kstats) { 1034 /* calculate exact size of KSTAT_DATA_STRINGs */ 1035 varsize = strlen(urdc->primary.file) + 1 1036 + strlen(urdc->secondary.file) + 1 1037 + strlen(urdc->primary.intf) + 1 1038 + strlen(urdc->secondary.intf) + 1; 1039 if (rdc_get_vflags(urdc) & RDC_PRIMARY) { 1040 varsize += strlen(urdc->primary.bitmap) + 1; 1041 } else { 1042 varsize += strlen(urdc->secondary.bitmap) + 1; 1043 } 1044 1045 krdc->set_kstats->ks_data_size += varsize; 1046 krdc->set_kstats->ks_data = &rdc_info_stats; 1047 krdc->set_kstats->ks_update = rdc_info_stats_update; 1048 krdc->set_kstats->ks_private = &rdc_k_info[j]; 1049 kstat_install(krdc->set_kstats); 1050 } else 1051 cmn_err(CE_WARN, "SNDR: k-kstats failed"); 1052 } 1053 1054 krdc->io_kstats = kstat_create(RDC_KSTAT_MODULE, j, NULL, 1055 "disk", KSTAT_TYPE_IO, 1, 0); 1056 if (krdc->io_kstats) { 1057 krdc->io_kstats->ks_lock = &krdc->kstat_mutex; 1058 kstat_install(krdc->io_kstats); 1059 } 1060 krdc->bmp_kstats = kstat_create("sndrbmp", j, NULL, 1061 "disk", KSTAT_TYPE_IO, 1, 0); 1062 if (krdc->bmp_kstats) { 1063 krdc->bmp_kstats->ks_lock = &krdc->bmp_kstat_mutex; 1064 kstat_install(krdc->bmp_kstats); 1065 } 1066 } 1067 1068 void 1069 rdc_kstat_delete(int index) 1070 { 1071 rdc_k_info_t *krdc = &rdc_k_info[index]; 1072 1073 if (krdc->set_kstats) { 1074 kstat_delete(krdc->set_kstats); 1075 krdc->set_kstats = NULL; 1076 } 1077 1078 if (krdc->io_kstats) { 1079 kstat_delete(krdc->io_kstats); 1080 krdc->io_kstats = NULL; 1081 } 1082 if (krdc->bmp_kstats) { 1083 kstat_delete(krdc->bmp_kstats); 1084 krdc->bmp_kstats = NULL; 1085 } 1086 } 1087 1088 #ifdef DEBUG 1089 /* 1090 * Reset the io_kstat structure of the krdc specified 1091 * by the arg index. 1092 */ 1093 static int 1094 rdc_clrkstat(void *arg) 1095 { 1096 int index; 1097 rdc_k_info_t *krdc; 1098 1099 index = (int)(unsigned long)arg; 1100 if ((index < 0) || (index >= rdc_max_sets)) { 1101 return (EINVAL); 1102 } 1103 krdc = &rdc_k_info[index]; 1104 if (krdc->io_kstats) { 1105 kstat_delete(krdc->io_kstats); 1106 krdc->io_kstats = NULL; 1107 } else { 1108 return (EINVAL); 1109 } 1110 krdc->io_kstats = kstat_create(RDC_KSTAT_MODULE, index, NULL, 1111 "disk", KSTAT_TYPE_IO, 1, 0); 1112 if (krdc->io_kstats) { 1113 krdc->io_kstats->ks_lock = &krdc->kstat_mutex; 1114 kstat_install(krdc->io_kstats); 1115 } else { 1116 return (EINVAL); 1117 } 1118 /* 1119 * clear the high water marks and throttle. 1120 */ 1121 if (krdc->group) { 1122 krdc->group->ra_queue.nitems_hwm = 0; 1123 krdc->group->ra_queue.blocks_hwm = 0; 1124 krdc->group->ra_queue.throttle_delay = 0; 1125 } 1126 return (0); 1127 } 1128 #endif 1129