1#!/usr/bin/perl -w 2# 3# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 4# Licensed under the terms of the GNU GPL License version 2 5# 6 7use strict; 8use IPC::Open2; 9use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); 10use File::Path qw(mkpath); 11use File::Copy qw(cp); 12use FileHandle; 13 14my $VERSION = "0.2"; 15 16$| = 1; 17 18my %opt; 19my %repeat_tests; 20my %repeats; 21my %default; 22 23#default opts 24$default{"NUM_TESTS"} = 1; 25$default{"REBOOT_TYPE"} = "grub"; 26$default{"TEST_TYPE"} = "test"; 27$default{"BUILD_TYPE"} = "randconfig"; 28$default{"MAKE_CMD"} = "make"; 29$default{"TIMEOUT"} = 120; 30$default{"TMP_DIR"} = "/tmp/ktest/\${MACHINE}"; 31$default{"SLEEP_TIME"} = 60; # sleep time between tests 32$default{"BUILD_NOCLEAN"} = 0; 33$default{"REBOOT_ON_ERROR"} = 0; 34$default{"POWEROFF_ON_ERROR"} = 0; 35$default{"REBOOT_ON_SUCCESS"} = 1; 36$default{"POWEROFF_ON_SUCCESS"} = 0; 37$default{"BUILD_OPTIONS"} = ""; 38$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects 39$default{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks 40$default{"CLEAR_LOG"} = 0; 41$default{"BISECT_MANUAL"} = 0; 42$default{"BISECT_SKIP"} = 1; 43$default{"SUCCESS_LINE"} = "login:"; 44$default{"DETECT_TRIPLE_FAULT"} = 1; 45$default{"NO_INSTALL"} = 0; 46$default{"BOOTED_TIMEOUT"} = 1; 47$default{"DIE_ON_FAILURE"} = 1; 48$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; 49$default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE"; 50$default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot"; 51$default{"STOP_AFTER_SUCCESS"} = 10; 52$default{"STOP_AFTER_FAILURE"} = 60; 53$default{"STOP_TEST_AFTER"} = 600; 54$default{"LOCALVERSION"} = "-test"; 55 56my $ktest_config; 57my $version; 58my $machine; 59my $ssh_user; 60my $tmpdir; 61my $builddir; 62my $outputdir; 63my $output_config; 64my $test_type; 65my $build_type; 66my $build_options; 67my $pre_build; 68my $post_build; 69my $pre_build_die; 70my $post_build_die; 71my $reboot_type; 72my $reboot_script; 73my $power_cycle; 74my $reboot; 75my $reboot_on_error; 76my $poweroff_on_error; 77my $die_on_failure; 78my $powercycle_after_reboot; 79my $poweroff_after_halt; 80my $ssh_exec; 81my $scp_to_target; 82my $power_off; 83my $grub_menu; 84my $grub_number; 85my $target; 86my $make; 87my $post_install; 88my $no_install; 89my $noclean; 90my $minconfig; 91my $start_minconfig; 92my $start_minconfig_defined; 93my $output_minconfig; 94my $ignore_config; 95my $addconfig; 96my $in_bisect = 0; 97my $bisect_bad = ""; 98my $reverse_bisect; 99my $bisect_manual; 100my $bisect_skip; 101my $config_bisect_good; 102my $in_patchcheck = 0; 103my $run_test; 104my $redirect; 105my $buildlog; 106my $dmesg; 107my $monitor_fp; 108my $monitor_pid; 109my $monitor_cnt = 0; 110my $sleep_time; 111my $bisect_sleep_time; 112my $patchcheck_sleep_time; 113my $ignore_warnings; 114my $store_failures; 115my $test_name; 116my $timeout; 117my $booted_timeout; 118my $detect_triplefault; 119my $console; 120my $reboot_success_line; 121my $success_line; 122my $stop_after_success; 123my $stop_after_failure; 124my $stop_test_after; 125my $build_target; 126my $target_image; 127my $localversion; 128my $iteration = 0; 129my $successes = 0; 130 131my %entered_configs; 132my %config_help; 133my %variable; 134my %force_config; 135 136# do not force reboots on config problems 137my $no_reboot = 1; 138 139# default variables that can be used 140chomp ($variable{"PWD"} = `pwd`); 141 142$config_help{"MACHINE"} = << "EOF" 143 The machine hostname that you will test. 144EOF 145 ; 146$config_help{"SSH_USER"} = << "EOF" 147 The box is expected to have ssh on normal bootup, provide the user 148 (most likely root, since you need privileged operations) 149EOF 150 ; 151$config_help{"BUILD_DIR"} = << "EOF" 152 The directory that contains the Linux source code (full path). 153EOF 154 ; 155$config_help{"OUTPUT_DIR"} = << "EOF" 156 The directory that the objects will be built (full path). 157 (can not be same as BUILD_DIR) 158EOF 159 ; 160$config_help{"BUILD_TARGET"} = << "EOF" 161 The location of the compiled file to copy to the target. 162 (relative to OUTPUT_DIR) 163EOF 164 ; 165$config_help{"TARGET_IMAGE"} = << "EOF" 166 The place to put your image on the test machine. 167EOF 168 ; 169$config_help{"POWER_CYCLE"} = << "EOF" 170 A script or command to reboot the box. 171 172 Here is a digital loggers power switch example 173 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 174 175 Here is an example to reboot a virtual box on the current host 176 with the name "Guest". 177 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 178EOF 179 ; 180$config_help{"CONSOLE"} = << "EOF" 181 The script or command that reads the console 182 183 If you use ttywatch server, something like the following would work. 184CONSOLE = nc -d localhost 3001 185 186 For a virtual machine with guest name "Guest". 187CONSOLE = virsh console Guest 188EOF 189 ; 190$config_help{"LOCALVERSION"} = << "EOF" 191 Required version ending to differentiate the test 192 from other linux builds on the system. 193EOF 194 ; 195$config_help{"REBOOT_TYPE"} = << "EOF" 196 Way to reboot the box to the test kernel. 197 Only valid options so far are "grub" and "script". 198 199 If you specify grub, it will assume grub version 1 200 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 201 and select that target to reboot to the kernel. If this is not 202 your setup, then specify "script" and have a command or script 203 specified in REBOOT_SCRIPT to boot to the target. 204 205 The entry in /boot/grub/menu.lst must be entered in manually. 206 The test will not modify that file. 207EOF 208 ; 209$config_help{"GRUB_MENU"} = << "EOF" 210 The grub title name for the test kernel to boot 211 (Only mandatory if REBOOT_TYPE = grub) 212 213 Note, ktest.pl will not update the grub menu.lst, you need to 214 manually add an option for the test. ktest.pl will search 215 the grub menu.lst for this option to find what kernel to 216 reboot into. 217 218 For example, if in the /boot/grub/menu.lst the test kernel title has: 219 title Test Kernel 220 kernel vmlinuz-test 221 GRUB_MENU = Test Kernel 222EOF 223 ; 224$config_help{"REBOOT_SCRIPT"} = << "EOF" 225 A script to reboot the target into the test kernel 226 (Only mandatory if REBOOT_TYPE = script) 227EOF 228 ; 229 230sub read_yn { 231 my ($prompt) = @_; 232 233 my $ans; 234 235 for (;;) { 236 print "$prompt [Y/n] "; 237 $ans = <STDIN>; 238 chomp $ans; 239 if ($ans =~ /^\s*$/) { 240 $ans = "y"; 241 } 242 last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 243 print "Please answer either 'y' or 'n'.\n"; 244 } 245 if ($ans !~ /^y$/i) { 246 return 0; 247 } 248 return 1; 249} 250 251sub get_ktest_config { 252 my ($config) = @_; 253 my $ans; 254 255 return if (defined($opt{$config})); 256 257 if (defined($config_help{$config})) { 258 print "\n"; 259 print $config_help{$config}; 260 } 261 262 for (;;) { 263 print "$config = "; 264 if (defined($default{$config})) { 265 print "\[$default{$config}\] "; 266 } 267 $ans = <STDIN>; 268 $ans =~ s/^\s*(.*\S)\s*$/$1/; 269 if ($ans =~ /^\s*$/) { 270 if ($default{$config}) { 271 $ans = $default{$config}; 272 } else { 273 print "Your answer can not be blank\n"; 274 next; 275 } 276 } 277 $entered_configs{$config} = process_variables($ans); 278 last; 279 } 280} 281 282sub get_ktest_configs { 283 get_ktest_config("MACHINE"); 284 get_ktest_config("SSH_USER"); 285 get_ktest_config("BUILD_DIR"); 286 get_ktest_config("OUTPUT_DIR"); 287 get_ktest_config("BUILD_TARGET"); 288 get_ktest_config("TARGET_IMAGE"); 289 get_ktest_config("POWER_CYCLE"); 290 get_ktest_config("CONSOLE"); 291 get_ktest_config("LOCALVERSION"); 292 293 my $rtype = $opt{"REBOOT_TYPE"}; 294 295 if (!defined($rtype)) { 296 if (!defined($opt{"GRUB_MENU"})) { 297 get_ktest_config("REBOOT_TYPE"); 298 $rtype = $entered_configs{"REBOOT_TYPE"}; 299 } else { 300 $rtype = "grub"; 301 } 302 } 303 304 if ($rtype eq "grub") { 305 get_ktest_config("GRUB_MENU"); 306 } else { 307 get_ktest_config("REBOOT_SCRIPT"); 308 } 309} 310 311sub process_variables { 312 my ($value, $remove_undef) = @_; 313 my $retval = ""; 314 315 # We want to check for '\', and it is just easier 316 # to check the previous characet of '$' and not need 317 # to worry if '$' is the first character. By adding 318 # a space to $value, we can just check [^\\]\$ and 319 # it will still work. 320 $value = " $value"; 321 322 while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 323 my $begin = $1; 324 my $var = $2; 325 my $end = $3; 326 # append beginning of value to retval 327 $retval = "$retval$begin"; 328 if (defined($variable{$var})) { 329 $retval = "$retval$variable{$var}"; 330 } elsif (defined($remove_undef) && $remove_undef) { 331 # for if statements, any variable that is not defined, 332 # we simple convert to 0 333 $retval = "${retval}0"; 334 } else { 335 # put back the origin piece. 336 $retval = "$retval\$\{$var\}"; 337 } 338 $value = $end; 339 } 340 $retval = "$retval$value"; 341 342 # remove the space added in the beginning 343 $retval =~ s/ //; 344 345 return "$retval" 346} 347 348sub set_value { 349 my ($lvalue, $rvalue, $override, $overrides, $name) = @_; 350 351 if (defined($opt{$lvalue})) { 352 if (!$override || defined(${$overrides}{$lvalue})) { 353 my $extra = ""; 354 if ($override) { 355 $extra = "In the same override section!\n"; 356 } 357 die "$name: $.: Option $lvalue defined more than once!\n$extra"; 358 } 359 ${$overrides}{$lvalue} = $rvalue; 360 } 361 if ($rvalue =~ /^\s*$/) { 362 delete $opt{$lvalue}; 363 } else { 364 $rvalue = process_variables($rvalue); 365 $opt{$lvalue} = $rvalue; 366 } 367} 368 369sub set_variable { 370 my ($lvalue, $rvalue) = @_; 371 372 if ($rvalue =~ /^\s*$/) { 373 delete $variable{$lvalue}; 374 } else { 375 $rvalue = process_variables($rvalue); 376 $variable{$lvalue} = $rvalue; 377 } 378} 379 380sub process_compare { 381 my ($lval, $cmp, $rval) = @_; 382 383 # remove whitespace 384 385 $lval =~ s/^\s*//; 386 $lval =~ s/\s*$//; 387 388 $rval =~ s/^\s*//; 389 $rval =~ s/\s*$//; 390 391 if ($cmp eq "==") { 392 return $lval eq $rval; 393 } elsif ($cmp eq "!=") { 394 return $lval ne $rval; 395 } 396 397 my $statement = "$lval $cmp $rval"; 398 my $ret = eval $statement; 399 400 # $@ stores error of eval 401 if ($@) { 402 return -1; 403 } 404 405 return $ret; 406} 407 408sub value_defined { 409 my ($val) = @_; 410 411 return defined($variable{$2}) || 412 defined($opt{$2}); 413} 414 415my $d = 0; 416sub process_expression { 417 my ($name, $val) = @_; 418 419 my $c = $d++; 420 421 while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) { 422 my $express = $1; 423 424 if (process_expression($name, $express)) { 425 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /; 426 } else { 427 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /; 428 } 429 } 430 431 $d--; 432 my $OR = "\\|\\|"; 433 my $AND = "\\&\\&"; 434 435 while ($val =~ s/^(.*?)($OR|$AND)//) { 436 my $express = $1; 437 my $op = $2; 438 439 if (process_expression($name, $express)) { 440 if ($op eq "||") { 441 return 1; 442 } 443 } else { 444 if ($op eq "&&") { 445 return 0; 446 } 447 } 448 } 449 450 if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) { 451 my $ret = process_compare($1, $2, $3); 452 if ($ret < 0) { 453 die "$name: $.: Unable to process comparison\n"; 454 } 455 return $ret; 456 } 457 458 if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) { 459 if (defined $1) { 460 return !value_defined($2); 461 } else { 462 return value_defined($2); 463 } 464 } 465 466 if ($val =~ /^\s*0\s*$/) { 467 return 0; 468 } elsif ($val =~ /^\s*\d+\s*$/) { 469 return 1; 470 } 471 472 die ("$name: $.: Undefined content $val in if statement\n"); 473} 474 475sub process_if { 476 my ($name, $value) = @_; 477 478 # Convert variables and replace undefined ones with 0 479 my $val = process_variables($value, 1); 480 my $ret = process_expression $name, $val; 481 482 return $ret; 483} 484 485sub __read_config { 486 my ($config, $current_test_num) = @_; 487 488 my $in; 489 open($in, $config) || die "can't read file $config"; 490 491 my $name = $config; 492 $name =~ s,.*/(.*),$1,; 493 494 my $test_num = $$current_test_num; 495 my $default = 1; 496 my $repeat = 1; 497 my $num_tests_set = 0; 498 my $skip = 0; 499 my $rest; 500 my $line; 501 my $test_case = 0; 502 my $if = 0; 503 my $if_set = 0; 504 my $override = 0; 505 506 my %overrides; 507 508 while (<$in>) { 509 510 # ignore blank lines and comments 511 next if (/^\s*$/ || /\s*\#/); 512 513 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) { 514 515 my $type = $1; 516 $rest = $2; 517 $line = $2; 518 519 my $old_test_num; 520 my $old_repeat; 521 $override = 0; 522 523 if ($type eq "TEST_START") { 524 525 if ($num_tests_set) { 526 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 527 } 528 529 $old_test_num = $test_num; 530 $old_repeat = $repeat; 531 532 $test_num += $repeat; 533 $default = 0; 534 $repeat = 1; 535 } else { 536 $default = 1; 537 } 538 539 # If SKIP is anywhere in the line, the command will be skipped 540 if ($rest =~ s/\s+SKIP\b//) { 541 $skip = 1; 542 } else { 543 $test_case = 1; 544 $skip = 0; 545 } 546 547 if ($rest =~ s/\sELSE\b//) { 548 if (!$if) { 549 die "$name: $.: ELSE found with out matching IF section\n$_"; 550 } 551 $if = 0; 552 553 if ($if_set) { 554 $skip = 1; 555 } else { 556 $skip = 0; 557 } 558 } 559 560 if ($rest =~ s/\sIF\s+(.*)//) { 561 if (process_if($name, $1)) { 562 $if_set = 1; 563 } else { 564 $skip = 1; 565 } 566 $if = 1; 567 } else { 568 $if = 0; 569 $if_set = 0; 570 } 571 572 if (!$skip) { 573 if ($type eq "TEST_START") { 574 if ($rest =~ s/\s+ITERATE\s+(\d+)//) { 575 $repeat = $1; 576 $repeat_tests{"$test_num"} = $repeat; 577 } 578 } elsif ($rest =~ s/\sOVERRIDE\b//) { 579 # DEFAULT only 580 $override = 1; 581 # Clear previous overrides 582 %overrides = (); 583 } 584 } 585 586 if (!$skip && $rest !~ /^\s*$/) { 587 die "$name: $.: Gargbage found after $type\n$_"; 588 } 589 590 if ($skip && $type eq "TEST_START") { 591 $test_num = $old_test_num; 592 $repeat = $old_repeat; 593 } 594 595 } elsif (/^\s*ELSE\b(.*)$/) { 596 if (!$if) { 597 die "$name: $.: ELSE found with out matching IF section\n$_"; 598 } 599 $rest = $1; 600 if ($if_set) { 601 $skip = 1; 602 $rest = ""; 603 } else { 604 $skip = 0; 605 606 if ($rest =~ /\sIF\s+(.*)/) { 607 # May be a ELSE IF section. 608 if (!process_if($name, $1)) { 609 $skip = 1; 610 } 611 $rest = ""; 612 } else { 613 $if = 0; 614 } 615 } 616 617 if ($rest !~ /^\s*$/) { 618 die "$name: $.: Gargbage found after DEFAULTS\n$_"; 619 } 620 621 } elsif (/^\s*INCLUDE\s+(\S+)/) { 622 623 next if ($skip); 624 625 if (!$default) { 626 die "$name: $.: INCLUDE can only be done in default sections\n$_"; 627 } 628 629 my $file = process_variables($1); 630 631 if ($file !~ m,^/,) { 632 # check the path of the config file first 633 if ($config =~ m,(.*)/,) { 634 if (-f "$1/$file") { 635 $file = "$1/$file"; 636 } 637 } 638 } 639 640 if ( ! -r $file ) { 641 die "$name: $.: Can't read file $file\n$_"; 642 } 643 644 if (__read_config($file, \$test_num)) { 645 $test_case = 1; 646 } 647 648 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 649 650 next if ($skip); 651 652 my $lvalue = $1; 653 my $rvalue = $2; 654 655 if (!$default && 656 ($lvalue eq "NUM_TESTS" || 657 $lvalue eq "LOG_FILE" || 658 $lvalue eq "CLEAR_LOG")) { 659 die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 660 } 661 662 if ($lvalue eq "NUM_TESTS") { 663 if ($test_num) { 664 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 665 } 666 if (!$default) { 667 die "$name: $.: NUM_TESTS must be set in default section\n"; 668 } 669 $num_tests_set = 1; 670 } 671 672 if ($default || $lvalue =~ /\[\d+\]$/) { 673 set_value($lvalue, $rvalue, $override, \%overrides, $name); 674 } else { 675 my $val = "$lvalue\[$test_num\]"; 676 set_value($val, $rvalue, $override, \%overrides, $name); 677 678 if ($repeat > 1) { 679 $repeats{$val} = $repeat; 680 } 681 } 682 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 683 next if ($skip); 684 685 my $lvalue = $1; 686 my $rvalue = $2; 687 688 # process config variables. 689 # Config variables are only active while reading the 690 # config and can be defined anywhere. They also ignore 691 # TEST_START and DEFAULTS, but are skipped if they are in 692 # on of these sections that have SKIP defined. 693 # The save variable can be 694 # defined multiple times and the new one simply overrides 695 # the prevous one. 696 set_variable($lvalue, $rvalue); 697 698 } else { 699 die "$name: $.: Garbage found in config\n$_"; 700 } 701 } 702 703 if ($test_num) { 704 $test_num += $repeat - 1; 705 $opt{"NUM_TESTS"} = $test_num; 706 } 707 708 close($in); 709 710 $$current_test_num = $test_num; 711 712 return $test_case; 713} 714 715sub read_config { 716 my ($config) = @_; 717 718 my $test_case; 719 my $test_num = 0; 720 721 $test_case = __read_config $config, \$test_num; 722 723 # make sure we have all mandatory configs 724 get_ktest_configs; 725 726 # was a test specified? 727 if (!$test_case) { 728 print "No test case specified.\n"; 729 print "What test case would you like to run?\n"; 730 my $ans = <STDIN>; 731 chomp $ans; 732 $default{"TEST_TYPE"} = $ans; 733 } 734 735 # set any defaults 736 737 foreach my $default (keys %default) { 738 if (!defined($opt{$default})) { 739 $opt{$default} = $default{$default}; 740 } 741 } 742} 743 744sub __eval_option { 745 my ($option, $i) = @_; 746 747 # Add space to evaluate the character before $ 748 $option = " $option"; 749 my $retval = ""; 750 my $repeated = 0; 751 my $parent = 0; 752 753 foreach my $test (keys %repeat_tests) { 754 if ($i >= $test && 755 $i < $test + $repeat_tests{$test}) { 756 757 $repeated = 1; 758 $parent = $test; 759 last; 760 } 761 } 762 763 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 764 my $start = $1; 765 my $var = $2; 766 my $end = $3; 767 768 # Append beginning of line 769 $retval = "$retval$start"; 770 771 # If the iteration option OPT[$i] exists, then use that. 772 # otherwise see if the default OPT (without [$i]) exists. 773 774 my $o = "$var\[$i\]"; 775 my $parento = "$var\[$parent\]"; 776 777 if (defined($opt{$o})) { 778 $o = $opt{$o}; 779 $retval = "$retval$o"; 780 } elsif ($repeated && defined($opt{$parento})) { 781 $o = $opt{$parento}; 782 $retval = "$retval$o"; 783 } elsif (defined($opt{$var})) { 784 $o = $opt{$var}; 785 $retval = "$retval$o"; 786 } else { 787 $retval = "$retval\$\{$var\}"; 788 } 789 790 $option = $end; 791 } 792 793 $retval = "$retval$option"; 794 795 $retval =~ s/^ //; 796 797 return $retval; 798} 799 800sub eval_option { 801 my ($option, $i) = @_; 802 803 my $prev = ""; 804 805 # Since an option can evaluate to another option, 806 # keep iterating until we do not evaluate any more 807 # options. 808 my $r = 0; 809 while ($prev ne $option) { 810 # Check for recursive evaluations. 811 # 100 deep should be more than enough. 812 if ($r++ > 100) { 813 die "Over 100 evaluations accurred with $option\n" . 814 "Check for recursive variables\n"; 815 } 816 $prev = $option; 817 $option = __eval_option($option, $i); 818 } 819 820 return $option; 821} 822 823sub _logit { 824 if (defined($opt{"LOG_FILE"})) { 825 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 826 print OUT @_; 827 close(OUT); 828 } 829} 830 831sub logit { 832 if (defined($opt{"LOG_FILE"})) { 833 _logit @_; 834 } else { 835 print @_; 836 } 837} 838 839sub doprint { 840 print @_; 841 _logit @_; 842} 843 844sub run_command; 845sub start_monitor; 846sub end_monitor; 847sub wait_for_monitor; 848 849sub reboot { 850 my ($time) = @_; 851 852 if (defined($time)) { 853 start_monitor; 854 # flush out current monitor 855 # May contain the reboot success line 856 wait_for_monitor 1; 857 } 858 859 # try to reboot normally 860 if (run_command $reboot) { 861 if (defined($powercycle_after_reboot)) { 862 sleep $powercycle_after_reboot; 863 run_command "$power_cycle"; 864 } 865 } else { 866 # nope? power cycle it. 867 run_command "$power_cycle"; 868 } 869 870 if (defined($time)) { 871 wait_for_monitor($time, $reboot_success_line); 872 end_monitor; 873 } 874} 875 876sub do_not_reboot { 877 my $i = $iteration; 878 879 return $test_type eq "build" || $no_reboot || 880 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 881 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 882} 883 884sub dodie { 885 doprint "CRITICAL FAILURE... ", @_, "\n"; 886 887 my $i = $iteration; 888 889 if ($reboot_on_error && !do_not_reboot) { 890 891 doprint "REBOOTING\n"; 892 reboot; 893 894 } elsif ($poweroff_on_error && defined($power_off)) { 895 doprint "POWERING OFF\n"; 896 `$power_off`; 897 } 898 899 if (defined($opt{"LOG_FILE"})) { 900 print " See $opt{LOG_FILE} for more info.\n"; 901 } 902 903 die @_, "\n"; 904} 905 906sub open_console { 907 my ($fp) = @_; 908 909 my $flags; 910 911 my $pid = open($fp, "$console|") or 912 dodie "Can't open console $console"; 913 914 $flags = fcntl($fp, F_GETFL, 0) or 915 dodie "Can't get flags for the socket: $!"; 916 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 917 dodie "Can't set flags for the socket: $!"; 918 919 return $pid; 920} 921 922sub close_console { 923 my ($fp, $pid) = @_; 924 925 doprint "kill child process $pid\n"; 926 kill 2, $pid; 927 928 print "closing!\n"; 929 close($fp); 930} 931 932sub start_monitor { 933 if ($monitor_cnt++) { 934 return; 935 } 936 $monitor_fp = \*MONFD; 937 $monitor_pid = open_console $monitor_fp; 938 939 return; 940 941 open(MONFD, "Stop perl from warning about single use of MONFD"); 942} 943 944sub end_monitor { 945 if (--$monitor_cnt) { 946 return; 947 } 948 close_console($monitor_fp, $monitor_pid); 949} 950 951sub wait_for_monitor { 952 my ($time, $stop) = @_; 953 my $full_line = ""; 954 my $line; 955 my $booted = 0; 956 957 doprint "** Wait for monitor to settle down **\n"; 958 959 # read the monitor and wait for the system to calm down 960 while (!$booted) { 961 $line = wait_for_input($monitor_fp, $time); 962 last if (!defined($line)); 963 print "$line"; 964 $full_line .= $line; 965 966 if (defined($stop) && $full_line =~ /$stop/) { 967 doprint "wait for monitor detected $stop\n"; 968 $booted = 1; 969 } 970 971 if ($line =~ /\n/) { 972 $full_line = ""; 973 } 974 } 975 print "** Monitor flushed **\n"; 976} 977 978sub fail { 979 980 if ($die_on_failure) { 981 dodie @_; 982 } 983 984 doprint "FAILED\n"; 985 986 my $i = $iteration; 987 988 # no need to reboot for just building. 989 if (!do_not_reboot) { 990 doprint "REBOOTING\n"; 991 reboot $sleep_time; 992 } 993 994 my $name = ""; 995 996 if (defined($test_name)) { 997 $name = " ($test_name)"; 998 } 999 1000 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1001 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1002 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 1003 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1004 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1005 1006 return 1 if (!defined($store_failures)); 1007 1008 my @t = localtime; 1009 my $date = sprintf "%04d%02d%02d%02d%02d%02d", 1010 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 1011 1012 my $type = $build_type; 1013 if ($type =~ /useconfig/) { 1014 $type = "useconfig"; 1015 } 1016 1017 my $dir = "$machine-$test_type-$type-fail-$date"; 1018 my $faildir = "$store_failures/$dir"; 1019 1020 if (!-d $faildir) { 1021 mkpath($faildir) or 1022 die "can't create $faildir"; 1023 } 1024 if (-f "$output_config") { 1025 cp "$output_config", "$faildir/config" or 1026 die "failed to copy .config"; 1027 } 1028 if (-f $buildlog) { 1029 cp $buildlog, "$faildir/buildlog" or 1030 die "failed to move $buildlog"; 1031 } 1032 if (-f $dmesg) { 1033 cp $dmesg, "$faildir/dmesg" or 1034 die "failed to move $dmesg"; 1035 } 1036 1037 doprint "*** Saved info to $faildir ***\n"; 1038 1039 return 1; 1040} 1041 1042sub run_command { 1043 my ($command) = @_; 1044 my $dolog = 0; 1045 my $dord = 0; 1046 my $pid; 1047 1048 $command =~ s/\$SSH_USER/$ssh_user/g; 1049 $command =~ s/\$MACHINE/$machine/g; 1050 1051 doprint("$command ... "); 1052 1053 $pid = open(CMD, "$command 2>&1 |") or 1054 (fail "unable to exec $command" and return 0); 1055 1056 if (defined($opt{"LOG_FILE"})) { 1057 open(LOG, ">>$opt{LOG_FILE}") or 1058 dodie "failed to write to log"; 1059 $dolog = 1; 1060 } 1061 1062 if (defined($redirect)) { 1063 open (RD, ">$redirect") or 1064 dodie "failed to write to redirect $redirect"; 1065 $dord = 1; 1066 } 1067 1068 while (<CMD>) { 1069 print LOG if ($dolog); 1070 print RD if ($dord); 1071 } 1072 1073 waitpid($pid, 0); 1074 my $failed = $?; 1075 1076 close(CMD); 1077 close(LOG) if ($dolog); 1078 close(RD) if ($dord); 1079 1080 if ($failed) { 1081 doprint "FAILED!\n"; 1082 } else { 1083 doprint "SUCCESS\n"; 1084 } 1085 1086 return !$failed; 1087} 1088 1089sub run_ssh { 1090 my ($cmd) = @_; 1091 my $cp_exec = $ssh_exec; 1092 1093 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 1094 return run_command "$cp_exec"; 1095} 1096 1097sub run_scp { 1098 my ($src, $dst) = @_; 1099 my $cp_scp = $scp_to_target; 1100 1101 $cp_scp =~ s/\$SRC_FILE/$src/g; 1102 $cp_scp =~ s/\$DST_FILE/$dst/g; 1103 1104 return run_command "$cp_scp"; 1105} 1106 1107sub get_grub_index { 1108 1109 if ($reboot_type ne "grub") { 1110 return; 1111 } 1112 return if (defined($grub_number)); 1113 1114 doprint "Find grub menu ... "; 1115 $grub_number = -1; 1116 1117 my $ssh_grub = $ssh_exec; 1118 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 1119 1120 open(IN, "$ssh_grub |") 1121 or die "unable to get menu.lst"; 1122 1123 my $found = 0; 1124 1125 while (<IN>) { 1126 if (/^\s*title\s+$grub_menu\s*$/) { 1127 $grub_number++; 1128 $found = 1; 1129 last; 1130 } elsif (/^\s*title\s/) { 1131 $grub_number++; 1132 } 1133 } 1134 close(IN); 1135 1136 die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 1137 if (!$found); 1138 doprint "$grub_number\n"; 1139} 1140 1141sub wait_for_input 1142{ 1143 my ($fp, $time) = @_; 1144 my $rin; 1145 my $ready; 1146 my $line; 1147 my $ch; 1148 1149 if (!defined($time)) { 1150 $time = $timeout; 1151 } 1152 1153 $rin = ''; 1154 vec($rin, fileno($fp), 1) = 1; 1155 $ready = select($rin, undef, undef, $time); 1156 1157 $line = ""; 1158 1159 # try to read one char at a time 1160 while (sysread $fp, $ch, 1) { 1161 $line .= $ch; 1162 last if ($ch eq "\n"); 1163 } 1164 1165 if (!length($line)) { 1166 return undef; 1167 } 1168 1169 return $line; 1170} 1171 1172sub reboot_to { 1173 if ($reboot_type eq "grub") { 1174 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 1175 reboot; 1176 return; 1177 } 1178 1179 run_command "$reboot_script"; 1180} 1181 1182sub get_sha1 { 1183 my ($commit) = @_; 1184 1185 doprint "git rev-list --max-count=1 $commit ... "; 1186 my $sha1 = `git rev-list --max-count=1 $commit`; 1187 my $ret = $?; 1188 1189 logit $sha1; 1190 1191 if ($ret) { 1192 doprint "FAILED\n"; 1193 dodie "Failed to get git $commit"; 1194 } 1195 1196 print "SUCCESS\n"; 1197 1198 chomp $sha1; 1199 1200 return $sha1; 1201} 1202 1203sub monitor { 1204 my $booted = 0; 1205 my $bug = 0; 1206 my $skip_call_trace = 0; 1207 my $loops; 1208 1209 wait_for_monitor 5; 1210 1211 my $line; 1212 my $full_line = ""; 1213 1214 open(DMESG, "> $dmesg") or 1215 die "unable to write to $dmesg"; 1216 1217 reboot_to; 1218 1219 my $success_start; 1220 my $failure_start; 1221 my $monitor_start = time; 1222 my $done = 0; 1223 my $version_found = 0; 1224 1225 while (!$done) { 1226 1227 if ($bug && defined($stop_after_failure) && 1228 $stop_after_failure >= 0) { 1229 my $time = $stop_after_failure - (time - $failure_start); 1230 $line = wait_for_input($monitor_fp, $time); 1231 if (!defined($line)) { 1232 doprint "bug timed out after $booted_timeout seconds\n"; 1233 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1234 last; 1235 } 1236 } elsif ($booted) { 1237 $line = wait_for_input($monitor_fp, $booted_timeout); 1238 if (!defined($line)) { 1239 my $s = $booted_timeout == 1 ? "" : "s"; 1240 doprint "Successful boot found: break after $booted_timeout second$s\n"; 1241 last; 1242 } 1243 } else { 1244 $line = wait_for_input($monitor_fp); 1245 if (!defined($line)) { 1246 my $s = $timeout == 1 ? "" : "s"; 1247 doprint "Timed out after $timeout second$s\n"; 1248 last; 1249 } 1250 } 1251 1252 doprint $line; 1253 print DMESG $line; 1254 1255 # we are not guaranteed to get a full line 1256 $full_line .= $line; 1257 1258 if ($full_line =~ /$success_line/) { 1259 $booted = 1; 1260 $success_start = time; 1261 } 1262 1263 if ($booted && defined($stop_after_success) && 1264 $stop_after_success >= 0) { 1265 my $now = time; 1266 if ($now - $success_start >= $stop_after_success) { 1267 doprint "Test forced to stop after $stop_after_success seconds after success\n"; 1268 last; 1269 } 1270 } 1271 1272 if ($full_line =~ /\[ backtrace testing \]/) { 1273 $skip_call_trace = 1; 1274 } 1275 1276 if ($full_line =~ /call trace:/i) { 1277 if (!$bug && !$skip_call_trace) { 1278 $bug = 1; 1279 $failure_start = time; 1280 } 1281 } 1282 1283 if ($bug && defined($stop_after_failure) && 1284 $stop_after_failure >= 0) { 1285 my $now = time; 1286 if ($now - $failure_start >= $stop_after_failure) { 1287 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1288 last; 1289 } 1290 } 1291 1292 if ($full_line =~ /\[ end of backtrace testing \]/) { 1293 $skip_call_trace = 0; 1294 } 1295 1296 if ($full_line =~ /Kernel panic -/) { 1297 $failure_start = time; 1298 $bug = 1; 1299 } 1300 1301 # Detect triple faults by testing the banner 1302 if ($full_line =~ /\bLinux version (\S+).*\n/) { 1303 if ($1 eq $version) { 1304 $version_found = 1; 1305 } elsif ($version_found && $detect_triplefault) { 1306 # We already booted into the kernel we are testing, 1307 # but now we booted into another kernel? 1308 # Consider this a triple fault. 1309 doprint "Aleady booted in Linux kernel $version, but now\n"; 1310 doprint "we booted into Linux kernel $1.\n"; 1311 doprint "Assuming that this is a triple fault.\n"; 1312 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 1313 last; 1314 } 1315 } 1316 1317 if ($line =~ /\n/) { 1318 $full_line = ""; 1319 } 1320 1321 if ($stop_test_after > 0 && !$booted && !$bug) { 1322 if (time - $monitor_start > $stop_test_after) { 1323 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 1324 $done = 1; 1325 } 1326 } 1327 } 1328 1329 close(DMESG); 1330 1331 if ($bug) { 1332 return 0 if ($in_bisect); 1333 fail "failed - got a bug report" and return 0; 1334 } 1335 1336 if (!$booted) { 1337 return 0 if ($in_bisect); 1338 fail "failed - never got a boot prompt." and return 0; 1339 } 1340 1341 return 1; 1342} 1343 1344sub do_post_install { 1345 1346 return if (!defined($post_install)); 1347 1348 my $cp_post_install = $post_install; 1349 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; 1350 run_command "$cp_post_install" or 1351 dodie "Failed to run post install"; 1352} 1353 1354sub install { 1355 1356 return if ($no_install); 1357 1358 run_scp "$outputdir/$build_target", "$target_image" or 1359 dodie "failed to copy image"; 1360 1361 my $install_mods = 0; 1362 1363 # should we process modules? 1364 $install_mods = 0; 1365 open(IN, "$output_config") or dodie("Can't read config file"); 1366 while (<IN>) { 1367 if (/CONFIG_MODULES(=y)?/) { 1368 $install_mods = 1 if (defined($1)); 1369 last; 1370 } 1371 } 1372 close(IN); 1373 1374 if (!$install_mods) { 1375 do_post_install; 1376 doprint "No modules needed\n"; 1377 return; 1378 } 1379 1380 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 1381 dodie "Failed to install modules"; 1382 1383 my $modlib = "/lib/modules/$version"; 1384 my $modtar = "ktest-mods.tar.bz2"; 1385 1386 run_ssh "rm -rf $modlib" or 1387 dodie "failed to remove old mods: $modlib"; 1388 1389 # would be nice if scp -r did not follow symbolic links 1390 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 1391 dodie "making tarball"; 1392 1393 run_scp "$tmpdir/$modtar", "/tmp" or 1394 dodie "failed to copy modules"; 1395 1396 unlink "$tmpdir/$modtar"; 1397 1398 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 1399 dodie "failed to tar modules"; 1400 1401 run_ssh "rm -f /tmp/$modtar"; 1402 1403 do_post_install; 1404} 1405 1406sub get_version { 1407 # get the release name 1408 doprint "$make kernelrelease ... "; 1409 $version = `$make kernelrelease | tail -1`; 1410 chomp($version); 1411 doprint "$version\n"; 1412} 1413 1414sub start_monitor_and_boot { 1415 # Make sure the stable kernel has finished booting 1416 start_monitor; 1417 wait_for_monitor 5; 1418 end_monitor; 1419 1420 get_grub_index; 1421 get_version; 1422 install; 1423 1424 start_monitor; 1425 return monitor; 1426} 1427 1428sub check_buildlog { 1429 my ($patch) = @_; 1430 1431 my @files = `git show $patch | diffstat -l`; 1432 1433 open(IN, "git show $patch |") or 1434 dodie "failed to show $patch"; 1435 while (<IN>) { 1436 if (m,^--- a/(.*),) { 1437 chomp $1; 1438 $files[$#files] = $1; 1439 } 1440 } 1441 close(IN); 1442 1443 open(IN, $buildlog) or dodie "Can't open $buildlog"; 1444 while (<IN>) { 1445 if (/^\s*(.*?):.*(warning|error)/) { 1446 my $err = $1; 1447 foreach my $file (@files) { 1448 my $fullpath = "$builddir/$file"; 1449 if ($file eq $err || $fullpath eq $err) { 1450 fail "$file built with warnings" and return 0; 1451 } 1452 } 1453 } 1454 } 1455 close(IN); 1456 1457 return 1; 1458} 1459 1460sub apply_min_config { 1461 my $outconfig = "$output_config.new"; 1462 1463 # Read the config file and remove anything that 1464 # is in the force_config hash (from minconfig and others) 1465 # then add the force config back. 1466 1467 doprint "Applying minimum configurations into $output_config.new\n"; 1468 1469 open (OUT, ">$outconfig") or 1470 dodie "Can't create $outconfig"; 1471 1472 if (-f $output_config) { 1473 open (IN, $output_config) or 1474 dodie "Failed to open $output_config"; 1475 while (<IN>) { 1476 if (/^(# )?(CONFIG_[^\s=]*)/) { 1477 next if (defined($force_config{$2})); 1478 } 1479 print OUT; 1480 } 1481 close IN; 1482 } 1483 foreach my $config (keys %force_config) { 1484 print OUT "$force_config{$config}\n"; 1485 } 1486 close OUT; 1487 1488 run_command "mv $outconfig $output_config"; 1489} 1490 1491sub make_oldconfig { 1492 1493 my @force_list = keys %force_config; 1494 1495 if ($#force_list >= 0) { 1496 apply_min_config; 1497 } 1498 1499 if (!run_command "$make oldnoconfig") { 1500 # Perhaps oldnoconfig doesn't exist in this version of the kernel 1501 # try a yes '' | oldconfig 1502 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1503 run_command "yes '' | $make oldconfig" or 1504 dodie "failed make config oldconfig"; 1505 } 1506} 1507 1508# read a config file and use this to force new configs. 1509sub load_force_config { 1510 my ($config) = @_; 1511 1512 open(IN, $config) or 1513 dodie "failed to read $config"; 1514 while (<IN>) { 1515 chomp; 1516 if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 1517 $force_config{$1} = $_; 1518 } elsif (/^# (CONFIG_\S*) is not set/) { 1519 $force_config{$1} = $_; 1520 } 1521 } 1522 close IN; 1523} 1524 1525sub build { 1526 my ($type) = @_; 1527 1528 unlink $buildlog; 1529 1530 # Failed builds should not reboot the target 1531 my $save_no_reboot = $no_reboot; 1532 $no_reboot = 1; 1533 1534 if (defined($pre_build)) { 1535 my $ret = run_command $pre_build; 1536 if (!$ret && defined($pre_build_die) && 1537 $pre_build_die) { 1538 dodie "failed to pre_build\n"; 1539 } 1540 } 1541 1542 if ($type =~ /^useconfig:(.*)/) { 1543 run_command "cp $1 $output_config" or 1544 dodie "could not copy $1 to .config"; 1545 1546 $type = "oldconfig"; 1547 } 1548 1549 # old config can ask questions 1550 if ($type eq "oldconfig") { 1551 $type = "oldnoconfig"; 1552 1553 # allow for empty configs 1554 run_command "touch $output_config"; 1555 1556 if (!$noclean) { 1557 run_command "mv $output_config $outputdir/config_temp" or 1558 dodie "moving .config"; 1559 1560 run_command "$make mrproper" or dodie "make mrproper"; 1561 1562 run_command "mv $outputdir/config_temp $output_config" or 1563 dodie "moving config_temp"; 1564 } 1565 1566 } elsif (!$noclean) { 1567 unlink "$output_config"; 1568 run_command "$make mrproper" or 1569 dodie "make mrproper"; 1570 } 1571 1572 # add something to distinguish this build 1573 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 1574 print OUT "$localversion\n"; 1575 close(OUT); 1576 1577 if (defined($minconfig)) { 1578 load_force_config($minconfig); 1579 } 1580 1581 if ($type ne "oldnoconfig") { 1582 run_command "$make $type" or 1583 dodie "failed make config"; 1584 } 1585 # Run old config regardless, to enforce min configurations 1586 make_oldconfig; 1587 1588 $redirect = "$buildlog"; 1589 my $build_ret = run_command "$make $build_options"; 1590 undef $redirect; 1591 1592 if (defined($post_build)) { 1593 my $ret = run_command $post_build; 1594 if (!$ret && defined($post_build_die) && 1595 $post_build_die) { 1596 dodie "failed to post_build\n"; 1597 } 1598 } 1599 1600 if (!$build_ret) { 1601 # bisect may need this to pass 1602 if ($in_bisect) { 1603 $no_reboot = $save_no_reboot; 1604 return 0; 1605 } 1606 fail "failed build" and return 0; 1607 } 1608 1609 $no_reboot = $save_no_reboot; 1610 1611 return 1; 1612} 1613 1614sub halt { 1615 if (!run_ssh "halt" or defined($power_off)) { 1616 if (defined($poweroff_after_halt)) { 1617 sleep $poweroff_after_halt; 1618 run_command "$power_off"; 1619 } 1620 } else { 1621 # nope? the zap it! 1622 run_command "$power_off"; 1623 } 1624} 1625 1626sub success { 1627 my ($i) = @_; 1628 1629 $successes++; 1630 1631 my $name = ""; 1632 1633 if (defined($test_name)) { 1634 $name = " ($test_name)"; 1635 } 1636 1637 doprint "\n\n*******************************************\n"; 1638 doprint "*******************************************\n"; 1639 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 1640 doprint "*******************************************\n"; 1641 doprint "*******************************************\n"; 1642 1643 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1644 doprint "Reboot and wait $sleep_time seconds\n"; 1645 reboot $sleep_time; 1646 } 1647} 1648 1649sub answer_bisect { 1650 for (;;) { 1651 doprint "Pass or fail? [p/f]"; 1652 my $ans = <STDIN>; 1653 chomp $ans; 1654 if ($ans eq "p" || $ans eq "P") { 1655 return 1; 1656 } elsif ($ans eq "f" || $ans eq "F") { 1657 return 0; 1658 } else { 1659 print "Please answer 'P' or 'F'\n"; 1660 } 1661 } 1662} 1663 1664sub child_run_test { 1665 my $failed = 0; 1666 1667 # child should have no power 1668 $reboot_on_error = 0; 1669 $poweroff_on_error = 0; 1670 $die_on_failure = 1; 1671 1672 run_command $run_test or $failed = 1; 1673 exit $failed; 1674} 1675 1676my $child_done; 1677 1678sub child_finished { 1679 $child_done = 1; 1680} 1681 1682sub do_run_test { 1683 my $child_pid; 1684 my $child_exit; 1685 my $line; 1686 my $full_line; 1687 my $bug = 0; 1688 1689 wait_for_monitor 1; 1690 1691 doprint "run test $run_test\n"; 1692 1693 $child_done = 0; 1694 1695 $SIG{CHLD} = qw(child_finished); 1696 1697 $child_pid = fork; 1698 1699 child_run_test if (!$child_pid); 1700 1701 $full_line = ""; 1702 1703 do { 1704 $line = wait_for_input($monitor_fp, 1); 1705 if (defined($line)) { 1706 1707 # we are not guaranteed to get a full line 1708 $full_line .= $line; 1709 doprint $line; 1710 1711 if ($full_line =~ /call trace:/i) { 1712 $bug = 1; 1713 } 1714 1715 if ($full_line =~ /Kernel panic -/) { 1716 $bug = 1; 1717 } 1718 1719 if ($line =~ /\n/) { 1720 $full_line = ""; 1721 } 1722 } 1723 } while (!$child_done && !$bug); 1724 1725 if ($bug) { 1726 my $failure_start = time; 1727 my $now; 1728 do { 1729 $line = wait_for_input($monitor_fp, 1); 1730 if (defined($line)) { 1731 doprint $line; 1732 } 1733 $now = time; 1734 if ($now - $failure_start >= $stop_after_failure) { 1735 last; 1736 } 1737 } while (defined($line)); 1738 1739 doprint "Detected kernel crash!\n"; 1740 # kill the child with extreme prejudice 1741 kill 9, $child_pid; 1742 } 1743 1744 waitpid $child_pid, 0; 1745 $child_exit = $?; 1746 1747 if ($bug || $child_exit) { 1748 return 0 if $in_bisect; 1749 fail "test failed" and return 0; 1750 } 1751 return 1; 1752} 1753 1754sub run_git_bisect { 1755 my ($command) = @_; 1756 1757 doprint "$command ... "; 1758 1759 my $output = `$command 2>&1`; 1760 my $ret = $?; 1761 1762 logit $output; 1763 1764 if ($ret) { 1765 doprint "FAILED\n"; 1766 dodie "Failed to git bisect"; 1767 } 1768 1769 doprint "SUCCESS\n"; 1770 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 1771 doprint "$1 [$2]\n"; 1772 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 1773 $bisect_bad = $1; 1774 doprint "Found bad commit... $1\n"; 1775 return 0; 1776 } else { 1777 # we already logged it, just print it now. 1778 print $output; 1779 } 1780 1781 return 1; 1782} 1783 1784sub bisect_reboot { 1785 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 1786 reboot $bisect_sleep_time; 1787} 1788 1789# returns 1 on success, 0 on failure, -1 on skip 1790sub run_bisect_test { 1791 my ($type, $buildtype) = @_; 1792 1793 my $failed = 0; 1794 my $result; 1795 my $output; 1796 my $ret; 1797 1798 $in_bisect = 1; 1799 1800 build $buildtype or $failed = 1; 1801 1802 if ($type ne "build") { 1803 if ($failed && $bisect_skip) { 1804 $in_bisect = 0; 1805 return -1; 1806 } 1807 dodie "Failed on build" if $failed; 1808 1809 # Now boot the box 1810 start_monitor_and_boot or $failed = 1; 1811 1812 if ($type ne "boot") { 1813 if ($failed && $bisect_skip) { 1814 end_monitor; 1815 bisect_reboot; 1816 $in_bisect = 0; 1817 return -1; 1818 } 1819 dodie "Failed on boot" if $failed; 1820 1821 do_run_test or $failed = 1; 1822 } 1823 end_monitor; 1824 } 1825 1826 if ($failed) { 1827 $result = 0; 1828 } else { 1829 $result = 1; 1830 } 1831 1832 # reboot the box to a kernel we can ssh to 1833 if ($type ne "build") { 1834 bisect_reboot; 1835 } 1836 $in_bisect = 0; 1837 1838 return $result; 1839} 1840 1841sub run_bisect { 1842 my ($type) = @_; 1843 my $buildtype = "oldconfig"; 1844 1845 # We should have a minconfig to use? 1846 if (defined($minconfig)) { 1847 $buildtype = "useconfig:$minconfig"; 1848 } 1849 1850 my $ret = run_bisect_test $type, $buildtype; 1851 1852 if ($bisect_manual) { 1853 $ret = answer_bisect; 1854 } 1855 1856 # Are we looking for where it worked, not failed? 1857 if ($reverse_bisect) { 1858 $ret = !$ret; 1859 } 1860 1861 if ($ret > 0) { 1862 return "good"; 1863 } elsif ($ret == 0) { 1864 return "bad"; 1865 } elsif ($bisect_skip) { 1866 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 1867 return "skip"; 1868 } 1869} 1870 1871sub bisect { 1872 my ($i) = @_; 1873 1874 my $result; 1875 1876 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 1877 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 1878 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 1879 1880 my $good = $opt{"BISECT_GOOD[$i]"}; 1881 my $bad = $opt{"BISECT_BAD[$i]"}; 1882 my $type = $opt{"BISECT_TYPE[$i]"}; 1883 my $start = $opt{"BISECT_START[$i]"}; 1884 my $replay = $opt{"BISECT_REPLAY[$i]"}; 1885 my $start_files = $opt{"BISECT_FILES[$i]"}; 1886 1887 if (defined($start_files)) { 1888 $start_files = " -- " . $start_files; 1889 } else { 1890 $start_files = ""; 1891 } 1892 1893 # convert to true sha1's 1894 $good = get_sha1($good); 1895 $bad = get_sha1($bad); 1896 1897 if (defined($opt{"BISECT_REVERSE[$i]"}) && 1898 $opt{"BISECT_REVERSE[$i]"} == 1) { 1899 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1900 $reverse_bisect = 1; 1901 } else { 1902 $reverse_bisect = 0; 1903 } 1904 1905 # Can't have a test without having a test to run 1906 if ($type eq "test" && !defined($run_test)) { 1907 $type = "boot"; 1908 } 1909 1910 my $check = $opt{"BISECT_CHECK[$i]"}; 1911 if (defined($check) && $check ne "0") { 1912 1913 # get current HEAD 1914 my $head = get_sha1("HEAD"); 1915 1916 if ($check ne "good") { 1917 doprint "TESTING BISECT BAD [$bad]\n"; 1918 run_command "git checkout $bad" or 1919 die "Failed to checkout $bad"; 1920 1921 $result = run_bisect $type; 1922 1923 if ($result ne "bad") { 1924 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1925 } 1926 } 1927 1928 if ($check ne "bad") { 1929 doprint "TESTING BISECT GOOD [$good]\n"; 1930 run_command "git checkout $good" or 1931 die "Failed to checkout $good"; 1932 1933 $result = run_bisect $type; 1934 1935 if ($result ne "good") { 1936 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1937 } 1938 } 1939 1940 # checkout where we started 1941 run_command "git checkout $head" or 1942 die "Failed to checkout $head"; 1943 } 1944 1945 run_command "git bisect start$start_files" or 1946 dodie "could not start bisect"; 1947 1948 run_command "git bisect good $good" or 1949 dodie "could not set bisect good to $good"; 1950 1951 run_git_bisect "git bisect bad $bad" or 1952 dodie "could not set bisect bad to $bad"; 1953 1954 if (defined($replay)) { 1955 run_command "git bisect replay $replay" or 1956 dodie "failed to run replay"; 1957 } 1958 1959 if (defined($start)) { 1960 run_command "git checkout $start" or 1961 dodie "failed to checkout $start"; 1962 } 1963 1964 my $test; 1965 do { 1966 $result = run_bisect $type; 1967 $test = run_git_bisect "git bisect $result"; 1968 } while ($test); 1969 1970 run_command "git bisect log" or 1971 dodie "could not capture git bisect log"; 1972 1973 run_command "git bisect reset" or 1974 dodie "could not reset git bisect"; 1975 1976 doprint "Bad commit was [$bisect_bad]\n"; 1977 1978 success $i; 1979} 1980 1981my %config_ignore; 1982my %config_set; 1983 1984my %config_list; 1985my %null_config; 1986 1987my %dependency; 1988 1989sub assign_configs { 1990 my ($hash, $config) = @_; 1991 1992 open (IN, $config) 1993 or dodie "Failed to read $config"; 1994 1995 while (<IN>) { 1996 if (/^((CONFIG\S*)=.*)/) { 1997 ${$hash}{$2} = $1; 1998 } 1999 } 2000 2001 close(IN); 2002} 2003 2004sub process_config_ignore { 2005 my ($config) = @_; 2006 2007 assign_configs \%config_ignore, $config; 2008} 2009 2010sub read_current_config { 2011 my ($config_ref) = @_; 2012 2013 %{$config_ref} = (); 2014 undef %{$config_ref}; 2015 2016 my @key = keys %{$config_ref}; 2017 if ($#key >= 0) { 2018 print "did not delete!\n"; 2019 exit; 2020 } 2021 open (IN, "$output_config"); 2022 2023 while (<IN>) { 2024 if (/^(CONFIG\S+)=(.*)/) { 2025 ${$config_ref}{$1} = $2; 2026 } 2027 } 2028 close(IN); 2029} 2030 2031sub get_dependencies { 2032 my ($config) = @_; 2033 2034 my $arr = $dependency{$config}; 2035 if (!defined($arr)) { 2036 return (); 2037 } 2038 2039 my @deps = @{$arr}; 2040 2041 foreach my $dep (@{$arr}) { 2042 print "ADD DEP $dep\n"; 2043 @deps = (@deps, get_dependencies $dep); 2044 } 2045 2046 return @deps; 2047} 2048 2049sub create_config { 2050 my @configs = @_; 2051 2052 open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 2053 2054 foreach my $config (@configs) { 2055 print OUT "$config_set{$config}\n"; 2056 my @deps = get_dependencies $config; 2057 foreach my $dep (@deps) { 2058 print OUT "$config_set{$dep}\n"; 2059 } 2060 } 2061 2062 foreach my $config (keys %config_ignore) { 2063 print OUT "$config_ignore{$config}\n"; 2064 } 2065 close(OUT); 2066 2067# exit; 2068 make_oldconfig; 2069} 2070 2071sub compare_configs { 2072 my (%a, %b) = @_; 2073 2074 foreach my $item (keys %a) { 2075 if (!defined($b{$item})) { 2076 print "diff $item\n"; 2077 return 1; 2078 } 2079 delete $b{$item}; 2080 } 2081 2082 my @keys = keys %b; 2083 if ($#keys) { 2084 print "diff2 $keys[0]\n"; 2085 } 2086 return -1 if ($#keys >= 0); 2087 2088 return 0; 2089} 2090 2091sub run_config_bisect_test { 2092 my ($type) = @_; 2093 2094 return run_bisect_test $type, "oldconfig"; 2095} 2096 2097sub process_passed { 2098 my (%configs) = @_; 2099 2100 doprint "These configs had no failure: (Enabling them for further compiles)\n"; 2101 # Passed! All these configs are part of a good compile. 2102 # Add them to the min options. 2103 foreach my $config (keys %configs) { 2104 if (defined($config_list{$config})) { 2105 doprint " removing $config\n"; 2106 $config_ignore{$config} = $config_list{$config}; 2107 delete $config_list{$config}; 2108 } 2109 } 2110 doprint "config copied to $outputdir/config_good\n"; 2111 run_command "cp -f $output_config $outputdir/config_good"; 2112} 2113 2114sub process_failed { 2115 my ($config) = @_; 2116 2117 doprint "\n\n***************************************\n"; 2118 doprint "Found bad config: $config\n"; 2119 doprint "***************************************\n\n"; 2120} 2121 2122sub run_config_bisect { 2123 2124 my @start_list = keys %config_list; 2125 2126 if ($#start_list < 0) { 2127 doprint "No more configs to test!!!\n"; 2128 return -1; 2129 } 2130 2131 doprint "***** RUN TEST ***\n"; 2132 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 2133 my $ret; 2134 my %current_config; 2135 2136 my $count = $#start_list + 1; 2137 doprint " $count configs to test\n"; 2138 2139 my $half = int($#start_list / 2); 2140 2141 do { 2142 my @tophalf = @start_list[0 .. $half]; 2143 2144 create_config @tophalf; 2145 read_current_config \%current_config; 2146 2147 $count = $#tophalf + 1; 2148 doprint "Testing $count configs\n"; 2149 my $found = 0; 2150 # make sure we test something 2151 foreach my $config (@tophalf) { 2152 if (defined($current_config{$config})) { 2153 logit " $config\n"; 2154 $found = 1; 2155 } 2156 } 2157 if (!$found) { 2158 # try the other half 2159 doprint "Top half produced no set configs, trying bottom half\n"; 2160 @tophalf = @start_list[$half + 1 .. $#start_list]; 2161 create_config @tophalf; 2162 read_current_config \%current_config; 2163 foreach my $config (@tophalf) { 2164 if (defined($current_config{$config})) { 2165 logit " $config\n"; 2166 $found = 1; 2167 } 2168 } 2169 if (!$found) { 2170 doprint "Failed: Can't make new config with current configs\n"; 2171 foreach my $config (@start_list) { 2172 doprint " CONFIG: $config\n"; 2173 } 2174 return -1; 2175 } 2176 $count = $#tophalf + 1; 2177 doprint "Testing $count configs\n"; 2178 } 2179 2180 $ret = run_config_bisect_test $type; 2181 if ($bisect_manual) { 2182 $ret = answer_bisect; 2183 } 2184 if ($ret) { 2185 process_passed %current_config; 2186 return 0; 2187 } 2188 2189 doprint "This config had a failure.\n"; 2190 doprint "Removing these configs that were not set in this config:\n"; 2191 doprint "config copied to $outputdir/config_bad\n"; 2192 run_command "cp -f $output_config $outputdir/config_bad"; 2193 2194 # A config exists in this group that was bad. 2195 foreach my $config (keys %config_list) { 2196 if (!defined($current_config{$config})) { 2197 doprint " removing $config\n"; 2198 delete $config_list{$config}; 2199 } 2200 } 2201 2202 @start_list = @tophalf; 2203 2204 if ($#start_list == 0) { 2205 process_failed $start_list[0]; 2206 return 1; 2207 } 2208 2209 # remove half the configs we are looking at and see if 2210 # they are good. 2211 $half = int($#start_list / 2); 2212 } while ($#start_list > 0); 2213 2214 # we found a single config, try it again unless we are running manually 2215 2216 if ($bisect_manual) { 2217 process_failed $start_list[0]; 2218 return 1; 2219 } 2220 2221 my @tophalf = @start_list[0 .. 0]; 2222 2223 $ret = run_config_bisect_test $type; 2224 if ($ret) { 2225 process_passed %current_config; 2226 return 0; 2227 } 2228 2229 process_failed $start_list[0]; 2230 return 1; 2231} 2232 2233sub config_bisect { 2234 my ($i) = @_; 2235 2236 my $start_config = $opt{"CONFIG_BISECT[$i]"}; 2237 2238 my $tmpconfig = "$tmpdir/use_config"; 2239 2240 if (defined($config_bisect_good)) { 2241 process_config_ignore $config_bisect_good; 2242 } 2243 2244 # Make the file with the bad config and the min config 2245 if (defined($minconfig)) { 2246 # read the min config for things to ignore 2247 run_command "cp $minconfig $tmpconfig" or 2248 dodie "failed to copy $minconfig to $tmpconfig"; 2249 } else { 2250 unlink $tmpconfig; 2251 } 2252 2253 if (-f $tmpconfig) { 2254 load_force_config($tmpconfig); 2255 process_config_ignore $tmpconfig; 2256 } 2257 2258 # now process the start config 2259 run_command "cp $start_config $output_config" or 2260 dodie "failed to copy $start_config to $output_config"; 2261 2262 # read directly what we want to check 2263 my %config_check; 2264 open (IN, $output_config) 2265 or dodie "faied to open $output_config"; 2266 2267 while (<IN>) { 2268 if (/^((CONFIG\S*)=.*)/) { 2269 $config_check{$2} = $1; 2270 } 2271 } 2272 close(IN); 2273 2274 # Now run oldconfig with the minconfig 2275 make_oldconfig; 2276 2277 # check to see what we lost (or gained) 2278 open (IN, $output_config) 2279 or dodie "Failed to read $start_config"; 2280 2281 my %removed_configs; 2282 my %added_configs; 2283 2284 while (<IN>) { 2285 if (/^((CONFIG\S*)=.*)/) { 2286 # save off all options 2287 $config_set{$2} = $1; 2288 if (defined($config_check{$2})) { 2289 if (defined($config_ignore{$2})) { 2290 $removed_configs{$2} = $1; 2291 } else { 2292 $config_list{$2} = $1; 2293 } 2294 } elsif (!defined($config_ignore{$2})) { 2295 $added_configs{$2} = $1; 2296 $config_list{$2} = $1; 2297 } 2298 } 2299 } 2300 close(IN); 2301 2302 my @confs = keys %removed_configs; 2303 if ($#confs >= 0) { 2304 doprint "Configs overridden by default configs and removed from check:\n"; 2305 foreach my $config (@confs) { 2306 doprint " $config\n"; 2307 } 2308 } 2309 @confs = keys %added_configs; 2310 if ($#confs >= 0) { 2311 doprint "Configs appearing in make oldconfig and added:\n"; 2312 foreach my $config (@confs) { 2313 doprint " $config\n"; 2314 } 2315 } 2316 2317 my %config_test; 2318 my $once = 0; 2319 2320 # Sometimes kconfig does weird things. We must make sure 2321 # that the config we autocreate has everything we need 2322 # to test, otherwise we may miss testing configs, or 2323 # may not be able to create a new config. 2324 # Here we create a config with everything set. 2325 create_config (keys %config_list); 2326 read_current_config \%config_test; 2327 foreach my $config (keys %config_list) { 2328 if (!defined($config_test{$config})) { 2329 if (!$once) { 2330 $once = 1; 2331 doprint "Configs not produced by kconfig (will not be checked):\n"; 2332 } 2333 doprint " $config\n"; 2334 delete $config_list{$config}; 2335 } 2336 } 2337 my $ret; 2338 do { 2339 $ret = run_config_bisect; 2340 } while (!$ret); 2341 2342 return $ret if ($ret < 0); 2343 2344 success $i; 2345} 2346 2347sub patchcheck_reboot { 2348 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 2349 reboot $patchcheck_sleep_time; 2350} 2351 2352sub patchcheck { 2353 my ($i) = @_; 2354 2355 die "PATCHCHECK_START[$i] not defined\n" 2356 if (!defined($opt{"PATCHCHECK_START[$i]"})); 2357 die "PATCHCHECK_TYPE[$i] not defined\n" 2358 if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 2359 2360 my $start = $opt{"PATCHCHECK_START[$i]"}; 2361 2362 my $end = "HEAD"; 2363 if (defined($opt{"PATCHCHECK_END[$i]"})) { 2364 $end = $opt{"PATCHCHECK_END[$i]"}; 2365 } 2366 2367 # Get the true sha1's since we can use things like HEAD~3 2368 $start = get_sha1($start); 2369 $end = get_sha1($end); 2370 2371 my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 2372 2373 # Can't have a test without having a test to run 2374 if ($type eq "test" && !defined($run_test)) { 2375 $type = "boot"; 2376 } 2377 2378 open (IN, "git log --pretty=oneline $end|") or 2379 dodie "could not get git list"; 2380 2381 my @list; 2382 2383 while (<IN>) { 2384 chomp; 2385 $list[$#list+1] = $_; 2386 last if (/^$start/); 2387 } 2388 close(IN); 2389 2390 if ($list[$#list] !~ /^$start/) { 2391 fail "SHA1 $start not found"; 2392 } 2393 2394 # go backwards in the list 2395 @list = reverse @list; 2396 2397 my $save_clean = $noclean; 2398 my %ignored_warnings; 2399 2400 if (defined($ignore_warnings)) { 2401 foreach my $sha1 (split /\s+/, $ignore_warnings) { 2402 $ignored_warnings{$sha1} = 1; 2403 } 2404 } 2405 2406 $in_patchcheck = 1; 2407 foreach my $item (@list) { 2408 my $sha1 = $item; 2409 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 2410 2411 doprint "\nProcessing commit $item\n\n"; 2412 2413 run_command "git checkout $sha1" or 2414 die "Failed to checkout $sha1"; 2415 2416 # only clean on the first and last patch 2417 if ($item eq $list[0] || 2418 $item eq $list[$#list]) { 2419 $noclean = $save_clean; 2420 } else { 2421 $noclean = 1; 2422 } 2423 2424 if (defined($minconfig)) { 2425 build "useconfig:$minconfig" or return 0; 2426 } else { 2427 # ?? no config to use? 2428 build "oldconfig" or return 0; 2429 } 2430 2431 2432 if (!defined($ignored_warnings{$sha1})) { 2433 check_buildlog $sha1 or return 0; 2434 } 2435 2436 next if ($type eq "build"); 2437 2438 my $failed = 0; 2439 2440 start_monitor_and_boot or $failed = 1; 2441 2442 if (!$failed && $type ne "boot"){ 2443 do_run_test or $failed = 1; 2444 } 2445 end_monitor; 2446 return 0 if ($failed); 2447 2448 patchcheck_reboot; 2449 2450 } 2451 $in_patchcheck = 0; 2452 success $i; 2453 2454 return 1; 2455} 2456 2457my %depends; 2458my %depcount; 2459my $iflevel = 0; 2460my @ifdeps; 2461 2462# prevent recursion 2463my %read_kconfigs; 2464 2465sub add_dep { 2466 # $config depends on $dep 2467 my ($config, $dep) = @_; 2468 2469 if (defined($depends{$config})) { 2470 $depends{$config} .= " " . $dep; 2471 } else { 2472 $depends{$config} = $dep; 2473 } 2474 2475 # record the number of configs depending on $dep 2476 if (defined $depcount{$dep}) { 2477 $depcount{$dep}++; 2478 } else { 2479 $depcount{$dep} = 1; 2480 } 2481} 2482 2483# taken from streamline_config.pl 2484sub read_kconfig { 2485 my ($kconfig) = @_; 2486 2487 my $state = "NONE"; 2488 my $config; 2489 my @kconfigs; 2490 2491 my $cont = 0; 2492 my $line; 2493 2494 2495 if (! -f $kconfig) { 2496 doprint "file $kconfig does not exist, skipping\n"; 2497 return; 2498 } 2499 2500 open(KIN, "$kconfig") 2501 or die "Can't open $kconfig"; 2502 while (<KIN>) { 2503 chomp; 2504 2505 # Make sure that lines ending with \ continue 2506 if ($cont) { 2507 $_ = $line . " " . $_; 2508 } 2509 2510 if (s/\\$//) { 2511 $cont = 1; 2512 $line = $_; 2513 next; 2514 } 2515 2516 $cont = 0; 2517 2518 # collect any Kconfig sources 2519 if (/^source\s*"(.*)"/) { 2520 $kconfigs[$#kconfigs+1] = $1; 2521 } 2522 2523 # configs found 2524 if (/^\s*(menu)?config\s+(\S+)\s*$/) { 2525 $state = "NEW"; 2526 $config = $2; 2527 2528 for (my $i = 0; $i < $iflevel; $i++) { 2529 add_dep $config, $ifdeps[$i]; 2530 } 2531 2532 # collect the depends for the config 2533 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 2534 2535 add_dep $config, $1; 2536 2537 # Get the configs that select this config 2538 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 2539 2540 # selected by depends on config 2541 add_dep $1, $config; 2542 2543 # Check for if statements 2544 } elsif (/^if\s+(.*\S)\s*$/) { 2545 my $deps = $1; 2546 # remove beginning and ending non text 2547 $deps =~ s/^[^a-zA-Z0-9_]*//; 2548 $deps =~ s/[^a-zA-Z0-9_]*$//; 2549 2550 my @deps = split /[^a-zA-Z0-9_]+/, $deps; 2551 2552 $ifdeps[$iflevel++] = join ':', @deps; 2553 2554 } elsif (/^endif/) { 2555 2556 $iflevel-- if ($iflevel); 2557 2558 # stop on "help" 2559 } elsif (/^\s*help\s*$/) { 2560 $state = "NONE"; 2561 } 2562 } 2563 close(KIN); 2564 2565 # read in any configs that were found. 2566 foreach $kconfig (@kconfigs) { 2567 if (!defined($read_kconfigs{$kconfig})) { 2568 $read_kconfigs{$kconfig} = 1; 2569 read_kconfig("$builddir/$kconfig"); 2570 } 2571 } 2572} 2573 2574sub read_depends { 2575 # find out which arch this is by the kconfig file 2576 open (IN, $output_config) 2577 or dodie "Failed to read $output_config"; 2578 my $arch; 2579 while (<IN>) { 2580 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 2581 $arch = $1; 2582 last; 2583 } 2584 } 2585 close IN; 2586 2587 if (!defined($arch)) { 2588 doprint "Could not find arch from config file\n"; 2589 doprint "no dependencies used\n"; 2590 return; 2591 } 2592 2593 # arch is really the subarch, we need to know 2594 # what directory to look at. 2595 if ($arch eq "i386" || $arch eq "x86_64") { 2596 $arch = "x86"; 2597 } elsif ($arch =~ /^tile/) { 2598 $arch = "tile"; 2599 } 2600 2601 my $kconfig = "$builddir/arch/$arch/Kconfig"; 2602 2603 if (! -f $kconfig && $arch =~ /\d$/) { 2604 my $orig = $arch; 2605 # some subarchs have numbers, truncate them 2606 $arch =~ s/\d*$//; 2607 $kconfig = "$builddir/arch/$arch/Kconfig"; 2608 if (! -f $kconfig) { 2609 doprint "No idea what arch dir $orig is for\n"; 2610 doprint "no dependencies used\n"; 2611 return; 2612 } 2613 } 2614 2615 read_kconfig($kconfig); 2616} 2617 2618sub read_config_list { 2619 my ($config) = @_; 2620 2621 open (IN, $config) 2622 or dodie "Failed to read $config"; 2623 2624 while (<IN>) { 2625 if (/^((CONFIG\S*)=.*)/) { 2626 if (!defined($config_ignore{$2})) { 2627 $config_list{$2} = $1; 2628 } 2629 } 2630 } 2631 2632 close(IN); 2633} 2634 2635sub read_output_config { 2636 my ($config) = @_; 2637 2638 assign_configs \%config_ignore, $config; 2639} 2640 2641sub make_new_config { 2642 my @configs = @_; 2643 2644 open (OUT, ">$output_config") 2645 or dodie "Failed to write $output_config"; 2646 2647 foreach my $config (@configs) { 2648 print OUT "$config\n"; 2649 } 2650 close OUT; 2651} 2652 2653sub chomp_config { 2654 my ($config) = @_; 2655 2656 $config =~ s/CONFIG_//; 2657 2658 return $config; 2659} 2660 2661sub get_depends { 2662 my ($dep) = @_; 2663 2664 my $kconfig = chomp_config $dep; 2665 2666 $dep = $depends{"$kconfig"}; 2667 2668 # the dep string we have saves the dependencies as they 2669 # were found, including expressions like ! && ||. We 2670 # want to split this out into just an array of configs. 2671 2672 my $valid = "A-Za-z_0-9"; 2673 2674 my @configs; 2675 2676 while ($dep =~ /[$valid]/) { 2677 2678 if ($dep =~ /^[^$valid]*([$valid]+)/) { 2679 my $conf = "CONFIG_" . $1; 2680 2681 $configs[$#configs + 1] = $conf; 2682 2683 $dep =~ s/^[^$valid]*[$valid]+//; 2684 } else { 2685 die "this should never happen"; 2686 } 2687 } 2688 2689 return @configs; 2690} 2691 2692my %min_configs; 2693my %keep_configs; 2694my %save_configs; 2695my %processed_configs; 2696my %nochange_config; 2697 2698sub test_this_config { 2699 my ($config) = @_; 2700 2701 my $found; 2702 2703 # if we already processed this config, skip it 2704 if (defined($processed_configs{$config})) { 2705 return undef; 2706 } 2707 $processed_configs{$config} = 1; 2708 2709 # if this config failed during this round, skip it 2710 if (defined($nochange_config{$config})) { 2711 return undef; 2712 } 2713 2714 my $kconfig = chomp_config $config; 2715 2716 # Test dependencies first 2717 if (defined($depends{"$kconfig"})) { 2718 my @parents = get_depends $config; 2719 foreach my $parent (@parents) { 2720 # if the parent is in the min config, check it first 2721 next if (!defined($min_configs{$parent})); 2722 $found = test_this_config($parent); 2723 if (defined($found)) { 2724 return $found; 2725 } 2726 } 2727 } 2728 2729 # Remove this config from the list of configs 2730 # do a make oldnoconfig and then read the resulting 2731 # .config to make sure it is missing the config that 2732 # we had before 2733 my %configs = %min_configs; 2734 delete $configs{$config}; 2735 make_new_config ((values %configs), (values %keep_configs)); 2736 make_oldconfig; 2737 undef %configs; 2738 assign_configs \%configs, $output_config; 2739 2740 return $config if (!defined($configs{$config})); 2741 2742 doprint "disabling config $config did not change .config\n"; 2743 2744 $nochange_config{$config} = 1; 2745 2746 return undef; 2747} 2748 2749sub make_min_config { 2750 my ($i) = @_; 2751 2752 if (!defined($output_minconfig)) { 2753 fail "OUTPUT_MIN_CONFIG not defined" and return; 2754 } 2755 2756 # If output_minconfig exists, and the start_minconfig 2757 # came from min_config, than ask if we should use 2758 # that instead. 2759 if (-f $output_minconfig && !$start_minconfig_defined) { 2760 print "$output_minconfig exists\n"; 2761 if (read_yn " Use it as minconfig?") { 2762 $start_minconfig = $output_minconfig; 2763 } 2764 } 2765 2766 if (!defined($start_minconfig)) { 2767 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 2768 } 2769 2770 my $temp_config = "$tmpdir/temp_config"; 2771 2772 # First things first. We build an allnoconfig to find 2773 # out what the defaults are that we can't touch. 2774 # Some are selections, but we really can't handle selections. 2775 2776 my $save_minconfig = $minconfig; 2777 undef $minconfig; 2778 2779 run_command "$make allnoconfig" or return 0; 2780 2781 read_depends; 2782 2783 process_config_ignore $output_config; 2784 2785 undef %save_configs; 2786 undef %min_configs; 2787 2788 if (defined($ignore_config)) { 2789 # make sure the file exists 2790 `touch $ignore_config`; 2791 assign_configs \%save_configs, $ignore_config; 2792 } 2793 2794 %keep_configs = %save_configs; 2795 2796 doprint "Load initial configs from $start_minconfig\n"; 2797 2798 # Look at the current min configs, and save off all the 2799 # ones that were set via the allnoconfig 2800 assign_configs \%min_configs, $start_minconfig; 2801 2802 my @config_keys = keys %min_configs; 2803 2804 # All configs need a depcount 2805 foreach my $config (@config_keys) { 2806 my $kconfig = chomp_config $config; 2807 if (!defined $depcount{$kconfig}) { 2808 $depcount{$kconfig} = 0; 2809 } 2810 } 2811 2812 # Remove anything that was set by the make allnoconfig 2813 # we shouldn't need them as they get set for us anyway. 2814 foreach my $config (@config_keys) { 2815 # Remove anything in the ignore_config 2816 if (defined($keep_configs{$config})) { 2817 my $file = $ignore_config; 2818 $file =~ s,.*/(.*?)$,$1,; 2819 doprint "$config set by $file ... ignored\n"; 2820 delete $min_configs{$config}; 2821 next; 2822 } 2823 # But make sure the settings are the same. If a min config 2824 # sets a selection, we do not want to get rid of it if 2825 # it is not the same as what we have. Just move it into 2826 # the keep configs. 2827 if (defined($config_ignore{$config})) { 2828 if ($config_ignore{$config} ne $min_configs{$config}) { 2829 doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 2830 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 2831 $keep_configs{$config} = $min_configs{$config}; 2832 } else { 2833 doprint "$config set by allnoconfig ... ignored\n"; 2834 } 2835 delete $min_configs{$config}; 2836 } 2837 } 2838 2839 my $done = 0; 2840 my $take_two = 0; 2841 2842 while (!$done) { 2843 2844 my $config; 2845 my $found; 2846 2847 # Now disable each config one by one and do a make oldconfig 2848 # till we find a config that changes our list. 2849 2850 my @test_configs = keys %min_configs; 2851 2852 # Sort keys by who is most dependent on 2853 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 2854 @test_configs ; 2855 2856 # Put configs that did not modify the config at the end. 2857 my $reset = 1; 2858 for (my $i = 0; $i < $#test_configs; $i++) { 2859 if (!defined($nochange_config{$test_configs[0]})) { 2860 $reset = 0; 2861 last; 2862 } 2863 # This config didn't change the .config last time. 2864 # Place it at the end 2865 my $config = shift @test_configs; 2866 push @test_configs, $config; 2867 } 2868 2869 # if every test config has failed to modify the .config file 2870 # in the past, then reset and start over. 2871 if ($reset) { 2872 undef %nochange_config; 2873 } 2874 2875 undef %processed_configs; 2876 2877 foreach my $config (@test_configs) { 2878 2879 $found = test_this_config $config; 2880 2881 last if (defined($found)); 2882 2883 # oh well, try another config 2884 } 2885 2886 if (!defined($found)) { 2887 # we could have failed due to the nochange_config hash 2888 # reset and try again 2889 if (!$take_two) { 2890 undef %nochange_config; 2891 $take_two = 1; 2892 next; 2893 } 2894 doprint "No more configs found that we can disable\n"; 2895 $done = 1; 2896 last; 2897 } 2898 $take_two = 0; 2899 2900 $config = $found; 2901 2902 doprint "Test with $config disabled\n"; 2903 2904 # set in_bisect to keep build and monitor from dieing 2905 $in_bisect = 1; 2906 2907 my $failed = 0; 2908 build "oldconfig"; 2909 start_monitor_and_boot or $failed = 1; 2910 end_monitor; 2911 2912 $in_bisect = 0; 2913 2914 if ($failed) { 2915 doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 2916 # this config is needed, add it to the ignore list. 2917 $keep_configs{$config} = $min_configs{$config}; 2918 $save_configs{$config} = $min_configs{$config}; 2919 delete $min_configs{$config}; 2920 2921 # update new ignore configs 2922 if (defined($ignore_config)) { 2923 open (OUT, ">$temp_config") 2924 or die "Can't write to $temp_config"; 2925 foreach my $config (keys %save_configs) { 2926 print OUT "$save_configs{$config}\n"; 2927 } 2928 close OUT; 2929 run_command "mv $temp_config $ignore_config" or 2930 dodie "failed to copy update to $ignore_config"; 2931 } 2932 2933 } else { 2934 # We booted without this config, remove it from the minconfigs. 2935 doprint "$config is not needed, disabling\n"; 2936 2937 delete $min_configs{$config}; 2938 2939 # Also disable anything that is not enabled in this config 2940 my %configs; 2941 assign_configs \%configs, $output_config; 2942 my @config_keys = keys %min_configs; 2943 foreach my $config (@config_keys) { 2944 if (!defined($configs{$config})) { 2945 doprint "$config is not set, disabling\n"; 2946 delete $min_configs{$config}; 2947 } 2948 } 2949 2950 # Save off all the current mandidory configs 2951 open (OUT, ">$temp_config") 2952 or die "Can't write to $temp_config"; 2953 foreach my $config (keys %keep_configs) { 2954 print OUT "$keep_configs{$config}\n"; 2955 } 2956 foreach my $config (keys %min_configs) { 2957 print OUT "$min_configs{$config}\n"; 2958 } 2959 close OUT; 2960 2961 run_command "mv $temp_config $output_minconfig" or 2962 dodie "failed to copy update to $output_minconfig"; 2963 } 2964 2965 doprint "Reboot and wait $sleep_time seconds\n"; 2966 reboot $sleep_time; 2967 } 2968 2969 success $i; 2970 return 1; 2971} 2972 2973$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 2974 2975if ($#ARGV == 0) { 2976 $ktest_config = $ARGV[0]; 2977 if (! -f $ktest_config) { 2978 print "$ktest_config does not exist.\n"; 2979 if (!read_yn "Create it?") { 2980 exit 0; 2981 } 2982 } 2983} else { 2984 $ktest_config = "ktest.conf"; 2985} 2986 2987if (! -f $ktest_config) { 2988 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 2989 print OUT << "EOF" 2990# Generated by ktest.pl 2991# 2992# Define each test with TEST_START 2993# The config options below it will override the defaults 2994TEST_START 2995 2996DEFAULTS 2997EOF 2998; 2999 close(OUT); 3000} 3001read_config $ktest_config; 3002 3003if (defined($opt{"LOG_FILE"})) { 3004 $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1); 3005} 3006 3007# Append any configs entered in manually to the config file. 3008my @new_configs = keys %entered_configs; 3009if ($#new_configs >= 0) { 3010 print "\nAppending entered in configs to $ktest_config\n"; 3011 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 3012 foreach my $config (@new_configs) { 3013 print OUT "$config = $entered_configs{$config}\n"; 3014 $opt{$config} = $entered_configs{$config}; 3015 } 3016} 3017 3018if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 3019 unlink $opt{"LOG_FILE"}; 3020} 3021 3022doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 3023 3024for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 3025 3026 if (!$i) { 3027 doprint "DEFAULT OPTIONS:\n"; 3028 } else { 3029 doprint "\nTEST $i OPTIONS"; 3030 if (defined($repeat_tests{$i})) { 3031 $repeat = $repeat_tests{$i}; 3032 doprint " ITERATE $repeat"; 3033 } 3034 doprint "\n"; 3035 } 3036 3037 foreach my $option (sort keys %opt) { 3038 3039 if ($option =~ /\[(\d+)\]$/) { 3040 next if ($i != $1); 3041 } else { 3042 next if ($i); 3043 } 3044 3045 doprint "$option = $opt{$option}\n"; 3046 } 3047} 3048 3049sub __set_test_option { 3050 my ($name, $i) = @_; 3051 3052 my $option = "$name\[$i\]"; 3053 3054 if (defined($opt{$option})) { 3055 return $opt{$option}; 3056 } 3057 3058 foreach my $test (keys %repeat_tests) { 3059 if ($i >= $test && 3060 $i < $test + $repeat_tests{$test}) { 3061 $option = "$name\[$test\]"; 3062 if (defined($opt{$option})) { 3063 return $opt{$option}; 3064 } 3065 } 3066 } 3067 3068 if (defined($opt{$name})) { 3069 return $opt{$name}; 3070 } 3071 3072 return undef; 3073} 3074 3075sub set_test_option { 3076 my ($name, $i) = @_; 3077 3078 my $option = __set_test_option($name, $i); 3079 return $option if (!defined($option)); 3080 3081 return eval_option($option, $i); 3082} 3083 3084# First we need to do is the builds 3085for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 3086 3087 # Do not reboot on failing test options 3088 $no_reboot = 1; 3089 3090 $iteration = $i; 3091 3092 my $makecmd = set_test_option("MAKE_CMD", $i); 3093 3094 $machine = set_test_option("MACHINE", $i); 3095 $ssh_user = set_test_option("SSH_USER", $i); 3096 $tmpdir = set_test_option("TMP_DIR", $i); 3097 $outputdir = set_test_option("OUTPUT_DIR", $i); 3098 $builddir = set_test_option("BUILD_DIR", $i); 3099 $test_type = set_test_option("TEST_TYPE", $i); 3100 $build_type = set_test_option("BUILD_TYPE", $i); 3101 $build_options = set_test_option("BUILD_OPTIONS", $i); 3102 $pre_build = set_test_option("PRE_BUILD", $i); 3103 $post_build = set_test_option("POST_BUILD", $i); 3104 $pre_build_die = set_test_option("PRE_BUILD_DIE", $i); 3105 $post_build_die = set_test_option("POST_BUILD_DIE", $i); 3106 $power_cycle = set_test_option("POWER_CYCLE", $i); 3107 $reboot = set_test_option("REBOOT", $i); 3108 $noclean = set_test_option("BUILD_NOCLEAN", $i); 3109 $minconfig = set_test_option("MIN_CONFIG", $i); 3110 $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i); 3111 $start_minconfig = set_test_option("START_MIN_CONFIG", $i); 3112 $ignore_config = set_test_option("IGNORE_CONFIG", $i); 3113 $run_test = set_test_option("TEST", $i); 3114 $addconfig = set_test_option("ADD_CONFIG", $i); 3115 $reboot_type = set_test_option("REBOOT_TYPE", $i); 3116 $grub_menu = set_test_option("GRUB_MENU", $i); 3117 $post_install = set_test_option("POST_INSTALL", $i); 3118 $no_install = set_test_option("NO_INSTALL", $i); 3119 $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 3120 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 3121 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 3122 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 3123 $power_off = set_test_option("POWER_OFF", $i); 3124 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 3125 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 3126 $sleep_time = set_test_option("SLEEP_TIME", $i); 3127 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 3128 $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); 3129 $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i); 3130 $bisect_manual = set_test_option("BISECT_MANUAL", $i); 3131 $bisect_skip = set_test_option("BISECT_SKIP", $i); 3132 $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); 3133 $store_failures = set_test_option("STORE_FAILURES", $i); 3134 $test_name = set_test_option("TEST_NAME", $i); 3135 $timeout = set_test_option("TIMEOUT", $i); 3136 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 3137 $console = set_test_option("CONSOLE", $i); 3138 $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i); 3139 $success_line = set_test_option("SUCCESS_LINE", $i); 3140 $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i); 3141 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 3142 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 3143 $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); 3144 $build_target = set_test_option("BUILD_TARGET", $i); 3145 $ssh_exec = set_test_option("SSH_EXEC", $i); 3146 $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 3147 $target_image = set_test_option("TARGET_IMAGE", $i); 3148 $localversion = set_test_option("LOCALVERSION", $i); 3149 3150 $start_minconfig_defined = 1; 3151 3152 if (!defined($start_minconfig)) { 3153 $start_minconfig_defined = 0; 3154 $start_minconfig = $minconfig; 3155 } 3156 3157 chdir $builddir || die "can't change directory to $builddir"; 3158 3159 foreach my $dir ($tmpdir, $outputdir) { 3160 if (!-d $dir) { 3161 mkpath($dir) or 3162 die "can't create $dir"; 3163 } 3164 } 3165 3166 $ENV{"SSH_USER"} = $ssh_user; 3167 $ENV{"MACHINE"} = $machine; 3168 3169 $target = "$ssh_user\@$machine"; 3170 3171 $buildlog = "$tmpdir/buildlog-$machine"; 3172 $dmesg = "$tmpdir/dmesg-$machine"; 3173 $make = "$makecmd O=$outputdir"; 3174 $output_config = "$outputdir/.config"; 3175 3176 if ($reboot_type eq "grub") { 3177 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3178 } elsif (!defined($reboot_script)) { 3179 dodie "REBOOT_SCRIPT not defined" 3180 } 3181 3182 my $run_type = $build_type; 3183 if ($test_type eq "patchcheck") { 3184 $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 3185 } elsif ($test_type eq "bisect") { 3186 $run_type = $opt{"BISECT_TYPE[$i]"}; 3187 } elsif ($test_type eq "config_bisect") { 3188 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 3189 } 3190 3191 if ($test_type eq "make_min_config") { 3192 $run_type = ""; 3193 } 3194 3195 # mistake in config file? 3196 if (!defined($run_type)) { 3197 $run_type = "ERROR"; 3198 } 3199 3200 my $installme = ""; 3201 $installme = " no_install" if ($no_install); 3202 3203 doprint "\n\n"; 3204 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; 3205 3206 unlink $dmesg; 3207 unlink $buildlog; 3208 3209 if (defined($addconfig)) { 3210 my $min = $minconfig; 3211 if (!defined($minconfig)) { 3212 $min = ""; 3213 } 3214 run_command "cat $addconfig $min > $tmpdir/add_config" or 3215 dodie "Failed to create temp config"; 3216 $minconfig = "$tmpdir/add_config"; 3217 } 3218 3219 my $checkout = $opt{"CHECKOUT[$i]"}; 3220 if (defined($checkout)) { 3221 run_command "git checkout $checkout" or 3222 die "failed to checkout $checkout"; 3223 } 3224 3225 $no_reboot = 0; 3226 3227 3228 if ($test_type eq "bisect") { 3229 bisect $i; 3230 next; 3231 } elsif ($test_type eq "config_bisect") { 3232 config_bisect $i; 3233 next; 3234 } elsif ($test_type eq "patchcheck") { 3235 patchcheck $i; 3236 next; 3237 } elsif ($test_type eq "make_min_config") { 3238 make_min_config $i; 3239 next; 3240 } 3241 3242 if ($build_type ne "nobuild") { 3243 build $build_type or next; 3244 } 3245 3246 if ($test_type eq "install") { 3247 get_version; 3248 install; 3249 success $i; 3250 next; 3251 } 3252 3253 if ($test_type ne "build") { 3254 my $failed = 0; 3255 start_monitor_and_boot or $failed = 1; 3256 3257 if (!$failed && $test_type ne "boot" && defined($run_test)) { 3258 do_run_test or $failed = 1; 3259 } 3260 end_monitor; 3261 next if ($failed); 3262 } 3263 3264 success $i; 3265} 3266 3267if ($opt{"POWEROFF_ON_SUCCESS"}) { 3268 halt; 3269} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 3270 reboot; 3271} 3272 3273doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 3274 3275exit 0; 3276