4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include <librcm_event.h>
38 * Event handling routine
48 static void process_event(int, int, nvlist_t
*, nvlist_t
**);
49 static void generate_reply_event(int, rcm_info_t
*, nvlist_t
**);
50 static void rcm_print_nvlist(nvlist_t
*);
53 * Top level function for event service
56 event_service(void **data
, size_t *datalen
)
64 rcm_log_message(RCM_TRACE1
, "received door operation\n");
66 /* Decode the data from the door into an unpacked nvlist */
67 if (data
== NULL
|| datalen
== NULL
) {
68 rcm_log_message(RCM_ERROR
, "received null door argument\n");
71 if (lerrno
= nvlist_unpack(*data
, *datalen
, &nvl
, 0)) {
72 rcm_log_message(RCM_ERROR
, "received bad door argument, %s\n",
77 /* Do nothing if the door is just being knocked on */
78 if (errno
= nvlist_lookup_int32(nvl
, RCM_CMD
, &cmd
)) {
79 rcm_log_message(RCM_ERROR
,
80 "bad door argument (nvlist_lookup=%s)\n", strerror(errno
));
84 if (cmd
== CMD_KNOCK
) {
85 rcm_log_message(RCM_TRACE1
, "door event was just a knock\n");
93 * Go increment thread count. Before daemon is fully initialized,
94 * the event processing blocks inside this function.
96 seq_num
= rcmd_thr_incr(cmd
);
98 process_event(cmd
, seq_num
, nvl
, &ret
);
103 * Decrement thread count
113 * Actually processes events; returns a reply event
116 process_event(int cmd
, int seq_num
, nvlist_t
*nvl
, nvlist_t
**ret
)
120 uint_t nvl_nrsrcs
= 0;
122 uint32_t flag
= (uint32_t)0;
123 uint64_t pid64
= (uint64_t)0;
125 size_t interval_size
= 0;
126 timespec_t
*interval
= NULL
;
127 nvlist_t
*change_data
= NULL
;
128 nvlist_t
*event_data
= NULL
;
129 rcm_info_t
*info
= NULL
;
130 char *modname
= NULL
;
132 char **rsrcnames
= NULL
;
133 char **nvl_rsrcs
= NULL
;
135 rcm_log_message(RCM_TRACE2
, "servicing door command=%d\n", cmd
);
137 rcm_print_nvlist(nvl
);
140 * Extract data from the door argument nvlist. Not all arguments
141 * are needed; sanity checks are performed later.
143 (void) nvlist_lookup_string_array(nvl
, RCM_RSRCNAMES
, &nvl_rsrcs
,
145 (void) nvlist_lookup_string(nvl
, RCM_CLIENT_MODNAME
, &modname
);
146 (void) nvlist_lookup_uint64(nvl
, RCM_CLIENT_ID
, (uint64_t *)&pid64
);
148 (void) nvlist_lookup_uint32(nvl
, RCM_REQUEST_FLAG
, (uint32_t *)&flag
);
149 (void) nvlist_lookup_byte_array(nvl
, RCM_SUSPEND_INTERVAL
,
150 (uchar_t
**)&interval
, &interval_size
);
151 (void) nvlist_lookup_byte_array(nvl
, RCM_CHANGE_DATA
, (uchar_t
**)&buf
,
153 if (buf
!= NULL
&& buflen
> 0) {
154 (void) nvlist_unpack(buf
, buflen
, &change_data
, 0);
158 (void) nvlist_lookup_byte_array(nvl
, RCM_EVENT_DATA
, (uchar_t
**)&buf
,
160 if (buf
!= NULL
&& buflen
> 0)
161 (void) nvlist_unpack(buf
, buflen
, &event_data
, 0);
163 rsrcnames
= s_calloc(nvl_nrsrcs
+ 1, sizeof (char *));
164 for (i
= 0; i
< nvl_nrsrcs
; i
++) {
165 rsrcnames
[i
] = nvl_rsrcs
[i
];
167 rsrcnames
[nvl_nrsrcs
] = NULL
;
170 * Switch off the command being performed to do the appropriate
171 * sanity checks and dispatch the arguments to the appropriate
172 * implementation routine.
176 if ((modname
== NULL
) || (rsrcnames
== NULL
) ||
177 (rsrcnames
[0] == NULL
))
179 error
= add_resource_client(modname
, rsrcnames
[0], pid
, flag
,
184 if ((modname
== NULL
) || (rsrcnames
== NULL
) ||
185 (rsrcnames
[0] == NULL
))
187 error
= remove_resource_client(modname
, rsrcnames
[0], pid
,
192 if ((rsrcnames
== NULL
) &&
193 ((flag
& (RCM_DR_OPERATION
| RCM_MOD_INFO
)) == 0))
195 if ((error
= get_resource_info(rsrcnames
, flag
, seq_num
, &info
))
197 rcm_log_message(RCM_DEBUG
,
198 "invalid argument in get info request\n");
199 generate_reply_event(EINVAL
, NULL
, ret
);
205 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
) ||
208 error
= process_resource_suspend(rsrcnames
, pid
, flag
, seq_num
,
213 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
))
215 error
= notify_resource_resume(rsrcnames
, pid
, flag
, seq_num
,
220 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
))
222 error
= process_resource_offline(rsrcnames
, pid
, flag
, seq_num
,
227 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
))
229 error
= notify_resource_online(rsrcnames
, pid
, flag
, seq_num
,
234 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
))
236 error
= notify_resource_remove(rsrcnames
, pid
, flag
, seq_num
,
241 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
) ||
242 (event_data
== NULL
))
244 error
= notify_resource_event(rsrcnames
[0], pid
, flag
, seq_num
,
246 nvlist_free(event_data
);
249 case CMD_REQUEST_CHANGE
:
250 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
) ||
251 (change_data
== NULL
))
253 error
= request_capacity_change(rsrcnames
[0], pid
, flag
,
254 seq_num
, change_data
, &info
);
255 nvlist_free(change_data
);
258 case CMD_NOTIFY_CHANGE
:
259 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
) ||
260 (change_data
== NULL
))
262 error
= notify_capacity_change(rsrcnames
[0], pid
, flag
, seq_num
,
264 nvlist_free(change_data
);
268 if ((rsrcnames
== NULL
) || (rsrcnames
[0] == NULL
))
270 error
= get_resource_state(rsrcnames
[0], pid
, &info
);
274 rcm_log_message(RCM_WARNING
,
275 gettext("unknown door command: %d\n"), cmd
);
276 generate_reply_event(EFAULT
, NULL
, ret
);
277 (void) free(rsrcnames
);
281 rcm_log_message(RCM_TRACE2
, "finish processing event 0x%x\n", cmd
);
282 generate_reply_event(error
, info
, ret
);
283 (void) free(rsrcnames
);
287 rcm_log_message(RCM_WARNING
,
288 gettext("data error in door arguments for cmd 0x%x\n"), cmd
);
290 generate_reply_event(EFAULT
, NULL
, ret
);
291 (void) free(rsrcnames
);
296 * Generate reply event from resource registration information
299 generate_reply_event(int error
, rcm_info_t
*info
, nvlist_t
**ret
)
301 nvlist_t
*nvl
= NULL
;
306 rcm_log_message(RCM_TRACE4
, "generating reply event\n");
308 /* Allocate an empty nvlist */
309 if ((errno
= nvlist_alloc(&nvl
, 0, 0)) > 0) {
310 rcm_log_message(RCM_ERROR
,
311 gettext("nvlist_alloc failed: %s\n"), strerror(errno
));
315 /* Encode the result of the operation in the nvlist */
316 if (errno
= nvlist_add_int32(nvl
, RCM_RESULT
, error
)) {
317 rcm_log_message(RCM_ERROR
,
318 gettext("nvlist_add(RESULT) failed: %s\n"),
323 /* Go through the RCM info tuples, appending them all to the nvlist */
329 if (errno
= nvlist_pack(tmp
->info
, &buf
, &buflen
,
330 NV_ENCODE_NATIVE
, 0)) {
331 rcm_log_message(RCM_ERROR
,
332 gettext("nvlist_pack(INFO) failed: %s\n"),
336 if (errno
= nvlist_add_byte_array(nvl
, RCM_RESULT_INFO
,
337 (uchar_t
*)buf
, buflen
)) {
338 rcm_log_message(RCM_ERROR
,
339 gettext("nvlist_add(INFO) failed: %s\n"),
344 nvlist_free(tmp
->info
);
351 /* Return the nvlist (unpacked) in the return argument */
352 rcm_print_nvlist(nvl
);
357 rcm_print_nvlist(nvlist_t
*nvl
)
361 uint16_t data_uint16
;
363 uint32_t data_uint32
;
365 uint64_t data_uint64
;
368 uint_t data_nstrings
;
369 nvpair_t
*nvp
= NULL
;
374 rcm_log_message(RCM_TRACE3
, "event attributes:\n");
376 while (nvp
= nvlist_next_nvpair(nvl
, nvp
)) {
377 type
= nvpair_type(nvp
);
378 name
= nvpair_name(nvp
);
379 rcm_log_message(RCM_TRACE3
, "\t%s(%d)=", name
, type
);
382 case DATA_TYPE_BOOLEAN
:
383 rcm_log_message(RCM_TRACE3
, "True (boolean)\n");
387 (void) nvpair_value_byte(nvp
, &data_byte
);
388 rcm_log_message(RCM_TRACE3
, "0x%x (byte)\n",
392 case DATA_TYPE_INT16
:
393 (void) nvpair_value_int16(nvp
, &data_int16
);
394 rcm_log_message(RCM_TRACE3
, "0x%x (int16)\n",
398 case DATA_TYPE_UINT16
:
399 (void) nvpair_value_uint16(nvp
, &data_uint16
);
400 rcm_log_message(RCM_TRACE3
, "0x%x (uint16)\n",
404 case DATA_TYPE_INT32
:
405 (void) nvpair_value_int32(nvp
, &data_int32
);
406 rcm_log_message(RCM_TRACE3
, "0x%x (int32)\n",
410 case DATA_TYPE_UINT32
:
411 (void) nvpair_value_uint32(nvp
, &data_uint32
);
412 rcm_log_message(RCM_TRACE3
, "0x%x (uint32)\n",
416 case DATA_TYPE_INT64
:
417 (void) nvpair_value_int64(nvp
, &data_int64
);
418 rcm_log_message(RCM_TRACE3
, "0x%lx (int64)\n",
422 case DATA_TYPE_UINT64
:
423 (void) nvpair_value_uint64(nvp
, &data_uint64
);
424 rcm_log_message(RCM_TRACE3
, "0x%lx (uint64)\n",
428 case DATA_TYPE_STRING
:
429 (void) nvpair_value_string(nvp
, &data_string
);
430 rcm_log_message(RCM_TRACE3
, "\"%s\" (string)\n",
434 case DATA_TYPE_STRING_ARRAY
:
435 (void) nvpair_value_string_array(nvp
, &data_strings
,
437 for (i
= 0; i
< data_nstrings
; i
++) {
438 rcm_log_message(RCM_TRACE3
,
439 "\t\"%s\" (string)\n", data_strings
[i
]);
440 if (i
< (data_nstrings
- 1))
441 rcm_log_message(RCM_TRACE3
, "\t\t\t");
446 rcm_log_message(RCM_TRACE3
, "<not dumped>\n");