xref: /titanic_41/usr/src/uts/common/avs/ns/sdbc/safestore_ram.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
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