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