xref: /titanic_50/usr/src/uts/common/avs/ns/dsw/dsw.c (revision 8e7248e505faa19396d4e853604e3fa7cd2cb3b5)
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	_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,
121 	NULL
122 };
123 
124 struct ii_state {
125 	dev_info_t *dip;
126 	int	instance;
127 };
128 
129 /* used for logging sysevent, gets set in _ii_attach */
130 dev_info_t *ii_dip = NULL;
131 
132 extern _ii_info_t *_ii_info_top;
133 extern _ii_lsthead_t *_ii_cluster_top;
134 extern _ii_lsthead_t *_ii_group_top;
135 extern kmutex_t _ii_cluster_mutex;
136 extern kmutex_t _ii_group_mutex;
137 
138 const int dsw_major_rev = ISS_VERSION_MAJ;	/* Major release number */
139 const int dsw_minor_rev = ISS_VERSION_MIN;	/* Minor release number */
140 const int dsw_micro_rev = ISS_VERSION_MIC;	/* Micro release number */
141 const int dsw_baseline_rev = ISS_VERSION_NUM;	/* Baseline revision */
142 static void *ii_statep;
143 
144 extern int _ii_init_dev();
145 extern void _ii_deinit_dev();
146 extern int _ii_config(intptr_t arg, int ilp32, int *rvp, int iflags);
147 extern int _ii_disable(intptr_t arg, int ilp32, int *rvp);
148 extern int _ii_suspend(intptr_t arg, int ilp32, int *rvp);
149 extern int _ii_bitmap(intptr_t arg, int ilp32, int *rvp);
150 extern int _ii_segment(intptr_t arg, int ilp32, int *rvp);
151 extern int _ii_abort(intptr_t arg, int ilp32, int *rvp);
152 extern int _ii_acopy(intptr_t arg, int ilp32, int *rvp);
153 extern int _ii_copy(intptr_t arg, int ilp32, int *rvp);
154 extern int _ii_shutdown(intptr_t arg, int *rvp);
155 extern int _ii_stat(intptr_t arg, int ilp32, int *rvp);
156 extern int _ii_version(intptr_t arg, int ilp32, int *rvp);
157 extern int _ii_wait(intptr_t arg, int ilp32, int *rvp);
158 extern int _ii_reset(intptr_t arg, int ilp32, int *rvp);
159 extern int _ii_offline(intptr_t arg, int ilp32, int *rvp);
160 extern int _ii_list(intptr_t arg, int ilp32, int *rvp);
161 extern int _ii_listlen(int cmd, int ilp32, int *rvp);
162 extern int _ii_export(intptr_t arg, int ilp32, int *rvp);
163 extern int _ii_join(intptr_t arg, int ilp32, int *rvp);
164 extern int _ii_copyparm(intptr_t arg, int ilp32, int *rvp);
165 extern int _ii_ocreate(intptr_t arg, int ilp32, int *rvp);
166 extern int _ii_oattach(intptr_t arg, int ilp32, int *rvp);
167 extern int _ii_odetach(intptr_t arg, int ilp32, int *rvp);
168 extern int _ii_olist(intptr_t arg, int ilp32, int *rvp);
169 extern int _ii_ostat(intptr_t arg, int ilp32, int *rvp, int is_iost_2);
170 extern int _ii_bitsset(intptr_t arg, int ilp32, int cmd, int *rvp);
171 extern int _ii_gc_list(intptr_t, int, int *, kmutex_t *, _ii_lsthead_t *);
172 extern int _ii_clist(intptr_t arg, int ilp32, int *rvp);
173 extern int _ii_move_grp(intptr_t arg, int ilp32, int *rvp);
174 extern int _ii_change_tag(intptr_t arg, int ilp32, int *rvp);
175 extern int ii_debug;
176 extern int ii_throttle_unit;
177 extern int ii_throttle_delay;
178 extern int ii_copy_direct;
179 extern int ii_bitmap;
180 
181 int
182 _init(void)
183 {
184 	int error;
185 
186 	error = ddi_soft_state_init(&ii_statep, sizeof (struct ii_state), 1);
187 	if (!error) {
188 		error = mod_install(&ii_modlinkage);
189 		if (error)
190 			ddi_soft_state_fini(&ii_statep);
191 	}
192 
193 	return (error);
194 }
195 
196 int
197 _fini(void)
198 {
199 	int error;
200 
201 	error = mod_remove(&ii_modlinkage);
202 	if (!error)
203 		ddi_soft_state_fini(&ii_statep);
204 
205 	return (error);
206 }
207 
208 int
209 _info(struct modinfo *modinfop)
210 {
211 	int rc;
212 
213 	rc = mod_info(&ii_modlinkage, modinfop);
214 
215 	return (rc);
216 }
217 
218 /* ARGSUSED */
219 
220 static int
221 iiprobe(dev_info_t *dip)
222 {
223 	return (DDI_PROBE_SUCCESS);
224 }
225 
226 /*ARGSUSED*/
227 static int
228 ii_stats_update(kstat_t *ksp, int rw)
229 {
230 	if (KSTAT_WRITE == rw) {
231 		return (EACCES);
232 	}
233 
234 	/*
235 	 * We do nothing here for now -- the kstat structure is
236 	 * updated in-place
237 	 */
238 
239 	return (0);
240 }
241 
242 static void
243 ii_create_kstats()
244 {
245 	/* create global info structure */
246 	if (!ii_gkstat) {
247 		ii_gkstat = kstat_create("ii", 0, "global", "StorEdge",
248 		    KSTAT_TYPE_NAMED,
249 		    sizeof (iigkstat) / sizeof (kstat_named_t),
250 		    KSTAT_FLAG_VIRTUAL);
251 		if (ii_gkstat) {
252 			ii_gkstat->ks_data = &iigkstat;
253 			ii_gkstat->ks_update = ii_stats_update;
254 			ii_gkstat->ks_private = 0;
255 			kstat_install(ii_gkstat);
256 
257 			/* fill in immutable values */
258 			iigkstat.ii_debug.value.ul = ii_debug;
259 			iigkstat.ii_bitmap.value.ul = ii_bitmap;
260 			iigkstat.ii_throttle_unit.value.ul = ii_throttle_unit;
261 			iigkstat.ii_throttle_delay.value.ul =
262 			    ii_throttle_delay;
263 			iigkstat.ii_copy_direct.value.ul = ii_copy_direct;
264 		} else {
265 			cmn_err(CE_WARN, "Unable to create II global stats");
266 		}
267 	}
268 }
269 
270 static int
271 iiattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
272 {
273 	struct ii_state *xsp;
274 	int instance;
275 	int i;
276 	intptr_t flags;
277 
278 	if (cmd != DDI_ATTACH) {
279 		return (DDI_FAILURE);
280 	}
281 	/* save the dev_info_t to be used in logging using ddi_log_sysevent */
282 	ii_dip = dip;
283 
284 	instance = ddi_get_instance(dip);
285 	if (ddi_soft_state_zalloc(ii_statep, instance) != 0) {
286 		cmn_err(CE_WARN, "ii: no memory for instance %d state.",
287 		    instance);
288 		return (DDI_FAILURE);
289 	}
290 
291 	flags = 0;
292 	xsp = ddi_get_soft_state(ii_statep, instance);
293 	if (xsp == NULL) {
294 		cmn_err(CE_WARN,
295 		    "ii: attach: could not get state for instance %d.",
296 		    instance);
297 		goto out;
298 	}
299 
300 	ii_debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
301 		DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_debug", 0);
302 	if (ii_debug != 0) {
303 #ifdef DEBUG
304 		cmn_err(CE_NOTE, "ii: initializing ii version %d.%d.%d.%d",
305 		    dsw_major_rev, dsw_minor_rev,
306 		    dsw_micro_rev, dsw_baseline_rev);
307 #else
308 		if (dsw_micro_rev) {
309 			cmn_err(CE_NOTE, "ii: initializing ii version %d.%d.%d",
310 			    dsw_major_rev, dsw_minor_rev, dsw_micro_rev);
311 		} else {
312 			cmn_err(CE_NOTE, "ii: initializing ii version %d.%d",
313 			    dsw_major_rev, dsw_minor_rev);
314 		}
315 #endif
316 		switch (ii_debug) {
317 		case 1:
318 		case 2:	cmn_err(CE_NOTE,
319 			    "ii: ii_debug=%d is enabled.", ii_debug);
320 			break;
321 		default:
322 			cmn_err(CE_WARN,
323 			    "ii: Value of ii_debug=%d is not 0,1 or 2.",
324 			    ii_debug);
325 		}
326 	}
327 
328 	ii_bitmap = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
329 		DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_bitmap", II_WTHRU);
330 	switch (ii_bitmap) {
331 		case II_KMEM:
332 		    if (ii_debug > 0)
333 			cmn_err(CE_NOTE, "ii: ii_bitmap is in memory");
334 		    break;
335 		case II_FWC:
336 		    if (ii_debug > 0)
337 			cmn_err(CE_NOTE, "ii: ii_bitmap is on disk, 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; defaulting WTHRU(%d)",
346 			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 }
655