1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * in kernel monitor support: allows rv to control in-kernel monitors. 4 * 5 * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> 6 */ 7 #include <getopt.h> 8 #include <stdlib.h> 9 #include <stdio.h> 10 #include <string.h> 11 #include <errno.h> 12 #include <unistd.h> 13 #include <dirent.h> 14 15 #include <trace.h> 16 #include <utils.h> 17 #include <rv.h> 18 19 static int config_has_id; 20 static int config_is_container; 21 static int config_my_pid; 22 static int config_trace; 23 24 static char *config_initial_reactor; 25 static char *config_reactor; 26 27 /* 28 * __ikm_read_enable - reads monitor's enable status 29 * 30 * __does not log errors. 31 * 32 * Returns the current status, or -1 if the monitor does not exist, 33 * __hence not logging errors. 34 */ 35 static int __ikm_read_enable(char *monitor_name) 36 { 37 char path[MAX_PATH]; 38 long long enabled; 39 int retval; 40 41 snprintf(path, MAX_PATH, "rv/monitors/%s/enable", monitor_name); 42 43 retval = tracefs_instance_file_read_number(NULL, path, &enabled); 44 if (retval < 0) 45 return -1; 46 47 return enabled; 48 } 49 50 /* 51 * __ikm_find_monitor - find the full name of a possibly nested module 52 * 53 * __does not log errors. 54 * 55 * Returns 1 if we found the monitor, -1 on error and 0 if it does not exist. 56 * The string out_name is populated with the full name, which can be 57 * equal to monitor_name or container/monitor_name if nested 58 */ 59 static int __ikm_find_monitor_name(char *monitor_name, char *out_name) 60 { 61 char *available_monitors, container[MAX_DA_NAME_LEN+1], *cursor, *end; 62 int retval = 1; 63 64 available_monitors = tracefs_instance_file_read(NULL, "rv/available_monitors", NULL); 65 if (!available_monitors) 66 return -1; 67 68 cursor = strstr(available_monitors, monitor_name); 69 if (!cursor) { 70 retval = 0; 71 goto out_free; 72 } 73 74 for (; cursor > available_monitors; cursor--) 75 if (*(cursor-1) == '\n') 76 break; 77 end = strstr(cursor, "\n"); 78 memcpy(out_name, cursor, end-cursor); 79 out_name[end-cursor] = '\0'; 80 81 cursor = strstr(out_name, ":"); 82 if (cursor) 83 *cursor = '/'; 84 else { 85 sprintf(container, "%s:", monitor_name); 86 if (strstr(available_monitors, container)) 87 config_is_container = 1; 88 } 89 90 out_free: 91 free(available_monitors); 92 return retval; 93 } 94 95 /* 96 * ikm_read_enable - reads monitor's enable status 97 * 98 * Returns the current status, or -1 on error. 99 */ 100 static int ikm_read_enable(char *monitor_name) 101 { 102 int enabled; 103 104 enabled = __ikm_read_enable(monitor_name); 105 if (enabled < 0) { 106 err_msg("ikm: fail read enabled: %d\n", enabled); 107 return -1; 108 } 109 110 debug_msg("ikm: read enabled: %d\n", enabled); 111 112 return enabled; 113 } 114 115 /* 116 * ikm_write_enable - write to the monitor's enable file 117 * 118 * Return the number of bytes written, -1 on error. 119 */ 120 static int ikm_write_enable(char *monitor_name, char *enable_disable) 121 { 122 char path[MAX_PATH]; 123 int retval; 124 125 debug_msg("ikm: writing enabled: %s\n", enable_disable); 126 127 snprintf(path, MAX_PATH, "rv/monitors/%s/enable", monitor_name); 128 retval = tracefs_instance_file_write(NULL, path, enable_disable); 129 if (retval < strlen(enable_disable)) { 130 err_msg("ikm: writing enabled: %s\n", enable_disable); 131 return -1; 132 } 133 134 return retval; 135 } 136 137 /* 138 * ikm_enable - enable a monitor 139 * 140 * Returns -1 on failure. Success otherwise. 141 */ 142 static int ikm_enable(char *monitor_name) 143 { 144 return ikm_write_enable(monitor_name, "1"); 145 } 146 147 /* 148 * ikm_disable - disable a monitor 149 * 150 * Returns -1 on failure. Success otherwise. 151 */ 152 static int ikm_disable(char *monitor_name) 153 { 154 return ikm_write_enable(monitor_name, "0"); 155 } 156 157 /* 158 * ikm_read_desc - read monitors' description 159 * 160 * Return a dynamically allocated string with the monitor's 161 * description, NULL otherwise. 162 */ 163 static char *ikm_read_desc(char *monitor_name) 164 { 165 char path[MAX_PATH]; 166 char *desc; 167 168 snprintf(path, MAX_PATH, "rv/monitors/%s/desc", monitor_name); 169 desc = tracefs_instance_file_read(NULL, path, NULL); 170 if (!desc) { 171 err_msg("ikm: error reading monitor %s desc\n", monitor_name); 172 return NULL; 173 } 174 175 *strstr(desc, "\n") = '\0'; 176 177 return desc; 178 } 179 180 /* 181 * ikm_fill_monitor_definition - fill monitor's definition 182 * 183 * Returns -1 on error, 1 if the monitor does not belong in the container, 0 otherwise. 184 * container can be NULL 185 */ 186 static int ikm_fill_monitor_definition(char *name, struct monitor *ikm, char *container) 187 { 188 int enabled; 189 char *desc, *nested_name; 190 191 nested_name = strstr(name, ":"); 192 if (nested_name) { 193 /* it belongs in container if it starts with "container:" */ 194 if (container && strstr(name, container) != name) 195 return 1; 196 *nested_name = '/'; 197 ++nested_name; 198 ikm->nested = 1; 199 } else { 200 if (container) 201 return 1; 202 nested_name = name; 203 ikm->nested = 0; 204 } 205 206 enabled = ikm_read_enable(name); 207 if (enabled < 0) { 208 err_msg("ikm: monitor %s fail to read enable file, bug?\n", name); 209 return -1; 210 } 211 212 desc = ikm_read_desc(name); 213 if (!desc) { 214 err_msg("ikm: monitor %s does not have desc file, bug?\n", name); 215 return -1; 216 } 217 218 strncpy(ikm->name, nested_name, sizeof(ikm->name) - 1); 219 ikm->name[sizeof(ikm->name) - 1] = '\0'; 220 ikm->enabled = enabled; 221 strncpy(ikm->desc, desc, sizeof(ikm->desc) - 1); 222 ikm->desc[sizeof(ikm->desc) - 1] = '\0'; 223 free(desc); 224 225 return 0; 226 } 227 228 /* 229 * ikm_write_reactor - switch the reactor to *reactor 230 * 231 * Return the number or characters written, -1 on error. 232 */ 233 static int ikm_write_reactor(char *monitor_name, char *reactor) 234 { 235 char path[MAX_PATH]; 236 int retval; 237 238 snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name); 239 retval = tracefs_instance_file_write(NULL, path, reactor); 240 debug_msg("ikm: write \"%s\" reactors: %d\n", reactor, retval); 241 242 return retval; 243 } 244 245 /* 246 * ikm_read_reactor - read the reactors file 247 * 248 * Returns a dynamically allocated string with monitor's 249 * available reactors, or NULL on error. 250 */ 251 static char *ikm_read_reactor(char *monitor_name) 252 { 253 char path[MAX_PATH]; 254 char *reactors; 255 256 snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name); 257 reactors = tracefs_instance_file_read(NULL, path, NULL); 258 if (!reactors) { 259 err_msg("ikm: fail reading monitor's %s reactors file\n", monitor_name); 260 return NULL; 261 } 262 263 return reactors; 264 } 265 266 /* 267 * ikm_get_current_reactor - get the current enabled reactor 268 * 269 * Reads the reactors file and find the currently enabled 270 * [reactor]. 271 * 272 * Returns a dynamically allocated memory with the current 273 * reactor. NULL otherwise. 274 */ 275 static char *ikm_get_current_reactor(char *monitor_name) 276 { 277 char *reactors = ikm_read_reactor(monitor_name); 278 char *curr_reactor = NULL; 279 char *start; 280 char *end; 281 282 if (!reactors) 283 return NULL; 284 285 start = strstr(reactors, "["); 286 if (!start) 287 goto out_free; 288 289 start++; 290 291 end = strstr(start, "]"); 292 if (!end) 293 goto out_free; 294 295 *end = '\0'; 296 297 curr_reactor = calloc(strlen(start) + 1, sizeof(char)); 298 if (!curr_reactor) 299 goto out_free; 300 301 strncpy(curr_reactor, start, strlen(start)); 302 debug_msg("ikm: read current reactor %s\n", curr_reactor); 303 304 out_free: 305 free(reactors); 306 307 return curr_reactor; 308 } 309 310 static int ikm_has_id(char *monitor_name) 311 { 312 char path[MAX_PATH]; 313 char *format; 314 int has_id; 315 316 snprintf(path, MAX_PATH, "events/rv/event_%s/format", monitor_name); 317 format = tracefs_instance_file_read(NULL, path, NULL); 318 if (!format) { 319 err_msg("ikm: fail reading monitor's %s format event file\n", monitor_name); 320 return -1; 321 } 322 323 /* print fmt: "%d: %s x %s -> %s %s", REC->id, ... */ 324 has_id = !!strstr(format, "REC->id"); 325 326 debug_msg("ikm: monitor %s has id: %s\n", monitor_name, has_id ? "yes" : "no"); 327 328 free(format); 329 330 return has_id; 331 } 332 333 /** 334 * ikm_list_monitors - list all available monitors 335 * 336 * Returns 0 on success, -1 otherwise. 337 */ 338 int ikm_list_monitors(char *container) 339 { 340 char *available_monitors; 341 struct monitor ikm = {0}; 342 char *curr, *next; 343 int retval, list_monitor = 0; 344 345 available_monitors = tracefs_instance_file_read(NULL, "rv/available_monitors", NULL); 346 347 if (!available_monitors) { 348 err_msg("ikm: available monitors is not available, is CONFIG_RV enabled?\n"); 349 return -1; 350 } 351 352 curr = available_monitors; 353 do { 354 next = strstr(curr, "\n"); 355 *next = '\0'; 356 357 retval = ikm_fill_monitor_definition(curr, &ikm, container); 358 if (retval < 0) 359 err_msg("ikm: error reading %d in kernel monitor, skipping\n", curr); 360 361 if (!retval) { 362 int indent = ikm.nested && !container; 363 364 list_monitor = 1; 365 printf("%s%-*s %s %s\n", indent ? " - " : "", 366 indent ? MAX_DA_NAME_LEN - 3 : MAX_DA_NAME_LEN, 367 ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF]"); 368 } 369 curr = ++next; 370 371 } while (strlen(curr)); 372 373 if (!list_monitor) { 374 if (container) 375 printf("-- No monitor found in container %s --\n", container); 376 else 377 printf("-- No monitor found --\n"); 378 } 379 380 free(available_monitors); 381 382 return 0; 383 } 384 385 static void ikm_print_header(struct trace_seq *s) 386 { 387 trace_seq_printf(s, "%16s-%-8s %5s %5s ", "<TASK>", "PID", "[CPU]", "TYPE"); 388 if (config_has_id) 389 trace_seq_printf(s, "%8s ", "ID"); 390 391 trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n", 392 "STATE", 393 "EVENT", 394 "NEXT_STATE", 395 "FINAL"); 396 397 trace_seq_printf(s, "%16s %-8s %5s %5s ", " | ", " | ", " | ", " | "); 398 399 if (config_has_id) 400 trace_seq_printf(s, "%8s ", " | "); 401 402 trace_seq_printf(s, "%24s %-24s %-24s %s\n", 403 " | ", 404 " | ", 405 " | ", 406 "|"); 407 408 } 409 410 /* 411 * ikm_event_handler - callback to handle event events 412 * 413 * Called any time a rv:"monitor"_event events is generated. 414 * It parses and prints event. 415 */ 416 static int 417 ikm_event_handler(struct trace_seq *s, struct tep_record *record, 418 struct tep_event *trace_event, void *context) 419 { 420 /* if needed: struct trace_instance *inst = context; */ 421 char *state, *event, *next_state; 422 unsigned long long final_state; 423 unsigned long long pid; 424 unsigned long long id; 425 int val; 426 bool missing_id; 427 428 if (config_has_id) 429 missing_id = tep_get_field_val(s, trace_event, "id", record, &id, 1); 430 431 tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1); 432 433 if (config_has_id && (config_my_pid == id)) 434 return 0; 435 else if (config_my_pid == pid) 436 return 0; 437 438 tep_print_event(trace_event->tep, s, record, "%16s-%-8d [%.3d] ", 439 TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU); 440 441 if (config_is_container) 442 tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME); 443 else 444 trace_seq_printf(s, "event "); 445 446 if (config_has_id) { 447 if (missing_id) 448 /* placeholder if we are dealing with a mixed-type container*/ 449 trace_seq_printf(s, " "); 450 else 451 trace_seq_printf(s, "%8llu ", id); 452 } 453 454 state = tep_get_field_raw(s, trace_event, "state", record, &val, 0); 455 event = tep_get_field_raw(s, trace_event, "event", record, &val, 0); 456 next_state = tep_get_field_raw(s, trace_event, "next_state", record, &val, 0); 457 tep_get_field_val(s, trace_event, "final_state", record, &final_state, 1); 458 459 trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n", 460 state, 461 event, 462 next_state, 463 final_state ? "Y" : "N"); 464 465 trace_seq_do_printf(s); 466 trace_seq_reset(s); 467 468 return 0; 469 } 470 471 /* 472 * ikm_error_handler - callback to handle error events 473 * 474 * Called any time a rv:"monitor"_errors events is generated. 475 * It parses and prints event. 476 */ 477 static int 478 ikm_error_handler(struct trace_seq *s, struct tep_record *record, 479 struct tep_event *trace_event, void *context) 480 { 481 unsigned long long pid, id; 482 int cpu = record->cpu; 483 char *state, *event; 484 int val; 485 bool missing_id; 486 487 if (config_has_id) 488 missing_id = tep_get_field_val(s, trace_event, "id", record, &id, 1); 489 490 tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1); 491 492 if (config_has_id && config_my_pid == id) 493 return 0; 494 else if (config_my_pid == pid) 495 return 0; 496 497 trace_seq_printf(s, "%8lld [%03d] ", pid, cpu); 498 499 if (config_is_container) 500 tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME); 501 else 502 trace_seq_printf(s, "error "); 503 504 if (config_has_id) { 505 if (missing_id) 506 /* placeholder if we are dealing with a mixed-type container*/ 507 trace_seq_printf(s, " "); 508 else 509 trace_seq_printf(s, "%8llu ", id); 510 } 511 512 state = tep_get_field_raw(s, trace_event, "state", record, &val, 0); 513 event = tep_get_field_raw(s, trace_event, "event", record, &val, 0); 514 515 trace_seq_printf(s, "%24s x %s\n", state, event); 516 517 trace_seq_do_printf(s); 518 trace_seq_reset(s); 519 520 return 0; 521 } 522 523 static int ikm_enable_trace_events(char *monitor_name, struct trace_instance *inst) 524 { 525 char event[MAX_DA_NAME_LEN + 7]; /* max(error_,event_) + '0' = 7 */ 526 int retval; 527 528 snprintf(event, sizeof(event), "event_%s", monitor_name); 529 retval = tracefs_event_enable(inst->inst, "rv", event); 530 if (retval) 531 return -1; 532 533 tep_register_event_handler(inst->tep, -1, "rv", event, 534 ikm_event_handler, NULL); 535 536 snprintf(event, sizeof(event), "error_%s", monitor_name); 537 retval = tracefs_event_enable(inst->inst, "rv", event); 538 if (retval) 539 return -1; 540 541 tep_register_event_handler(inst->tep, -1, "rv", event, 542 ikm_error_handler, NULL); 543 544 /* set if at least 1 monitor has id in case of a container */ 545 config_has_id = ikm_has_id(monitor_name); 546 if (config_has_id < 0) 547 return -1; 548 549 550 return 0; 551 } 552 553 static int ikm_enable_trace_container(char *monitor_name, 554 struct trace_instance *inst) 555 { 556 DIR *dp; 557 char *abs_path, rv_path[MAX_PATH]; 558 struct dirent *ep; 559 int retval = 0; 560 561 snprintf(rv_path, MAX_PATH, "rv/monitors/%s", monitor_name); 562 abs_path = tracefs_instance_get_file(NULL, rv_path); 563 if (!abs_path) 564 return -1; 565 dp = opendir(abs_path); 566 if (!dp) 567 goto out_free; 568 569 while (!retval && (ep = readdir(dp))) { 570 if (ep->d_type != DT_DIR || ep->d_name[0] == '.') 571 continue; 572 retval = ikm_enable_trace_events(ep->d_name, inst); 573 } 574 575 closedir(dp); 576 out_free: 577 free(abs_path); 578 return retval; 579 } 580 581 /* 582 * ikm_setup_trace_instance - set up a tracing instance to collect data 583 * 584 * Create a trace instance, enable rv: events and enable the trace. 585 * 586 * Returns the trace_instance * with all set, NULL otherwise. 587 */ 588 static struct trace_instance *ikm_setup_trace_instance(char *monitor_name) 589 { 590 struct trace_instance *inst; 591 int retval; 592 593 if (!config_trace) 594 return NULL; 595 596 /* alloc data */ 597 inst = calloc(1, sizeof(*inst)); 598 if (!inst) { 599 err_msg("ikm: failed to allocate trace instance"); 600 goto out_err; 601 } 602 603 retval = trace_instance_init(inst, monitor_name); 604 if (retval) 605 goto out_free; 606 607 if (config_is_container) 608 retval = ikm_enable_trace_container(monitor_name, inst); 609 else 610 retval = ikm_enable_trace_events(monitor_name, inst); 611 if (retval) 612 goto out_inst; 613 614 /* ready to enable */ 615 tracefs_trace_on(inst->inst); 616 617 return inst; 618 619 out_inst: 620 trace_instance_destroy(inst); 621 out_free: 622 free(inst); 623 out_err: 624 return NULL; 625 } 626 627 /** 628 * ikm_destroy_trace_instance - destroy a previously created instance 629 */ 630 static void ikm_destroy_trace_instance(struct trace_instance *inst) 631 { 632 if (!inst) 633 return; 634 635 trace_instance_destroy(inst); 636 free(inst); 637 } 638 639 /* 640 * ikm_usage_print_reactors - print all available reactors, one per line. 641 */ 642 static void ikm_usage_print_reactors(void) 643 { 644 char *reactors = tracefs_instance_file_read(NULL, "rv/available_reactors", NULL); 645 char *start, *end; 646 647 if (!reactors) 648 return; 649 650 fprintf(stderr, " available reactors:"); 651 652 start = reactors; 653 end = strstr(start, "\n"); 654 655 while (end) { 656 *end = '\0'; 657 658 fprintf(stderr, " %s", start); 659 660 start = ++end; 661 end = strstr(start, "\n"); 662 } 663 664 fprintf(stderr, "\n"); 665 } 666 /* 667 * ikm_usage - print usage 668 */ 669 static void ikm_usage(int exit_val, char *monitor_name, const char *fmt, ...) 670 { 671 672 char message[1024]; 673 va_list ap; 674 int i; 675 676 static const char *const usage[] = { 677 "", 678 " -h/--help: print this menu and the reactor list", 679 " -r/--reactor 'reactor': enables the 'reactor'", 680 " -s/--self: when tracing (-t), also trace rv command", 681 " -t/--trace: trace monitor's event", 682 " -v/--verbose: print debug messages", 683 "", 684 NULL, 685 }; 686 687 va_start(ap, fmt); 688 vsnprintf(message, sizeof(message), fmt, ap); 689 va_end(ap); 690 691 fprintf(stderr, " %s\n", message); 692 693 fprintf(stderr, "\n usage: rv mon %s [-h] [-q] [-r reactor] [-s] [-v]", monitor_name); 694 695 for (i = 0; usage[i]; i++) 696 fprintf(stderr, "%s\n", usage[i]); 697 698 ikm_usage_print_reactors(); 699 exit(exit_val); 700 } 701 702 /* 703 * parse_arguments - parse arguments and set config 704 */ 705 static int parse_arguments(char *monitor_name, int argc, char **argv) 706 { 707 int c, retval; 708 709 config_my_pid = getpid(); 710 711 while (1) { 712 static struct option long_options[] = { 713 {"help", no_argument, 0, 'h'}, 714 {"reactor", required_argument, 0, 'r'}, 715 {"self", no_argument, 0, 's'}, 716 {"trace", no_argument, 0, 't'}, 717 {"verbose", no_argument, 0, 'v'}, 718 {0, 0, 0, 0} 719 }; 720 721 /* getopt_long stores the option index here. */ 722 int option_index = 0; 723 724 c = getopt_long(argc, argv, "hr:stv", long_options, &option_index); 725 726 /* detect the end of the options. */ 727 if (c == -1) 728 break; 729 730 switch (c) { 731 case 'h': 732 ikm_usage(0, monitor_name, "help:"); 733 break; 734 case 'r': 735 config_reactor = optarg; 736 break; 737 case 's': 738 config_my_pid = -1; 739 break; 740 case 't': 741 config_trace = 1; 742 break; 743 case 'v': 744 config_debug = 1; 745 break; 746 } 747 } 748 749 if (config_reactor) { 750 config_initial_reactor = ikm_get_current_reactor(monitor_name); 751 if (!config_initial_reactor) 752 ikm_usage(1, monitor_name, 753 "ikm: failed to read current reactor, are reactors enabled?"); 754 755 retval = ikm_write_reactor(monitor_name, config_reactor); 756 if (retval <= 0) 757 ikm_usage(1, monitor_name, 758 "ikm: failed to set %s reactor, is it available?", 759 config_reactor); 760 } 761 762 debug_msg("ikm: my pid is %d\n", config_my_pid); 763 764 return 0; 765 } 766 767 /** 768 * ikm_run_monitor - apply configs and run the monitor 769 * 770 * Returns 1 if a monitor was found an executed, 0 if no 771 * monitors were found, or -1 on error. 772 */ 773 int ikm_run_monitor(char *monitor_name, int argc, char **argv) 774 { 775 struct trace_instance *inst = NULL; 776 char *nested_name, full_name[2*MAX_DA_NAME_LEN]; 777 int retval; 778 779 nested_name = strstr(monitor_name, ":"); 780 if (nested_name) 781 ++nested_name; 782 else 783 nested_name = monitor_name; 784 785 retval = __ikm_find_monitor_name(monitor_name, full_name); 786 if (!retval) 787 return 0; 788 if (retval < 0) { 789 err_msg("ikm: error finding monitor %s\n", nested_name); 790 return -1; 791 } 792 793 retval = __ikm_read_enable(full_name); 794 if (retval) { 795 err_msg("ikm: monitor %s (in-kernel) is already enabled\n", nested_name); 796 return -1; 797 } 798 799 /* we should be good to go */ 800 retval = parse_arguments(full_name, argc, argv); 801 if (retval) 802 ikm_usage(1, nested_name, "ikm: failed parsing arguments"); 803 804 if (config_trace) { 805 inst = ikm_setup_trace_instance(nested_name); 806 if (!inst) 807 return -1; 808 } 809 810 retval = ikm_enable(full_name); 811 if (retval < 0) 812 goto out_free_instance; 813 814 if (config_trace) 815 ikm_print_header(inst->seq); 816 817 while (!should_stop()) { 818 if (config_trace) { 819 retval = tracefs_iterate_raw_events(inst->tep, 820 inst->inst, 821 NULL, 822 0, 823 collect_registered_events, 824 inst); 825 if (retval) { 826 err_msg("ikm: error reading trace buffer\n"); 827 break; 828 } 829 } 830 831 sleep(1); 832 } 833 834 ikm_disable(full_name); 835 ikm_destroy_trace_instance(inst); 836 837 if (config_reactor && config_initial_reactor) 838 ikm_write_reactor(full_name, config_initial_reactor); 839 840 return 1; 841 842 out_free_instance: 843 ikm_destroy_trace_instance(inst); 844 if (config_reactor && config_initial_reactor) 845 ikm_write_reactor(full_name, config_initial_reactor); 846 return -1; 847 } 848