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
ss_ram_init()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
ss_ram_deinit()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
ss_ram_configure(ss_common_config_t * clientptr,spcs_s_info_t kstatus)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
ss_ram_deconfigure(int dirty)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
ss_ram_deconfigure_locked()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
ss_ram_getvdir(const ss_vdirkey_t * key,ss_vdir_t * vdir)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
ss_ram_getvdirent(const ss_vdir_t * vdir,ss_voldata_t * vol)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
ss_ram_getvol(ss_voldata_t * voldata)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
ss_ram_setvol(const ss_voldata_t * voldata)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
ss_ram_getcdir(const ss_cdirkey_t * key,ss_cdir_t * cdir)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
ss_ram_getcdirent(ss_cdir_t * cdir,ss_centry_info_t * centry)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
ss_ram_allocresource(int need,int * stall,ss_resourcelist_t ** reslist)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
ss_ram_deallocresource(ss_resource_t * res)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
ss_ram_getresource(ss_resourcelist_t ** reslist,ss_resource_t ** res)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
ss_ram_getcentry(ss_centry_info_t * centry)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
ss_ram_setcentry(const ss_centry_info_t * centry)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
ss_ram_cblock_read(const ss_resource_t * res,void * buf,int count,int srcoffset)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
ss_ram_cblock_write(const ss_resource_t * res,const void * buf,int count,int destoffset)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
ss_ram_ctl(uint_t cmd,uintptr_t arg)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
ss_ram_vol_configure(int maxvols)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
ss_ram_vol_deconfigure()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
ss_ram_wctl_configure()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
ss_ram_wctl_deconfigure()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 }
615