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 2009 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
_init(void)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
_fini(void)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
_info(struct modinfo * modinfop)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
iiprobe(dev_info_t * dip)221 iiprobe(dev_info_t *dip)
222 {
223 return (DDI_PROBE_SUCCESS);
224 }
225
226 /*ARGSUSED*/
227 static int
ii_stats_update(kstat_t * ksp,int rw)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
ii_create_kstats()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
iiattach(dev_info_t * dip,ddi_attach_cmd_t cmd)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 vers %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,"
338 " no FWC");
339 break;
340 case II_WTHRU:
341 if (ii_debug > 0)
342 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk");
343 break;
344 default:
345 cmn_err(CE_NOTE,
346 "!ii: ii_bitmap=%d out of range; "
347 "defaulting WTHRU(%d)", ii_bitmap, II_WTHRU);
348 ii_bitmap = II_WTHRU;
349 }
350
351 /* pick up these values if in ii.conf, otherwise leave alone */
352 i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
353 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_unit", 0);
354 if (i > 0) {
355 ii_throttle_unit = i;
356 if ((ii_throttle_unit < MIN_THROTTLE_UNIT) ||
357 (ii_throttle_unit > MAX_THROTTLE_UNIT) ||
358 (ii_debug > 0))
359 cmn_err(CE_NOTE,
360 "!ii: ii_throttle_unit=%d", ii_throttle_unit);
361 }
362
363 i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
364 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_delay", 0);
365 if (i > 0) {
366 ii_throttle_delay = i;
367 if ((ii_throttle_delay < MIN_THROTTLE_DELAY) ||
368 (ii_throttle_delay > MIN_THROTTLE_DELAY) ||
369 (ii_debug > 0))
370 cmn_err(CE_NOTE,
371 "!ii: ii_throttle_delay=%d", ii_throttle_delay);
372 }
373
374 ii_copy_direct = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
375 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_copy_direct", 1);
376 if (i > 0) {
377 ii_copy_direct = i;
378 if ((ii_copy_direct < 0) || (ii_copy_direct > 1))
379 cmn_err(CE_NOTE,
380 "!ii: ii_copy_direct=%d", ii_copy_direct);
381 }
382
383 if (_ii_init_dev()) {
384 cmn_err(CE_WARN, "!ii: _ii_init_dev failed");
385 goto out;
386 }
387 flags |= DIDINIT;
388
389 xsp->dip = dip;
390 xsp->instance = instance;
391
392 if (ddi_create_minor_node(dip, "ii", S_IFCHR, instance, DDI_PSEUDO, 0)
393 != DDI_SUCCESS) {
394 cmn_err(CE_WARN, "!ii: could not create node.");
395 goto out;
396 }
397 flags |= DIDNODES;
398
399 ddi_set_driver_private(dip, (caddr_t)flags);
400 ddi_report_dev(dip);
401
402 ii_create_kstats();
403
404 return (DDI_SUCCESS);
405
406 out:
407 ddi_set_driver_private(dip, (caddr_t)flags);
408 (void) iidetach(dip, DDI_DETACH);
409
410 return (DDI_FAILURE);
411 }
412
413 static int
iidetach(dev_info_t * dip,ddi_detach_cmd_t cmd)414 iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
415 {
416 struct ii_state *xsp;
417 int instance;
418 intptr_t flags;
419
420 if (cmd != DDI_DETACH) {
421 return (DDI_FAILURE);
422 }
423
424 if (_ii_info_top) {
425 return (DDI_FAILURE); /* busy */
426 }
427
428 instance = ddi_get_instance(dip);
429 xsp = ddi_get_soft_state(ii_statep, instance);
430 if (xsp == NULL) {
431 cmn_err(CE_WARN,
432 "!ii: detach: could not get state for instance %d.",
433 instance);
434 return (DDI_FAILURE);
435 }
436
437 flags = (intptr_t)ddi_get_driver_private(dip);
438 if (flags & DIDNODES)
439 ddi_remove_minor_node(dip, NULL);
440 if (flags & DIDINIT)
441 _ii_deinit_dev();
442
443 ddi_soft_state_free(ii_statep, instance);
444
445 if (ii_gkstat) {
446 kstat_delete(ii_gkstat);
447 ii_gkstat = NULL;
448 }
449
450 return (DDI_SUCCESS);
451 }
452
453
454 /* ARGSUSED */
455
456 static int
iiopen(dev_t * devp,int flag,int otyp,cred_t * crp)457 iiopen(dev_t *devp, int flag, int otyp, cred_t *crp)
458 {
459 int error;
460
461 error = drv_priv(crp);
462
463 return (error);
464 }
465
466
467 /* ARGSUSED */
468
469 static int
iiclose(dev_t dev,int flag,int otyp,cred_t * crp)470 iiclose(dev_t dev, int flag, int otyp, cred_t *crp)
471 {
472 return (0);
473 }
474
475 /* ARGSUSED */
476
477 static int
iiprint(dev_t dev,char * str)478 iiprint(dev_t dev, char *str)
479 {
480 int instance = 0;
481
482 cmn_err(CE_WARN, "!ii%d: %s", instance, str);
483 return (0);
484 }
485
486 /* ARGSUSED */
487
488 static int
iiioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * crp,int * rvp)489 iiioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp)
490 {
491 int rc;
492 int ilp32;
493
494 ilp32 = (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32);
495
496
497 switch (cmd) {
498 case DSWIOC_WAIT:
499 rc = _ii_wait(arg, ilp32, rvp);
500 break;
501
502 case DSWIOC_RESET:
503 rc = _ii_reset(arg, ilp32, rvp);
504 break;
505
506 case DSWIOC_VERSION:
507 rc = _ii_version(arg, ilp32, rvp);
508 break;
509
510 case DSWIOC_ENABLE:
511 rc = _ii_config(arg, ilp32, rvp, 0);
512 break;
513
514 case DSWIOC_RESUME:
515 rc = _ii_config(arg, ilp32, rvp, II_EXISTING);
516 break;
517
518 case DSWIOC_DISABLE:
519 rc = _ii_disable(arg, ilp32, rvp);
520 break;
521
522 case DSWIOC_SUSPEND:
523 rc = _ii_suspend(arg, ilp32, rvp);
524 break;
525
526 case DSWIOC_ACOPY:
527 rc = _ii_acopy(arg, ilp32, rvp);
528 break;
529
530 case DSWIOC_COPY:
531 rc = _ii_copy(arg, ilp32, rvp);
532 break;
533
534 case DSWIOC_SHUTDOWN:
535 rc = _ii_shutdown(arg, rvp);
536 break;
537
538 case DSWIOC_STAT:
539 rc = _ii_stat(arg, ilp32, rvp);
540 break;
541
542 case DSWIOC_BITMAP:
543 rc = _ii_bitmap(arg, ilp32, rvp);
544 break;
545
546 case DSWIOC_SEGMENT:
547 rc = _ii_segment(arg, ilp32, rvp);
548 break;
549
550 case DSWIOC_ABORT:
551 rc = _ii_abort(arg, ilp32, rvp);
552 break;
553
554 case DSWIOC_OFFLINE:
555 rc = _ii_offline(arg, ilp32, rvp);
556 break;
557
558 case DSWIOC_LIST:
559 rc = _ii_list(arg, ilp32, rvp);
560 break;
561
562 case DSWIOC_LISTLEN:
563 case DSWIOC_OLISTLEN:
564 rc = _ii_listlen(cmd, ilp32, rvp);
565 break;
566
567 case DSWIOC_EXPORT:
568 rc = _ii_export(arg, ilp32, rvp);
569 break;
570
571 case DSWIOC_IMPORT:
572 rc = _ii_config(arg, ilp32, rvp, II_IMPORT);
573 break;
574
575 case DSWIOC_JOIN:
576 rc = _ii_join(arg, ilp32, rvp);
577 break;
578
579 case DSWIOC_COPYP:
580 rc = _ii_copyparm(arg, ilp32, rvp);
581 break;
582
583 case DSWIOC_OCREAT:
584 rc = _ii_ocreate(arg, ilp32, rvp);
585 break;
586
587 case DSWIOC_OATTACH:
588 rc = _ii_oattach(arg, ilp32, rvp);
589 break;
590
591 case DSWIOC_ODETACH:
592 rc = _ii_odetach(arg, ilp32, rvp);
593 break;
594
595 case DSWIOC_OLIST:
596 rc = _ii_olist(arg, ilp32, rvp);
597 break;
598
599 case DSWIOC_OSTAT:
600 rc = _ii_ostat(arg, ilp32, rvp, FALSE);
601 break;
602
603 case DSWIOC_OSTAT2:
604 rc = _ii_ostat(arg, ilp32, rvp, TRUE);
605 break;
606
607 case DSWIOC_SBITSSET:
608 case DSWIOC_CBITSSET:
609 rc = _ii_bitsset(arg, ilp32, cmd, rvp);
610 break;
611
612 case DSWIOC_CLIST:
613 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_cluster_mutex,
614 _ii_cluster_top);
615 break;
616
617 case DSWIOC_GLIST:
618 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_group_mutex,
619 _ii_group_top);
620 break;
621
622 case DSWIOC_MOVEGRP:
623 rc = _ii_move_grp(arg, ilp32, rvp);
624 break;
625
626 case DSWIOC_CHANGETAG:
627 rc = _ii_change_tag(arg, ilp32, rvp);
628 break;
629
630 default:
631 rc = EINVAL;
632 break;
633 }
634
635 return (rc);
636 }
637
638 /*
639 * dummy function
640 */
641
642 static int
iistrat(struct buf * bp)643 iistrat(struct buf *bp)
644 {
645 bp->b_error = EIO;
646 biodone(bp);
647
648 return (0);
649 }
650
651 static int
iiread()652 iiread()
653 {
654 return (EIO);
655 }
656