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 751 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 752 my $start = $1; 753 my $var = $2; 754 my $end = $3; 755 756 # Append beginning of line 757 $retval = "$retval$start"; 758 759 # If the iteration option OPT[$i] exists, then use that. 760 # otherwise see if the default OPT (without [$i]) exists. 761 762 my $o = "$var\[$i\]"; 763 764 if (defined($opt{$o})) { 765 $o = $opt{$o}; 766 $retval = "$retval$o"; 767 } elsif (defined($opt{$var})) { 768 $o = $opt{$var}; 769 $retval = "$retval$o"; 770 } else { 771 $retval = "$retval\$\{$var\}"; 772 } 773 774 $option = $end; 775 } 776 777 $retval = "$retval$option"; 778 779 $retval =~ s/^ //; 780 781 return $retval; 782} 783 784sub eval_option { 785 my ($option, $i) = @_; 786 787 my $prev = ""; 788 789 # Since an option can evaluate to another option, 790 # keep iterating until we do not evaluate any more 791 # options. 792 my $r = 0; 793 while ($prev ne $option) { 794 # Check for recursive evaluations. 795 # 100 deep should be more than enough. 796 if ($r++ > 100) { 797 die "Over 100 evaluations accurred with $option\n" . 798 "Check for recursive variables\n"; 799 } 800 $prev = $option; 801 $option = __eval_option($option, $i); 802 } 803 804 return $option; 805} 806 807sub _logit { 808 if (defined($opt{"LOG_FILE"})) { 809 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 810 print OUT @_; 811 close(OUT); 812 } 813} 814 815sub logit { 816 if (defined($opt{"LOG_FILE"})) { 817 _logit @_; 818 } else { 819 print @_; 820 } 821} 822 823sub doprint { 824 print @_; 825 _logit @_; 826} 827 828sub run_command; 829sub start_monitor; 830sub end_monitor; 831sub wait_for_monitor; 832 833sub reboot { 834 my ($time) = @_; 835 836 if (defined($time)) { 837 start_monitor; 838 # flush out current monitor 839 # May contain the reboot success line 840 wait_for_monitor 1; 841 } 842 843 # try to reboot normally 844 if (run_command $reboot) { 845 if (defined($powercycle_after_reboot)) { 846 sleep $powercycle_after_reboot; 847 run_command "$power_cycle"; 848 } 849 } else { 850 # nope? power cycle it. 851 run_command "$power_cycle"; 852 } 853 854 if (defined($time)) { 855 wait_for_monitor($time, $reboot_success_line); 856 end_monitor; 857 } 858} 859 860sub do_not_reboot { 861 my $i = $iteration; 862 863 return $test_type eq "build" || $no_reboot || 864 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 865 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 866} 867 868sub dodie { 869 doprint "CRITICAL FAILURE... ", @_, "\n"; 870 871 my $i = $iteration; 872 873 if ($reboot_on_error && !do_not_reboot) { 874 875 doprint "REBOOTING\n"; 876 reboot; 877 878 } elsif ($poweroff_on_error && defined($power_off)) { 879 doprint "POWERING OFF\n"; 880 `$power_off`; 881 } 882 883 if (defined($opt{"LOG_FILE"})) { 884 print " See $opt{LOG_FILE} for more info.\n"; 885 } 886 887 die @_, "\n"; 888} 889 890sub open_console { 891 my ($fp) = @_; 892 893 my $flags; 894 895 my $pid = open($fp, "$console|") or 896 dodie "Can't open console $console"; 897 898 $flags = fcntl($fp, F_GETFL, 0) or 899 dodie "Can't get flags for the socket: $!"; 900 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 901 dodie "Can't set flags for the socket: $!"; 902 903 return $pid; 904} 905 906sub close_console { 907 my ($fp, $pid) = @_; 908 909 doprint "kill child process $pid\n"; 910 kill 2, $pid; 911 912 print "closing!\n"; 913 close($fp); 914} 915 916sub start_monitor { 917 if ($monitor_cnt++) { 918 return; 919 } 920 $monitor_fp = \*MONFD; 921 $monitor_pid = open_console $monitor_fp; 922 923 return; 924 925 open(MONFD, "Stop perl from warning about single use of MONFD"); 926} 927 928sub end_monitor { 929 if (--$monitor_cnt) { 930 return; 931 } 932 close_console($monitor_fp, $monitor_pid); 933} 934 935sub wait_for_monitor { 936 my ($time, $stop) = @_; 937 my $full_line = ""; 938 my $line; 939 my $booted = 0; 940 941 doprint "** Wait for monitor to settle down **\n"; 942 943 # read the monitor and wait for the system to calm down 944 while (!$booted) { 945 $line = wait_for_input($monitor_fp, $time); 946 last if (!defined($line)); 947 print "$line"; 948 $full_line .= $line; 949 950 if (defined($stop) && $full_line =~ /$stop/) { 951 doprint "wait for monitor detected $stop\n"; 952 $booted = 1; 953 } 954 955 if ($line =~ /\n/) { 956 $full_line = ""; 957 } 958 } 959 print "** Monitor flushed **\n"; 960} 961 962sub fail { 963 964 if ($die_on_failure) { 965 dodie @_; 966 } 967 968 doprint "FAILED\n"; 969 970 my $i = $iteration; 971 972 # no need to reboot for just building. 973 if (!do_not_reboot) { 974 doprint "REBOOTING\n"; 975 reboot $sleep_time; 976 } 977 978 my $name = ""; 979 980 if (defined($test_name)) { 981 $name = " ($test_name)"; 982 } 983 984 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 985 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 986 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 987 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 988 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 989 990 return 1 if (!defined($store_failures)); 991 992 my @t = localtime; 993 my $date = sprintf "%04d%02d%02d%02d%02d%02d", 994 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 995 996 my $type = $build_type; 997 if ($type =~ /useconfig/) { 998 $type = "useconfig"; 999 } 1000 1001 my $dir = "$machine-$test_type-$type-fail-$date"; 1002 my $faildir = "$store_failures/$dir"; 1003 1004 if (!-d $faildir) { 1005 mkpath($faildir) or 1006 die "can't create $faildir"; 1007 } 1008 if (-f "$output_config") { 1009 cp "$output_config", "$faildir/config" or 1010 die "failed to copy .config"; 1011 } 1012 if (-f $buildlog) { 1013 cp $buildlog, "$faildir/buildlog" or 1014 die "failed to move $buildlog"; 1015 } 1016 if (-f $dmesg) { 1017 cp $dmesg, "$faildir/dmesg" or 1018 die "failed to move $dmesg"; 1019 } 1020 1021 doprint "*** Saved info to $faildir ***\n"; 1022 1023 return 1; 1024} 1025 1026sub run_command { 1027 my ($command) = @_; 1028 my $dolog = 0; 1029 my $dord = 0; 1030 my $pid; 1031 1032 $command =~ s/\$SSH_USER/$ssh_user/g; 1033 $command =~ s/\$MACHINE/$machine/g; 1034 1035 doprint("$command ... "); 1036 1037 $pid = open(CMD, "$command 2>&1 |") or 1038 (fail "unable to exec $command" and return 0); 1039 1040 if (defined($opt{"LOG_FILE"})) { 1041 open(LOG, ">>$opt{LOG_FILE}") or 1042 dodie "failed to write to log"; 1043 $dolog = 1; 1044 } 1045 1046 if (defined($redirect)) { 1047 open (RD, ">$redirect") or 1048 dodie "failed to write to redirect $redirect"; 1049 $dord = 1; 1050 } 1051 1052 while (<CMD>) { 1053 print LOG if ($dolog); 1054 print RD if ($dord); 1055 } 1056 1057 waitpid($pid, 0); 1058 my $failed = $?; 1059 1060 close(CMD); 1061 close(LOG) if ($dolog); 1062 close(RD) if ($dord); 1063 1064 if ($failed) { 1065 doprint "FAILED!\n"; 1066 } else { 1067 doprint "SUCCESS\n"; 1068 } 1069 1070 return !$failed; 1071} 1072 1073sub run_ssh { 1074 my ($cmd) = @_; 1075 my $cp_exec = $ssh_exec; 1076 1077 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 1078 return run_command "$cp_exec"; 1079} 1080 1081sub run_scp { 1082 my ($src, $dst) = @_; 1083 my $cp_scp = $scp_to_target; 1084 1085 $cp_scp =~ s/\$SRC_FILE/$src/g; 1086 $cp_scp =~ s/\$DST_FILE/$dst/g; 1087 1088 return run_command "$cp_scp"; 1089} 1090 1091sub get_grub_index { 1092 1093 if ($reboot_type ne "grub") { 1094 return; 1095 } 1096 return if (defined($grub_number)); 1097 1098 doprint "Find grub menu ... "; 1099 $grub_number = -1; 1100 1101 my $ssh_grub = $ssh_exec; 1102 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 1103 1104 open(IN, "$ssh_grub |") 1105 or die "unable to get menu.lst"; 1106 1107 my $found = 0; 1108 1109 while (<IN>) { 1110 if (/^\s*title\s+$grub_menu\s*$/) { 1111 $grub_number++; 1112 $found = 1; 1113 last; 1114 } elsif (/^\s*title\s/) { 1115 $grub_number++; 1116 } 1117 } 1118 close(IN); 1119 1120 die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 1121 if (!$found); 1122 doprint "$grub_number\n"; 1123} 1124 1125sub wait_for_input 1126{ 1127 my ($fp, $time) = @_; 1128 my $rin; 1129 my $ready; 1130 my $line; 1131 my $ch; 1132 1133 if (!defined($time)) { 1134 $time = $timeout; 1135 } 1136 1137 $rin = ''; 1138 vec($rin, fileno($fp), 1) = 1; 1139 $ready = select($rin, undef, undef, $time); 1140 1141 $line = ""; 1142 1143 # try to read one char at a time 1144 while (sysread $fp, $ch, 1) { 1145 $line .= $ch; 1146 last if ($ch eq "\n"); 1147 } 1148 1149 if (!length($line)) { 1150 return undef; 1151 } 1152 1153 return $line; 1154} 1155 1156sub reboot_to { 1157 if ($reboot_type eq "grub") { 1158 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 1159 reboot; 1160 return; 1161 } 1162 1163 run_command "$reboot_script"; 1164} 1165 1166sub get_sha1 { 1167 my ($commit) = @_; 1168 1169 doprint "git rev-list --max-count=1 $commit ... "; 1170 my $sha1 = `git rev-list --max-count=1 $commit`; 1171 my $ret = $?; 1172 1173 logit $sha1; 1174 1175 if ($ret) { 1176 doprint "FAILED\n"; 1177 dodie "Failed to get git $commit"; 1178 } 1179 1180 print "SUCCESS\n"; 1181 1182 chomp $sha1; 1183 1184 return $sha1; 1185} 1186 1187sub monitor { 1188 my $booted = 0; 1189 my $bug = 0; 1190 my $skip_call_trace = 0; 1191 my $loops; 1192 1193 wait_for_monitor 5; 1194 1195 my $line; 1196 my $full_line = ""; 1197 1198 open(DMESG, "> $dmesg") or 1199 die "unable to write to $dmesg"; 1200 1201 reboot_to; 1202 1203 my $success_start; 1204 my $failure_start; 1205 my $monitor_start = time; 1206 my $done = 0; 1207 my $version_found = 0; 1208 1209 while (!$done) { 1210 1211 if ($bug && defined($stop_after_failure) && 1212 $stop_after_failure >= 0) { 1213 my $time = $stop_after_failure - (time - $failure_start); 1214 $line = wait_for_input($monitor_fp, $time); 1215 if (!defined($line)) { 1216 doprint "bug timed out after $booted_timeout seconds\n"; 1217 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1218 last; 1219 } 1220 } elsif ($booted) { 1221 $line = wait_for_input($monitor_fp, $booted_timeout); 1222 if (!defined($line)) { 1223 my $s = $booted_timeout == 1 ? "" : "s"; 1224 doprint "Successful boot found: break after $booted_timeout second$s\n"; 1225 last; 1226 } 1227 } else { 1228 $line = wait_for_input($monitor_fp); 1229 if (!defined($line)) { 1230 my $s = $timeout == 1 ? "" : "s"; 1231 doprint "Timed out after $timeout second$s\n"; 1232 last; 1233 } 1234 } 1235 1236 doprint $line; 1237 print DMESG $line; 1238 1239 # we are not guaranteed to get a full line 1240 $full_line .= $line; 1241 1242 if ($full_line =~ /$success_line/) { 1243 $booted = 1; 1244 $success_start = time; 1245 } 1246 1247 if ($booted && defined($stop_after_success) && 1248 $stop_after_success >= 0) { 1249 my $now = time; 1250 if ($now - $success_start >= $stop_after_success) { 1251 doprint "Test forced to stop after $stop_after_success seconds after success\n"; 1252 last; 1253 } 1254 } 1255 1256 if ($full_line =~ /\[ backtrace testing \]/) { 1257 $skip_call_trace = 1; 1258 } 1259 1260 if ($full_line =~ /call trace:/i) { 1261 if (!$bug && !$skip_call_trace) { 1262 $bug = 1; 1263 $failure_start = time; 1264 } 1265 } 1266 1267 if ($bug && defined($stop_after_failure) && 1268 $stop_after_failure >= 0) { 1269 my $now = time; 1270 if ($now - $failure_start >= $stop_after_failure) { 1271 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1272 last; 1273 } 1274 } 1275 1276 if ($full_line =~ /\[ end of backtrace testing \]/) { 1277 $skip_call_trace = 0; 1278 } 1279 1280 if ($full_line =~ /Kernel panic -/) { 1281 $failure_start = time; 1282 $bug = 1; 1283 } 1284 1285 # Detect triple faults by testing the banner 1286 if ($full_line =~ /\bLinux version (\S+).*\n/) { 1287 if ($1 eq $version) { 1288 $version_found = 1; 1289 } elsif ($version_found && $detect_triplefault) { 1290 # We already booted into the kernel we are testing, 1291 # but now we booted into another kernel? 1292 # Consider this a triple fault. 1293 doprint "Aleady booted in Linux kernel $version, but now\n"; 1294 doprint "we booted into Linux kernel $1.\n"; 1295 doprint "Assuming that this is a triple fault.\n"; 1296 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 1297 last; 1298 } 1299 } 1300 1301 if ($line =~ /\n/) { 1302 $full_line = ""; 1303 } 1304 1305 if ($stop_test_after > 0 && !$booted && !$bug) { 1306 if (time - $monitor_start > $stop_test_after) { 1307 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 1308 $done = 1; 1309 } 1310 } 1311 } 1312 1313 close(DMESG); 1314 1315 if ($bug) { 1316 return 0 if ($in_bisect); 1317 fail "failed - got a bug report" and return 0; 1318 } 1319 1320 if (!$booted) { 1321 return 0 if ($in_bisect); 1322 fail "failed - never got a boot prompt." and return 0; 1323 } 1324 1325 return 1; 1326} 1327 1328sub do_post_install { 1329 1330 return if (!defined($post_install)); 1331 1332 my $cp_post_install = $post_install; 1333 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; 1334 run_command "$cp_post_install" or 1335 dodie "Failed to run post install"; 1336} 1337 1338sub install { 1339 1340 return if ($no_install); 1341 1342 run_scp "$outputdir/$build_target", "$target_image" or 1343 dodie "failed to copy image"; 1344 1345 my $install_mods = 0; 1346 1347 # should we process modules? 1348 $install_mods = 0; 1349 open(IN, "$output_config") or dodie("Can't read config file"); 1350 while (<IN>) { 1351 if (/CONFIG_MODULES(=y)?/) { 1352 $install_mods = 1 if (defined($1)); 1353 last; 1354 } 1355 } 1356 close(IN); 1357 1358 if (!$install_mods) { 1359 do_post_install; 1360 doprint "No modules needed\n"; 1361 return; 1362 } 1363 1364 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 1365 dodie "Failed to install modules"; 1366 1367 my $modlib = "/lib/modules/$version"; 1368 my $modtar = "ktest-mods.tar.bz2"; 1369 1370 run_ssh "rm -rf $modlib" or 1371 dodie "failed to remove old mods: $modlib"; 1372 1373 # would be nice if scp -r did not follow symbolic links 1374 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 1375 dodie "making tarball"; 1376 1377 run_scp "$tmpdir/$modtar", "/tmp" or 1378 dodie "failed to copy modules"; 1379 1380 unlink "$tmpdir/$modtar"; 1381 1382 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 1383 dodie "failed to tar modules"; 1384 1385 run_ssh "rm -f /tmp/$modtar"; 1386 1387 do_post_install; 1388} 1389 1390sub get_version { 1391 # get the release name 1392 doprint "$make kernelrelease ... "; 1393 $version = `$make kernelrelease | tail -1`; 1394 chomp($version); 1395 doprint "$version\n"; 1396} 1397 1398sub start_monitor_and_boot { 1399 # Make sure the stable kernel has finished booting 1400 start_monitor; 1401 wait_for_monitor 5; 1402 end_monitor; 1403 1404 get_grub_index; 1405 get_version; 1406 install; 1407 1408 start_monitor; 1409 return monitor; 1410} 1411 1412sub check_buildlog { 1413 my ($patch) = @_; 1414 1415 my @files = `git show $patch | diffstat -l`; 1416 1417 open(IN, "git show $patch |") or 1418 dodie "failed to show $patch"; 1419 while (<IN>) { 1420 if (m,^--- a/(.*),) { 1421 chomp $1; 1422 $files[$#files] = $1; 1423 } 1424 } 1425 close(IN); 1426 1427 open(IN, $buildlog) or dodie "Can't open $buildlog"; 1428 while (<IN>) { 1429 if (/^\s*(.*?):.*(warning|error)/) { 1430 my $err = $1; 1431 foreach my $file (@files) { 1432 my $fullpath = "$builddir/$file"; 1433 if ($file eq $err || $fullpath eq $err) { 1434 fail "$file built with warnings" and return 0; 1435 } 1436 } 1437 } 1438 } 1439 close(IN); 1440 1441 return 1; 1442} 1443 1444sub apply_min_config { 1445 my $outconfig = "$output_config.new"; 1446 1447 # Read the config file and remove anything that 1448 # is in the force_config hash (from minconfig and others) 1449 # then add the force config back. 1450 1451 doprint "Applying minimum configurations into $output_config.new\n"; 1452 1453 open (OUT, ">$outconfig") or 1454 dodie "Can't create $outconfig"; 1455 1456 if (-f $output_config) { 1457 open (IN, $output_config) or 1458 dodie "Failed to open $output_config"; 1459 while (<IN>) { 1460 if (/^(# )?(CONFIG_[^\s=]*)/) { 1461 next if (defined($force_config{$2})); 1462 } 1463 print OUT; 1464 } 1465 close IN; 1466 } 1467 foreach my $config (keys %force_config) { 1468 print OUT "$force_config{$config}\n"; 1469 } 1470 close OUT; 1471 1472 run_command "mv $outconfig $output_config"; 1473} 1474 1475sub make_oldconfig { 1476 1477 my @force_list = keys %force_config; 1478 1479 if ($#force_list >= 0) { 1480 apply_min_config; 1481 } 1482 1483 if (!run_command "$make oldnoconfig") { 1484 # Perhaps oldnoconfig doesn't exist in this version of the kernel 1485 # try a yes '' | oldconfig 1486 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1487 run_command "yes '' | $make oldconfig" or 1488 dodie "failed make config oldconfig"; 1489 } 1490} 1491 1492# read a config file and use this to force new configs. 1493sub load_force_config { 1494 my ($config) = @_; 1495 1496 open(IN, $config) or 1497 dodie "failed to read $config"; 1498 while (<IN>) { 1499 chomp; 1500 if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 1501 $force_config{$1} = $_; 1502 } elsif (/^# (CONFIG_\S*) is not set/) { 1503 $force_config{$1} = $_; 1504 } 1505 } 1506 close IN; 1507} 1508 1509sub build { 1510 my ($type) = @_; 1511 1512 unlink $buildlog; 1513 1514 # Failed builds should not reboot the target 1515 my $save_no_reboot = $no_reboot; 1516 $no_reboot = 1; 1517 1518 if (defined($pre_build)) { 1519 my $ret = run_command $pre_build; 1520 if (!$ret && defined($pre_build_die) && 1521 $pre_build_die) { 1522 dodie "failed to pre_build\n"; 1523 } 1524 } 1525 1526 if ($type =~ /^useconfig:(.*)/) { 1527 run_command "cp $1 $output_config" or 1528 dodie "could not copy $1 to .config"; 1529 1530 $type = "oldconfig"; 1531 } 1532 1533 # old config can ask questions 1534 if ($type eq "oldconfig") { 1535 $type = "oldnoconfig"; 1536 1537 # allow for empty configs 1538 run_command "touch $output_config"; 1539 1540 if (!$noclean) { 1541 run_command "mv $output_config $outputdir/config_temp" or 1542 dodie "moving .config"; 1543 1544 run_command "$make mrproper" or dodie "make mrproper"; 1545 1546 run_command "mv $outputdir/config_temp $output_config" or 1547 dodie "moving config_temp"; 1548 } 1549 1550 } elsif (!$noclean) { 1551 unlink "$output_config"; 1552 run_command "$make mrproper" or 1553 dodie "make mrproper"; 1554 } 1555 1556 # add something to distinguish this build 1557 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 1558 print OUT "$localversion\n"; 1559 close(OUT); 1560 1561 if (defined($minconfig)) { 1562 load_force_config($minconfig); 1563 } 1564 1565 if ($type ne "oldnoconfig") { 1566 run_command "$make $type" or 1567 dodie "failed make config"; 1568 } 1569 # Run old config regardless, to enforce min configurations 1570 make_oldconfig; 1571 1572 $redirect = "$buildlog"; 1573 my $build_ret = run_command "$make $build_options"; 1574 undef $redirect; 1575 1576 if (defined($post_build)) { 1577 my $ret = run_command $post_build; 1578 if (!$ret && defined($post_build_die) && 1579 $post_build_die) { 1580 dodie "failed to post_build\n"; 1581 } 1582 } 1583 1584 if (!$build_ret) { 1585 # bisect may need this to pass 1586 if ($in_bisect) { 1587 $no_reboot = $save_no_reboot; 1588 return 0; 1589 } 1590 fail "failed build" and return 0; 1591 } 1592 1593 $no_reboot = $save_no_reboot; 1594 1595 return 1; 1596} 1597 1598sub halt { 1599 if (!run_ssh "halt" or defined($power_off)) { 1600 if (defined($poweroff_after_halt)) { 1601 sleep $poweroff_after_halt; 1602 run_command "$power_off"; 1603 } 1604 } else { 1605 # nope? the zap it! 1606 run_command "$power_off"; 1607 } 1608} 1609 1610sub success { 1611 my ($i) = @_; 1612 1613 $successes++; 1614 1615 my $name = ""; 1616 1617 if (defined($test_name)) { 1618 $name = " ($test_name)"; 1619 } 1620 1621 doprint "\n\n*******************************************\n"; 1622 doprint "*******************************************\n"; 1623 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 1624 doprint "*******************************************\n"; 1625 doprint "*******************************************\n"; 1626 1627 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1628 doprint "Reboot and wait $sleep_time seconds\n"; 1629 reboot $sleep_time; 1630 } 1631} 1632 1633sub answer_bisect { 1634 for (;;) { 1635 doprint "Pass or fail? [p/f]"; 1636 my $ans = <STDIN>; 1637 chomp $ans; 1638 if ($ans eq "p" || $ans eq "P") { 1639 return 1; 1640 } elsif ($ans eq "f" || $ans eq "F") { 1641 return 0; 1642 } else { 1643 print "Please answer 'P' or 'F'\n"; 1644 } 1645 } 1646} 1647 1648sub child_run_test { 1649 my $failed = 0; 1650 1651 # child should have no power 1652 $reboot_on_error = 0; 1653 $poweroff_on_error = 0; 1654 $die_on_failure = 1; 1655 1656 run_command $run_test or $failed = 1; 1657 exit $failed; 1658} 1659 1660my $child_done; 1661 1662sub child_finished { 1663 $child_done = 1; 1664} 1665 1666sub do_run_test { 1667 my $child_pid; 1668 my $child_exit; 1669 my $line; 1670 my $full_line; 1671 my $bug = 0; 1672 1673 wait_for_monitor 1; 1674 1675 doprint "run test $run_test\n"; 1676 1677 $child_done = 0; 1678 1679 $SIG{CHLD} = qw(child_finished); 1680 1681 $child_pid = fork; 1682 1683 child_run_test if (!$child_pid); 1684 1685 $full_line = ""; 1686 1687 do { 1688 $line = wait_for_input($monitor_fp, 1); 1689 if (defined($line)) { 1690 1691 # we are not guaranteed to get a full line 1692 $full_line .= $line; 1693 doprint $line; 1694 1695 if ($full_line =~ /call trace:/i) { 1696 $bug = 1; 1697 } 1698 1699 if ($full_line =~ /Kernel panic -/) { 1700 $bug = 1; 1701 } 1702 1703 if ($line =~ /\n/) { 1704 $full_line = ""; 1705 } 1706 } 1707 } while (!$child_done && !$bug); 1708 1709 if ($bug) { 1710 my $failure_start = time; 1711 my $now; 1712 do { 1713 $line = wait_for_input($monitor_fp, 1); 1714 if (defined($line)) { 1715 doprint $line; 1716 } 1717 $now = time; 1718 if ($now - $failure_start >= $stop_after_failure) { 1719 last; 1720 } 1721 } while (defined($line)); 1722 1723 doprint "Detected kernel crash!\n"; 1724 # kill the child with extreme prejudice 1725 kill 9, $child_pid; 1726 } 1727 1728 waitpid $child_pid, 0; 1729 $child_exit = $?; 1730 1731 if ($bug || $child_exit) { 1732 return 0 if $in_bisect; 1733 fail "test failed" and return 0; 1734 } 1735 return 1; 1736} 1737 1738sub run_git_bisect { 1739 my ($command) = @_; 1740 1741 doprint "$command ... "; 1742 1743 my $output = `$command 2>&1`; 1744 my $ret = $?; 1745 1746 logit $output; 1747 1748 if ($ret) { 1749 doprint "FAILED\n"; 1750 dodie "Failed to git bisect"; 1751 } 1752 1753 doprint "SUCCESS\n"; 1754 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 1755 doprint "$1 [$2]\n"; 1756 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 1757 $bisect_bad = $1; 1758 doprint "Found bad commit... $1\n"; 1759 return 0; 1760 } else { 1761 # we already logged it, just print it now. 1762 print $output; 1763 } 1764 1765 return 1; 1766} 1767 1768sub bisect_reboot { 1769 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 1770 reboot $bisect_sleep_time; 1771} 1772 1773# returns 1 on success, 0 on failure, -1 on skip 1774sub run_bisect_test { 1775 my ($type, $buildtype) = @_; 1776 1777 my $failed = 0; 1778 my $result; 1779 my $output; 1780 my $ret; 1781 1782 $in_bisect = 1; 1783 1784 build $buildtype or $failed = 1; 1785 1786 if ($type ne "build") { 1787 if ($failed && $bisect_skip) { 1788 $in_bisect = 0; 1789 return -1; 1790 } 1791 dodie "Failed on build" if $failed; 1792 1793 # Now boot the box 1794 start_monitor_and_boot or $failed = 1; 1795 1796 if ($type ne "boot") { 1797 if ($failed && $bisect_skip) { 1798 end_monitor; 1799 bisect_reboot; 1800 $in_bisect = 0; 1801 return -1; 1802 } 1803 dodie "Failed on boot" if $failed; 1804 1805 do_run_test or $failed = 1; 1806 } 1807 end_monitor; 1808 } 1809 1810 if ($failed) { 1811 $result = 0; 1812 } else { 1813 $result = 1; 1814 } 1815 1816 # reboot the box to a kernel we can ssh to 1817 if ($type ne "build") { 1818 bisect_reboot; 1819 } 1820 $in_bisect = 0; 1821 1822 return $result; 1823} 1824 1825sub run_bisect { 1826 my ($type) = @_; 1827 my $buildtype = "oldconfig"; 1828 1829 # We should have a minconfig to use? 1830 if (defined($minconfig)) { 1831 $buildtype = "useconfig:$minconfig"; 1832 } 1833 1834 my $ret = run_bisect_test $type, $buildtype; 1835 1836 if ($bisect_manual) { 1837 $ret = answer_bisect; 1838 } 1839 1840 # Are we looking for where it worked, not failed? 1841 if ($reverse_bisect) { 1842 $ret = !$ret; 1843 } 1844 1845 if ($ret > 0) { 1846 return "good"; 1847 } elsif ($ret == 0) { 1848 return "bad"; 1849 } elsif ($bisect_skip) { 1850 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 1851 return "skip"; 1852 } 1853} 1854 1855sub bisect { 1856 my ($i) = @_; 1857 1858 my $result; 1859 1860 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 1861 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 1862 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 1863 1864 my $good = $opt{"BISECT_GOOD[$i]"}; 1865 my $bad = $opt{"BISECT_BAD[$i]"}; 1866 my $type = $opt{"BISECT_TYPE[$i]"}; 1867 my $start = $opt{"BISECT_START[$i]"}; 1868 my $replay = $opt{"BISECT_REPLAY[$i]"}; 1869 my $start_files = $opt{"BISECT_FILES[$i]"}; 1870 1871 if (defined($start_files)) { 1872 $start_files = " -- " . $start_files; 1873 } else { 1874 $start_files = ""; 1875 } 1876 1877 # convert to true sha1's 1878 $good = get_sha1($good); 1879 $bad = get_sha1($bad); 1880 1881 if (defined($opt{"BISECT_REVERSE[$i]"}) && 1882 $opt{"BISECT_REVERSE[$i]"} == 1) { 1883 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1884 $reverse_bisect = 1; 1885 } else { 1886 $reverse_bisect = 0; 1887 } 1888 1889 # Can't have a test without having a test to run 1890 if ($type eq "test" && !defined($run_test)) { 1891 $type = "boot"; 1892 } 1893 1894 my $check = $opt{"BISECT_CHECK[$i]"}; 1895 if (defined($check) && $check ne "0") { 1896 1897 # get current HEAD 1898 my $head = get_sha1("HEAD"); 1899 1900 if ($check ne "good") { 1901 doprint "TESTING BISECT BAD [$bad]\n"; 1902 run_command "git checkout $bad" or 1903 die "Failed to checkout $bad"; 1904 1905 $result = run_bisect $type; 1906 1907 if ($result ne "bad") { 1908 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1909 } 1910 } 1911 1912 if ($check ne "bad") { 1913 doprint "TESTING BISECT GOOD [$good]\n"; 1914 run_command "git checkout $good" or 1915 die "Failed to checkout $good"; 1916 1917 $result = run_bisect $type; 1918 1919 if ($result ne "good") { 1920 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1921 } 1922 } 1923 1924 # checkout where we started 1925 run_command "git checkout $head" or 1926 die "Failed to checkout $head"; 1927 } 1928 1929 run_command "git bisect start$start_files" or 1930 dodie "could not start bisect"; 1931 1932 run_command "git bisect good $good" or 1933 dodie "could not set bisect good to $good"; 1934 1935 run_git_bisect "git bisect bad $bad" or 1936 dodie "could not set bisect bad to $bad"; 1937 1938 if (defined($replay)) { 1939 run_command "git bisect replay $replay" or 1940 dodie "failed to run replay"; 1941 } 1942 1943 if (defined($start)) { 1944 run_command "git checkout $start" or 1945 dodie "failed to checkout $start"; 1946 } 1947 1948 my $test; 1949 do { 1950 $result = run_bisect $type; 1951 $test = run_git_bisect "git bisect $result"; 1952 } while ($test); 1953 1954 run_command "git bisect log" or 1955 dodie "could not capture git bisect log"; 1956 1957 run_command "git bisect reset" or 1958 dodie "could not reset git bisect"; 1959 1960 doprint "Bad commit was [$bisect_bad]\n"; 1961 1962 success $i; 1963} 1964 1965my %config_ignore; 1966my %config_set; 1967 1968my %config_list; 1969my %null_config; 1970 1971my %dependency; 1972 1973sub assign_configs { 1974 my ($hash, $config) = @_; 1975 1976 open (IN, $config) 1977 or dodie "Failed to read $config"; 1978 1979 while (<IN>) { 1980 if (/^((CONFIG\S*)=.*)/) { 1981 ${$hash}{$2} = $1; 1982 } 1983 } 1984 1985 close(IN); 1986} 1987 1988sub process_config_ignore { 1989 my ($config) = @_; 1990 1991 assign_configs \%config_ignore, $config; 1992} 1993 1994sub read_current_config { 1995 my ($config_ref) = @_; 1996 1997 %{$config_ref} = (); 1998 undef %{$config_ref}; 1999 2000 my @key = keys %{$config_ref}; 2001 if ($#key >= 0) { 2002 print "did not delete!\n"; 2003 exit; 2004 } 2005 open (IN, "$output_config"); 2006 2007 while (<IN>) { 2008 if (/^(CONFIG\S+)=(.*)/) { 2009 ${$config_ref}{$1} = $2; 2010 } 2011 } 2012 close(IN); 2013} 2014 2015sub get_dependencies { 2016 my ($config) = @_; 2017 2018 my $arr = $dependency{$config}; 2019 if (!defined($arr)) { 2020 return (); 2021 } 2022 2023 my @deps = @{$arr}; 2024 2025 foreach my $dep (@{$arr}) { 2026 print "ADD DEP $dep\n"; 2027 @deps = (@deps, get_dependencies $dep); 2028 } 2029 2030 return @deps; 2031} 2032 2033sub create_config { 2034 my @configs = @_; 2035 2036 open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 2037 2038 foreach my $config (@configs) { 2039 print OUT "$config_set{$config}\n"; 2040 my @deps = get_dependencies $config; 2041 foreach my $dep (@deps) { 2042 print OUT "$config_set{$dep}\n"; 2043 } 2044 } 2045 2046 foreach my $config (keys %config_ignore) { 2047 print OUT "$config_ignore{$config}\n"; 2048 } 2049 close(OUT); 2050 2051# exit; 2052 make_oldconfig; 2053} 2054 2055sub compare_configs { 2056 my (%a, %b) = @_; 2057 2058 foreach my $item (keys %a) { 2059 if (!defined($b{$item})) { 2060 print "diff $item\n"; 2061 return 1; 2062 } 2063 delete $b{$item}; 2064 } 2065 2066 my @keys = keys %b; 2067 if ($#keys) { 2068 print "diff2 $keys[0]\n"; 2069 } 2070 return -1 if ($#keys >= 0); 2071 2072 return 0; 2073} 2074 2075sub run_config_bisect_test { 2076 my ($type) = @_; 2077 2078 return run_bisect_test $type, "oldconfig"; 2079} 2080 2081sub process_passed { 2082 my (%configs) = @_; 2083 2084 doprint "These configs had no failure: (Enabling them for further compiles)\n"; 2085 # Passed! All these configs are part of a good compile. 2086 # Add them to the min options. 2087 foreach my $config (keys %configs) { 2088 if (defined($config_list{$config})) { 2089 doprint " removing $config\n"; 2090 $config_ignore{$config} = $config_list{$config}; 2091 delete $config_list{$config}; 2092 } 2093 } 2094 doprint "config copied to $outputdir/config_good\n"; 2095 run_command "cp -f $output_config $outputdir/config_good"; 2096} 2097 2098sub process_failed { 2099 my ($config) = @_; 2100 2101 doprint "\n\n***************************************\n"; 2102 doprint "Found bad config: $config\n"; 2103 doprint "***************************************\n\n"; 2104} 2105 2106sub run_config_bisect { 2107 2108 my @start_list = keys %config_list; 2109 2110 if ($#start_list < 0) { 2111 doprint "No more configs to test!!!\n"; 2112 return -1; 2113 } 2114 2115 doprint "***** RUN TEST ***\n"; 2116 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 2117 my $ret; 2118 my %current_config; 2119 2120 my $count = $#start_list + 1; 2121 doprint " $count configs to test\n"; 2122 2123 my $half = int($#start_list / 2); 2124 2125 do { 2126 my @tophalf = @start_list[0 .. $half]; 2127 2128 create_config @tophalf; 2129 read_current_config \%current_config; 2130 2131 $count = $#tophalf + 1; 2132 doprint "Testing $count configs\n"; 2133 my $found = 0; 2134 # make sure we test something 2135 foreach my $config (@tophalf) { 2136 if (defined($current_config{$config})) { 2137 logit " $config\n"; 2138 $found = 1; 2139 } 2140 } 2141 if (!$found) { 2142 # try the other half 2143 doprint "Top half produced no set configs, trying bottom half\n"; 2144 @tophalf = @start_list[$half + 1 .. $#start_list]; 2145 create_config @tophalf; 2146 read_current_config \%current_config; 2147 foreach my $config (@tophalf) { 2148 if (defined($current_config{$config})) { 2149 logit " $config\n"; 2150 $found = 1; 2151 } 2152 } 2153 if (!$found) { 2154 doprint "Failed: Can't make new config with current configs\n"; 2155 foreach my $config (@start_list) { 2156 doprint " CONFIG: $config\n"; 2157 } 2158 return -1; 2159 } 2160 $count = $#tophalf + 1; 2161 doprint "Testing $count configs\n"; 2162 } 2163 2164 $ret = run_config_bisect_test $type; 2165 if ($bisect_manual) { 2166 $ret = answer_bisect; 2167 } 2168 if ($ret) { 2169 process_passed %current_config; 2170 return 0; 2171 } 2172 2173 doprint "This config had a failure.\n"; 2174 doprint "Removing these configs that were not set in this config:\n"; 2175 doprint "config copied to $outputdir/config_bad\n"; 2176 run_command "cp -f $output_config $outputdir/config_bad"; 2177 2178 # A config exists in this group that was bad. 2179 foreach my $config (keys %config_list) { 2180 if (!defined($current_config{$config})) { 2181 doprint " removing $config\n"; 2182 delete $config_list{$config}; 2183 } 2184 } 2185 2186 @start_list = @tophalf; 2187 2188 if ($#start_list == 0) { 2189 process_failed $start_list[0]; 2190 return 1; 2191 } 2192 2193 # remove half the configs we are looking at and see if 2194 # they are good. 2195 $half = int($#start_list / 2); 2196 } while ($#start_list > 0); 2197 2198 # we found a single config, try it again unless we are running manually 2199 2200 if ($bisect_manual) { 2201 process_failed $start_list[0]; 2202 return 1; 2203 } 2204 2205 my @tophalf = @start_list[0 .. 0]; 2206 2207 $ret = run_config_bisect_test $type; 2208 if ($ret) { 2209 process_passed %current_config; 2210 return 0; 2211 } 2212 2213 process_failed $start_list[0]; 2214 return 1; 2215} 2216 2217sub config_bisect { 2218 my ($i) = @_; 2219 2220 my $start_config = $opt{"CONFIG_BISECT[$i]"}; 2221 2222 my $tmpconfig = "$tmpdir/use_config"; 2223 2224 if (defined($config_bisect_good)) { 2225 process_config_ignore $config_bisect_good; 2226 } 2227 2228 # Make the file with the bad config and the min config 2229 if (defined($minconfig)) { 2230 # read the min config for things to ignore 2231 run_command "cp $minconfig $tmpconfig" or 2232 dodie "failed to copy $minconfig to $tmpconfig"; 2233 } else { 2234 unlink $tmpconfig; 2235 } 2236 2237 if (-f $tmpconfig) { 2238 load_force_config($tmpconfig); 2239 process_config_ignore $tmpconfig; 2240 } 2241 2242 # now process the start config 2243 run_command "cp $start_config $output_config" or 2244 dodie "failed to copy $start_config to $output_config"; 2245 2246 # read directly what we want to check 2247 my %config_check; 2248 open (IN, $output_config) 2249 or dodie "faied to open $output_config"; 2250 2251 while (<IN>) { 2252 if (/^((CONFIG\S*)=.*)/) { 2253 $config_check{$2} = $1; 2254 } 2255 } 2256 close(IN); 2257 2258 # Now run oldconfig with the minconfig 2259 make_oldconfig; 2260 2261 # check to see what we lost (or gained) 2262 open (IN, $output_config) 2263 or dodie "Failed to read $start_config"; 2264 2265 my %removed_configs; 2266 my %added_configs; 2267 2268 while (<IN>) { 2269 if (/^((CONFIG\S*)=.*)/) { 2270 # save off all options 2271 $config_set{$2} = $1; 2272 if (defined($config_check{$2})) { 2273 if (defined($config_ignore{$2})) { 2274 $removed_configs{$2} = $1; 2275 } else { 2276 $config_list{$2} = $1; 2277 } 2278 } elsif (!defined($config_ignore{$2})) { 2279 $added_configs{$2} = $1; 2280 $config_list{$2} = $1; 2281 } 2282 } 2283 } 2284 close(IN); 2285 2286 my @confs = keys %removed_configs; 2287 if ($#confs >= 0) { 2288 doprint "Configs overridden by default configs and removed from check:\n"; 2289 foreach my $config (@confs) { 2290 doprint " $config\n"; 2291 } 2292 } 2293 @confs = keys %added_configs; 2294 if ($#confs >= 0) { 2295 doprint "Configs appearing in make oldconfig and added:\n"; 2296 foreach my $config (@confs) { 2297 doprint " $config\n"; 2298 } 2299 } 2300 2301 my %config_test; 2302 my $once = 0; 2303 2304 # Sometimes kconfig does weird things. We must make sure 2305 # that the config we autocreate has everything we need 2306 # to test, otherwise we may miss testing configs, or 2307 # may not be able to create a new config. 2308 # Here we create a config with everything set. 2309 create_config (keys %config_list); 2310 read_current_config \%config_test; 2311 foreach my $config (keys %config_list) { 2312 if (!defined($config_test{$config})) { 2313 if (!$once) { 2314 $once = 1; 2315 doprint "Configs not produced by kconfig (will not be checked):\n"; 2316 } 2317 doprint " $config\n"; 2318 delete $config_list{$config}; 2319 } 2320 } 2321 my $ret; 2322 do { 2323 $ret = run_config_bisect; 2324 } while (!$ret); 2325 2326 return $ret if ($ret < 0); 2327 2328 success $i; 2329} 2330 2331sub patchcheck_reboot { 2332 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 2333 reboot $patchcheck_sleep_time; 2334} 2335 2336sub patchcheck { 2337 my ($i) = @_; 2338 2339 die "PATCHCHECK_START[$i] not defined\n" 2340 if (!defined($opt{"PATCHCHECK_START[$i]"})); 2341 die "PATCHCHECK_TYPE[$i] not defined\n" 2342 if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 2343 2344 my $start = $opt{"PATCHCHECK_START[$i]"}; 2345 2346 my $end = "HEAD"; 2347 if (defined($opt{"PATCHCHECK_END[$i]"})) { 2348 $end = $opt{"PATCHCHECK_END[$i]"}; 2349 } 2350 2351 # Get the true sha1's since we can use things like HEAD~3 2352 $start = get_sha1($start); 2353 $end = get_sha1($end); 2354 2355 my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 2356 2357 # Can't have a test without having a test to run 2358 if ($type eq "test" && !defined($run_test)) { 2359 $type = "boot"; 2360 } 2361 2362 open (IN, "git log --pretty=oneline $end|") or 2363 dodie "could not get git list"; 2364 2365 my @list; 2366 2367 while (<IN>) { 2368 chomp; 2369 $list[$#list+1] = $_; 2370 last if (/^$start/); 2371 } 2372 close(IN); 2373 2374 if ($list[$#list] !~ /^$start/) { 2375 fail "SHA1 $start not found"; 2376 } 2377 2378 # go backwards in the list 2379 @list = reverse @list; 2380 2381 my $save_clean = $noclean; 2382 my %ignored_warnings; 2383 2384 if (defined($ignore_warnings)) { 2385 foreach my $sha1 (split /\s+/, $ignore_warnings) { 2386 $ignored_warnings{$sha1} = 1; 2387 } 2388 } 2389 2390 $in_patchcheck = 1; 2391 foreach my $item (@list) { 2392 my $sha1 = $item; 2393 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 2394 2395 doprint "\nProcessing commit $item\n\n"; 2396 2397 run_command "git checkout $sha1" or 2398 die "Failed to checkout $sha1"; 2399 2400 # only clean on the first and last patch 2401 if ($item eq $list[0] || 2402 $item eq $list[$#list]) { 2403 $noclean = $save_clean; 2404 } else { 2405 $noclean = 1; 2406 } 2407 2408 if (defined($minconfig)) { 2409 build "useconfig:$minconfig" or return 0; 2410 } else { 2411 # ?? no config to use? 2412 build "oldconfig" or return 0; 2413 } 2414 2415 2416 if (!defined($ignored_warnings{$sha1})) { 2417 check_buildlog $sha1 or return 0; 2418 } 2419 2420 next if ($type eq "build"); 2421 2422 my $failed = 0; 2423 2424 start_monitor_and_boot or $failed = 1; 2425 2426 if (!$failed && $type ne "boot"){ 2427 do_run_test or $failed = 1; 2428 } 2429 end_monitor; 2430 return 0 if ($failed); 2431 2432 patchcheck_reboot; 2433 2434 } 2435 $in_patchcheck = 0; 2436 success $i; 2437 2438 return 1; 2439} 2440 2441my %depends; 2442my %depcount; 2443my $iflevel = 0; 2444my @ifdeps; 2445 2446# prevent recursion 2447my %read_kconfigs; 2448 2449sub add_dep { 2450 # $config depends on $dep 2451 my ($config, $dep) = @_; 2452 2453 if (defined($depends{$config})) { 2454 $depends{$config} .= " " . $dep; 2455 } else { 2456 $depends{$config} = $dep; 2457 } 2458 2459 # record the number of configs depending on $dep 2460 if (defined $depcount{$dep}) { 2461 $depcount{$dep}++; 2462 } else { 2463 $depcount{$dep} = 1; 2464 } 2465} 2466 2467# taken from streamline_config.pl 2468sub read_kconfig { 2469 my ($kconfig) = @_; 2470 2471 my $state = "NONE"; 2472 my $config; 2473 my @kconfigs; 2474 2475 my $cont = 0; 2476 my $line; 2477 2478 2479 if (! -f $kconfig) { 2480 doprint "file $kconfig does not exist, skipping\n"; 2481 return; 2482 } 2483 2484 open(KIN, "$kconfig") 2485 or die "Can't open $kconfig"; 2486 while (<KIN>) { 2487 chomp; 2488 2489 # Make sure that lines ending with \ continue 2490 if ($cont) { 2491 $_ = $line . " " . $_; 2492 } 2493 2494 if (s/\\$//) { 2495 $cont = 1; 2496 $line = $_; 2497 next; 2498 } 2499 2500 $cont = 0; 2501 2502 # collect any Kconfig sources 2503 if (/^source\s*"(.*)"/) { 2504 $kconfigs[$#kconfigs+1] = $1; 2505 } 2506 2507 # configs found 2508 if (/^\s*(menu)?config\s+(\S+)\s*$/) { 2509 $state = "NEW"; 2510 $config = $2; 2511 2512 for (my $i = 0; $i < $iflevel; $i++) { 2513 add_dep $config, $ifdeps[$i]; 2514 } 2515 2516 # collect the depends for the config 2517 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 2518 2519 add_dep $config, $1; 2520 2521 # Get the configs that select this config 2522 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 2523 2524 # selected by depends on config 2525 add_dep $1, $config; 2526 2527 # Check for if statements 2528 } elsif (/^if\s+(.*\S)\s*$/) { 2529 my $deps = $1; 2530 # remove beginning and ending non text 2531 $deps =~ s/^[^a-zA-Z0-9_]*//; 2532 $deps =~ s/[^a-zA-Z0-9_]*$//; 2533 2534 my @deps = split /[^a-zA-Z0-9_]+/, $deps; 2535 2536 $ifdeps[$iflevel++] = join ':', @deps; 2537 2538 } elsif (/^endif/) { 2539 2540 $iflevel-- if ($iflevel); 2541 2542 # stop on "help" 2543 } elsif (/^\s*help\s*$/) { 2544 $state = "NONE"; 2545 } 2546 } 2547 close(KIN); 2548 2549 # read in any configs that were found. 2550 foreach $kconfig (@kconfigs) { 2551 if (!defined($read_kconfigs{$kconfig})) { 2552 $read_kconfigs{$kconfig} = 1; 2553 read_kconfig("$builddir/$kconfig"); 2554 } 2555 } 2556} 2557 2558sub read_depends { 2559 # find out which arch this is by the kconfig file 2560 open (IN, $output_config) 2561 or dodie "Failed to read $output_config"; 2562 my $arch; 2563 while (<IN>) { 2564 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 2565 $arch = $1; 2566 last; 2567 } 2568 } 2569 close IN; 2570 2571 if (!defined($arch)) { 2572 doprint "Could not find arch from config file\n"; 2573 doprint "no dependencies used\n"; 2574 return; 2575 } 2576 2577 # arch is really the subarch, we need to know 2578 # what directory to look at. 2579 if ($arch eq "i386" || $arch eq "x86_64") { 2580 $arch = "x86"; 2581 } elsif ($arch =~ /^tile/) { 2582 $arch = "tile"; 2583 } 2584 2585 my $kconfig = "$builddir/arch/$arch/Kconfig"; 2586 2587 if (! -f $kconfig && $arch =~ /\d$/) { 2588 my $orig = $arch; 2589 # some subarchs have numbers, truncate them 2590 $arch =~ s/\d*$//; 2591 $kconfig = "$builddir/arch/$arch/Kconfig"; 2592 if (! -f $kconfig) { 2593 doprint "No idea what arch dir $orig is for\n"; 2594 doprint "no dependencies used\n"; 2595 return; 2596 } 2597 } 2598 2599 read_kconfig($kconfig); 2600} 2601 2602sub read_config_list { 2603 my ($config) = @_; 2604 2605 open (IN, $config) 2606 or dodie "Failed to read $config"; 2607 2608 while (<IN>) { 2609 if (/^((CONFIG\S*)=.*)/) { 2610 if (!defined($config_ignore{$2})) { 2611 $config_list{$2} = $1; 2612 } 2613 } 2614 } 2615 2616 close(IN); 2617} 2618 2619sub read_output_config { 2620 my ($config) = @_; 2621 2622 assign_configs \%config_ignore, $config; 2623} 2624 2625sub make_new_config { 2626 my @configs = @_; 2627 2628 open (OUT, ">$output_config") 2629 or dodie "Failed to write $output_config"; 2630 2631 foreach my $config (@configs) { 2632 print OUT "$config\n"; 2633 } 2634 close OUT; 2635} 2636 2637sub chomp_config { 2638 my ($config) = @_; 2639 2640 $config =~ s/CONFIG_//; 2641 2642 return $config; 2643} 2644 2645sub get_depends { 2646 my ($dep) = @_; 2647 2648 my $kconfig = chomp_config $dep; 2649 2650 $dep = $depends{"$kconfig"}; 2651 2652 # the dep string we have saves the dependencies as they 2653 # were found, including expressions like ! && ||. We 2654 # want to split this out into just an array of configs. 2655 2656 my $valid = "A-Za-z_0-9"; 2657 2658 my @configs; 2659 2660 while ($dep =~ /[$valid]/) { 2661 2662 if ($dep =~ /^[^$valid]*([$valid]+)/) { 2663 my $conf = "CONFIG_" . $1; 2664 2665 $configs[$#configs + 1] = $conf; 2666 2667 $dep =~ s/^[^$valid]*[$valid]+//; 2668 } else { 2669 die "this should never happen"; 2670 } 2671 } 2672 2673 return @configs; 2674} 2675 2676my %min_configs; 2677my %keep_configs; 2678my %save_configs; 2679my %processed_configs; 2680my %nochange_config; 2681 2682sub test_this_config { 2683 my ($config) = @_; 2684 2685 my $found; 2686 2687 # if we already processed this config, skip it 2688 if (defined($processed_configs{$config})) { 2689 return undef; 2690 } 2691 $processed_configs{$config} = 1; 2692 2693 # if this config failed during this round, skip it 2694 if (defined($nochange_config{$config})) { 2695 return undef; 2696 } 2697 2698 my $kconfig = chomp_config $config; 2699 2700 # Test dependencies first 2701 if (defined($depends{"$kconfig"})) { 2702 my @parents = get_depends $config; 2703 foreach my $parent (@parents) { 2704 # if the parent is in the min config, check it first 2705 next if (!defined($min_configs{$parent})); 2706 $found = test_this_config($parent); 2707 if (defined($found)) { 2708 return $found; 2709 } 2710 } 2711 } 2712 2713 # Remove this config from the list of configs 2714 # do a make oldnoconfig and then read the resulting 2715 # .config to make sure it is missing the config that 2716 # we had before 2717 my %configs = %min_configs; 2718 delete $configs{$config}; 2719 make_new_config ((values %configs), (values %keep_configs)); 2720 make_oldconfig; 2721 undef %configs; 2722 assign_configs \%configs, $output_config; 2723 2724 return $config if (!defined($configs{$config})); 2725 2726 doprint "disabling config $config did not change .config\n"; 2727 2728 $nochange_config{$config} = 1; 2729 2730 return undef; 2731} 2732 2733sub make_min_config { 2734 my ($i) = @_; 2735 2736 if (!defined($output_minconfig)) { 2737 fail "OUTPUT_MIN_CONFIG not defined" and return; 2738 } 2739 2740 # If output_minconfig exists, and the start_minconfig 2741 # came from min_config, than ask if we should use 2742 # that instead. 2743 if (-f $output_minconfig && !$start_minconfig_defined) { 2744 print "$output_minconfig exists\n"; 2745 if (read_yn " Use it as minconfig?") { 2746 $start_minconfig = $output_minconfig; 2747 } 2748 } 2749 2750 if (!defined($start_minconfig)) { 2751 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 2752 } 2753 2754 my $temp_config = "$tmpdir/temp_config"; 2755 2756 # First things first. We build an allnoconfig to find 2757 # out what the defaults are that we can't touch. 2758 # Some are selections, but we really can't handle selections. 2759 2760 my $save_minconfig = $minconfig; 2761 undef $minconfig; 2762 2763 run_command "$make allnoconfig" or return 0; 2764 2765 read_depends; 2766 2767 process_config_ignore $output_config; 2768 2769 undef %save_configs; 2770 undef %min_configs; 2771 2772 if (defined($ignore_config)) { 2773 # make sure the file exists 2774 `touch $ignore_config`; 2775 assign_configs \%save_configs, $ignore_config; 2776 } 2777 2778 %keep_configs = %save_configs; 2779 2780 doprint "Load initial configs from $start_minconfig\n"; 2781 2782 # Look at the current min configs, and save off all the 2783 # ones that were set via the allnoconfig 2784 assign_configs \%min_configs, $start_minconfig; 2785 2786 my @config_keys = keys %min_configs; 2787 2788 # All configs need a depcount 2789 foreach my $config (@config_keys) { 2790 my $kconfig = chomp_config $config; 2791 if (!defined $depcount{$kconfig}) { 2792 $depcount{$kconfig} = 0; 2793 } 2794 } 2795 2796 # Remove anything that was set by the make allnoconfig 2797 # we shouldn't need them as they get set for us anyway. 2798 foreach my $config (@config_keys) { 2799 # Remove anything in the ignore_config 2800 if (defined($keep_configs{$config})) { 2801 my $file = $ignore_config; 2802 $file =~ s,.*/(.*?)$,$1,; 2803 doprint "$config set by $file ... ignored\n"; 2804 delete $min_configs{$config}; 2805 next; 2806 } 2807 # But make sure the settings are the same. If a min config 2808 # sets a selection, we do not want to get rid of it if 2809 # it is not the same as what we have. Just move it into 2810 # the keep configs. 2811 if (defined($config_ignore{$config})) { 2812 if ($config_ignore{$config} ne $min_configs{$config}) { 2813 doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 2814 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 2815 $keep_configs{$config} = $min_configs{$config}; 2816 } else { 2817 doprint "$config set by allnoconfig ... ignored\n"; 2818 } 2819 delete $min_configs{$config}; 2820 } 2821 } 2822 2823 my $done = 0; 2824 my $take_two = 0; 2825 2826 while (!$done) { 2827 2828 my $config; 2829 my $found; 2830 2831 # Now disable each config one by one and do a make oldconfig 2832 # till we find a config that changes our list. 2833 2834 my @test_configs = keys %min_configs; 2835 2836 # Sort keys by who is most dependent on 2837 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 2838 @test_configs ; 2839 2840 # Put configs that did not modify the config at the end. 2841 my $reset = 1; 2842 for (my $i = 0; $i < $#test_configs; $i++) { 2843 if (!defined($nochange_config{$test_configs[0]})) { 2844 $reset = 0; 2845 last; 2846 } 2847 # This config didn't change the .config last time. 2848 # Place it at the end 2849 my $config = shift @test_configs; 2850 push @test_configs, $config; 2851 } 2852 2853 # if every test config has failed to modify the .config file 2854 # in the past, then reset and start over. 2855 if ($reset) { 2856 undef %nochange_config; 2857 } 2858 2859 undef %processed_configs; 2860 2861 foreach my $config (@test_configs) { 2862 2863 $found = test_this_config $config; 2864 2865 last if (defined($found)); 2866 2867 # oh well, try another config 2868 } 2869 2870 if (!defined($found)) { 2871 # we could have failed due to the nochange_config hash 2872 # reset and try again 2873 if (!$take_two) { 2874 undef %nochange_config; 2875 $take_two = 1; 2876 next; 2877 } 2878 doprint "No more configs found that we can disable\n"; 2879 $done = 1; 2880 last; 2881 } 2882 $take_two = 0; 2883 2884 $config = $found; 2885 2886 doprint "Test with $config disabled\n"; 2887 2888 # set in_bisect to keep build and monitor from dieing 2889 $in_bisect = 1; 2890 2891 my $failed = 0; 2892 build "oldconfig"; 2893 start_monitor_and_boot or $failed = 1; 2894 end_monitor; 2895 2896 $in_bisect = 0; 2897 2898 if ($failed) { 2899 doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 2900 # this config is needed, add it to the ignore list. 2901 $keep_configs{$config} = $min_configs{$config}; 2902 $save_configs{$config} = $min_configs{$config}; 2903 delete $min_configs{$config}; 2904 2905 # update new ignore configs 2906 if (defined($ignore_config)) { 2907 open (OUT, ">$temp_config") 2908 or die "Can't write to $temp_config"; 2909 foreach my $config (keys %save_configs) { 2910 print OUT "$save_configs{$config}\n"; 2911 } 2912 close OUT; 2913 run_command "mv $temp_config $ignore_config" or 2914 dodie "failed to copy update to $ignore_config"; 2915 } 2916 2917 } else { 2918 # We booted without this config, remove it from the minconfigs. 2919 doprint "$config is not needed, disabling\n"; 2920 2921 delete $min_configs{$config}; 2922 2923 # Also disable anything that is not enabled in this config 2924 my %configs; 2925 assign_configs \%configs, $output_config; 2926 my @config_keys = keys %min_configs; 2927 foreach my $config (@config_keys) { 2928 if (!defined($configs{$config})) { 2929 doprint "$config is not set, disabling\n"; 2930 delete $min_configs{$config}; 2931 } 2932 } 2933 2934 # Save off all the current mandidory configs 2935 open (OUT, ">$temp_config") 2936 or die "Can't write to $temp_config"; 2937 foreach my $config (keys %keep_configs) { 2938 print OUT "$keep_configs{$config}\n"; 2939 } 2940 foreach my $config (keys %min_configs) { 2941 print OUT "$min_configs{$config}\n"; 2942 } 2943 close OUT; 2944 2945 run_command "mv $temp_config $output_minconfig" or 2946 dodie "failed to copy update to $output_minconfig"; 2947 } 2948 2949 doprint "Reboot and wait $sleep_time seconds\n"; 2950 reboot $sleep_time; 2951 } 2952 2953 success $i; 2954 return 1; 2955} 2956 2957$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 2958 2959if ($#ARGV == 0) { 2960 $ktest_config = $ARGV[0]; 2961 if (! -f $ktest_config) { 2962 print "$ktest_config does not exist.\n"; 2963 if (!read_yn "Create it?") { 2964 exit 0; 2965 } 2966 } 2967} else { 2968 $ktest_config = "ktest.conf"; 2969} 2970 2971if (! -f $ktest_config) { 2972 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 2973 print OUT << "EOF" 2974# Generated by ktest.pl 2975# 2976# Define each test with TEST_START 2977# The config options below it will override the defaults 2978TEST_START 2979 2980DEFAULTS 2981EOF 2982; 2983 close(OUT); 2984} 2985read_config $ktest_config; 2986 2987if (defined($opt{"LOG_FILE"})) { 2988 $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1); 2989} 2990 2991# Append any configs entered in manually to the config file. 2992my @new_configs = keys %entered_configs; 2993if ($#new_configs >= 0) { 2994 print "\nAppending entered in configs to $ktest_config\n"; 2995 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 2996 foreach my $config (@new_configs) { 2997 print OUT "$config = $entered_configs{$config}\n"; 2998 $opt{$config} = $entered_configs{$config}; 2999 } 3000} 3001 3002if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 3003 unlink $opt{"LOG_FILE"}; 3004} 3005 3006doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 3007 3008for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 3009 3010 if (!$i) { 3011 doprint "DEFAULT OPTIONS:\n"; 3012 } else { 3013 doprint "\nTEST $i OPTIONS"; 3014 if (defined($repeat_tests{$i})) { 3015 $repeat = $repeat_tests{$i}; 3016 doprint " ITERATE $repeat"; 3017 } 3018 doprint "\n"; 3019 } 3020 3021 foreach my $option (sort keys %opt) { 3022 3023 if ($option =~ /\[(\d+)\]$/) { 3024 next if ($i != $1); 3025 } else { 3026 next if ($i); 3027 } 3028 3029 doprint "$option = $opt{$option}\n"; 3030 } 3031} 3032 3033sub __set_test_option { 3034 my ($name, $i) = @_; 3035 3036 my $option = "$name\[$i\]"; 3037 3038 if (defined($opt{$option})) { 3039 return $opt{$option}; 3040 } 3041 3042 foreach my $test (keys %repeat_tests) { 3043 if ($i >= $test && 3044 $i < $test + $repeat_tests{$test}) { 3045 $option = "$name\[$test\]"; 3046 if (defined($opt{$option})) { 3047 return $opt{$option}; 3048 } 3049 } 3050 } 3051 3052 if (defined($opt{$name})) { 3053 return $opt{$name}; 3054 } 3055 3056 return undef; 3057} 3058 3059sub set_test_option { 3060 my ($name, $i) = @_; 3061 3062 my $option = __set_test_option($name, $i); 3063 return $option if (!defined($option)); 3064 3065 return eval_option($option, $i); 3066} 3067 3068# First we need to do is the builds 3069for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 3070 3071 # Do not reboot on failing test options 3072 $no_reboot = 1; 3073 3074 $iteration = $i; 3075 3076 my $makecmd = set_test_option("MAKE_CMD", $i); 3077 3078 $machine = set_test_option("MACHINE", $i); 3079 $ssh_user = set_test_option("SSH_USER", $i); 3080 $tmpdir = set_test_option("TMP_DIR", $i); 3081 $outputdir = set_test_option("OUTPUT_DIR", $i); 3082 $builddir = set_test_option("BUILD_DIR", $i); 3083 $test_type = set_test_option("TEST_TYPE", $i); 3084 $build_type = set_test_option("BUILD_TYPE", $i); 3085 $build_options = set_test_option("BUILD_OPTIONS", $i); 3086 $pre_build = set_test_option("PRE_BUILD", $i); 3087 $post_build = set_test_option("POST_BUILD", $i); 3088 $pre_build_die = set_test_option("PRE_BUILD_DIE", $i); 3089 $post_build_die = set_test_option("POST_BUILD_DIE", $i); 3090 $power_cycle = set_test_option("POWER_CYCLE", $i); 3091 $reboot = set_test_option("REBOOT", $i); 3092 $noclean = set_test_option("BUILD_NOCLEAN", $i); 3093 $minconfig = set_test_option("MIN_CONFIG", $i); 3094 $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i); 3095 $start_minconfig = set_test_option("START_MIN_CONFIG", $i); 3096 $ignore_config = set_test_option("IGNORE_CONFIG", $i); 3097 $run_test = set_test_option("TEST", $i); 3098 $addconfig = set_test_option("ADD_CONFIG", $i); 3099 $reboot_type = set_test_option("REBOOT_TYPE", $i); 3100 $grub_menu = set_test_option("GRUB_MENU", $i); 3101 $post_install = set_test_option("POST_INSTALL", $i); 3102 $no_install = set_test_option("NO_INSTALL", $i); 3103 $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 3104 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 3105 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 3106 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 3107 $power_off = set_test_option("POWER_OFF", $i); 3108 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 3109 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 3110 $sleep_time = set_test_option("SLEEP_TIME", $i); 3111 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 3112 $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); 3113 $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i); 3114 $bisect_manual = set_test_option("BISECT_MANUAL", $i); 3115 $bisect_skip = set_test_option("BISECT_SKIP", $i); 3116 $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); 3117 $store_failures = set_test_option("STORE_FAILURES", $i); 3118 $test_name = set_test_option("TEST_NAME", $i); 3119 $timeout = set_test_option("TIMEOUT", $i); 3120 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 3121 $console = set_test_option("CONSOLE", $i); 3122 $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i); 3123 $success_line = set_test_option("SUCCESS_LINE", $i); 3124 $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i); 3125 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 3126 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 3127 $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); 3128 $build_target = set_test_option("BUILD_TARGET", $i); 3129 $ssh_exec = set_test_option("SSH_EXEC", $i); 3130 $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 3131 $target_image = set_test_option("TARGET_IMAGE", $i); 3132 $localversion = set_test_option("LOCALVERSION", $i); 3133 3134 $start_minconfig_defined = 1; 3135 3136 if (!defined($start_minconfig)) { 3137 $start_minconfig_defined = 0; 3138 $start_minconfig = $minconfig; 3139 } 3140 3141 chdir $builddir || die "can't change directory to $builddir"; 3142 3143 foreach my $dir ($tmpdir, $outputdir) { 3144 if (!-d $dir) { 3145 mkpath($dir) or 3146 die "can't create $dir"; 3147 } 3148 } 3149 3150 $ENV{"SSH_USER"} = $ssh_user; 3151 $ENV{"MACHINE"} = $machine; 3152 3153 $target = "$ssh_user\@$machine"; 3154 3155 $buildlog = "$tmpdir/buildlog-$machine"; 3156 $dmesg = "$tmpdir/dmesg-$machine"; 3157 $make = "$makecmd O=$outputdir"; 3158 $output_config = "$outputdir/.config"; 3159 3160 if ($reboot_type eq "grub") { 3161 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3162 } elsif (!defined($reboot_script)) { 3163 dodie "REBOOT_SCRIPT not defined" 3164 } 3165 3166 my $run_type = $build_type; 3167 if ($test_type eq "patchcheck") { 3168 $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 3169 } elsif ($test_type eq "bisect") { 3170 $run_type = $opt{"BISECT_TYPE[$i]"}; 3171 } elsif ($test_type eq "config_bisect") { 3172 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 3173 } 3174 3175 if ($test_type eq "make_min_config") { 3176 $run_type = ""; 3177 } 3178 3179 # mistake in config file? 3180 if (!defined($run_type)) { 3181 $run_type = "ERROR"; 3182 } 3183 3184 my $installme = ""; 3185 $installme = " no_install" if ($no_install); 3186 3187 doprint "\n\n"; 3188 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; 3189 3190 unlink $dmesg; 3191 unlink $buildlog; 3192 3193 if (defined($addconfig)) { 3194 my $min = $minconfig; 3195 if (!defined($minconfig)) { 3196 $min = ""; 3197 } 3198 run_command "cat $addconfig $min > $tmpdir/add_config" or 3199 dodie "Failed to create temp config"; 3200 $minconfig = "$tmpdir/add_config"; 3201 } 3202 3203 my $checkout = $opt{"CHECKOUT[$i]"}; 3204 if (defined($checkout)) { 3205 run_command "git checkout $checkout" or 3206 die "failed to checkout $checkout"; 3207 } 3208 3209 $no_reboot = 0; 3210 3211 3212 if ($test_type eq "bisect") { 3213 bisect $i; 3214 next; 3215 } elsif ($test_type eq "config_bisect") { 3216 config_bisect $i; 3217 next; 3218 } elsif ($test_type eq "patchcheck") { 3219 patchcheck $i; 3220 next; 3221 } elsif ($test_type eq "make_min_config") { 3222 make_min_config $i; 3223 next; 3224 } 3225 3226 if ($build_type ne "nobuild") { 3227 build $build_type or next; 3228 } 3229 3230 if ($test_type eq "install") { 3231 get_version; 3232 install; 3233 success $i; 3234 next; 3235 } 3236 3237 if ($test_type ne "build") { 3238 my $failed = 0; 3239 start_monitor_and_boot or $failed = 1; 3240 3241 if (!$failed && $test_type ne "boot" && defined($run_test)) { 3242 do_run_test or $failed = 1; 3243 } 3244 end_monitor; 3245 next if ($failed); 3246 } 3247 3248 success $i; 3249} 3250 3251if ($opt{"POWEROFF_ON_SUCCESS"}) { 3252 halt; 3253} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 3254 reboot; 3255} 3256 3257doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 3258 3259exit 0; 3260