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 /* 27 * RAM Safe Store Module 28 */ 29 30 #include <sys/types.h> 31 #include <sys/ksynch.h> 32 #include <sys/kmem.h> 33 #include <sys/cmn_err.h> 34 #include <sys/errno.h> 35 36 #include <sys/nsc_thread.h> 37 #include "sd_cache.h" 38 #include "sd_trace.h" 39 #include <sys/unistat/spcs_s.h> 40 #include <sys/unistat/spcs_s_k.h> 41 #include <sys/unistat/spcs_errors.h> 42 43 #include "safestore.h" 44 #include "safestore_impl.h" 45 #include "safestore_ram.h" 46 47 extern void _sd_print(int level, char *fmt, ...); 48 49 static int ss_ram_configure(ss_common_config_t *, spcs_s_info_t); 50 static int ss_ram_deconfigure(int); 51 static int ss_ram_getvdir(const ss_vdirkey_t *, ss_vdir_t *); 52 static int ss_ram_getvdirent(const ss_vdir_t *, ss_voldata_t *); 53 static int ss_ram_getvol(ss_voldata_t *); 54 static int ss_ram_setvol(const ss_voldata_t *); 55 static int ss_ram_getcdir(const ss_cdirkey_t *, ss_cdir_t *); 56 static int ss_ram_getcdirent(ss_cdir_t *, ss_centry_info_t *); 57 static int ss_ram_allocresource(int, int *, ss_resourcelist_t **); 58 static void ss_ram_deallocresource(ss_resource_t *); 59 static int ss_ram_getresource(ss_resourcelist_t **, ss_resource_t **); 60 static int ss_ram_getcentry(ss_centry_info_t *); 61 static int ss_ram_setcentry(const ss_centry_info_t *); 62 static int ss_ram_cblock_read(const ss_resource_t *, void *, int, int); 63 static int ss_ram_cblock_write(const ss_resource_t *, const void *, int, int); 64 static int ss_ram_ctl(uint_t, uintptr_t); 65 66 67 safestore_ops_t ss_ram_ops = { 68 "safestore_ram", 69 SS_M_RAM | SS_T_NONE, 70 0, 71 ss_ram_configure, 72 ss_ram_deconfigure, 73 ss_ram_getvdir, 74 ss_ram_getvdirent, 75 ss_ram_getvol, 76 ss_ram_setvol, 77 ss_ram_getcdir, 78 ss_ram_getcdirent, 79 ss_ram_allocresource, 80 ss_ram_deallocresource, 81 ss_ram_getresource, 82 ss_ram_getcentry, 83 ss_ram_setcentry, 84 ss_ram_cblock_read, 85 ss_ram_cblock_write, 86 ss_ram_ctl 87 }; 88 89 static void ss_ram_vol_deconfigure(); 90 static int ss_ram_vol_configure(int); 91 static int ss_ram_wctl_configure(); 92 static void ss_ram_wctl_deconfigure(void); 93 static int ss_ram_deconfigure_locked(); 94 95 static kmutex_t ss_ram_config_lock; 96 97 static ss_common_config_t ss_ramcommon_config; 98 static ss_ram_config_t ss_ram_config; 99 100 static char default_cblock [8192]; 101 102 103 #define MEGABYTE (1024*1024) 104 105 void 106 ss_ram_init() 107 { 108 mutex_init(&ss_ram_config_lock, NULL, MUTEX_DRIVER, NULL); 109 bzero(&ss_ram_config, sizeof (ss_ram_config_t)); 110 bzero(&ss_ramcommon_config, sizeof (ss_common_config_t)); 111 sst_register_mod(&ss_ram_ops); 112 113 ss_ram_config.ss_configured = SS_INITTED; 114 } 115 116 void 117 ss_ram_deinit() 118 { 119 mutex_destroy(&ss_ram_config_lock); 120 sst_unregister_mod(&ss_ram_ops); 121 } 122 123 124 /* ARGSUSED */ 125 static int 126 ss_ram_configure(ss_common_config_t *clientptr, spcs_s_info_t kstatus) 127 { 128 129 if (clientptr->ssc_wsize == 0) /* choose a default? */ 130 return (EINVAL); 131 132 mutex_enter(&ss_ram_config_lock); 133 134 /* read in the parameters */ 135 bcopy(clientptr, &ss_ramcommon_config, sizeof (ss_common_config_t)); 136 137 /* set the page size */ 138 ss_ramcommon_config.ssc_ss_psize = BLK_SIZE(1); 139 140 /* initialize client page size if not set */ 141 if (ss_ramcommon_config.ssc_client_psize == 0) 142 ss_ramcommon_config.ssc_client_psize = 143 ss_ramcommon_config.ssc_ss_psize; 144 145 /* setup volume directory */ 146 if (ss_ram_vol_configure(clientptr->ssc_maxfiles)) { 147 (void) ss_ram_deconfigure_locked(); 148 mutex_exit(&ss_ram_config_lock); 149 return (SDBC_ENONETMEM); 150 } 151 152 /* setup write q */ 153 if (ss_ram_wctl_configure()) { 154 (void) ss_ram_deconfigure_locked(); 155 mutex_exit(&ss_ram_config_lock); 156 return (SDBC_ENONETMEM); 157 } 158 159 if (ss_ramcommon_config.ssc_flag & SS_GENPATTERN) { 160 (void) _sd_fill_pattern(default_cblock, 161 ss_ramcommon_config.ssc_pattern, 162 sizeof (default_cblock)); 163 } 164 165 ss_ram_config.ss_configured = SS_CONFIGURED; 166 /* update client */ 167 bcopy(&ss_ramcommon_config, clientptr, sizeof (ss_common_config_t)); 168 169 mutex_exit(&ss_ram_config_lock); 170 return (SS_OK); 171 } 172 173 /* acquires the ss_ram_config_lock and calls ss_ram_deconfigure_locked() */ 174 /* ARGSUSED */ 175 static int 176 ss_ram_deconfigure(int dirty) 177 { 178 int rc; 179 180 if (ss_ram_config.ss_configured != SS_CONFIGURED) 181 return (SS_ERR); 182 183 mutex_enter(&ss_ram_config_lock); 184 rc = ss_ram_deconfigure_locked(); 185 mutex_exit(&ss_ram_config_lock); 186 187 return (rc); 188 } 189 190 /* 191 * internal use only 192 * caller should acquire config lock before calling this function 193 */ 194 static int 195 ss_ram_deconfigure_locked() 196 { 197 ss_ram_wctl_deconfigure(); 198 ss_ram_vol_deconfigure(); 199 200 ss_ram_config.ss_configured = 0; 201 return (SS_OK); 202 } 203 204 static int 205 ss_ram_getvdir(const ss_vdirkey_t *key, ss_vdir_t *vdir) 206 { 207 ss_ram_vdir_t *ram_vdir = (ss_ram_vdir_t *)vdir; 208 int rc = SS_OK; 209 210 if ((key == NULL) || (vdir == NULL)) 211 return (SS_ERR); 212 213 switch (key->vk_type) { 214 case VDIR_ALL: 215 ram_vdir->rv_type = VDIR_ALL; 216 ram_vdir->rv_u.rv_all.rv_current = 217 ss_ram_config.sn_volumes; 218 ram_vdir->rv_u.rv_all.rv_end = 219 ss_ram_config.sn_volumes + 220 ss_ramcommon_config.ssc_maxfiles; 221 break; 222 case VDIR_VOL: 223 case VDIR_NODE: 224 default: 225 rc = SS_ERR; 226 break; 227 } 228 229 return (rc); 230 } 231 232 233 static int 234 ss_ram_getvdirent(const ss_vdir_t *vdir, ss_voldata_t *vol) 235 { 236 int rc = SS_OK; 237 238 ss_ram_vdir_t *ram_vdir = (ss_ram_vdir_t *)vdir; 239 240 if (vol == NULL) 241 return (SS_ERR); 242 243 if (vdir == NULL) 244 return (SS_ERR); 245 246 switch (ram_vdir->rv_type) { 247 case VDIR_ALL: 248 if (ram_vdir->rv_u.rv_all.rv_current == 249 ram_vdir->rv_u.rv_all.rv_end) { 250 rc = SS_EOF; 251 } else { 252 /* stuff client copy with token */ 253 vol->sv_vol = (ss_vol_t *) 254 ram_vdir->rv_u.rv_all.rv_current++; 255 256 /* get the volume data */ 257 rc = ss_ram_getvol(vol); 258 } 259 break; 260 case VDIR_VOL: 261 case VDIR_NODE: 262 default: 263 rc = SS_ERR; 264 break; 265 } 266 267 return (rc); 268 } 269 270 static int 271 ss_ram_getvol(ss_voldata_t *voldata) 272 { 273 ss_voldata_impl_t *ramvoldata; 274 275 if (voldata == NULL) 276 return (SS_ERR); 277 278 /* get the pointer to the volume entry */ 279 ramvoldata = (ss_voldata_impl_t *)voldata->sv_vol; 280 281 if (ramvoldata == NULL) 282 return (SS_ERR); 283 284 /* stuff the client structure from the ram entry */ 285 voldata->sv_cd = ramvoldata->svi_cd; 286 voldata->sv_pinned = ramvoldata->svi_pinned; 287 voldata->sv_attached = ramvoldata->svi_attached; 288 voldata->sv_devidsz = ramvoldata->svi_devidsz; 289 290 bcopy(ramvoldata->svi_volname, voldata->sv_volname, 291 sizeof (voldata->sv_volname)); 292 293 bcopy(ramvoldata->svi_devid, voldata->sv_devid, 294 sizeof (voldata->sv_devid)); 295 return (SS_OK); 296 } 297 298 static int 299 ss_ram_setvol(const ss_voldata_t *voldata) 300 { 301 ss_voldata_impl_t *ramvoldata; 302 303 if (voldata == NULL) 304 return (SS_ERR); 305 306 /* get the pointer to the volume entry */ 307 ramvoldata = (ss_voldata_impl_t *)voldata->sv_vol; 308 309 if (ramvoldata == NULL) 310 return (SS_ERR); 311 312 /* load the volume entry from the client structure */ 313 ramvoldata->svi_cd = voldata->sv_cd; 314 ramvoldata->svi_pinned = voldata->sv_pinned; 315 ramvoldata->svi_attached = voldata->sv_attached; 316 ramvoldata->svi_devidsz = voldata->sv_devidsz; 317 bcopy(voldata->sv_volname, ramvoldata->svi_volname, 318 sizeof (ramvoldata->svi_volname)); 319 320 bcopy(voldata->sv_devid, ramvoldata->svi_devid, 321 sizeof (ramvoldata->svi_devid)); 322 return (SS_OK); 323 } 324 325 static int 326 ss_ram_getcdir(const ss_cdirkey_t *key, ss_cdir_t *cdir) 327 { 328 ss_ram_cdir_t *ram_cdir = (ss_ram_cdir_t *)cdir; 329 int rc = 0; 330 331 if ((key == NULL) || (cdir == NULL)) 332 return (SS_ERR); 333 334 switch (key->ck_type) { 335 case CDIR_ALL: 336 { int blocks; 337 338 blocks = ss_ramcommon_config.ssc_wsize / 339 ss_ramcommon_config.ssc_client_psize; 340 341 ram_cdir->rc_type = CDIR_ALL; 342 ram_cdir->rc_u.rc_all.rc_current = 343 ss_ram_config.sn_wr_cctl; 344 ram_cdir->rc_u.rc_all.rc_end = 345 ss_ram_config.sn_wr_cctl + blocks; 346 } 347 break; 348 case CDIR_VOL: 349 case CDIR_NODE: 350 default: 351 rc = SS_ERR; 352 break; 353 } 354 355 return (rc); 356 } 357 358 static int 359 ss_ram_getcdirent(ss_cdir_t *cdir, ss_centry_info_t *centry) 360 { 361 int rc = SS_OK; 362 363 ss_ram_cdir_t *ram_cdir = (ss_ram_cdir_t *)cdir; 364 365 if (centry == NULL) 366 return (SS_ERR); 367 368 if (cdir == NULL) 369 return (SS_ERR); 370 371 switch (ram_cdir->rc_type) { 372 case CDIR_ALL: 373 if (ram_cdir->rc_u.rc_all.rc_current == 374 ram_cdir->rc_u.rc_all.rc_end) { 375 rc = SS_EOF; 376 } else { 377 /* stuff client copy with token */ 378 centry->sc_res = (ss_resource_t *) 379 ram_cdir->rc_u.rc_all.rc_current++; 380 381 /* get the centry data */ 382 rc = ss_ram_getcentry(centry); 383 } 384 break; 385 case CDIR_VOL: 386 case CDIR_NODE: 387 default: 388 rc = SS_ERR; 389 break; 390 } 391 392 return (rc); 393 } 394 395 static int 396 ss_ram_allocresource(int need, int *stall, ss_resourcelist_t **reslist) 397 { 398 if (reslist == NULL) 399 return (SS_ERR); 400 401 *reslist = ((ss_resourcelist_t *)ss_alloc_write(need, stall, 402 &(ss_ram_config.sn_wr_queue))); 403 if (*reslist == NULL) /* do sync write */ 404 return (SS_ERR); 405 406 return (SS_OK); 407 } 408 409 static void 410 ss_ram_deallocresource(ss_resource_t *res) 411 { 412 ss_release_write((ss_wr_cctl_t *)res, &(ss_ram_config.sn_wr_queue)); 413 } 414 415 static int 416 ss_ram_getresource(ss_resourcelist_t **reslist, ss_resource_t **res) 417 { 418 if ((res == NULL) || (reslist == NULL)) { 419 return (SS_ERR); 420 } 421 422 if (*reslist == NULL) 423 return (SS_EOF); 424 425 *res = (ss_resource_t *)(*reslist); 426 *reslist = (ss_resourcelist_t *) 427 ((ss_wr_cctl_t *)(*reslist))->wc_next; 428 429 return (SS_OK); 430 } 431 432 static int 433 ss_ram_getcentry(ss_centry_info_t *centry) 434 { 435 ss_wr_cctl_t *wctl; 436 ss_centry_info_impl_t *ramcentry = (ss_centry_info_impl_t *)centry; 437 438 if (centry == NULL) 439 return (SS_ERR); 440 else 441 wctl = (ss_wr_cctl_t *)centry->sc_res; 442 443 if (wctl == NULL) 444 return (SS_ERR); 445 446 if (wctl->wc_gl_info) 447 bcopy(wctl->wc_gl_info, ramcentry, 448 sizeof (ss_centry_info_impl_t)); 449 else 450 return (SS_ERR); 451 452 return (SS_OK); 453 } 454 455 static int 456 ss_ram_setcentry(const ss_centry_info_t *centry) 457 { 458 ss_wr_cctl_t *wctl; 459 ss_centry_info_impl_t *ramcentry = (ss_centry_info_impl_t *)centry; 460 461 if (centry == NULL) 462 return (SS_ERR); 463 else 464 wctl = (ss_wr_cctl_t *)centry->sc_res; 465 466 if (wctl == NULL) 467 return (SS_ERR); 468 469 if (wctl->wc_gl_info) 470 bcopy(ramcentry, wctl->wc_gl_info, 471 sizeof (ss_centry_info_impl_t)); 472 else 473 return (SS_ERR); 474 475 return (SS_OK); 476 } 477 478 479 static int 480 ss_ram_cblock_read(const ss_resource_t *res, void *buf, 481 int count, int srcoffset) 482 { 483 if ((res == NULL) || (buf == NULL)) 484 return (SS_ERR); 485 486 if ((srcoffset < 0) || 487 (srcoffset > ss_ramcommon_config.ssc_client_psize)) 488 return (SS_ERR); 489 490 bcopy(default_cblock + srcoffset, buf, count); 491 492 return (SS_OK); 493 } 494 495 static int 496 ss_ram_cblock_write(const ss_resource_t *res, 497 const void *buf, int count, int destoffset) 498 { 499 if ((res == NULL) || (buf == NULL)) 500 return (SS_ERR); 501 502 if ((destoffset < 0) || 503 (destoffset > ss_ramcommon_config.ssc_client_psize)) 504 return (SS_ERR); 505 506 bcopy(buf, default_cblock + destoffset, count); 507 508 return (SS_OK); 509 } 510 511 static int 512 ss_ram_ctl(uint_t cmd, uintptr_t arg) 513 { 514 int rc = SS_OK; 515 516 switch (cmd) { 517 case SSIOC_STATS: 518 ((ssioc_stats_t *)arg)->wq_inq = 519 ss_ram_config.sn_wr_queue.wq_inq; 520 break; 521 default: 522 cmn_err(CE_WARN, "ss_nvs_ctl: cmd %x not supported", 523 cmd); 524 rc = ENOTTY; 525 break; 526 } 527 528 return (rc); 529 } 530 531 static int 532 ss_ram_vol_configure(int maxvols) 533 { 534 if ((ss_ram_config.sn_volumes = kmem_zalloc(maxvols * 535 sizeof (ss_voldata_impl_t), KM_NOSLEEP)) == NULL) 536 return (-1); 537 538 return (0); 539 } 540 541 static void 542 ss_ram_vol_deconfigure() 543 { 544 int maxvols = ss_ramcommon_config.ssc_maxfiles; 545 546 if (ss_ram_config.sn_volumes) 547 kmem_free(ss_ram_config.sn_volumes, 548 maxvols * sizeof (ss_voldata_impl_t)); 549 } 550 551 static int 552 ss_ram_wctl_configure() 553 { 554 int blocks; 555 ss_wr_cctl_t *wentry; 556 static ss_centry_info_impl_t *gl; 557 int i; 558 559 blocks = ss_ramcommon_config.ssc_wsize / 560 ss_ramcommon_config.ssc_client_psize; 561 562 if ((ss_ram_config.sn_wr_cctl = (ss_wr_cctl_t *) 563 kmem_zalloc(blocks * sizeof (ss_wr_cctl_t), KM_NOSLEEP)) 564 == NULL) { 565 return (-1); 566 } 567 568 if ((ss_ram_config.sn_gl_centry_info = (ss_centry_info_impl_t *) 569 kmem_zalloc(blocks * sizeof (ss_centry_info_impl_t), 570 KM_NOSLEEP)) == NULL) { 571 return (-1); 572 } 573 574 /* 575 * Mini-DSP: no write/ft area 576 * (ie forced_wrthru clear) 577 */ 578 579 if (_sdbc_writeq_configure(&(ss_ram_config.sn_wr_queue)) != 0) 580 return (-1); 581 582 gl = ss_ram_config.sn_gl_centry_info; 583 584 wentry = ss_ram_config.sn_wr_cctl; 585 for (i = 0; i < blocks; ++i, ++wentry) { 586 wentry->wc_gl_info = gl++; 587 ss_release_write(wentry, &(ss_ram_config.sn_wr_queue)); 588 } 589 590 ss_ram_config.sn_wr_queue.wq_nentries = blocks; 591 592 return (0); 593 } 594 595 static void 596 ss_ram_wctl_deconfigure() 597 { 598 int blocks; 599 600 _sdbc_writeq_deconfigure(&(ss_ram_config.sn_wr_queue)); 601 602 blocks = ss_ramcommon_config.ssc_wsize / 603 ss_ramcommon_config.ssc_client_psize; 604 605 if (ss_ram_config.sn_wr_cctl) { 606 kmem_free(ss_ram_config.sn_wr_cctl, 607 blocks * sizeof (ss_wr_cctl_t)); 608 } 609 610 if (ss_ram_config.sn_gl_centry_info) { 611 kmem_free(ss_ram_config.sn_gl_centry_info, 612 blocks * sizeof (ss_centry_info_impl_t)); 613 } 614 }