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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * The "program" executed by the injector consists of a tree of commands.
29 * Routines in this file build and execute said command tree.
32 #include <sys/fm/protocol.h>
36 #include <inj_event.h>
41 * Command tree construction
44 static inj_list_t inj_cmds
;
47 inj_cmds_add(inj_cmd_t
*cmd
)
49 inj_list_append(&inj_cmds
, cmd
);
59 inj_rand_create(inj_defn_t
*ev
, uint_t prob
)
61 inj_randelem_t
*re
= inj_zalloc(sizeof (inj_randelem_t
));
70 inj_rand_add(inj_randelem_t
*list
, inj_randelem_t
*new)
77 inj_cmd_rand(inj_randelem_t
*rlist
)
85 for (i
= 0, r
= rlist
; r
!= NULL
; r
= r
->re_next
, i
++)
89 yyerror("probabilities don't sum to 100\n");
95 cmd
= inj_zalloc(sizeof (inj_cmd_t
));
96 cmd
->cmd_type
= CMD_RANDOM
;
97 cmd
->cmd_num
= nelems
;
98 cmd
->cmd_rand
= inj_alloc(sizeof (inj_randelem_t
*) * nelems
);
101 for (r
= rlist
, i
= 0; i
< nelems
; i
++, r
= r
->re_next
) {
102 tmpprob
= r
->re_prob
;
106 cmd
->cmd_rand
[i
] = r
;
113 inj_cmd_repeat(inj_cmd_t
*repcmd
, uint_t num
)
115 inj_cmd_t
*cmd
= inj_zalloc(sizeof (inj_cmd_t
));
117 cmd
->cmd_type
= CMD_REPEAT
;
119 cmd
->cmd_subcmd
= repcmd
;
125 inj_cmd_send(inj_defn_t
*ev
)
127 inj_cmd_t
*cmd
= inj_zalloc(sizeof (inj_cmd_t
));
129 cmd
->cmd_type
= CMD_SEND_EVENT
;
136 inj_cmd_sleep(uint_t secs
)
138 inj_cmd_t
*cmd
= inj_zalloc(sizeof (inj_cmd_t
));
140 cmd
->cmd_type
= CMD_SLEEP
;
147 inj_cmd_addhrt(hrtime_t delta
)
149 const char *class = "resource.fm.fmd.clock.addhrtime";
150 inj_cmd_t
*cmd
= inj_zalloc(sizeof (inj_cmd_t
));
151 inj_defn_t
*ev
= inj_zalloc(sizeof (inj_defn_t
));
153 ev
->defn_name
= class;
154 ev
->defn_lineno
= yylineno
;
156 if ((errno
= nvlist_alloc(&ev
->defn_nvl
, NV_UNIQUE_NAME
, 0)) != 0)
157 die("failed to allocate nvl for %s event", class);
159 if ((errno
= nvlist_add_string(ev
->defn_nvl
, FM_CLASS
, class)) != 0 ||
160 (errno
= nvlist_add_uint8(ev
->defn_nvl
, FM_VERSION
, 1)) != 0 ||
161 (errno
= nvlist_add_int64(ev
->defn_nvl
, "delta", delta
)) != 0)
162 die("failed to build nvl for %s event", class);
164 cmd
->cmd_type
= CMD_SEND_EVENT
;
173 return (inj_cmd_addhrt(-1LL)); /* clock underflow causes end of time */
179 return (((gethrtime() & ENA_FMT1_TIME_MASK
) <<
180 ENA_FMT1_TIME_SHFT
) | (FM_ENA_FMT1
& ENA_FORMAT_MASK
));
184 cmd_run_send(const inj_mode_ops_t
*mode
, void *hdl
, inj_defn_t
*ev
)
187 (void) printf("sending event %s ... ", ev
->defn_name
);
188 (void) fflush(stdout
);
191 if ((errno
= nvlist_add_boolean_value(ev
->defn_nvl
, "__injected",
193 warn("failed to add __injected to %s", ev
->defn_name
);
195 if (ev
->defn_decl
&& (ev
->defn_decl
->decl_flags
& DECL_F_AUTOENA
) &&
196 (errno
= nvlist_add_uint64(ev
->defn_nvl
, "ena", inj_ena())) != 0)
197 warn("failed to add ena to %s", ev
->defn_name
);
200 nvlist_print(stdout
, ev
->defn_nvl
);
204 mode
->mo_send(hdl
, ev
->defn_nvl
);
207 (void) printf("done\n");
211 cmd_run_random(const inj_mode_ops_t
*mode
, void *hdl
, inj_cmd_t
*cmd
)
213 uint_t num
= lrand48() % 100;
216 for (i
= 1; i
< cmd
->cmd_num
; i
++) {
217 if (cmd
->cmd_rand
[i
]->re_prob
> num
)
221 cmd_run_send(mode
, hdl
, cmd
->cmd_rand
[i
- 1]->re_event
);
225 cmd_run(const inj_mode_ops_t
*mode
, void *hdl
, inj_cmd_t
*cmd
)
227 switch (cmd
->cmd_type
) {
229 cmd_run_send(mode
, hdl
, cmd
->cmd_event
);
233 (void) printf("sleeping for %d sec%s ... ",
234 cmd
->cmd_num
, cmd
->cmd_num
> 1 ? "s" : "");
235 (void) fflush(stdout
);
236 (void) sleep(cmd
->cmd_num
);
237 (void) printf("done\n");
241 cmd_run_random(mode
, hdl
, cmd
);
245 warn("ignoring unknown command type: %d\n", cmd
->cmd_type
);
250 inj_program_run(inj_list_t
*prog
, const inj_mode_ops_t
*mode
, void *mode_arg
)
252 void *hdl
= mode
->mo_open(mode_arg
);
256 for (cmd
= inj_list_next(prog
); cmd
!= NULL
; cmd
= inj_list_next(cmd
)) {
257 if (cmd
->cmd_type
== CMD_REPEAT
) {
258 for (i
= 1; i
<= cmd
->cmd_num
; i
++) {
260 (void) printf("(repeat %d of %d)\n",
263 cmd_run(mode
, hdl
, cmd
->cmd_subcmd
);
266 cmd_run(mode
, hdl
, cmd
);