1#!/usr/bin/perl -w 2# SPDX-License-Identifier: GPL-2.0-only 3# 4# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 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; 13use FindBin; 14use IO::Handle; 15 16my $VERSION = "0.2"; 17 18$| = 1; 19 20my %opt; 21my %repeat_tests; 22my %repeats; 23my %evals; 24my @command_vars; 25my %command_tmp_vars; 26 27#default opts 28my %default = ( 29 "MAILER" => "sendmail", # default mailer 30 "EMAIL_ON_ERROR" => 1, 31 "EMAIL_WHEN_FINISHED" => 1, 32 "EMAIL_WHEN_CANCELED" => 0, 33 "EMAIL_WHEN_STARTED" => 0, 34 "NUM_TESTS" => 1, 35 "TEST_TYPE" => "build", 36 "BUILD_TYPE" => "oldconfig", 37 "MAKE_CMD" => "make", 38 "CLOSE_CONSOLE_SIGNAL" => "INT", 39 "TIMEOUT" => 120, 40 "TMP_DIR" => "/tmp/ktest/\${MACHINE}", 41 "SLEEP_TIME" => 60, # sleep time between tests 42 "BUILD_NOCLEAN" => 0, 43 "REBOOT_ON_ERROR" => 0, 44 "POWEROFF_ON_ERROR" => 0, 45 "REBOOT_ON_SUCCESS" => 1, 46 "POWEROFF_ON_SUCCESS" => 0, 47 "BUILD_OPTIONS" => "", 48 "BISECT_SLEEP_TIME" => 60, # sleep time between bisects 49 "PATCHCHECK_SLEEP_TIME" => 60, # sleep time between patch checks 50 "CLEAR_LOG" => 0, 51 "BISECT_MANUAL" => 0, 52 "BISECT_SKIP" => 1, 53 "BISECT_TRIES" => 1, 54 "MIN_CONFIG_TYPE" => "boot", 55 "SUCCESS_LINE" => "login:", 56 "DETECT_TRIPLE_FAULT" => 1, 57 "NO_INSTALL" => 0, 58 "BOOTED_TIMEOUT" => 1, 59 "DIE_ON_FAILURE" => 1, 60 "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND", 61 "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE", 62 "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}", 63 "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot", 64 "REBOOT_RETURN_CODE" => 255, 65 "STOP_AFTER_SUCCESS" => 10, 66 "STOP_AFTER_FAILURE" => 60, 67 "STOP_TEST_AFTER" => 600, 68 "MAX_MONITOR_WAIT" => 1800, 69 "GRUB_REBOOT" => "grub2-reboot", 70 "GRUB_BLS_GET" => "grubby --info=ALL", 71 "SYSLINUX" => "extlinux", 72 "SYSLINUX_PATH" => "/boot/extlinux", 73 "CONNECT_TIMEOUT" => 25, 74 75# required, and we will ask users if they don't have them but we keep the default 76# value something that is common. 77 "REBOOT_TYPE" => "grub", 78 "LOCALVERSION" => "-test", 79 "SSH_USER" => "root", 80 "BUILD_TARGET" => "arch/x86/boot/bzImage", 81 "TARGET_IMAGE" => "/boot/vmlinuz-test", 82 83 "LOG_FILE" => undef, 84 "IGNORE_UNUSED" => 0, 85); 86 87my $test_log_start = 0; 88my $dry_run = 0; 89 90my $ktest_config = "ktest.conf"; 91my $version; 92my $have_version = 0; 93my $machine; 94my $last_machine; 95my $ssh_user; 96my $tmpdir; 97my $builddir; 98my $outputdir; 99my $output_config; 100my $test_type; 101my $build_type; 102my $build_options; 103my $final_post_ktest; 104my $post_ktest_done = 0; 105my $pre_ktest; 106my $pre_ktest_die; 107my $post_ktest; 108my $pre_test; 109my $pre_test_die; 110my $post_test; 111my $pre_build; 112my $post_build; 113my $pre_build_die; 114my $post_build_die; 115my $reboot_type; 116my $reboot_script; 117my $power_cycle; 118my $reboot; 119my $reboot_return_code; 120my $reboot_on_error; 121my $switch_to_good; 122my $switch_to_test; 123my $poweroff_on_error; 124my $reboot_on_success; 125my $die_on_failure; 126my $powercycle_after_reboot; 127my $poweroff_after_halt; 128my $max_monitor_wait; 129my $ssh_exec; 130my $scp_to_target; 131my $scp_to_target_install; 132my $power_off; 133my $grub_menu; 134my $last_grub_menu; 135my $grub_file; 136my $grub_number; 137my $grub_reboot; 138my $grub_bls_get; 139my $syslinux; 140my $syslinux_path; 141my $syslinux_label; 142my $target; 143my $make; 144my $pre_install; 145my $post_install; 146my $no_install; 147my $noclean; 148my $minconfig; 149my $start_minconfig; 150my $start_minconfig_defined; 151my $output_minconfig; 152my $minconfig_type; 153my $use_output_minconfig; 154my $warnings_file; 155my $ignore_config; 156my $ignore_errors; 157my $addconfig; 158my $in_bisect = 0; 159my $bisect_bad_commit = ""; 160my $reverse_bisect; 161my $bisect_manual; 162my $bisect_skip; 163my $bisect_tries; 164my $config_bisect_good; 165my $bisect_ret_good; 166my $bisect_ret_bad; 167my $bisect_ret_skip; 168my $bisect_ret_abort; 169my $bisect_ret_default; 170my $in_patchcheck = 0; 171my $run_test; 172my $buildlog; 173my $testlog; 174my $dmesg; 175my $monitor_fp; 176my $monitor_pid; 177my $monitor_cnt = 0; 178my $sleep_time; 179my $bisect_sleep_time; 180my $patchcheck_sleep_time; 181my $ignore_warnings; 182my $store_failures; 183my $store_successes; 184my $test_name; 185my $timeout; 186my $run_timeout; 187my $connect_timeout; 188my $config_bisect_exec; 189my $booted_timeout; 190my $detect_triplefault; 191my $console; 192my $close_console_signal; 193my $reboot_success_line; 194my $success_line; 195my $stop_after_success; 196my $stop_after_failure; 197my $stop_test_after; 198my $build_target; 199my $target_image; 200my $checkout; 201my $localversion; 202my $iteration = 0; 203my $successes = 0; 204my $stty_orig; 205my $run_command_status = 0; 206 207my $bisect_good; 208my $bisect_bad; 209my $bisect_type; 210my $bisect_start; 211my $bisect_replay; 212my $bisect_files; 213my $bisect_reverse; 214my $bisect_check; 215 216my $config_bisect; 217my $config_bisect_type; 218my $config_bisect_check; 219 220my $patchcheck_type; 221my $patchcheck_start; 222my $patchcheck_cherry; 223my $patchcheck_end; 224my $patchcheck_skip; 225 226my $build_time; 227my $install_time; 228my $reboot_time; 229my $test_time; 230 231my $warning_found = 0; 232 233my $pwd; 234my $dirname = $FindBin::Bin; 235 236my $mailto; 237my $mailer; 238my $mail_path; 239my $mail_max_size; 240my $mail_command; 241my $email_on_error; 242my $email_when_finished; 243my $email_when_started; 244my $email_when_canceled; 245 246my $script_start_time = localtime(); 247 248# set when a test is something other that just building or install 249# which would require more options. 250my $buildonly = 1; 251 252# tell build not to worry about warnings, even when WARNINGS_FILE is set 253my $warnings_ok = 0; 254 255# set when creating a new config 256my $newconfig = 0; 257 258my %entered_configs; 259my %config_help; 260my %variable; 261 262# force_config is the list of configs that we force enabled (or disabled) 263# in a .config file. The MIN_CONFIG and ADD_CONFIG configs. 264my %force_config; 265 266# do not force reboots on config problems 267my $no_reboot = 1; 268 269# reboot on success 270my $reboot_success = 0; 271 272my %option_map = ( 273 "MAILTO" => \$mailto, 274 "MAILER" => \$mailer, 275 "MAIL_PATH" => \$mail_path, 276 "MAIL_MAX_SIZE" => \$mail_max_size, 277 "MAIL_COMMAND" => \$mail_command, 278 "EMAIL_ON_ERROR" => \$email_on_error, 279 "EMAIL_WHEN_FINISHED" => \$email_when_finished, 280 "EMAIL_WHEN_STARTED" => \$email_when_started, 281 "EMAIL_WHEN_CANCELED" => \$email_when_canceled, 282 "MACHINE" => \$machine, 283 "SSH_USER" => \$ssh_user, 284 "TMP_DIR" => \$tmpdir, 285 "OUTPUT_DIR" => \$outputdir, 286 "BUILD_DIR" => \$builddir, 287 "TEST_TYPE" => \$test_type, 288 "PRE_KTEST" => \$pre_ktest, 289 "PRE_KTEST_DIE" => \$pre_ktest_die, 290 "POST_KTEST" => \$post_ktest, 291 "PRE_TEST" => \$pre_test, 292 "PRE_TEST_DIE" => \$pre_test_die, 293 "POST_TEST" => \$post_test, 294 "BUILD_TYPE" => \$build_type, 295 "BUILD_OPTIONS" => \$build_options, 296 "PRE_BUILD" => \$pre_build, 297 "POST_BUILD" => \$post_build, 298 "PRE_BUILD_DIE" => \$pre_build_die, 299 "POST_BUILD_DIE" => \$post_build_die, 300 "POWER_CYCLE" => \$power_cycle, 301 "REBOOT" => \$reboot, 302 "REBOOT_RETURN_CODE" => \$reboot_return_code, 303 "BUILD_NOCLEAN" => \$noclean, 304 "MIN_CONFIG" => \$minconfig, 305 "OUTPUT_MIN_CONFIG" => \$output_minconfig, 306 "START_MIN_CONFIG" => \$start_minconfig, 307 "MIN_CONFIG_TYPE" => \$minconfig_type, 308 "USE_OUTPUT_MIN_CONFIG" => \$use_output_minconfig, 309 "WARNINGS_FILE" => \$warnings_file, 310 "IGNORE_CONFIG" => \$ignore_config, 311 "TEST" => \$run_test, 312 "ADD_CONFIG" => \$addconfig, 313 "REBOOT_TYPE" => \$reboot_type, 314 "GRUB_MENU" => \$grub_menu, 315 "GRUB_FILE" => \$grub_file, 316 "GRUB_REBOOT" => \$grub_reboot, 317 "GRUB_BLS_GET" => \$grub_bls_get, 318 "SYSLINUX" => \$syslinux, 319 "SYSLINUX_PATH" => \$syslinux_path, 320 "SYSLINUX_LABEL" => \$syslinux_label, 321 "PRE_INSTALL" => \$pre_install, 322 "POST_INSTALL" => \$post_install, 323 "NO_INSTALL" => \$no_install, 324 "REBOOT_SCRIPT" => \$reboot_script, 325 "REBOOT_ON_ERROR" => \$reboot_on_error, 326 "SWITCH_TO_GOOD" => \$switch_to_good, 327 "SWITCH_TO_TEST" => \$switch_to_test, 328 "POWEROFF_ON_ERROR" => \$poweroff_on_error, 329 "REBOOT_ON_SUCCESS" => \$reboot_on_success, 330 "DIE_ON_FAILURE" => \$die_on_failure, 331 "POWER_OFF" => \$power_off, 332 "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot, 333 "POWEROFF_AFTER_HALT" => \$poweroff_after_halt, 334 "MAX_MONITOR_WAIT" => \$max_monitor_wait, 335 "SLEEP_TIME" => \$sleep_time, 336 "BISECT_SLEEP_TIME" => \$bisect_sleep_time, 337 "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time, 338 "IGNORE_WARNINGS" => \$ignore_warnings, 339 "IGNORE_ERRORS" => \$ignore_errors, 340 "BISECT_MANUAL" => \$bisect_manual, 341 "BISECT_SKIP" => \$bisect_skip, 342 "BISECT_TRIES" => \$bisect_tries, 343 "CONFIG_BISECT_GOOD" => \$config_bisect_good, 344 "BISECT_RET_GOOD" => \$bisect_ret_good, 345 "BISECT_RET_BAD" => \$bisect_ret_bad, 346 "BISECT_RET_SKIP" => \$bisect_ret_skip, 347 "BISECT_RET_ABORT" => \$bisect_ret_abort, 348 "BISECT_RET_DEFAULT" => \$bisect_ret_default, 349 "STORE_FAILURES" => \$store_failures, 350 "STORE_SUCCESSES" => \$store_successes, 351 "TEST_NAME" => \$test_name, 352 "TIMEOUT" => \$timeout, 353 "RUN_TIMEOUT" => \$run_timeout, 354 "CONNECT_TIMEOUT" => \$connect_timeout, 355 "CONFIG_BISECT_EXEC" => \$config_bisect_exec, 356 "BOOTED_TIMEOUT" => \$booted_timeout, 357 "CONSOLE" => \$console, 358 "CLOSE_CONSOLE_SIGNAL" => \$close_console_signal, 359 "DETECT_TRIPLE_FAULT" => \$detect_triplefault, 360 "SUCCESS_LINE" => \$success_line, 361 "REBOOT_SUCCESS_LINE" => \$reboot_success_line, 362 "STOP_AFTER_SUCCESS" => \$stop_after_success, 363 "STOP_AFTER_FAILURE" => \$stop_after_failure, 364 "STOP_TEST_AFTER" => \$stop_test_after, 365 "BUILD_TARGET" => \$build_target, 366 "SSH_EXEC" => \$ssh_exec, 367 "SCP_TO_TARGET" => \$scp_to_target, 368 "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install, 369 "CHECKOUT" => \$checkout, 370 "TARGET_IMAGE" => \$target_image, 371 "LOCALVERSION" => \$localversion, 372 373 "BISECT_GOOD" => \$bisect_good, 374 "BISECT_BAD" => \$bisect_bad, 375 "BISECT_TYPE" => \$bisect_type, 376 "BISECT_START" => \$bisect_start, 377 "BISECT_REPLAY" => \$bisect_replay, 378 "BISECT_FILES" => \$bisect_files, 379 "BISECT_REVERSE" => \$bisect_reverse, 380 "BISECT_CHECK" => \$bisect_check, 381 382 "CONFIG_BISECT" => \$config_bisect, 383 "CONFIG_BISECT_TYPE" => \$config_bisect_type, 384 "CONFIG_BISECT_CHECK" => \$config_bisect_check, 385 386 "PATCHCHECK_TYPE" => \$patchcheck_type, 387 "PATCHCHECK_START" => \$patchcheck_start, 388 "PATCHCHECK_CHERRY" => \$patchcheck_cherry, 389 "PATCHCHECK_END" => \$patchcheck_end, 390 "PATCHCHECK_SKIP" => \$patchcheck_skip, 391); 392 393# Options may be used by other options, record them. 394my %used_options; 395 396# default variables that can be used 397chomp ($variable{"PWD"} = `pwd`); 398$pwd = $variable{"PWD"}; 399 400$config_help{"MACHINE"} = << "EOF" 401 The machine hostname that you will test. 402 For build only tests, it is still needed to differentiate log files. 403EOF 404 ; 405$config_help{"SSH_USER"} = << "EOF" 406 The box is expected to have ssh on normal bootup, provide the user 407 (most likely root, since you need privileged operations) 408EOF 409 ; 410$config_help{"BUILD_DIR"} = << "EOF" 411 The directory that contains the Linux source code (full path). 412 You can use \${PWD} that will be the path where ktest.pl is run, or use 413 \${THIS_DIR} which is assigned \${PWD} but may be changed later. 414EOF 415 ; 416$config_help{"OUTPUT_DIR"} = << "EOF" 417 The directory that the objects will be built (full path). 418 (can not be same as BUILD_DIR) 419 You can use \${PWD} that will be the path where ktest.pl is run, or use 420 \${THIS_DIR} which is assigned \${PWD} but may be changed later. 421EOF 422 ; 423$config_help{"BUILD_TARGET"} = << "EOF" 424 The location of the compiled file to copy to the target. 425 (relative to OUTPUT_DIR) 426EOF 427 ; 428$config_help{"BUILD_OPTIONS"} = << "EOF" 429 Options to add to \"make\" when building. 430 i.e. -j20 431EOF 432 ; 433$config_help{"TARGET_IMAGE"} = << "EOF" 434 The place to put your image on the test machine. 435EOF 436 ; 437$config_help{"POWER_CYCLE"} = << "EOF" 438 A script or command to reboot the box. 439 440 Here is a digital loggers power switch example 441 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 442 443 Here is an example to reboot a virtual box on the current host 444 with the name "Guest". 445 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 446EOF 447 ; 448$config_help{"CONSOLE"} = << "EOF" 449 The script or command that reads the console 450 451 If you use ttywatch server, something like the following would work. 452CONSOLE = nc -d localhost 3001 453 454 For a virtual machine with guest name "Guest". 455CONSOLE = virsh console Guest 456EOF 457 ; 458$config_help{"LOCALVERSION"} = << "EOF" 459 Required version ending to differentiate the test 460 from other linux builds on the system. 461EOF 462 ; 463$config_help{"REBOOT_TYPE"} = << "EOF" 464 Way to reboot the box to the test kernel. 465 Only valid options so far are "grub", "grub2", "grub2bls", "syslinux", and "script". 466 467 If you specify grub, it will assume grub version 1 468 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 469 and select that target to reboot to the kernel. If this is not 470 your setup, then specify "script" and have a command or script 471 specified in REBOOT_SCRIPT to boot to the target. 472 473 The entry in /boot/grub/menu.lst must be entered in manually. 474 The test will not modify that file. 475 476 If you specify grub2, then you also need to specify both \$GRUB_MENU 477 and \$GRUB_FILE. 478 479 If you specify grub2bls, then you also need to specify \$GRUB_MENU. 480 481 If you specify syslinux, then you may use SYSLINUX to define the syslinux 482 command (defaults to extlinux), and SYSLINUX_PATH to specify the path to 483 the syslinux install (defaults to /boot/extlinux). But you have to specify 484 SYSLINUX_LABEL to define the label to boot to for the test kernel. 485EOF 486 ; 487$config_help{"GRUB_MENU"} = << "EOF" 488 The grub title name for the test kernel to boot 489 (Only mandatory if REBOOT_TYPE = grub or grub2) 490 491 Note, ktest.pl will not update the grub menu.lst, you need to 492 manually add an option for the test. ktest.pl will search 493 the grub menu.lst for this option to find what kernel to 494 reboot into. 495 496 For example, if in the /boot/grub/menu.lst the test kernel title has: 497 title Test Kernel 498 kernel vmlinuz-test 499 GRUB_MENU = Test Kernel 500 501 For grub2, a search of \$GRUB_FILE is performed for the lines 502 that begin with "menuentry". It will not detect submenus. The 503 menu must be a non-nested menu. Add the quotes used in the menu 504 to guarantee your selection, as the first menuentry with the content 505 of \$GRUB_MENU that is found will be used. 506 507 For grub2bls, \$GRUB_MENU is searched on the result of \$GRUB_BLS_GET 508 command for the lines that begin with "title". 509EOF 510 ; 511$config_help{"GRUB_FILE"} = << "EOF" 512 If grub2 is used, the full path for the grub.cfg file is placed 513 here. Use something like /boot/grub2/grub.cfg to search. 514EOF 515 ; 516$config_help{"SYSLINUX_LABEL"} = << "EOF" 517 If syslinux is used, the label that boots the target kernel must 518 be specified with SYSLINUX_LABEL. 519EOF 520 ; 521$config_help{"REBOOT_SCRIPT"} = << "EOF" 522 A script to reboot the target into the test kernel 523 (Only mandatory if REBOOT_TYPE = script) 524EOF 525 ; 526 527# used with process_expression() 528my $d = 0; 529 530# defined before get_test_name() 531my $in_die = 0; 532 533# defined before process_warning_line() 534my $check_build_re = ".*:.*(warning|error|Error):.*"; 535my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})"; 536 537# defined before child_finished() 538my $child_done; 539 540# config_ignore holds the configs that were set (or unset) for 541# a good config and we will ignore these configs for the rest 542# of a config bisect. These configs stay as they were. 543my %config_ignore; 544 545# config_set holds what all configs were set as. 546my %config_set; 547 548# config_off holds the set of configs that the bad config had disabled. 549# We need to record them and set them in the .config when running 550# olddefconfig, because olddefconfig keeps the defaults. 551my %config_off; 552 553# config_off_tmp holds a set of configs to turn off for now 554my @config_off_tmp; 555 556# config_list is the set of configs that are being tested 557my %config_list; 558my %null_config; 559 560my %dependency; 561 562# found above run_config_bisect() 563my $pass = 1; 564 565# found above add_dep() 566 567my %depends; 568my %depcount; 569my $iflevel = 0; 570my @ifdeps; 571 572# prevent recursion 573my %read_kconfigs; 574 575# found above test_this_config() 576my %min_configs; 577my %keep_configs; 578my %save_configs; 579my %processed_configs; 580my %nochange_config; 581 582# 583# These are first defined here, main function later on 584# 585sub run_command; 586sub start_monitor; 587sub end_monitor; 588sub wait_for_monitor; 589 590sub _logit { 591 if (defined($opt{"LOG_FILE"}) && defined(fileno(LOG))) { 592 print LOG @_; 593 } 594} 595 596sub logit { 597 if (defined($opt{"LOG_FILE"})) { 598 _logit @_; 599 } else { 600 print @_; 601 } 602} 603 604sub doprint { 605 print @_; 606 _logit @_; 607} 608 609sub read_prompt { 610 my ($cancel, $prompt) = @_; 611 612 my $ans; 613 614 for (;;) { 615 if ($cancel) { 616 print "$prompt [y/n/C] "; 617 } else { 618 print "$prompt [Y/n] "; 619 } 620 $ans = <STDIN>; 621 chomp $ans; 622 if ($ans =~ /^\s*$/) { 623 if ($cancel) { 624 $ans = "c"; 625 } else { 626 $ans = "y"; 627 } 628 } 629 last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 630 if ($cancel) { 631 last if ($ans =~ /^c$/i); 632 print "Please answer either 'y', 'n' or 'c'.\n"; 633 } else { 634 print "Please answer either 'y' or 'n'.\n"; 635 } 636 } 637 if ($ans =~ /^c/i) { 638 exit; 639 } 640 if ($ans !~ /^y$/i) { 641 return 0; 642 } 643 return 1; 644} 645 646sub read_yn { 647 my ($prompt) = @_; 648 649 return read_prompt 0, $prompt; 650} 651 652sub read_ync { 653 my ($prompt) = @_; 654 655 return read_prompt 1, $prompt; 656} 657 658sub get_mandatory_config { 659 my ($config) = @_; 660 my $ans; 661 662 return if (defined($opt{$config})); 663 664 if (defined($config_help{$config})) { 665 print "\n"; 666 print $config_help{$config}; 667 } 668 669 for (;;) { 670 print "$config = "; 671 if (defined($default{$config}) && length($default{$config})) { 672 print "\[$default{$config}\] "; 673 } 674 $ans = <STDIN>; 675 $ans =~ s/^\s*(.*\S)\s*$/$1/; 676 if ($ans =~ /^\s*$/) { 677 if ($default{$config}) { 678 $ans = $default{$config}; 679 } else { 680 print "Your answer can not be blank\n"; 681 next; 682 } 683 } 684 $entered_configs{$config} = ${ans}; 685 last; 686 } 687} 688 689sub show_time { 690 my ($time) = @_; 691 692 my $hours = 0; 693 my $minutes = 0; 694 695 if ($time > 3600) { 696 $hours = int($time / 3600); 697 $time -= $hours * 3600; 698 } 699 if ($time > 60) { 700 $minutes = int($time / 60); 701 $time -= $minutes * 60; 702 } 703 704 if ($hours > 0) { 705 doprint "$hours hour"; 706 doprint "s" if ($hours > 1); 707 doprint " "; 708 } 709 710 if ($minutes > 0) { 711 doprint "$minutes minute"; 712 doprint "s" if ($minutes > 1); 713 doprint " "; 714 } 715 716 doprint "$time second"; 717 doprint "s" if ($time != 1); 718} 719 720sub print_times { 721 doprint "\n"; 722 if ($build_time) { 723 doprint "Build time: "; 724 show_time($build_time); 725 doprint "\n"; 726 } 727 if ($install_time) { 728 doprint "Install time: "; 729 show_time($install_time); 730 doprint "\n"; 731 } 732 if ($reboot_time) { 733 doprint "Reboot time: "; 734 show_time($reboot_time); 735 doprint "\n"; 736 } 737 if ($test_time) { 738 doprint "Test time: "; 739 show_time($test_time); 740 doprint "\n"; 741 } 742 if ($warning_found) { 743 doprint "\n*** WARNING"; 744 doprint "S" if ($warning_found > 1); 745 doprint " found in build: $warning_found ***\n\n"; 746 } 747 748 # reset for iterations like bisect 749 $build_time = 0; 750 $install_time = 0; 751 $reboot_time = 0; 752 $test_time = 0; 753 $warning_found = 0; 754} 755 756sub get_mandatory_configs { 757 get_mandatory_config("MACHINE"); 758 get_mandatory_config("BUILD_DIR"); 759 get_mandatory_config("OUTPUT_DIR"); 760 761 if ($newconfig) { 762 get_mandatory_config("BUILD_OPTIONS"); 763 } 764 765 # options required for other than just building a kernel 766 if (!$buildonly) { 767 get_mandatory_config("POWER_CYCLE"); 768 get_mandatory_config("CONSOLE"); 769 } 770 771 # options required for install and more 772 if ($buildonly != 1) { 773 get_mandatory_config("SSH_USER"); 774 get_mandatory_config("BUILD_TARGET"); 775 get_mandatory_config("TARGET_IMAGE"); 776 } 777 778 get_mandatory_config("LOCALVERSION"); 779 780 return if ($buildonly); 781 782 my $rtype = $opt{"REBOOT_TYPE"}; 783 784 if (!defined($rtype)) { 785 if (!defined($opt{"GRUB_MENU"})) { 786 get_mandatory_config("REBOOT_TYPE"); 787 $rtype = $entered_configs{"REBOOT_TYPE"}; 788 } else { 789 $rtype = "grub"; 790 } 791 } 792 793 if (($rtype eq "grub") or ($rtype eq "grub2bls")) { 794 get_mandatory_config("GRUB_MENU"); 795 } 796 797 if ($rtype eq "grub2") { 798 get_mandatory_config("GRUB_MENU"); 799 get_mandatory_config("GRUB_FILE"); 800 } 801 802 if ($rtype eq "syslinux") { 803 get_mandatory_config("SYSLINUX_LABEL"); 804 } 805} 806 807sub process_variables { 808 my ($value, $remove_undef) = @_; 809 my $retval = ""; 810 811 # We want to check for '\', and it is just easier 812 # to check the previous character of '$' and not need 813 # to worry if '$' is the first character. By adding 814 # a space to $value, we can just check [^\\]\$ and 815 # it will still work. 816 $value = " $value"; 817 818 while ($value =~ /(.*?[^\\])\$\{([^\{]*?)\}(.*)/) { 819 my $begin = $1; 820 my $var = $2; 821 my $end = $3; 822 # append beginning of value to retval 823 $retval = "$retval$begin"; 824 if ($var =~ s/^shell\s+//) { 825 $retval = `$var`; 826 if ($?) { 827 doprint "WARNING: $var returned an error\n"; 828 } else { 829 chomp $retval; 830 } 831 } elsif (defined($variable{$var})) { 832 $retval = "$retval$variable{$var}"; 833 } elsif (defined($remove_undef) && $remove_undef) { 834 # for if statements, any variable that is not defined, 835 # we simple convert to 0 836 $retval = "${retval}0"; 837 } else { 838 # put back the origin piece, but with $#### to not reprocess it 839 $retval = "$retval\$####\{$var\}"; 840 # This could be an option that is used later, save 841 # it so we don't warn if this option is not one of 842 # ktests options. 843 $used_options{$var} = 1; 844 } 845 $value = "$retval$end"; 846 $retval = ""; 847 } 848 $retval = $value; 849 850 # Convert the saved variables with $####{var} back to ${var} 851 $retval =~ s/\$####/\$/g; 852 853 # remove the space added in the beginning 854 $retval =~ s/ //; 855 856 return "$retval"; 857} 858 859sub set_value { 860 my ($lvalue, $rvalue, $override, $overrides, $name) = @_; 861 862 my $prvalue = process_variables($rvalue); 863 864 if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ && 865 $prvalue !~ /^(config_|)bisect$/ && 866 $prvalue !~ /^build$/ && 867 $prvalue !~ /^make_warnings_file$/ && 868 $buildonly) { 869 870 # Note if a test is something other than build, then we 871 # will need other mandatory options. 872 if ($prvalue ne "install") { 873 $buildonly = 0; 874 } else { 875 # install still limits some mandatory options. 876 $buildonly = 2; 877 } 878 } 879 880 if (defined($opt{$lvalue})) { 881 if (!$override || defined(${$overrides}{$lvalue})) { 882 my $extra = ""; 883 if ($override) { 884 $extra = "In the same override section!\n"; 885 } 886 die "$name: $.: Option $lvalue defined more than once!\n$extra"; 887 } 888 ${$overrides}{$lvalue} = $prvalue; 889 } 890 891 $opt{$lvalue} = $prvalue; 892} 893 894sub set_eval { 895 my ($lvalue, $rvalue, $name) = @_; 896 897 my $prvalue = process_variables($rvalue); 898 my $arr; 899 900 if (defined($evals{$lvalue})) { 901 $arr = $evals{$lvalue}; 902 } else { 903 $arr = []; 904 $evals{$lvalue} = $arr; 905 } 906 907 push @{$arr}, $rvalue; 908} 909 910sub set_variable { 911 my ($lvalue, $rvalue, $command) = @_; 912 913 # Command line variables override all others 914 if (defined($command_tmp_vars{$lvalue})) { 915 return; 916 } 917 918 # If a variable is undefined, treat an unescaped self-reference as empty. 919 if (!defined($variable{$lvalue})) { 920 $rvalue =~ s/(?<!\\)\$\{\Q$lvalue\E\}//g; 921 $rvalue =~ s/^\s+//; 922 $rvalue =~ s/\s+$//; 923 } 924 925 if ($rvalue =~ /^\s*$/) { 926 delete $variable{$lvalue}; 927 } else { 928 $rvalue = process_variables($rvalue); 929 $variable{$lvalue} = $rvalue; 930 } 931 932 if (defined($command)) { 933 $command_tmp_vars{$lvalue} = 1; 934 } 935} 936 937sub process_compare { 938 my ($lval, $cmp, $rval) = @_; 939 940 # remove whitespace 941 942 $lval =~ s/^\s*//; 943 $lval =~ s/\s*$//; 944 945 $rval =~ s/^\s*//; 946 $rval =~ s/\s*$//; 947 948 if ($cmp eq "==") { 949 return $lval eq $rval; 950 } elsif ($cmp eq "!=") { 951 return $lval ne $rval; 952 } elsif ($cmp eq "=~") { 953 return $lval =~ m/$rval/; 954 } elsif ($cmp eq "!~") { 955 return $lval !~ m/$rval/; 956 } 957 958 my $statement = "$lval $cmp $rval"; 959 my $ret = eval $statement; 960 961 # $@ stores error of eval 962 if ($@) { 963 return -1; 964 } 965 966 return $ret; 967} 968 969sub value_defined { 970 my ($val) = @_; 971 972 return defined($variable{$2}) || 973 defined($opt{$2}); 974} 975 976sub process_expression { 977 my ($name, $val) = @_; 978 979 my $c = $d++; 980 981 while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) { 982 my $express = $1; 983 984 if (process_expression($name, $express)) { 985 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /; 986 } else { 987 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /; 988 } 989 } 990 991 $d--; 992 my $OR = "\\|\\|"; 993 my $AND = "\\&\\&"; 994 995 while ($val =~ s/^(.*?)($OR|$AND)//) { 996 my $express = $1; 997 my $op = $2; 998 999 if (process_expression($name, $express)) { 1000 if ($op eq "||") { 1001 return 1; 1002 } 1003 } else { 1004 if ($op eq "&&") { 1005 return 0; 1006 } 1007 } 1008 } 1009 1010 if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) { 1011 my $ret = process_compare($1, $2, $3); 1012 if ($ret < 0) { 1013 die "$name: $.: Unable to process comparison\n"; 1014 } 1015 return $ret; 1016 } 1017 1018 if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) { 1019 if (defined $1) { 1020 return !value_defined($2); 1021 } else { 1022 return value_defined($2); 1023 } 1024 } 1025 1026 if ($val =~ s/^\s*NOT\s+(.*)//) { 1027 my $express = $1; 1028 my $ret = process_expression($name, $express); 1029 return !$ret; 1030 } 1031 1032 if ($val =~ /^\s*0\s*$/) { 1033 return 0; 1034 } elsif ($val =~ /^\s*\d+\s*$/) { 1035 return 1; 1036 } 1037 1038 die ("$name: $.: Undefined content $val in if statement\n"); 1039} 1040 1041sub process_if { 1042 my ($name, $value) = @_; 1043 1044 # Convert variables and replace undefined ones with 0 1045 my $val = process_variables($value, 1); 1046 my $ret = process_expression $name, $val; 1047 1048 return $ret; 1049} 1050 1051sub __read_config { 1052 my ($config, $current_test_num) = @_; 1053 1054 my $in; 1055 open($in, $config) || die "can't read file $config"; 1056 1057 my $name = $config; 1058 $name =~ s,.*/(.*),$1,; 1059 1060 my $test_num = $$current_test_num; 1061 my $default = 1; 1062 my $repeat = 1; 1063 my $num_tests_set = 0; 1064 my $skip = 0; 1065 my $rest; 1066 my $line; 1067 my $test_case = 0; 1068 my $if = 0; 1069 my $if_set = 0; 1070 my $override = 0; 1071 1072 my %overrides; 1073 1074 while (<$in>) { 1075 1076 # ignore blank lines and comments 1077 next if (/^\s*$/ || /\s*\#/); 1078 1079 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) { 1080 1081 my $type = $1; 1082 $rest = $2; 1083 $line = $2; 1084 1085 my $old_test_num; 1086 my $old_repeat; 1087 $override = 0; 1088 1089 if ($type eq "TEST_START") { 1090 if ($num_tests_set) { 1091 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 1092 } 1093 1094 $old_test_num = $test_num; 1095 $old_repeat = $repeat; 1096 1097 $test_num += $repeat; 1098 $default = 0; 1099 $repeat = 1; 1100 } else { 1101 $default = 1; 1102 } 1103 1104 # If SKIP is anywhere in the line, the command will be skipped 1105 if ($rest =~ s/\s+SKIP\b//) { 1106 $skip = 1; 1107 } else { 1108 $test_case = 1; 1109 $skip = 0; 1110 } 1111 1112 if ($rest =~ s/\sELSE\b//) { 1113 if (!$if) { 1114 die "$name: $.: ELSE found with out matching IF section\n$_"; 1115 } 1116 $if = 0; 1117 1118 if ($if_set) { 1119 $skip = 1; 1120 } else { 1121 $skip = 0; 1122 } 1123 } 1124 1125 if ($rest =~ s/\sIF\s+(.*)//) { 1126 if (process_if($name, $1)) { 1127 $if_set = 1; 1128 } else { 1129 $skip = 1; 1130 } 1131 $if = 1; 1132 } else { 1133 $if = 0; 1134 $if_set = 0; 1135 } 1136 1137 if (!$skip) { 1138 if ($type eq "TEST_START") { 1139 if ($rest =~ s/\s+ITERATE\s+(\d+)//) { 1140 $repeat = $1; 1141 $repeat_tests{"$test_num"} = $repeat; 1142 } 1143 } elsif ($rest =~ s/\sOVERRIDE\b//) { 1144 # DEFAULT only 1145 $override = 1; 1146 # Clear previous overrides 1147 %overrides = (); 1148 } 1149 } 1150 1151 if (!$skip && $rest !~ /^\s*$/) { 1152 die "$name: $.: Garbage found after $type\n$_"; 1153 } 1154 1155 if ($skip && $type eq "TEST_START") { 1156 $test_num = $old_test_num; 1157 $repeat = $old_repeat; 1158 } 1159 } elsif (/^\s*ELSE\b(.*)$/) { 1160 if (!$if) { 1161 die "$name: $.: ELSE found with out matching IF section\n$_"; 1162 } 1163 $rest = $1; 1164 if ($if_set) { 1165 $skip = 1; 1166 $rest = ""; 1167 } else { 1168 $skip = 0; 1169 1170 if ($rest =~ /\sIF\s+(.*)/) { 1171 # May be a ELSE IF section. 1172 if (process_if($name, $1)) { 1173 $if_set = 1; 1174 } else { 1175 $skip = 1; 1176 } 1177 $rest = ""; 1178 } else { 1179 $if = 0; 1180 } 1181 } 1182 1183 if ($rest !~ /^\s*$/) { 1184 die "$name: $.: Garbage found after DEFAULTS\n$_"; 1185 } 1186 1187 } elsif (/^\s*INCLUDE\s+(\S+)/) { 1188 1189 next if ($skip); 1190 1191 if (!$default) { 1192 die "$name: $.: INCLUDE can only be done in default sections\n$_"; 1193 } 1194 1195 my $file = process_variables($1); 1196 1197 if ($file !~ m,^/,) { 1198 # check the path of the config file first 1199 if ($config =~ m,(.*)/,) { 1200 if (-f "$1/$file") { 1201 $file = "$1/$file"; 1202 } 1203 } 1204 } 1205 1206 if ( ! -r $file ) { 1207 die "$name: $.: Can't read file $file\n$_"; 1208 } 1209 1210 if (__read_config($file, \$test_num)) { 1211 $test_case = 1; 1212 } 1213 1214 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) { 1215 1216 next if ($skip); 1217 1218 my $lvalue = $1; 1219 my $rvalue = $2; 1220 1221 if ($default || $lvalue =~ /\[\d+\]$/) { 1222 set_eval($lvalue, $rvalue, $name); 1223 } else { 1224 my $val = "$lvalue\[$test_num\]"; 1225 set_eval($val, $rvalue, $name); 1226 } 1227 1228 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 1229 1230 next if ($skip); 1231 1232 my $lvalue = $1; 1233 my $rvalue = $2; 1234 1235 if (!$default && 1236 ($lvalue eq "NUM_TESTS" || 1237 $lvalue eq "LOG_FILE" || 1238 $lvalue eq "CLEAR_LOG")) { 1239 die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 1240 } 1241 1242 if ($lvalue eq "NUM_TESTS") { 1243 if ($test_num) { 1244 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 1245 } 1246 if (!$default) { 1247 die "$name: $.: NUM_TESTS must be set in default section\n"; 1248 } 1249 $num_tests_set = 1; 1250 } 1251 1252 if ($default || $lvalue =~ /\[\d+\]$/) { 1253 set_value($lvalue, $rvalue, $override, \%overrides, $name); 1254 } else { 1255 my $val = "$lvalue\[$test_num\]"; 1256 set_value($val, $rvalue, $override, \%overrides, $name); 1257 1258 if ($repeat > 1) { 1259 $repeats{$val} = $repeat; 1260 } 1261 } 1262 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 1263 next if ($skip); 1264 1265 my $lvalue = $1; 1266 my $rvalue = $2; 1267 1268 # process config variables. 1269 # Config variables are only active while reading the 1270 # config and can be defined anywhere. They also ignore 1271 # TEST_START and DEFAULTS, but are skipped if they are in 1272 # one of these sections that have SKIP defined. 1273 # The save variable can be 1274 # defined multiple times and the new one simply overrides 1275 # the previous one. 1276 set_variable($lvalue, $rvalue); 1277 1278 } else { 1279 die "$name: $.: Garbage found in config\n$_"; 1280 } 1281 } 1282 1283 if ($test_num) { 1284 $test_num += $repeat - 1; 1285 $opt{"NUM_TESTS"} = $test_num; 1286 } 1287 1288 close($in); 1289 1290 $$current_test_num = $test_num; 1291 1292 return $test_case; 1293} 1294 1295sub get_test_case { 1296 print "What test case would you like to run?\n"; 1297 print " (build, install or boot)\n"; 1298 print " Other tests are available but require editing ktest.conf\n"; 1299 print " (see tools/testing/ktest/sample.conf)\n"; 1300 my $ans = <STDIN>; 1301 chomp $ans; 1302 $default{"TEST_TYPE"} = $ans; 1303} 1304 1305sub read_config { 1306 my ($config) = @_; 1307 1308 my $test_case; 1309 my $test_num = 0; 1310 1311 $test_case = __read_config $config, \$test_num; 1312 1313 foreach my $val (@command_vars) { 1314 chomp $val; 1315 my %command_overrides; 1316 if ($val =~ m/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 1317 my $lvalue = $1; 1318 my $rvalue = $2; 1319 1320 set_value($lvalue, $rvalue, 1, \%command_overrides, "COMMAND LINE"); 1321 } else { 1322 die "Invalid option definition '$val'\n"; 1323 } 1324 } 1325 1326 # make sure we have all mandatory configs 1327 get_mandatory_configs; 1328 1329 # was a test specified? 1330 if (!$test_case) { 1331 print "No test case specified.\n"; 1332 get_test_case; 1333 } 1334 1335 # set any defaults 1336 1337 foreach my $default (keys %default) { 1338 if (!defined($opt{$default})) { 1339 $opt{$default} = $default{$default}; 1340 } 1341 } 1342 1343 if ($opt{"IGNORE_UNUSED"} == 1) { 1344 return; 1345 } 1346 1347 my %not_used; 1348 1349 # check if there are any stragglers (typos?) 1350 foreach my $option (keys %opt) { 1351 my $op = $option; 1352 # remove per test labels. 1353 $op =~ s/\[.*\]//; 1354 if (!exists($option_map{$op}) && 1355 !exists($default{$op}) && 1356 !exists($used_options{$op})) { 1357 $not_used{$op} = 1; 1358 } 1359 } 1360 1361 if (%not_used) { 1362 my $s = "s are"; 1363 $s = " is" if (keys %not_used == 1); 1364 print "The following option$s not used; could be a typo:\n"; 1365 foreach my $option (keys %not_used) { 1366 print "$option\n"; 1367 } 1368 print "Set IGNORE_UNUSED = 1 to have ktest ignore unused variables\n"; 1369 if ($dry_run) { 1370 return; 1371 } 1372 if (!read_yn "Do you want to continue?") { 1373 exit -1; 1374 } 1375 } 1376} 1377 1378sub __eval_option { 1379 my ($name, $option, $i) = @_; 1380 1381 # Add space to evaluate the character before $ 1382 $option = " $option"; 1383 my $retval = ""; 1384 my $repeated = 0; 1385 my $parent = 0; 1386 1387 foreach my $test (keys %repeat_tests) { 1388 if ($i >= $test && 1389 $i < $test + $repeat_tests{$test}) { 1390 1391 $repeated = 1; 1392 $parent = $test; 1393 last; 1394 } 1395 } 1396 1397 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 1398 my $start = $1; 1399 my $var = $2; 1400 my $end = $3; 1401 1402 # Append beginning of line 1403 $retval = "$retval$start"; 1404 1405 # If the iteration option OPT[$i] exists, then use that. 1406 # otherwise see if the default OPT (without [$i]) exists. 1407 1408 my $o = "$var\[$i\]"; 1409 my $parento = "$var\[$parent\]"; 1410 1411 # If a variable contains itself, use the default var 1412 if (($var eq $name) && defined($opt{$var})) { 1413 $o = $opt{$var}; 1414 # Only append if the default doesn't contain itself 1415 if ($o !~ m/\$\{$var\}/) { 1416 $retval = "$retval$o"; 1417 } 1418 } elsif (defined($opt{$o})) { 1419 $o = $opt{$o}; 1420 $retval = "$retval$o"; 1421 } elsif ($repeated && defined($opt{$parento})) { 1422 $o = $opt{$parento}; 1423 $retval = "$retval$o"; 1424 } elsif (defined($opt{$var})) { 1425 $o = $opt{$var}; 1426 $retval = "$retval$o"; 1427 } elsif ($var eq "KERNEL_VERSION" && defined($make)) { 1428 # special option KERNEL_VERSION uses kernel version 1429 get_version(); 1430 $retval = "$retval$version"; 1431 } else { 1432 $retval = "$retval\$\{$var\}"; 1433 } 1434 1435 $option = $end; 1436 } 1437 1438 $retval = "$retval$option"; 1439 1440 $retval =~ s/^ //; 1441 1442 return $retval; 1443} 1444 1445sub process_evals { 1446 my ($name, $option, $i) = @_; 1447 1448 my $option_name = "$name\[$i\]"; 1449 my $ev; 1450 1451 my $old_option = $option; 1452 1453 if (defined($evals{$option_name})) { 1454 $ev = $evals{$option_name}; 1455 } elsif (defined($evals{$name})) { 1456 $ev = $evals{$name}; 1457 } else { 1458 return $option; 1459 } 1460 1461 for my $e (@{$ev}) { 1462 eval "\$option =~ $e"; 1463 } 1464 1465 if ($option ne $old_option) { 1466 doprint("$name changed from '$old_option' to '$option'\n"); 1467 } 1468 1469 return $option; 1470} 1471 1472sub eval_option { 1473 my ($name, $option, $i) = @_; 1474 1475 my $prev = ""; 1476 1477 # Since an option can evaluate to another option, 1478 # keep iterating until we do not evaluate any more 1479 # options. 1480 my $r = 0; 1481 while ($prev ne $option) { 1482 # Check for recursive evaluations. 1483 # 100 deep should be more than enough. 1484 if ($r++ > 100) { 1485 die "Over 100 evaluations occurred with $option\n" . 1486 "Check for recursive variables\n"; 1487 } 1488 $prev = $option; 1489 $option = __eval_option($name, $option, $i); 1490 } 1491 1492 $option = process_evals($name, $option, $i); 1493 1494 return $option; 1495} 1496 1497sub reboot { 1498 my ($time) = @_; 1499 my $powercycle = 0; 1500 1501 # test if the machine can be connected to within a few seconds 1502 my $stat = run_ssh("echo check machine status", $connect_timeout); 1503 if (!$stat) { 1504 doprint("power cycle\n"); 1505 $powercycle = 1; 1506 } 1507 1508 if ($powercycle) { 1509 start_monitor; 1510 if (defined($time)) { 1511 # Flush stale console output from the old kernel before power-cycling. 1512 wait_for_monitor 1; 1513 } 1514 1515 run_command "$power_cycle"; 1516 1517 } else { 1518 # Make sure everything has been written to disk 1519 run_ssh("sync", 10); 1520 1521 if (defined($time)) { 1522 start_monitor; 1523 # flush out current monitor 1524 # May contain the reboot success line 1525 wait_for_monitor 1; 1526 } 1527 1528 # try to reboot normally 1529 if (run_command $reboot) { 1530 if (defined($powercycle_after_reboot)) { 1531 sleep $powercycle_after_reboot; 1532 run_command "$power_cycle"; 1533 } 1534 } else { 1535 # nope? power cycle it. 1536 run_command "$power_cycle"; 1537 } 1538 } 1539 1540 if (defined($time)) { 1541 1542 # We only want to get to the new kernel, don't fail 1543 # if we stumble over a call trace. 1544 my $save_ignore_errors = $ignore_errors; 1545 $ignore_errors = 1; 1546 1547 # Look for the good kernel to boot 1548 if (wait_for_monitor($time, "Linux version")) { 1549 # reboot got stuck? 1550 doprint "Reboot did not finish. Forcing power cycle\n"; 1551 run_command "$power_cycle"; 1552 } 1553 1554 $ignore_errors = $save_ignore_errors; 1555 1556 # Still need to wait for the reboot to finish 1557 wait_for_monitor($time, $reboot_success_line); 1558 } 1559 if ($powercycle || $time) { 1560 end_monitor; 1561 } 1562} 1563 1564sub reboot_to_good { 1565 my ($time) = @_; 1566 1567 if (defined($switch_to_good)) { 1568 run_command $switch_to_good; 1569 } 1570 1571 reboot $time; 1572} 1573 1574sub do_not_reboot { 1575 my $i = $iteration; 1576 1577 return $test_type eq "build" || $no_reboot || 1578 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 1579 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build") || 1580 ($test_type eq "config_bisect" && $opt{"CONFIG_BISECT_TYPE[$i]"} eq "build"); 1581} 1582 1583sub get_test_name() { 1584 my $name; 1585 1586 if (defined($test_name)) { 1587 $name = "$test_name:$test_type"; 1588 } else { 1589 $name = $test_type; 1590 } 1591 return $name; 1592} 1593 1594sub run_post_ktest { 1595 my $cmd; 1596 1597 return if ($post_ktest_done); 1598 1599 if (defined($final_post_ktest)) { 1600 $cmd = $final_post_ktest; 1601 } elsif (defined($post_ktest)) { 1602 $cmd = $post_ktest; 1603 } else { 1604 return; 1605 } 1606 1607 my $cp_post_ktest = eval_kernel_version($cmd); 1608 run_command $cp_post_ktest; 1609 $post_ktest_done = 1; 1610} 1611 1612sub dodie { 1613 # avoid recursion 1614 return if ($in_die); 1615 $in_die = 1; 1616 1617 if ($monitor_cnt) { 1618 # restore terminal settings 1619 system("stty $stty_orig"); 1620 } 1621 1622 my $i = $iteration; 1623 1624 doprint "CRITICAL FAILURE... [TEST $i] ", @_, "\n"; 1625 1626 if ($reboot_on_error && !do_not_reboot) { 1627 doprint "REBOOTING\n"; 1628 reboot_to_good; 1629 } elsif ($poweroff_on_error && defined($power_off)) { 1630 doprint "POWERING OFF\n"; 1631 `$power_off`; 1632 } 1633 1634 if (defined($opt{"LOG_FILE"})) { 1635 print " See $opt{LOG_FILE} for more info.\n"; 1636 } 1637 1638 # Fatal paths bypass fail(), so STORE_FAILURES needs to be handled here. 1639 if (defined($store_failures)) { 1640 save_logs("fail", $store_failures); 1641 } 1642 1643 if ($email_on_error) { 1644 my $name = get_test_name; 1645 my $log_file; 1646 1647 if (defined($opt{"LOG_FILE"})) { 1648 my $whence = 2; # End of file 1649 my $log_size = tell LOG; 1650 my $size = $log_size - $test_log_start; 1651 1652 if (defined($mail_max_size)) { 1653 if ($size > $mail_max_size) { 1654 $size = $mail_max_size; 1655 } 1656 } 1657 my $pos = - $size; 1658 $log_file = "$tmpdir/log"; 1659 open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; 1660 open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; 1661 seek(L, $pos, $whence); 1662 while (<L>) { 1663 print O; 1664 } 1665 close O; 1666 close L; 1667 } 1668 1669 send_email("KTEST: critical failure for test $i [$name]", 1670 "Your test started at $script_start_time has failed with:\n@_\n", $log_file); 1671 } 1672 1673 if (defined($post_test)) { 1674 run_command $post_test; 1675 } 1676 run_post_ktest; 1677 1678 die @_, "\n"; 1679} 1680 1681sub create_pty { 1682 my ($ptm, $pts) = @_; 1683 my $tmp; 1684 my $TIOCSPTLCK = 0x40045431; 1685 my $TIOCGPTN = 0x80045430; 1686 1687 sysopen($ptm, "/dev/ptmx", O_RDWR | O_NONBLOCK) or 1688 dodie "Can't open /dev/ptmx"; 1689 1690 # unlockpt() 1691 $tmp = pack("i", 0); 1692 ioctl($ptm, $TIOCSPTLCK, $tmp) or 1693 dodie "ioctl TIOCSPTLCK for /dev/ptmx failed"; 1694 1695 # ptsname() 1696 ioctl($ptm, $TIOCGPTN, $tmp) or 1697 dodie "ioctl TIOCGPTN for /dev/ptmx failed"; 1698 $tmp = unpack("i", $tmp); 1699 1700 sysopen($pts, "/dev/pts/$tmp", O_RDWR | O_NONBLOCK) or 1701 dodie "Can't open /dev/pts/$tmp"; 1702} 1703 1704sub exec_console { 1705 my ($ptm, $pts) = @_; 1706 1707 close($ptm); 1708 1709 close(\*STDIN); 1710 close(\*STDOUT); 1711 close(\*STDERR); 1712 1713 open(\*STDIN, '<&', $pts); 1714 open(\*STDOUT, '>&', $pts); 1715 open(\*STDERR, '>&', $pts); 1716 1717 close($pts); 1718 1719 exec $console or 1720 dodie "Can't open console $console"; 1721} 1722 1723sub open_console { 1724 my ($ptm) = @_; 1725 my $pts = \*PTSFD; 1726 my $pid; 1727 1728 # save terminal settings 1729 $stty_orig = `stty -g`; 1730 1731 # place terminal in cbreak mode so that stdin can be read one character at 1732 # a time without having to wait for a newline 1733 system("stty -icanon -echo -icrnl"); 1734 1735 create_pty($ptm, $pts); 1736 1737 $pid = fork; 1738 1739 if (!$pid) { 1740 # child 1741 exec_console($ptm, $pts) 1742 } 1743 1744 # parent 1745 close($pts); 1746 1747 return $pid; 1748 1749 open(PTSFD, "Stop perl from warning about single use of PTSFD"); 1750} 1751 1752sub close_console { 1753 my ($fp, $pid) = @_; 1754 1755 doprint "kill child process $pid\n"; 1756 kill $close_console_signal, $pid; 1757 1758 doprint "wait for child process $pid to exit\n"; 1759 waitpid($pid, 0); 1760 1761 print "closing!\n"; 1762 close($fp); 1763 1764 # restore terminal settings 1765 system("stty $stty_orig"); 1766} 1767 1768sub start_monitor { 1769 if ($monitor_cnt++) { 1770 return; 1771 } 1772 $monitor_fp = \*MONFD; 1773 $monitor_pid = open_console $monitor_fp; 1774 1775 return; 1776 1777 open(MONFD, "Stop perl from warning about single use of MONFD"); 1778} 1779 1780sub end_monitor { 1781 return if (!defined $console); 1782 if (--$monitor_cnt) { 1783 return; 1784 } 1785 close_console($monitor_fp, $monitor_pid); 1786} 1787 1788sub wait_for_monitor { 1789 my ($time, $stop) = @_; 1790 my $full_line = ""; 1791 my $line; 1792 my $booted = 0; 1793 my $start_time = time; 1794 my $skip_call_trace = 0; 1795 my $bug = 0; 1796 my $bug_ignored = 0; 1797 my $now; 1798 1799 doprint "** Wait for monitor to settle down **\n"; 1800 1801 # read the monitor and wait for the system to calm down 1802 while (!$booted) { 1803 $line = wait_for_input($monitor_fp, $time); 1804 last if (!defined($line)); 1805 print "$line"; 1806 $full_line .= $line; 1807 1808 if (defined($stop) && $full_line =~ /$stop/) { 1809 doprint "wait for monitor detected $stop\n"; 1810 $booted = 1; 1811 } 1812 1813 if ($full_line =~ /\[ backtrace testing \]/) { 1814 $skip_call_trace = 1; 1815 } 1816 1817 if ($full_line =~ /call trace:/i) { 1818 if (!$bug && !$skip_call_trace) { 1819 if ($ignore_errors) { 1820 $bug_ignored = 1; 1821 } else { 1822 $bug = 1; 1823 } 1824 } 1825 } 1826 1827 if ($full_line =~ /\[ end of backtrace testing \]/) { 1828 $skip_call_trace = 0; 1829 } 1830 1831 if ($full_line =~ /Kernel panic -/) { 1832 $bug = 1; 1833 } 1834 1835 if ($line =~ /\n/) { 1836 $full_line = ""; 1837 } 1838 $now = time; 1839 if ($now - $start_time >= $max_monitor_wait) { 1840 doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n"; 1841 return 1; 1842 } 1843 } 1844 print "** Monitor flushed **\n"; 1845 1846 # if stop is defined but wasn't hit, return error 1847 # used by reboot (which wants to see a reboot) 1848 if (defined($stop) && !$booted) { 1849 $bug = 1; 1850 } 1851 return $bug; 1852} 1853 1854sub save_logs { 1855 my ($result, $basedir) = @_; 1856 my @t = localtime; 1857 my $date = sprintf "%04d%02d%02d%02d%02d%02d", 1858 1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1],$t[0]; 1859 1860 my $type = $build_type; 1861 if ($type =~ /useconfig/) { 1862 $type = "useconfig"; 1863 } 1864 1865 my $dir = "$machine-$test_type-$type-$result-$date"; 1866 1867 $dir = "$basedir/$dir"; 1868 1869 if (!-d $dir) { 1870 mkpath($dir) or 1871 dodie "can't create $dir"; 1872 } 1873 1874 my %files = ( 1875 "config" => $output_config, 1876 "buildlog" => $buildlog, 1877 "dmesg" => $dmesg, 1878 "testlog" => $testlog, 1879 ); 1880 1881 if (defined($opt{"LOG_FILE"})) { 1882 if (-f $opt{"LOG_FILE"}) { 1883 cp $opt{"LOG_FILE"}, "$dir/logfile"; 1884 } 1885 } 1886 1887 while (my ($name, $source) = each(%files)) { 1888 if (-f "$source") { 1889 cp "$source", "$dir/$name" or 1890 dodie "failed to copy $source"; 1891 } 1892 } 1893 1894 doprint "*** Saved info to $dir ***\n"; 1895} 1896 1897sub fail { 1898 1899 if ($die_on_failure) { 1900 dodie @_; 1901 } 1902 1903 doprint "FAILED\n"; 1904 1905 my $i = $iteration; 1906 1907 # no need to reboot for just building. 1908 if (!do_not_reboot) { 1909 doprint "REBOOTING\n"; 1910 reboot_to_good $sleep_time; 1911 } 1912 1913 my $name = ""; 1914 1915 if (defined($test_name)) { 1916 $name = " ($test_name)"; 1917 } 1918 1919 print_times; 1920 1921 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1922 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1923 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 1924 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1925 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1926 1927 if (defined($store_failures)) { 1928 save_logs "fail", $store_failures; 1929 } 1930 1931 if (defined($post_test)) { 1932 run_command $post_test; 1933 } 1934 1935 return 1; 1936} 1937 1938sub run_command { 1939 my ($command, $redirect, $timeout) = @_; 1940 my $start_time; 1941 my $end_time; 1942 my $dolog = 0; 1943 my $dord = 0; 1944 my $dostdout = 0; 1945 my $pid; 1946 my $command_orig = $command; 1947 1948 $command =~ s/\$SSH_USER/$ssh_user/g; 1949 $command =~ s/\$MACHINE/$machine/g; 1950 1951 if (!defined($timeout)) { 1952 $timeout = $run_timeout; 1953 } 1954 1955 if (!defined($timeout)) { 1956 $timeout = -1; # tell wait_for_input to wait indefinitely 1957 } 1958 1959 doprint("$command ... "); 1960 $start_time = time; 1961 1962 $pid = open(CMD, "-|", 1963 "sh", "-c", 1964 'command=$1; shift; exec 2>&1; eval "$command"', 1965 "sh", $command) or 1966 (fail "unable to exec $command" and return 0); 1967 1968 if (defined($opt{"LOG_FILE"})) { 1969 $dolog = 1; 1970 } 1971 1972 if (defined($redirect)) { 1973 if ($redirect eq 1) { 1974 $dostdout = 1; 1975 # Have the output of the command on its own line 1976 doprint "\n"; 1977 } else { 1978 open (RD, ">$redirect") or 1979 dodie "failed to write to redirect $redirect"; 1980 $dord = 1; 1981 } 1982 } 1983 1984 my $hit_timeout = 0; 1985 1986 while (1) { 1987 my $fp = \*CMD; 1988 my $line = wait_for_input($fp, $timeout); 1989 if (!defined($line)) { 1990 my $now = time; 1991 if ($timeout >= 0 && (($now - $start_time) >= $timeout)) { 1992 doprint "Hit timeout of $timeout, killing process\n"; 1993 $hit_timeout = 1; 1994 kill 9, $pid; 1995 } 1996 last; 1997 } 1998 print LOG $line if ($dolog); 1999 print RD $line if ($dord); 2000 print $line if ($dostdout); 2001 } 2002 2003 waitpid($pid, 0); 2004 # shift 8 for real exit status 2005 $run_command_status = $? >> 8; 2006 2007 if ($command_orig eq $default{REBOOT} && 2008 $run_command_status == $reboot_return_code) { 2009 $run_command_status = 0; 2010 } 2011 2012 close(CMD); 2013 close(RD) if ($dord); 2014 2015 $end_time = time; 2016 my $delta = $end_time - $start_time; 2017 2018 if ($delta == 1) { 2019 doprint "[1 second] "; 2020 } else { 2021 doprint "[$delta seconds] "; 2022 } 2023 2024 if ($hit_timeout) { 2025 $run_command_status = 1; 2026 } 2027 2028 if ($run_command_status) { 2029 doprint "FAILED!\n"; 2030 } else { 2031 doprint "SUCCESS\n"; 2032 } 2033 2034 return !$run_command_status; 2035} 2036 2037sub run_ssh { 2038 my ($cmd, $timeout) = @_; 2039 my $cp_exec = $ssh_exec; 2040 2041 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 2042 return run_command "$cp_exec", undef , $timeout; 2043} 2044 2045sub run_scp { 2046 my ($src, $dst, $cp_scp) = @_; 2047 2048 $cp_scp =~ s/\$SRC_FILE/$src/g; 2049 $cp_scp =~ s/\$DST_FILE/$dst/g; 2050 2051 return run_command "$cp_scp"; 2052} 2053 2054sub run_scp_install { 2055 my ($src, $dst) = @_; 2056 2057 my $cp_scp = $scp_to_target_install; 2058 2059 return run_scp($src, $dst, $cp_scp); 2060} 2061 2062sub run_scp_mod { 2063 my ($src, $dst) = @_; 2064 2065 my $cp_scp = $scp_to_target; 2066 2067 return run_scp($src, $dst, $cp_scp); 2068} 2069 2070sub _get_grub_index { 2071 2072 my ($command, $target, $skip, $submenu) = @_; 2073 2074 return if (defined($grub_number) && defined($last_grub_menu) && 2075 $last_grub_menu eq $grub_menu && defined($last_machine) && 2076 $last_machine eq $machine); 2077 2078 doprint "Find $reboot_type menu ... "; 2079 $grub_number = -1; 2080 2081 my $ssh_grub = $ssh_exec; 2082 $ssh_grub =~ s,\$SSH_COMMAND,$command,g; 2083 2084 open(IN, "$ssh_grub |") or 2085 dodie "unable to execute $command"; 2086 2087 my $found = 0; 2088 2089 my $submenu_number = 0; 2090 2091 while (<IN>) { 2092 if (/$target/) { 2093 $grub_number++; 2094 $found = 1; 2095 last; 2096 } elsif (defined($submenu) && /$submenu/) { 2097 $submenu_number++; 2098 $grub_number = -1; 2099 } elsif (/$skip/) { 2100 $grub_number++; 2101 } 2102 } 2103 close(IN); 2104 2105 dodie "Could not find '$grub_menu' through $command on $machine" 2106 if (!$found); 2107 if ($submenu_number > 0) { 2108 $grub_number = "$submenu_number>$grub_number"; 2109 } 2110 doprint "$grub_number\n"; 2111 $last_grub_menu = $grub_menu; 2112 $last_machine = $machine; 2113} 2114 2115sub get_grub_index { 2116 2117 my $command; 2118 my $target; 2119 my $skip; 2120 my $submenu; 2121 my $grub_menu_qt; 2122 2123 if ($reboot_type !~ /^grub/) { 2124 return; 2125 } 2126 2127 $grub_menu_qt = quotemeta($grub_menu); 2128 2129 if ($reboot_type eq "grub") { 2130 $command = "cat /boot/grub/menu.lst"; 2131 $target = '^\s*title\s+' . $grub_menu_qt . '\s*$'; 2132 $skip = '^\s*title\s'; 2133 } elsif ($reboot_type eq "grub2") { 2134 $command = "cat $grub_file"; 2135 $target = '^\s*menuentry.*' . $grub_menu_qt; 2136 $skip = '^\s*menuentry\s'; 2137 $submenu = '^\s*submenu\s'; 2138 } elsif ($reboot_type eq "grub2bls") { 2139 $command = $grub_bls_get; 2140 $target = '^title=.*' . $grub_menu_qt; 2141 $skip = '^title='; 2142 } else { 2143 return; 2144 } 2145 2146 _get_grub_index($command, $target, $skip, $submenu); 2147} 2148 2149sub wait_for_input { 2150 my ($fp, $time) = @_; 2151 my $start_time; 2152 my $rin; 2153 my $rout; 2154 my $nr; 2155 my $buf; 2156 my $line; 2157 my $ch; 2158 2159 if (!defined($time)) { 2160 $time = $timeout; 2161 } 2162 2163 if ($time < 0) { 2164 # Negative number means wait indefinitely 2165 undef $time; 2166 } 2167 2168 $rin = ''; 2169 vec($rin, fileno($fp), 1) = 1; 2170 vec($rin, fileno(\*STDIN), 1) = 1; 2171 2172 $start_time = time; 2173 2174 while (1) { 2175 $nr = select($rout=$rin, undef, undef, $time); 2176 2177 last if ($nr <= 0); 2178 2179 # copy data from stdin to the console 2180 if (vec($rout, fileno(\*STDIN), 1) == 1) { 2181 $nr = sysread(\*STDIN, $buf, 1000); 2182 syswrite($fp, $buf, $nr) if ($nr > 0); 2183 } 2184 2185 # The timeout is based on time waiting for the fp data 2186 if (vec($rout, fileno($fp), 1) != 1) { 2187 last if (defined($time) && (time - $start_time > $time)); 2188 next; 2189 } 2190 2191 $line = ""; 2192 2193 # try to read one char at a time 2194 while (sysread $fp, $ch, 1) { 2195 $line .= $ch; 2196 last if ($ch eq "\n"); 2197 } 2198 2199 last if (!length($line)); 2200 2201 return $line; 2202 } 2203 return undef; 2204} 2205 2206sub reboot_to { 2207 if (defined($switch_to_test)) { 2208 run_command $switch_to_test; 2209 } 2210 2211 if ($reboot_type eq "grub") { 2212 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 2213 } elsif (($reboot_type eq "grub2") or ($reboot_type eq "grub2bls")) { 2214 run_ssh "$grub_reboot \"'$grub_number'\""; 2215 } elsif ($reboot_type eq "syslinux") { 2216 run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path"; 2217 } elsif (defined $reboot_script) { 2218 run_command "$reboot_script"; 2219 } 2220 reboot; 2221} 2222 2223sub get_sha1 { 2224 my ($commit) = @_; 2225 2226 doprint "git rev-list --max-count=1 $commit ... "; 2227 my $sha1 = `git rev-list --max-count=1 $commit`; 2228 my $ret = $?; 2229 2230 logit $sha1; 2231 2232 if ($ret) { 2233 doprint "FAILED\n"; 2234 dodie "Failed to get git $commit"; 2235 } 2236 2237 print "SUCCESS\n"; 2238 2239 chomp $sha1; 2240 2241 return $sha1; 2242} 2243 2244sub monitor { 2245 my $booted = 0; 2246 my $bug = 0; 2247 my $bug_ignored = 0; 2248 my $skip_call_trace = 0; 2249 my $loops; 2250 2251 my $start_time = time; 2252 2253 wait_for_monitor 5; 2254 2255 my $line; 2256 my $full_line = ""; 2257 2258 open(DMESG, "> $dmesg") or 2259 dodie "unable to write to $dmesg"; 2260 2261 reboot_to; 2262 2263 my $success_start; 2264 my $failure_start; 2265 my $monitor_start = time; 2266 my $done = 0; 2267 my $version_found = 0; 2268 2269 while (!$done) { 2270 if ($bug && defined($stop_after_failure) && 2271 $stop_after_failure >= 0) { 2272 my $time = $stop_after_failure - (time - $failure_start); 2273 $line = wait_for_input($monitor_fp, $time); 2274 if (!defined($line)) { 2275 doprint "bug timed out after $booted_timeout seconds\n"; 2276 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 2277 last; 2278 } 2279 } elsif ($booted) { 2280 $line = wait_for_input($monitor_fp, $booted_timeout); 2281 if (!defined($line)) { 2282 my $s = $booted_timeout == 1 ? "" : "s"; 2283 doprint "Successful boot found: break after $booted_timeout second$s\n"; 2284 last; 2285 } 2286 } else { 2287 $line = wait_for_input($monitor_fp); 2288 if (!defined($line)) { 2289 my $s = $timeout == 1 ? "" : "s"; 2290 doprint "Timed out after $timeout second$s\n"; 2291 last; 2292 } 2293 } 2294 2295 doprint $line; 2296 print DMESG $line; 2297 2298 # we are not guaranteed to get a full line 2299 $full_line .= $line; 2300 2301 if ($full_line =~ /$success_line/) { 2302 $booted = 1; 2303 $success_start = time; 2304 } 2305 2306 if ($booted && defined($stop_after_success) && 2307 $stop_after_success >= 0) { 2308 my $now = time; 2309 if ($now - $success_start >= $stop_after_success) { 2310 doprint "Test forced to stop after $stop_after_success seconds after success\n"; 2311 last; 2312 } 2313 } 2314 2315 if ($full_line =~ /\[ backtrace testing \]/) { 2316 $skip_call_trace = 1; 2317 } 2318 2319 if ($full_line =~ /call trace:/i) { 2320 if (!$bug && !$skip_call_trace) { 2321 if ($ignore_errors) { 2322 $bug_ignored = 1; 2323 } else { 2324 $bug = 1; 2325 $failure_start = time; 2326 } 2327 } 2328 } 2329 2330 if ($bug && defined($stop_after_failure) && 2331 $stop_after_failure >= 0) { 2332 my $now = time; 2333 if ($now - $failure_start >= $stop_after_failure) { 2334 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 2335 last; 2336 } 2337 } 2338 2339 if ($full_line =~ /\[ end of backtrace testing \]/) { 2340 $skip_call_trace = 0; 2341 } 2342 2343 if ($full_line =~ /Kernel panic -/) { 2344 $failure_start = time; 2345 $bug = 1; 2346 } 2347 2348 # Detect triple faults by testing the banner 2349 if ($full_line =~ /\bLinux version (\S+).*\n/) { 2350 if ($1 eq $version) { 2351 $version_found = 1; 2352 } elsif ($version_found && $detect_triplefault) { 2353 # We already booted into the kernel we are testing, 2354 # but now we booted into another kernel? 2355 # Consider this a triple fault. 2356 doprint "Already booted in Linux kernel $version, but now\n"; 2357 doprint "we booted into Linux kernel $1.\n"; 2358 doprint "Assuming that this is a triple fault.\n"; 2359 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 2360 last; 2361 } 2362 } 2363 2364 if ($line =~ /\n/) { 2365 $full_line = ""; 2366 } 2367 2368 if ($stop_test_after > 0 && !$booted && !$bug) { 2369 if (time - $monitor_start > $stop_test_after) { 2370 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 2371 $done = 1; 2372 } 2373 } 2374 } 2375 2376 my $end_time = time; 2377 $reboot_time = $end_time - $start_time; 2378 2379 close(DMESG); 2380 2381 if ($bug) { 2382 return 0 if ($in_bisect); 2383 fail "failed - got a bug report" and return 0; 2384 } 2385 2386 if (!$booted) { 2387 return 0 if ($in_bisect); 2388 fail "failed - never got a boot prompt." and return 0; 2389 } 2390 2391 if ($bug_ignored) { 2392 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2393 } 2394 2395 return 1; 2396} 2397 2398sub eval_kernel_version { 2399 my ($option) = @_; 2400 2401 $option =~ s/\$KERNEL_VERSION/$version/g; 2402 2403 return $option; 2404} 2405 2406sub do_post_install { 2407 2408 return if (!defined($post_install)); 2409 2410 my $cp_post_install = eval_kernel_version $post_install; 2411 run_command "$cp_post_install" or 2412 dodie "Failed to run post install"; 2413} 2414 2415# Sometimes the reboot fails, and will hang. We try to ssh to the box 2416# and if we fail, we force another reboot, that should powercycle it. 2417sub test_booted { 2418 if (!run_ssh "echo testing connection") { 2419 reboot $sleep_time; 2420 } 2421} 2422 2423sub install { 2424 2425 return if ($no_install); 2426 2427 my $start_time = time; 2428 2429 if (defined($pre_install)) { 2430 my $cp_pre_install = eval_kernel_version $pre_install; 2431 run_command "$cp_pre_install" or 2432 dodie "Failed to run pre install"; 2433 } 2434 2435 my $cp_target = eval_kernel_version $target_image; 2436 2437 test_booted; 2438 2439 run_scp_install "$outputdir/$build_target", "$cp_target" or 2440 dodie "failed to copy image"; 2441 2442 my $install_mods = 0; 2443 2444 # should we process modules? 2445 $install_mods = 0; 2446 open(IN, "$output_config") or dodie("Can't read config file"); 2447 while (<IN>) { 2448 if (/CONFIG_MODULES(=y)?/) { 2449 if (defined($1)) { 2450 $install_mods = 1; 2451 last; 2452 } 2453 } 2454 } 2455 close(IN); 2456 2457 if (!$install_mods) { 2458 do_post_install; 2459 doprint "No modules needed\n"; 2460 my $end_time = time; 2461 $install_time = $end_time - $start_time; 2462 return; 2463 } 2464 2465 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or 2466 dodie "Failed to install modules"; 2467 2468 my $modlib = "/lib/modules/$version"; 2469 my $modtar = "ktest-mods.tar.bz2"; 2470 2471 run_ssh "rm -rf $modlib" or 2472 dodie "failed to remove old mods: $modlib"; 2473 2474 # would be nice if scp -r did not follow symbolic links 2475 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 2476 dodie "making tarball"; 2477 2478 run_scp_mod "$tmpdir/$modtar", "/tmp" or 2479 dodie "failed to copy modules"; 2480 2481 unlink "$tmpdir/$modtar"; 2482 2483 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 2484 dodie "failed to tar modules"; 2485 2486 run_ssh "rm -f /tmp/$modtar"; 2487 2488 do_post_install; 2489 2490 my $end_time = time; 2491 $install_time = $end_time - $start_time; 2492} 2493 2494sub get_version { 2495 # get the release name 2496 return if ($have_version); 2497 doprint "$make kernelrelease ... "; 2498 $version = `$make -s kernelrelease | tail -1`; 2499 if (!length($version)) { 2500 run_command "$make allnoconfig" or return 0; 2501 doprint "$make kernelrelease ... "; 2502 $version = `$make -s kernelrelease | tail -1`; 2503 } 2504 chomp($version); 2505 doprint "$version\n"; 2506 $have_version = 1; 2507} 2508 2509sub start_monitor_and_install { 2510 # Make sure the stable kernel has finished booting 2511 2512 # Install bisects, don't need console 2513 if (defined $console) { 2514 start_monitor; 2515 wait_for_monitor 5; 2516 end_monitor; 2517 } 2518 2519 get_grub_index; 2520 get_version; 2521 install; 2522 2523 start_monitor if (defined $console); 2524 return monitor; 2525} 2526 2527sub process_warning_line { 2528 my ($line) = @_; 2529 2530 chomp $line; 2531 2532 # for distcc heterogeneous systems, some compilers 2533 # do things differently causing warning lines 2534 # to be slightly different. This makes an attempt 2535 # to fixe those issues. 2536 2537 # chop off the index into the line 2538 # using distcc, some compilers give different indexes 2539 # depending on white space 2540 $line =~ s/^(\s*\S+:\d+:)\d+/$1/; 2541 2542 # Some compilers use UTF-8 extended for quotes and some don't. 2543 $line =~ s/$utf8_quote/'/g; 2544 2545 return $line; 2546} 2547 2548# Read buildlog and check against warnings file for any 2549# new warnings. 2550# 2551# Returns 1 if OK 2552# 0 otherwise 2553sub check_buildlog { 2554 my %warnings_list; 2555 2556 # Failed builds should not reboot the target 2557 my $save_no_reboot = $no_reboot; 2558 $no_reboot = 1; 2559 2560 if (defined($warnings_file) && -f $warnings_file) { 2561 open(IN, $warnings_file) or 2562 dodie "Error opening $warnings_file"; 2563 2564 while (<IN>) { 2565 if (/$check_build_re/) { 2566 my $warning = process_warning_line $_; 2567 2568 $warnings_list{$warning} = 1; 2569 } 2570 } 2571 close(IN); 2572 } 2573 2574 open(IN, $buildlog) or dodie "Can't open $buildlog"; 2575 while (<IN>) { 2576 if (/$check_build_re/) { 2577 my $warning = process_warning_line $_; 2578 2579 if (!defined $warnings_list{$warning}) { 2580 $warning_found++; 2581 2582 # If warnings file didn't exist, and WARNINGS_FILE exist, 2583 # then we fail on any warning! 2584 if (defined $warnings_file) { 2585 fail "New warning found (not in $warnings_file)\n$_\n"; 2586 $no_reboot = $save_no_reboot; 2587 return 0; 2588 } 2589 } 2590 } 2591 } 2592 $no_reboot = $save_no_reboot; 2593 close(IN); 2594} 2595 2596sub check_patch_buildlog { 2597 my ($patch) = @_; 2598 2599 my @files = `git show $patch | diffstat -l`; 2600 2601 foreach my $file (@files) { 2602 chomp $file; 2603 } 2604 2605 open(IN, "git show $patch |") or 2606 dodie "failed to show $patch"; 2607 while (<IN>) { 2608 if (m,^--- a/(.*),) { 2609 chomp $1; 2610 $files[$#files] = $1; 2611 } 2612 } 2613 close(IN); 2614 2615 open(IN, $buildlog) or dodie "Can't open $buildlog"; 2616 while (<IN>) { 2617 if (/^\s*(.*?):.*(warning|error)/) { 2618 my $err = $1; 2619 foreach my $file (@files) { 2620 my $fullpath = "$builddir/$file"; 2621 if ($file eq $err || $fullpath eq $err) { 2622 fail "$file built with warnings" and return 0; 2623 } 2624 } 2625 } 2626 } 2627 close(IN); 2628 2629 return 1; 2630} 2631 2632sub apply_min_config { 2633 my $outconfig = "$output_config.new"; 2634 2635 # Read the config file and remove anything that 2636 # is in the force_config hash (from minconfig and others) 2637 # then add the force config back. 2638 2639 doprint "Applying minimum configurations into $output_config.new\n"; 2640 2641 open (OUT, ">$outconfig") or 2642 dodie "Can't create $outconfig"; 2643 2644 if (-f $output_config) { 2645 open (IN, $output_config) or 2646 dodie "Failed to open $output_config"; 2647 while (<IN>) { 2648 if (/^(# )?(CONFIG_[^\s=]*)/) { 2649 next if (defined($force_config{$2})); 2650 } 2651 print OUT; 2652 } 2653 close IN; 2654 } 2655 foreach my $config (keys %force_config) { 2656 print OUT "$force_config{$config}\n"; 2657 } 2658 close OUT; 2659 2660 run_command "mv $outconfig $output_config"; 2661} 2662 2663sub make_oldconfig { 2664 2665 my @force_list = keys %force_config; 2666 2667 if ($#force_list >= 0) { 2668 apply_min_config; 2669 } 2670 2671 if (!run_command "$make olddefconfig") { 2672 # Perhaps olddefconfig doesn't exist in this version of the kernel 2673 # try oldnoconfig 2674 doprint "olddefconfig failed, trying make oldnoconfig\n"; 2675 if (!run_command "$make oldnoconfig") { 2676 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 2677 # try a yes '' | oldconfig 2678 run_command "yes '' | $make oldconfig" or 2679 dodie "failed make config oldconfig"; 2680 } 2681 } 2682} 2683 2684# read a config file and use this to force new configs. 2685sub load_force_config { 2686 my ($config) = @_; 2687 2688 doprint "Loading force configs from $config\n"; 2689 open(IN, $config) or 2690 dodie "failed to read $config"; 2691 while (<IN>) { 2692 chomp; 2693 if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 2694 $force_config{$1} = $_; 2695 } elsif (/^# (CONFIG_\S*) is not set/) { 2696 $force_config{$1} = $_; 2697 } 2698 } 2699 close IN; 2700} 2701 2702sub build { 2703 my ($type) = @_; 2704 2705 unlink $buildlog; 2706 2707 my $start_time = time; 2708 2709 # Failed builds should not reboot the target 2710 my $save_no_reboot = $no_reboot; 2711 $no_reboot = 1; 2712 2713 # Calculate a new version from here. 2714 $have_version = 0; 2715 2716 if (defined($pre_build)) { 2717 my $ret = run_command $pre_build; 2718 if (!$ret && defined($pre_build_die) && 2719 $pre_build_die) { 2720 dodie "failed to pre_build\n"; 2721 } 2722 } 2723 2724 if ($type =~ /^useconfig:(.*)/) { 2725 run_command "cp $1 $output_config" or 2726 dodie "could not copy $1 to .config"; 2727 2728 $type = "oldconfig"; 2729 } 2730 2731 # old config can ask questions 2732 if ($type eq "oldconfig") { 2733 $type = "olddefconfig"; 2734 2735 # allow for empty configs 2736 run_command "touch $output_config"; 2737 2738 if (!$noclean) { 2739 run_command "mv $output_config $outputdir/config_temp" or 2740 dodie "moving .config"; 2741 2742 run_command "$make mrproper" or dodie "make mrproper"; 2743 2744 run_command "mv $outputdir/config_temp $output_config" or 2745 dodie "moving config_temp"; 2746 } 2747 } elsif (!$noclean) { 2748 unlink "$output_config"; 2749 run_command "$make mrproper" or 2750 dodie "make mrproper"; 2751 } 2752 2753 # add something to distinguish this build 2754 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 2755 print OUT "$localversion\n"; 2756 close(OUT); 2757 2758 if (defined($minconfig)) { 2759 load_force_config($minconfig); 2760 } 2761 2762 if ($type ne "olddefconfig") { 2763 run_command "$make $type" or 2764 dodie "failed make config"; 2765 } 2766 # Run old config regardless, to enforce min configurations 2767 make_oldconfig; 2768 2769 if (not defined($build_options)){ 2770 $build_options = ""; 2771 } 2772 my $build_ret = run_command "$make $build_options", $buildlog; 2773 2774 if (defined($post_build)) { 2775 # Because a post build may change the kernel version 2776 # do it now. 2777 get_version; 2778 my $ret = run_command $post_build; 2779 if (!$ret && defined($post_build_die) && 2780 $post_build_die) { 2781 dodie "failed to post_build\n"; 2782 } 2783 } 2784 2785 if (!$build_ret) { 2786 # bisect may need this to pass 2787 if ($in_bisect) { 2788 $no_reboot = $save_no_reboot; 2789 return 0; 2790 } 2791 fail "failed build" and return 0; 2792 } 2793 2794 $no_reboot = $save_no_reboot; 2795 2796 my $end_time = time; 2797 $build_time = $end_time - $start_time; 2798 2799 return 1; 2800} 2801 2802sub halt { 2803 if (!run_ssh "halt" or defined($power_off)) { 2804 if (defined($poweroff_after_halt)) { 2805 sleep $poweroff_after_halt; 2806 run_command "$power_off"; 2807 } 2808 } else { 2809 # nope? the zap it! 2810 run_command "$power_off"; 2811 } 2812} 2813 2814sub success { 2815 my ($i) = @_; 2816 2817 $successes++; 2818 2819 my $name = ""; 2820 2821 if (defined($test_name)) { 2822 $name = " ($test_name)"; 2823 } 2824 2825 print_times; 2826 2827 doprint "\n\n"; 2828 doprint "*******************************************\n"; 2829 doprint "*******************************************\n"; 2830 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 2831 doprint "*******************************************\n"; 2832 doprint "*******************************************\n"; 2833 2834 if (defined($store_successes)) { 2835 save_logs "success", $store_successes; 2836 } 2837 2838 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 2839 doprint "Reboot and wait $sleep_time seconds\n"; 2840 reboot_to_good $sleep_time; 2841 } 2842 2843 if (defined($post_test)) { 2844 run_command $post_test; 2845 } 2846} 2847 2848sub answer_bisect { 2849 for (;;) { 2850 doprint "Pass, fail, or skip? [p/f/s]"; 2851 my $ans = <STDIN>; 2852 chomp $ans; 2853 if ($ans eq "p" || $ans eq "P") { 2854 return 1; 2855 } elsif ($ans eq "f" || $ans eq "F") { 2856 return 0; 2857 } elsif ($ans eq "s" || $ans eq "S") { 2858 return -1; 2859 } else { 2860 print "Please answer 'p', 'f', or 's'\n"; 2861 } 2862 } 2863} 2864 2865sub child_run_test { 2866 2867 # child should have no power 2868 $reboot_on_error = 0; 2869 $poweroff_on_error = 0; 2870 $die_on_failure = 1; 2871 2872 run_command $run_test, $testlog; 2873 2874 exit $run_command_status; 2875} 2876 2877sub child_finished { 2878 $child_done = 1; 2879} 2880 2881sub do_run_test { 2882 my $child_pid; 2883 my $child_exit; 2884 my $line; 2885 my $full_line; 2886 my $bug = 0; 2887 my $bug_ignored = 0; 2888 2889 my $start_time = time; 2890 2891 wait_for_monitor 1; 2892 2893 doprint "run test $run_test\n"; 2894 2895 $child_done = 0; 2896 2897 $SIG{CHLD} = qw(child_finished); 2898 2899 $child_pid = fork; 2900 2901 child_run_test if (!$child_pid); 2902 2903 $full_line = ""; 2904 2905 do { 2906 $line = wait_for_input($monitor_fp, 1); 2907 if (defined($line)) { 2908 2909 # we are not guaranteed to get a full line 2910 $full_line .= $line; 2911 doprint $line; 2912 2913 if ($full_line =~ /call trace:/i) { 2914 if ($ignore_errors) { 2915 $bug_ignored = 1; 2916 } else { 2917 $bug = 1; 2918 } 2919 } 2920 2921 if ($full_line =~ /Kernel panic -/) { 2922 $bug = 1; 2923 } 2924 2925 if ($line =~ /\n/) { 2926 $full_line = ""; 2927 } 2928 } 2929 } while (!$child_done && !$bug); 2930 2931 if (!$bug && $bug_ignored) { 2932 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2933 } 2934 2935 if ($bug) { 2936 my $failure_start = time; 2937 my $now; 2938 do { 2939 $line = wait_for_input($monitor_fp, 1); 2940 if (defined($line)) { 2941 doprint $line; 2942 } 2943 $now = time; 2944 if ($now - $failure_start >= $stop_after_failure) { 2945 last; 2946 } 2947 } while (defined($line)); 2948 2949 doprint "Detected kernel crash!\n"; 2950 # kill the child with extreme prejudice 2951 kill 9, $child_pid; 2952 } 2953 2954 waitpid $child_pid, 0; 2955 $child_exit = $? >> 8; 2956 2957 my $end_time = time; 2958 $test_time = $end_time - $start_time; 2959 2960 if (!$bug && $in_bisect) { 2961 if (defined($bisect_ret_good)) { 2962 if ($child_exit == $bisect_ret_good) { 2963 return 1; 2964 } 2965 } 2966 if (defined($bisect_ret_skip)) { 2967 if ($child_exit == $bisect_ret_skip) { 2968 return -1; 2969 } 2970 } 2971 if (defined($bisect_ret_abort)) { 2972 if ($child_exit == $bisect_ret_abort) { 2973 fail "test abort" and return -2; 2974 } 2975 } 2976 if (defined($bisect_ret_bad)) { 2977 if ($child_exit == $bisect_ret_skip) { 2978 return 0; 2979 } 2980 } 2981 if (defined($bisect_ret_default)) { 2982 if ($bisect_ret_default eq "good") { 2983 return 1; 2984 } elsif ($bisect_ret_default eq "bad") { 2985 return 0; 2986 } elsif ($bisect_ret_default eq "skip") { 2987 return -1; 2988 } elsif ($bisect_ret_default eq "abort") { 2989 return -2; 2990 } else { 2991 fail "unknown default action: $bisect_ret_default" 2992 and return -2; 2993 } 2994 } 2995 } 2996 2997 if ($bug || $child_exit) { 2998 return 0 if $in_bisect; 2999 fail "test failed" and return 0; 3000 } 3001 return 1; 3002} 3003 3004sub run_git_bisect { 3005 my ($command) = @_; 3006 3007 doprint "$command ... "; 3008 3009 my $output = `$command 2>&1`; 3010 my $ret = $?; 3011 3012 logit $output; 3013 3014 if ($ret) { 3015 doprint "FAILED\n"; 3016 dodie "Failed to git bisect"; 3017 } 3018 3019 doprint "SUCCESS\n"; 3020 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 3021 doprint "$1 [$2]\n"; 3022 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 3023 $bisect_bad_commit = $1; 3024 doprint "Found bad commit... $1\n"; 3025 return 0; 3026 } else { 3027 # we already logged it, just print it now. 3028 print $output; 3029 } 3030 3031 return 1; 3032} 3033 3034sub bisect_reboot { 3035 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 3036 reboot_to_good $bisect_sleep_time; 3037} 3038 3039# returns 1 on success, 0 on failure, -1 on skip 3040sub run_bisect_test { 3041 my ($type, $buildtype) = @_; 3042 3043 my $failed = 0; 3044 my $result; 3045 3046 $in_bisect = 1; 3047 3048 build $buildtype or $failed = 1; 3049 3050 if ($type ne "build") { 3051 if ($failed && $bisect_skip) { 3052 $in_bisect = 0; 3053 return -1; 3054 } 3055 dodie "Failed on build" if $failed; 3056 3057 # Now boot the box 3058 start_monitor_and_install or $failed = 1; 3059 3060 if ($type ne "boot") { 3061 if ($failed && $bisect_skip) { 3062 end_monitor; 3063 bisect_reboot; 3064 $in_bisect = 0; 3065 return -1; 3066 } 3067 dodie "Failed on boot" if $failed; 3068 3069 do_run_test or $failed = 1; 3070 } 3071 end_monitor; 3072 } 3073 3074 if ($failed) { 3075 $result = 0; 3076 } else { 3077 $result = 1; 3078 } 3079 3080 # reboot the box to a kernel we can ssh to 3081 if ($type ne "build") { 3082 bisect_reboot; 3083 } 3084 $in_bisect = 0; 3085 3086 return $result; 3087} 3088 3089sub run_bisect { 3090 my ($type) = @_; 3091 my $buildtype = "oldconfig"; 3092 3093 # We should have a minconfig to use? 3094 if (defined($minconfig)) { 3095 $buildtype = "useconfig:$minconfig"; 3096 } 3097 3098 # If the user sets bisect_tries to less than 1, then no tries 3099 # is a success. 3100 my $ret = 1; 3101 3102 # Still let the user manually decide that though. 3103 if ($bisect_tries < 1 && $bisect_manual) { 3104 $ret = answer_bisect; 3105 } 3106 3107 for (my $i = 0; $i < $bisect_tries; $i++) { 3108 if ($bisect_tries > 1) { 3109 my $t = $i + 1; 3110 doprint("Running bisect trial $t of $bisect_tries:\n"); 3111 } 3112 $ret = run_bisect_test $type, $buildtype; 3113 3114 if ($bisect_manual) { 3115 $ret = answer_bisect; 3116 } 3117 3118 last if (!$ret); 3119 } 3120 3121 # Are we looking for where it worked, not failed? 3122 if ($reverse_bisect && $ret >= 0) { 3123 $ret = !$ret; 3124 } 3125 3126 if ($ret > 0) { 3127 return "good"; 3128 } elsif ($ret == 0) { 3129 return "bad"; 3130 } elsif ($bisect_skip) { 3131 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 3132 return "skip"; 3133 } 3134} 3135 3136sub update_bisect_replay { 3137 my $tmp_log = "$tmpdir/ktest_bisect_log"; 3138 run_command "git bisect log > $tmp_log" or 3139 dodie "can't create bisect log"; 3140 return $tmp_log; 3141} 3142 3143sub bisect { 3144 my ($i) = @_; 3145 3146 my $result; 3147 3148 dodie "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good)); 3149 dodie "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad)); 3150 dodie "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type)); 3151 3152 my $good = $bisect_good; 3153 my $bad = $bisect_bad; 3154 my $type = $bisect_type; 3155 my $start = $bisect_start; 3156 my $replay = $bisect_replay; 3157 my $start_files = $bisect_files; 3158 3159 if (defined($start_files)) { 3160 $start_files = " -- " . $start_files; 3161 } else { 3162 $start_files = ""; 3163 } 3164 3165 # convert to true sha1's 3166 $good = get_sha1($good); 3167 $bad = get_sha1($bad); 3168 3169 if (defined($bisect_reverse) && $bisect_reverse == 1) { 3170 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 3171 $reverse_bisect = 1; 3172 } else { 3173 $reverse_bisect = 0; 3174 } 3175 3176 # Can't have a test without having a test to run 3177 if ($type eq "test" && !defined($run_test)) { 3178 $type = "boot"; 3179 } 3180 3181 # Check if a bisect was running 3182 my $bisect_start_file = "$builddir/.git/BISECT_START"; 3183 3184 my $check = $bisect_check; 3185 my $do_check = defined($check) && $check ne "0"; 3186 3187 if ( -f $bisect_start_file ) { 3188 print "Bisect in progress found\n"; 3189 if ($do_check) { 3190 print " If you say yes, then no checks of good or bad will be done\n"; 3191 } 3192 if (defined($replay)) { 3193 print "** BISECT_REPLAY is defined in config file **"; 3194 print " Ignore config option and perform new git bisect log?\n"; 3195 if (read_ync " (yes, no, or cancel) ") { 3196 $replay = update_bisect_replay; 3197 $do_check = 0; 3198 } 3199 } elsif (read_yn "read git log and continue?") { 3200 $replay = update_bisect_replay; 3201 $do_check = 0; 3202 } 3203 } 3204 3205 if ($do_check) { 3206 # get current HEAD 3207 my $head = get_sha1("HEAD"); 3208 3209 if ($check ne "good") { 3210 doprint "TESTING BISECT BAD [$bad]\n"; 3211 run_command "git checkout $bad" or 3212 dodie "Failed to checkout $bad"; 3213 3214 $result = run_bisect $type; 3215 3216 if ($result ne "bad") { 3217 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 3218 } 3219 } 3220 3221 if ($check ne "bad") { 3222 doprint "TESTING BISECT GOOD [$good]\n"; 3223 run_command "git checkout $good" or 3224 dodie "Failed to checkout $good"; 3225 3226 $result = run_bisect $type; 3227 3228 if ($result ne "good") { 3229 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 3230 } 3231 } 3232 3233 # checkout where we started 3234 run_command "git checkout $head" or 3235 dodie "Failed to checkout $head"; 3236 } 3237 3238 run_command "git bisect start$start_files" or 3239 dodie "could not start bisect"; 3240 3241 if (defined($replay)) { 3242 run_command "git bisect replay $replay" or 3243 dodie "failed to run replay"; 3244 } else { 3245 run_command "git bisect good $good" or 3246 dodie "could not set bisect good to $good"; 3247 3248 run_git_bisect "git bisect bad $bad" or 3249 dodie "could not set bisect bad to $bad"; 3250 } 3251 3252 if (defined($start)) { 3253 run_command "git checkout $start" or 3254 dodie "failed to checkout $start"; 3255 } 3256 3257 my $test; 3258 do { 3259 $result = run_bisect $type; 3260 $test = run_git_bisect "git bisect $result"; 3261 print_times; 3262 } while ($test); 3263 3264 run_command "git bisect log" or 3265 dodie "could not capture git bisect log"; 3266 3267 run_command "git bisect reset" or 3268 dodie "could not reset git bisect"; 3269 3270 doprint "Bad commit was [$bisect_bad_commit]\n"; 3271 3272 success $i; 3273} 3274 3275sub assign_configs { 3276 my ($hash, $config) = @_; 3277 3278 doprint "Reading configs from $config\n"; 3279 3280 open (IN, $config) or 3281 dodie "Failed to read $config"; 3282 3283 while (<IN>) { 3284 chomp; 3285 if (/^((CONFIG\S*)=.*)/) { 3286 ${$hash}{$2} = $1; 3287 } elsif (/^(# (CONFIG\S*) is not set)/) { 3288 ${$hash}{$2} = $1; 3289 } 3290 } 3291 3292 close(IN); 3293} 3294 3295sub process_config_ignore { 3296 my ($config) = @_; 3297 3298 assign_configs \%config_ignore, $config; 3299} 3300 3301sub get_dependencies { 3302 my ($config) = @_; 3303 3304 my $arr = $dependency{$config}; 3305 if (!defined($arr)) { 3306 return (); 3307 } 3308 3309 my @deps = @{$arr}; 3310 3311 foreach my $dep (@{$arr}) { 3312 print "ADD DEP $dep\n"; 3313 @deps = (@deps, get_dependencies $dep); 3314 } 3315 3316 return @deps; 3317} 3318 3319sub save_config { 3320 my ($pc, $file) = @_; 3321 3322 my %configs = %{$pc}; 3323 3324 doprint "Saving configs into $file\n"; 3325 3326 open(OUT, ">$file") or dodie "Can not write to $file"; 3327 3328 foreach my $config (keys %configs) { 3329 print OUT "$configs{$config}\n"; 3330 } 3331 close(OUT); 3332} 3333 3334sub create_config { 3335 my ($name, $pc) = @_; 3336 3337 doprint "Creating old config from $name configs\n"; 3338 3339 save_config $pc, $output_config; 3340 3341 make_oldconfig; 3342} 3343 3344sub run_config_bisect_test { 3345 my ($type) = @_; 3346 3347 my $ret = run_bisect_test $type, "oldconfig"; 3348 3349 if ($bisect_manual) { 3350 $ret = answer_bisect; 3351 } 3352 3353 return $ret; 3354} 3355 3356sub config_bisect_end { 3357 my ($good, $bad) = @_; 3358 my $diffexec = "diff -u"; 3359 3360 if (-f "$builddir/scripts/diffconfig") { 3361 $diffexec = "$builddir/scripts/diffconfig"; 3362 } 3363 doprint "\n\n***************************************\n"; 3364 doprint "No more config bisecting possible.\n"; 3365 run_command "$diffexec $good $bad", 1; 3366 doprint "***************************************\n\n"; 3367} 3368 3369sub run_config_bisect { 3370 my ($good, $bad, $last_result) = @_; 3371 my $reset = ""; 3372 my $cmd; 3373 my $ret; 3374 3375 if (!length($last_result)) { 3376 $reset = "-r"; 3377 } 3378 run_command "$config_bisect_exec $reset -b $outputdir $good $bad $last_result", 1; 3379 3380 # config-bisect returns: 3381 # 0 if there is more to bisect 3382 # 1 for finding a good config 3383 # 2 if it can not find any more configs 3384 # -1 (255) on error 3385 if ($run_command_status) { 3386 return $run_command_status; 3387 } 3388 3389 $ret = run_config_bisect_test $config_bisect_type; 3390 if ($ret) { 3391 doprint "NEW GOOD CONFIG ($pass)\n"; 3392 system("cp $output_config $tmpdir/good_config.tmp.$pass"); 3393 $pass++; 3394 # Return 3 for good config 3395 return 3; 3396 } else { 3397 doprint "NEW BAD CONFIG ($pass)\n"; 3398 system("cp $output_config $tmpdir/bad_config.tmp.$pass"); 3399 $pass++; 3400 # Return 4 for bad config 3401 return 4; 3402 } 3403} 3404 3405sub config_bisect { 3406 my ($i) = @_; 3407 3408 my $good_config; 3409 my $bad_config; 3410 3411 my $type = $config_bisect_type; 3412 my $ret; 3413 3414 $bad_config = $config_bisect; 3415 3416 if (defined($config_bisect_good)) { 3417 $good_config = $config_bisect_good; 3418 } elsif (defined($minconfig)) { 3419 $good_config = $minconfig; 3420 } else { 3421 doprint "No config specified, checking if defconfig works"; 3422 $ret = run_bisect_test $type, "defconfig"; 3423 if (!$ret) { 3424 fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD"; 3425 return 1; 3426 } 3427 $good_config = $output_config; 3428 } 3429 3430 if (!defined($config_bisect_exec)) { 3431 # First check the location that ktest.pl ran 3432 my @locations = ( 3433 "$pwd/config-bisect.pl", 3434 "$dirname/config-bisect.pl", 3435 "$builddir/tools/testing/ktest/config-bisect.pl", 3436 undef ); 3437 foreach my $loc (@locations) { 3438 doprint "loc = $loc\n"; 3439 $config_bisect_exec = $loc; 3440 last if (defined($config_bisect_exec && -x $config_bisect_exec)); 3441 } 3442 if (!defined($config_bisect_exec)) { 3443 fail "Could not find an executable config-bisect.pl\n", 3444 " Set CONFIG_BISECT_EXEC to point to config-bisect.pl"; 3445 return 1; 3446 } 3447 } 3448 3449 # we don't want min configs to cause issues here. 3450 doprint "Disabling 'MIN_CONFIG' for this test\n"; 3451 undef $minconfig; 3452 3453 my %good_configs; 3454 my %bad_configs; 3455 my %tmp_configs; 3456 3457 if (-f "$tmpdir/good_config.tmp" || -f "$tmpdir/bad_config.tmp") { 3458 if (read_yn "Interrupted config-bisect. Continue (n - will start new)?") { 3459 if (-f "$tmpdir/good_config.tmp") { 3460 $good_config = "$tmpdir/good_config.tmp"; 3461 } else { 3462 $good_config = "$tmpdir/good_config"; 3463 } 3464 if (-f "$tmpdir/bad_config.tmp") { 3465 $bad_config = "$tmpdir/bad_config.tmp"; 3466 } else { 3467 $bad_config = "$tmpdir/bad_config"; 3468 } 3469 } 3470 } 3471 doprint "Run good configs through make oldconfig\n"; 3472 assign_configs \%tmp_configs, $good_config; 3473 create_config "$good_config", \%tmp_configs; 3474 $good_config = "$tmpdir/good_config"; 3475 system("cp $output_config $good_config") == 0 or dodie "cp good config"; 3476 3477 doprint "Run bad configs through make oldconfig\n"; 3478 assign_configs \%tmp_configs, $bad_config; 3479 create_config "$bad_config", \%tmp_configs; 3480 $bad_config = "$tmpdir/bad_config"; 3481 system("cp $output_config $bad_config") == 0 or dodie "cp bad config"; 3482 3483 if (defined($config_bisect_check) && $config_bisect_check ne "0") { 3484 if ($config_bisect_check ne "good") { 3485 doprint "Testing bad config\n"; 3486 3487 $ret = run_bisect_test $type, "useconfig:$bad_config"; 3488 if ($ret) { 3489 fail "Bad config succeeded when expected to fail!"; 3490 return 0; 3491 } 3492 } 3493 if ($config_bisect_check ne "bad") { 3494 doprint "Testing good config\n"; 3495 3496 $ret = run_bisect_test $type, "useconfig:$good_config"; 3497 if (!$ret) { 3498 fail "Good config failed when expected to succeed!"; 3499 return 0; 3500 } 3501 } 3502 } 3503 3504 my $last_run = ""; 3505 3506 do { 3507 $ret = run_config_bisect $good_config, $bad_config, $last_run; 3508 if ($ret == 3) { 3509 $last_run = "good"; 3510 } elsif ($ret == 4) { 3511 $last_run = "bad"; 3512 } 3513 print_times; 3514 } while ($ret == 3 || $ret == 4); 3515 3516 if ($ret == 2) { 3517 config_bisect_end "$good_config.tmp", "$bad_config.tmp"; 3518 } 3519 3520 return $ret if ($ret < 0); 3521 3522 success $i; 3523} 3524 3525sub patchcheck_reboot { 3526 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 3527 reboot_to_good $patchcheck_sleep_time; 3528} 3529 3530sub patchcheck { 3531 my ($i) = @_; 3532 3533 dodie "PATCHCHECK_START[$i] not defined\n" 3534 if (!defined($patchcheck_start)); 3535 dodie "PATCHCHECK_TYPE[$i] not defined\n" 3536 if (!defined($patchcheck_type)); 3537 3538 my $start = $patchcheck_start; 3539 3540 my $cherry = $patchcheck_cherry; 3541 if (!defined($cherry)) { 3542 $cherry = 0; 3543 } 3544 3545 my $end = "HEAD"; 3546 if (defined($patchcheck_end)) { 3547 $end = $patchcheck_end; 3548 } elsif ($cherry) { 3549 dodie "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n"; 3550 } 3551 3552 # Get the true sha1's since we can use things like HEAD~3 3553 $start = get_sha1($start); 3554 $end = get_sha1($end); 3555 3556 my $type = $patchcheck_type; 3557 3558 # Can't have a test without having a test to run 3559 if ($type eq "test" && !defined($run_test)) { 3560 $type = "boot"; 3561 } 3562 3563 if ($cherry) { 3564 open (IN, "git cherry -v $start $end|") or 3565 dodie "could not get git list"; 3566 } else { 3567 open (IN, "git log --pretty=oneline $end|") or 3568 dodie "could not get git list"; 3569 } 3570 3571 my @list; 3572 3573 while (<IN>) { 3574 chomp; 3575 # git cherry adds a '+' we want to remove 3576 s/^\+ //; 3577 $list[$#list+1] = $_; 3578 last if (/^$start/); 3579 } 3580 close(IN); 3581 3582 if (!$cherry) { 3583 if ($list[$#list] !~ /^$start/) { 3584 fail "SHA1 $start not found"; 3585 } 3586 3587 # go backwards in the list 3588 @list = reverse @list; 3589 } 3590 3591 my %skip_list; 3592 my $will_skip = 0; 3593 3594 if (defined($patchcheck_skip)) { 3595 foreach my $s (split /\s+/, $patchcheck_skip) { 3596 $s = `git log --pretty=oneline $s~1..$s`; 3597 $s =~ s/^(\S+).*/$1/; 3598 chomp $s; 3599 $skip_list{$s} = 1; 3600 $will_skip++; 3601 } 3602 } 3603 3604 doprint("Going to test the following commits:\n"); 3605 foreach my $l (@list) { 3606 my $sha1 = $l; 3607 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 3608 next if (defined($skip_list{$sha1})); 3609 doprint "$l\n"; 3610 } 3611 3612 if ($will_skip) { 3613 doprint("\nSkipping the following commits:\n"); 3614 foreach my $l (@list) { 3615 my $sha1 = $l; 3616 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 3617 next if (!defined($skip_list{$sha1})); 3618 doprint "$l\n"; 3619 } 3620 } 3621 3622 my $save_clean = $noclean; 3623 my %ignored_warnings; 3624 3625 if (defined($ignore_warnings)) { 3626 foreach my $sha1 (split /\s+/, $ignore_warnings) { 3627 $ignored_warnings{$sha1} = 1; 3628 } 3629 } 3630 3631 $in_patchcheck = 1; 3632 foreach my $item (@list) { 3633 my $sha1 = $item; 3634 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 3635 3636 if (defined($skip_list{$sha1})) { 3637 doprint "\nSkipping \"$item\"\n\n"; 3638 next; 3639 } 3640 3641 doprint "\nProcessing commit \"$item\"\n\n"; 3642 3643 run_command "git checkout $sha1" or 3644 dodie "Failed to checkout $sha1"; 3645 3646 # only clean on the first and last patch 3647 if ($item eq $list[0] || 3648 $item eq $list[$#list]) { 3649 $noclean = $save_clean; 3650 } else { 3651 $noclean = 1; 3652 } 3653 3654 if (defined($minconfig)) { 3655 build "useconfig:$minconfig" or return 0; 3656 } else { 3657 # ?? no config to use? 3658 build "oldconfig" or return 0; 3659 } 3660 3661 # No need to do per patch checking if warnings file exists 3662 if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) { 3663 check_patch_buildlog $sha1 or return 0; 3664 } 3665 3666 check_buildlog or return 0; 3667 3668 next if ($type eq "build"); 3669 3670 my $failed = 0; 3671 3672 start_monitor_and_install or $failed = 1; 3673 3674 if (!$failed && $type ne "boot"){ 3675 do_run_test or $failed = 1; 3676 } 3677 end_monitor; 3678 if ($failed) { 3679 print_times; 3680 return 0; 3681 } 3682 patchcheck_reboot; 3683 print_times; 3684 } 3685 $in_patchcheck = 0; 3686 success $i; 3687 3688 return 1; 3689} 3690 3691sub add_dep { 3692 # $config depends on $dep 3693 my ($config, $dep) = @_; 3694 3695 if (defined($depends{$config})) { 3696 $depends{$config} .= " " . $dep; 3697 } else { 3698 $depends{$config} = $dep; 3699 } 3700 3701 # record the number of configs depending on $dep 3702 if (defined $depcount{$dep}) { 3703 $depcount{$dep}++; 3704 } else { 3705 $depcount{$dep} = 1; 3706 } 3707} 3708 3709# taken from streamline_config.pl 3710sub read_kconfig { 3711 my ($kconfig) = @_; 3712 3713 my $state = "NONE"; 3714 my $config; 3715 my @kconfigs; 3716 3717 my $cont = 0; 3718 my $line; 3719 3720 if (! -f $kconfig) { 3721 doprint "file $kconfig does not exist, skipping\n"; 3722 return; 3723 } 3724 3725 open(KIN, "$kconfig") 3726 or dodie "Can't open $kconfig"; 3727 while (<KIN>) { 3728 chomp; 3729 3730 # Make sure that lines ending with \ continue 3731 if ($cont) { 3732 $_ = $line . " " . $_; 3733 } 3734 3735 if (s/\\$//) { 3736 $cont = 1; 3737 $line = $_; 3738 next; 3739 } 3740 3741 $cont = 0; 3742 3743 # collect any Kconfig sources 3744 if (/^source\s*"(.*)"/) { 3745 $kconfigs[$#kconfigs+1] = $1; 3746 } 3747 3748 # configs found 3749 if (/^\s*(menu)?config\s+(\S+)\s*$/) { 3750 $state = "NEW"; 3751 $config = $2; 3752 3753 for (my $i = 0; $i < $iflevel; $i++) { 3754 add_dep $config, $ifdeps[$i]; 3755 } 3756 3757 # collect the depends for the config 3758 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 3759 3760 add_dep $config, $1; 3761 3762 # Get the configs that select this config 3763 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 3764 3765 # selected by depends on config 3766 add_dep $1, $config; 3767 3768 # Check for if statements 3769 } elsif (/^if\s+(.*\S)\s*$/) { 3770 my $deps = $1; 3771 # remove beginning and ending non text 3772 $deps =~ s/^[^a-zA-Z0-9_]*//; 3773 $deps =~ s/[^a-zA-Z0-9_]*$//; 3774 3775 my @deps = split /[^a-zA-Z0-9_]+/, $deps; 3776 3777 $ifdeps[$iflevel++] = join ':', @deps; 3778 3779 } elsif (/^endif/) { 3780 3781 $iflevel-- if ($iflevel); 3782 3783 # stop on "help" 3784 } elsif (/^\s*help\s*$/) { 3785 $state = "NONE"; 3786 } 3787 } 3788 close(KIN); 3789 3790 # read in any configs that were found. 3791 foreach $kconfig (@kconfigs) { 3792 if (!defined($read_kconfigs{$kconfig})) { 3793 $read_kconfigs{$kconfig} = 1; 3794 read_kconfig("$builddir/$kconfig"); 3795 } 3796 } 3797} 3798 3799sub read_depends { 3800 # find out which arch this is by the kconfig file 3801 open (IN, $output_config) or 3802 dodie "Failed to read $output_config"; 3803 my $arch; 3804 while (<IN>) { 3805 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 3806 $arch = $1; 3807 last; 3808 } 3809 } 3810 close IN; 3811 3812 if (!defined($arch)) { 3813 doprint "Could not find arch from config file\n"; 3814 doprint "no dependencies used\n"; 3815 return; 3816 } 3817 3818 # arch is really the subarch, we need to know 3819 # what directory to look at. 3820 if ($arch eq "i386" || $arch eq "x86_64") { 3821 $arch = "x86"; 3822 } 3823 3824 my $kconfig = "$builddir/arch/$arch/Kconfig"; 3825 3826 if (! -f $kconfig && $arch =~ /\d$/) { 3827 my $orig = $arch; 3828 # some subarchs have numbers, truncate them 3829 $arch =~ s/\d*$//; 3830 $kconfig = "$builddir/arch/$arch/Kconfig"; 3831 if (! -f $kconfig) { 3832 doprint "No idea what arch dir $orig is for\n"; 3833 doprint "no dependencies used\n"; 3834 return; 3835 } 3836 } 3837 3838 read_kconfig($kconfig); 3839} 3840 3841sub make_new_config { 3842 my @configs = @_; 3843 3844 open (OUT, ">$output_config") 3845 or dodie "Failed to write $output_config"; 3846 3847 foreach my $config (@configs) { 3848 print OUT "$config\n"; 3849 } 3850 close OUT; 3851} 3852 3853sub chomp_config { 3854 my ($config) = @_; 3855 3856 $config =~ s/CONFIG_//; 3857 3858 return $config; 3859} 3860 3861sub get_depends { 3862 my ($dep) = @_; 3863 3864 my $kconfig = chomp_config $dep; 3865 3866 $dep = $depends{"$kconfig"}; 3867 3868 # the dep string we have saves the dependencies as they 3869 # were found, including expressions like ! && ||. We 3870 # want to split this out into just an array of configs. 3871 3872 my $valid = "A-Za-z_0-9"; 3873 3874 my @configs; 3875 3876 while ($dep =~ /[$valid]/) { 3877 if ($dep =~ /^[^$valid]*([$valid]+)/) { 3878 my $conf = "CONFIG_" . $1; 3879 3880 $configs[$#configs + 1] = $conf; 3881 3882 $dep =~ s/^[^$valid]*[$valid]+//; 3883 } else { 3884 dodie "this should never happen"; 3885 } 3886 } 3887 3888 return @configs; 3889} 3890 3891sub test_this_config { 3892 my ($config) = @_; 3893 3894 my $found; 3895 3896 # if we already processed this config, skip it 3897 if (defined($processed_configs{$config})) { 3898 return undef; 3899 } 3900 $processed_configs{$config} = 1; 3901 3902 # if this config failed during this round, skip it 3903 if (defined($nochange_config{$config})) { 3904 return undef; 3905 } 3906 3907 my $kconfig = chomp_config $config; 3908 3909 # Test dependencies first 3910 if (defined($depends{"$kconfig"})) { 3911 my @parents = get_depends $config; 3912 foreach my $parent (@parents) { 3913 # if the parent is in the min config, check it first 3914 next if (!defined($min_configs{$parent})); 3915 $found = test_this_config($parent); 3916 if (defined($found)) { 3917 return $found; 3918 } 3919 } 3920 } 3921 3922 # Remove this config from the list of configs 3923 # do a make olddefconfig and then read the resulting 3924 # .config to make sure it is missing the config that 3925 # we had before 3926 my %configs = %min_configs; 3927 $configs{$config} = "# $config is not set"; 3928 make_new_config ((values %configs), (values %keep_configs)); 3929 make_oldconfig; 3930 delete $configs{$config}; 3931 undef %configs; 3932 assign_configs \%configs, $output_config; 3933 3934 if (!defined($configs{$config}) || $configs{$config} =~ /^#/) { 3935 return $config; 3936 } 3937 3938 doprint "disabling config $config did not change .config\n"; 3939 3940 $nochange_config{$config} = 1; 3941 3942 return undef; 3943} 3944 3945sub make_min_config { 3946 my ($i) = @_; 3947 3948 my $type = $minconfig_type; 3949 if ($type ne "boot" && $type ne "test") { 3950 fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" . 3951 " make_min_config works only with 'boot' and 'test'\n" and return; 3952 } 3953 3954 if (!defined($output_minconfig)) { 3955 fail "OUTPUT_MIN_CONFIG not defined" and return; 3956 } 3957 3958 # If output_minconfig exists, and the start_minconfig 3959 # came from min_config, than ask if we should use 3960 # that instead. 3961 if (-f $output_minconfig && !$start_minconfig_defined) { 3962 print "$output_minconfig exists\n"; 3963 if (!defined($use_output_minconfig)) { 3964 if (read_yn " Use it as minconfig?") { 3965 $start_minconfig = $output_minconfig; 3966 } 3967 } elsif ($use_output_minconfig > 0) { 3968 doprint "Using $output_minconfig as MIN_CONFIG\n"; 3969 $start_minconfig = $output_minconfig; 3970 } else { 3971 doprint "Set to still use MIN_CONFIG as starting point\n"; 3972 } 3973 } 3974 3975 if (!defined($start_minconfig)) { 3976 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 3977 } 3978 3979 my $temp_config = "$tmpdir/temp_config"; 3980 3981 # First things first. We build an allnoconfig to find 3982 # out what the defaults are that we can't touch. 3983 # Some are selections, but we really can't handle selections. 3984 3985 my $save_minconfig = $minconfig; 3986 undef $minconfig; 3987 3988 run_command "$make allnoconfig" or return 0; 3989 3990 read_depends; 3991 3992 process_config_ignore $output_config; 3993 3994 undef %save_configs; 3995 undef %min_configs; 3996 3997 if (defined($ignore_config)) { 3998 # make sure the file exists 3999 `touch $ignore_config`; 4000 assign_configs \%save_configs, $ignore_config; 4001 } 4002 4003 %keep_configs = %save_configs; 4004 4005 doprint "Load initial configs from $start_minconfig\n"; 4006 4007 # Look at the current min configs, and save off all the 4008 # ones that were set via the allnoconfig 4009 assign_configs \%min_configs, $start_minconfig; 4010 4011 my @config_keys = keys %min_configs; 4012 4013 # All configs need a depcount 4014 foreach my $config (@config_keys) { 4015 my $kconfig = chomp_config $config; 4016 if (!defined $depcount{$kconfig}) { 4017 $depcount{$kconfig} = 0; 4018 } 4019 } 4020 4021 # Remove anything that was set by the make allnoconfig 4022 # we shouldn't need them as they get set for us anyway. 4023 foreach my $config (@config_keys) { 4024 # Remove anything in the ignore_config 4025 if (defined($keep_configs{$config})) { 4026 my $file = $ignore_config; 4027 $file =~ s,.*/(.*?)$,$1,; 4028 doprint "$config set by $file ... ignored\n"; 4029 delete $min_configs{$config}; 4030 next; 4031 } 4032 # But make sure the settings are the same. If a min config 4033 # sets a selection, we do not want to get rid of it if 4034 # it is not the same as what we have. Just move it into 4035 # the keep configs. 4036 if (defined($config_ignore{$config})) { 4037 if ($config_ignore{$config} ne $min_configs{$config}) { 4038 doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 4039 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 4040 $keep_configs{$config} = $min_configs{$config}; 4041 } else { 4042 doprint "$config set by allnoconfig ... ignored\n"; 4043 } 4044 delete $min_configs{$config}; 4045 } 4046 } 4047 4048 my $done = 0; 4049 my $take_two = 0; 4050 4051 while (!$done) { 4052 my $config; 4053 my $found; 4054 4055 # Now disable each config one by one and do a make oldconfig 4056 # till we find a config that changes our list. 4057 4058 my @test_configs = keys %min_configs; 4059 4060 # Sort keys by who is most dependent on 4061 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 4062 @test_configs ; 4063 4064 # Put configs that did not modify the config at the end. 4065 my $reset = 1; 4066 for (my $i = 0; $i < $#test_configs; $i++) { 4067 if (!defined($nochange_config{$test_configs[0]})) { 4068 $reset = 0; 4069 last; 4070 } 4071 # This config didn't change the .config last time. 4072 # Place it at the end 4073 my $config = shift @test_configs; 4074 push @test_configs, $config; 4075 } 4076 4077 # if every test config has failed to modify the .config file 4078 # in the past, then reset and start over. 4079 if ($reset) { 4080 undef %nochange_config; 4081 } 4082 4083 undef %processed_configs; 4084 4085 foreach my $config (@test_configs) { 4086 4087 $found = test_this_config $config; 4088 4089 last if (defined($found)); 4090 4091 # oh well, try another config 4092 } 4093 4094 if (!defined($found)) { 4095 # we could have failed due to the nochange_config hash 4096 # reset and try again 4097 if (!$take_two) { 4098 undef %nochange_config; 4099 $take_two = 1; 4100 next; 4101 } 4102 doprint "No more configs found that we can disable\n"; 4103 $done = 1; 4104 last; 4105 } 4106 $take_two = 0; 4107 4108 $config = $found; 4109 4110 doprint "Test with $config disabled\n"; 4111 4112 # set in_bisect to keep build and monitor from dieing 4113 $in_bisect = 1; 4114 4115 my $failed = 0; 4116 build "oldconfig" or $failed = 1; 4117 if (!$failed) { 4118 start_monitor_and_install or $failed = 1; 4119 4120 if ($type eq "test" && !$failed) { 4121 do_run_test or $failed = 1; 4122 } 4123 4124 end_monitor; 4125 } 4126 4127 $in_bisect = 0; 4128 4129 if ($failed) { 4130 doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 4131 # this config is needed, add it to the ignore list. 4132 $keep_configs{$config} = $min_configs{$config}; 4133 $save_configs{$config} = $min_configs{$config}; 4134 delete $min_configs{$config}; 4135 4136 # update new ignore configs 4137 if (defined($ignore_config)) { 4138 open (OUT, ">$temp_config") or 4139 dodie "Can't write to $temp_config"; 4140 foreach my $config (keys %save_configs) { 4141 print OUT "$save_configs{$config}\n"; 4142 } 4143 close OUT; 4144 run_command "mv $temp_config $ignore_config" or 4145 dodie "failed to copy update to $ignore_config"; 4146 } 4147 4148 } else { 4149 # We booted without this config, remove it from the minconfigs. 4150 doprint "$config is not needed, disabling\n"; 4151 4152 delete $min_configs{$config}; 4153 4154 # Also disable anything that is not enabled in this config 4155 my %configs; 4156 assign_configs \%configs, $output_config; 4157 my @config_keys = keys %min_configs; 4158 foreach my $config (@config_keys) { 4159 if (!defined($configs{$config})) { 4160 doprint "$config is not set, disabling\n"; 4161 delete $min_configs{$config}; 4162 } 4163 } 4164 4165 # Save off all the current mandatory configs 4166 open (OUT, ">$temp_config") or 4167 dodie "Can't write to $temp_config"; 4168 foreach my $config (keys %keep_configs) { 4169 print OUT "$keep_configs{$config}\n"; 4170 } 4171 foreach my $config (keys %min_configs) { 4172 print OUT "$min_configs{$config}\n"; 4173 } 4174 close OUT; 4175 4176 run_command "mv $temp_config $output_minconfig" or 4177 dodie "failed to copy update to $output_minconfig"; 4178 } 4179 4180 doprint "Reboot and wait $sleep_time seconds\n"; 4181 reboot_to_good $sleep_time; 4182 } 4183 4184 success $i; 4185 return 1; 4186} 4187 4188sub make_warnings_file { 4189 my ($i) = @_; 4190 4191 if (!defined($warnings_file)) { 4192 dodie "Must define WARNINGS_FILE for make_warnings_file test"; 4193 } 4194 4195 if ($build_type eq "nobuild") { 4196 dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test"; 4197 } 4198 4199 build $build_type or dodie "Failed to build"; 4200 4201 open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file"; 4202 4203 open(IN, $buildlog) or dodie "Can't open $buildlog"; 4204 while (<IN>) { 4205 # Some compilers use UTF-8 extended for quotes 4206 # for distcc heterogeneous systems, this causes issues 4207 s/$utf8_quote/'/g; 4208 4209 if (/$check_build_re/) { 4210 print OUT; 4211 } 4212 } 4213 close(IN); 4214 4215 close(OUT); 4216 4217 success $i; 4218} 4219 4220sub option_defined { 4221 my ($option) = @_; 4222 4223 if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) { 4224 return 1; 4225 } 4226 4227 return 0; 4228} 4229 4230sub __set_test_option { 4231 my ($name, $i) = @_; 4232 4233 my $option = "$name\[$i\]"; 4234 4235 if (exists($opt{$option})) { 4236 return undef if (!option_defined($option)); 4237 return $opt{$option}; 4238 } 4239 4240 foreach my $test (keys %repeat_tests) { 4241 if ($i >= $test && 4242 $i < $test + $repeat_tests{$test}) { 4243 $option = "$name\[$test\]"; 4244 if (exists($opt{$option})) { 4245 return undef if (!option_defined($option)); 4246 return $opt{$option}; 4247 } 4248 } 4249 } 4250 4251 if (option_defined($name)) { 4252 return $opt{$name}; 4253 } 4254 4255 return undef; 4256} 4257 4258sub set_test_option { 4259 my ($name, $i) = @_; 4260 4261 my $option = __set_test_option($name, $i); 4262 return $option if (!defined($option)); 4263 4264 return eval_option($name, $option, $i); 4265} 4266 4267sub print_test_preamble { 4268 my ($resolved) = @_; 4269 4270 doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 4271 4272 for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 4273 4274 if (!$i) { 4275 doprint "DEFAULT OPTIONS:\n"; 4276 } else { 4277 doprint "\nTEST $i OPTIONS"; 4278 if (defined($repeat_tests{$i})) { 4279 $repeat = $repeat_tests{$i}; 4280 doprint " ITERATE $repeat"; 4281 } 4282 doprint "\n"; 4283 } 4284 4285 foreach my $option (sort keys %opt) { 4286 my $value; 4287 4288 if ($option =~ /\[(\d+)\]$/) { 4289 next if ($i != $1); 4290 4291 if ($resolved) { 4292 my $name = $option; 4293 $name =~ s/\[\d+\]$//; 4294 $value = set_test_option($name, $i); 4295 } else { 4296 $value = $opt{$option}; 4297 } 4298 } else { 4299 next if ($i); 4300 4301 if ($resolved) { 4302 $value = set_test_option($option, 0); 4303 } else { 4304 $value = $opt{$option}; 4305 } 4306 } 4307 4308 $value = "" if (!defined($value)); 4309 doprint "$option = $value\n"; 4310 } 4311 } 4312} 4313 4314sub find_mailer { 4315 my ($mailer) = @_; 4316 4317 my @paths = split /:/, $ENV{PATH}; 4318 4319 # sendmail is usually in /usr/sbin 4320 $paths[$#paths + 1] = "/usr/sbin"; 4321 4322 foreach my $path (@paths) { 4323 if (-x "$path/$mailer") { 4324 return $path; 4325 } 4326 } 4327 4328 return undef; 4329} 4330 4331sub do_send_mail { 4332 my ($subject, $message, $file) = @_; 4333 4334 if (!defined($mail_path)) { 4335 # find the mailer 4336 $mail_path = find_mailer $mailer; 4337 if (!defined($mail_path)) { 4338 die "\nCan not find $mailer in PATH\n"; 4339 } 4340 } 4341 4342 my $header_file = "$tmpdir/header"; 4343 open (HEAD, ">$header_file") or die "Can not create $header_file\n"; 4344 print HEAD "To: $mailto\n"; 4345 print HEAD "Subject: $subject\n\n"; 4346 print HEAD "$message\n"; 4347 close HEAD; 4348 4349 if (!defined($mail_command)) { 4350 if ($mailer eq "mail" || $mailer eq "mailx") { 4351 $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO"; 4352 } elsif ($mailer eq "sendmail" ) { 4353 $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO"; 4354 } else { 4355 die "\nYour mailer: $mailer is not supported.\n"; 4356 } 4357 } 4358 4359 if (defined($file)) { 4360 $mail_command =~ s/\$BODY_FILE/$file/g; 4361 } else { 4362 $mail_command =~ s/\$BODY_FILE//g; 4363 } 4364 4365 $mail_command =~ s/\$HEADER_FILE/$header_file/g; 4366 $mail_command =~ s/\$MAILER/$mailer/g; 4367 $mail_command =~ s/\$MAIL_PATH/$mail_path/g; 4368 $mail_command =~ s/\$MAILTO/$mailto/g; 4369 $mail_command =~ s/\$SUBJECT/$subject/g; 4370 $mail_command =~ s/\$MESSAGE/$message/g; 4371 4372 my $ret = run_command $mail_command; 4373 if (!$ret && defined($file)) { 4374 # try again without the file 4375 $message .= "\n\n*** FAILED TO SEND LOG ***\n\n"; 4376 do_send_email($subject, $message); 4377 } 4378} 4379 4380sub send_email { 4381 if (defined($mailto)) { 4382 if (!defined($mailer)) { 4383 doprint "No email sent: email or mailer not specified in config.\n"; 4384 return; 4385 } 4386 do_send_mail @_; 4387 } 4388} 4389 4390sub cancel_test { 4391 if ($monitor_cnt) { 4392 end_monitor; 4393 } 4394 if ($email_when_canceled) { 4395 my $name = get_test_name; 4396 send_email("KTEST: Your [$name] test was cancelled", 4397 "Your test started at $script_start_time was cancelled: sig int"); 4398 } 4399 run_post_ktest; 4400 die "\nCaught Sig Int, test interrupted: $!\n" 4401} 4402 4403sub die_usage { 4404 die << "EOF" 4405ktest.pl version: $VERSION 4406 usage: ktest.pl [options] [config-file] 4407 [options]: 4408 -D value: Where value can act as an option override. 4409 -D BUILD_NOCLEAN=1 4410 Sets global BUILD_NOCLEAN to 1 4411 -D TEST_TYPE[2]=build 4412 Sets TEST_TYPE of test 2 to "build" 4413 --dry-run 4414 Print resolved test options and exit without running tests. 4415 4416 It can also override all temp variables. 4417 -D USE_TEMP_DIR:=1 4418 Will override all variables that use 4419 "USE_TEMP_DIR=" 4420 4421EOF 4422; 4423} 4424 4425while ( $#ARGV >= 0 ) { 4426 if ( $ARGV[0] eq "-D" ) { 4427 shift; 4428 die_usage if ($#ARGV < 1); 4429 my $val = shift; 4430 4431 if ($val =~ m/(.*?):=(.*)$/) { 4432 set_variable($1, $2, 1); 4433 } else { 4434 $command_vars[$#command_vars + 1] = $val; 4435 } 4436 4437 } elsif ( $ARGV[0] =~ m/^-D(.*)/) { 4438 my $val = $1; 4439 shift; 4440 4441 if ($val =~ m/(.*?):=(.*)$/) { 4442 set_variable($1, $2, 1); 4443 } else { 4444 $command_vars[$#command_vars + 1] = $val; 4445 } 4446 } elsif ( $ARGV[0] eq "--dry-run" ) { 4447 $dry_run = 1; 4448 shift; 4449 } elsif ( $ARGV[0] eq "-h" ) { 4450 die_usage; 4451 } else { 4452 last; 4453 } 4454} 4455 4456$#ARGV < 1 or die_usage; 4457if ($#ARGV == 0) { 4458 $ktest_config = $ARGV[0]; 4459 if (! -f $ktest_config) { 4460 print "$ktest_config does not exist.\n"; 4461 if (!read_yn "Create it?") { 4462 exit 0; 4463 } 4464 } 4465} 4466 4467if (! -f $ktest_config) { 4468 $newconfig = 1; 4469 get_test_case; 4470 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 4471 print OUT << "EOF" 4472# Generated by ktest.pl 4473# 4474 4475# PWD is a ktest.pl variable that will result in the process working 4476# directory that ktest.pl is executed in. 4477 4478# THIS_DIR is automatically assigned the PWD of the path that generated 4479# the config file. It is best to use this variable when assigning other 4480# directory paths within this directory. This allows you to easily 4481# move the test cases to other locations or to other machines. 4482# 4483THIS_DIR := $variable{"PWD"} 4484 4485# Define each test with TEST_START 4486# The config options below it will override the defaults 4487TEST_START 4488TEST_TYPE = $default{"TEST_TYPE"} 4489 4490DEFAULTS 4491EOF 4492; 4493 close(OUT); 4494} 4495read_config $ktest_config; 4496 4497if ($dry_run) { 4498 print_test_preamble 1; 4499 exit 0; 4500} 4501 4502if (defined($opt{"LOG_FILE"})) { 4503 $opt{"LOG_FILE"} = set_test_option("LOG_FILE", 1); 4504} 4505 4506# Append any configs entered in manually to the config file. 4507my @new_configs = keys %entered_configs; 4508if ($#new_configs >= 0) { 4509 print "\nAppending entered in configs to $ktest_config\n"; 4510 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 4511 foreach my $config (@new_configs) { 4512 print OUT "$config = $entered_configs{$config}\n"; 4513 $opt{$config} = process_variables($entered_configs{$config}); 4514 } 4515} 4516 4517if (defined($opt{"LOG_FILE"})) { 4518 if ($opt{"CLEAR_LOG"}) { 4519 unlink $opt{"LOG_FILE"}; 4520 } 4521 4522 if (! -e $opt{"LOG_FILE"} && $opt{"LOG_FILE"} =~ m,^(.*/),) { 4523 my $dir = $1; 4524 if (! -d $dir) { 4525 mkpath($dir) or die "Failed to create directories '$dir': $!"; 4526 print "\nThe log directory $dir did not exist, so it was created.\n"; 4527 } 4528 } 4529 open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 4530 LOG->autoflush(1); 4531} 4532 4533print_test_preamble 0; 4534 4535$SIG{INT} = qw(cancel_test); 4536 4537# First we need to do is the builds 4538for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 4539 4540 # Do not reboot on failing test options 4541 $no_reboot = 1; 4542 $reboot_success = 0; 4543 4544 $have_version = 0; 4545 4546 $iteration = $i; 4547 4548 $build_time = 0; 4549 $install_time = 0; 4550 $reboot_time = 0; 4551 $test_time = 0; 4552 4553 undef %force_config; 4554 4555 my $makecmd = set_test_option("MAKE_CMD", $i); 4556 4557 $outputdir = set_test_option("OUTPUT_DIR", $i); 4558 $builddir = set_test_option("BUILD_DIR", $i); 4559 4560 chdir $builddir || dodie "can't change directory to $builddir"; 4561 4562 if (!-d $outputdir) { 4563 mkpath($outputdir) or 4564 dodie "can't create $outputdir"; 4565 } 4566 4567 $make = "$makecmd O=$outputdir"; 4568 4569 # Load all the options into their mapped variable names 4570 foreach my $opt (keys %option_map) { 4571 ${$option_map{$opt}} = set_test_option($opt, $i); 4572 } 4573 4574 $start_minconfig_defined = 1; 4575 4576 # The first test may override the PRE_KTEST option 4577 if ($i == 1) { 4578 if (defined($pre_ktest)) { 4579 doprint "\n"; 4580 my $ret = run_command $pre_ktest; 4581 if (!$ret && defined($pre_ktest_die) && 4582 $pre_ktest_die) { 4583 dodie "failed to pre_ktest\n"; 4584 } 4585 } 4586 if ($email_when_started) { 4587 my $name = get_test_name; 4588 send_email("KTEST: Your [$name] test was started", 4589 "Your test was started on $script_start_time"); 4590 } 4591 } 4592 4593 # Any test can override the POST_KTEST option 4594 # The last test takes precedence. 4595 if (defined($post_ktest)) { 4596 $final_post_ktest = $post_ktest; 4597 } 4598 4599 if (!defined($start_minconfig)) { 4600 $start_minconfig_defined = 0; 4601 $start_minconfig = $minconfig; 4602 } 4603 4604 if (!-d $tmpdir) { 4605 mkpath($tmpdir) or 4606 dodie "can't create $tmpdir"; 4607 } 4608 4609 $ENV{"SSH_USER"} = $ssh_user; 4610 $ENV{"MACHINE"} = $machine; 4611 4612 $buildlog = "$tmpdir/buildlog-$machine"; 4613 $testlog = "$tmpdir/testlog-$machine"; 4614 $dmesg = "$tmpdir/dmesg-$machine"; 4615 $output_config = "$outputdir/.config"; 4616 4617 if (!$buildonly) { 4618 $target = "$ssh_user\@$machine"; 4619 if (($reboot_type eq "grub") or ($reboot_type eq "grub2bls")) { 4620 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 4621 } elsif ($reboot_type eq "grub2") { 4622 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 4623 dodie "GRUB_FILE not defined" if (!defined($grub_file)); 4624 } elsif ($reboot_type eq "syslinux") { 4625 dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label)); 4626 } 4627 } 4628 4629 my $run_type = $build_type; 4630 if ($test_type eq "patchcheck") { 4631 $run_type = $patchcheck_type; 4632 } elsif ($test_type eq "bisect") { 4633 $run_type = $bisect_type; 4634 } elsif ($test_type eq "config_bisect") { 4635 $run_type = $config_bisect_type; 4636 } elsif ($test_type eq "make_min_config") { 4637 $run_type = ""; 4638 } elsif ($test_type eq "make_warnings_file") { 4639 $run_type = ""; 4640 } 4641 4642 # mistake in config file? 4643 if (!defined($run_type)) { 4644 $run_type = "ERROR"; 4645 } 4646 4647 my $installme = ""; 4648 $installme = " no_install" if ($no_install); 4649 4650 my $name = ""; 4651 4652 if (defined($test_name)) { 4653 $name = " ($test_name)"; 4654 } 4655 4656 doprint "\n\n"; 4657 4658 if (defined($opt{"LOG_FILE"})) { 4659 $test_log_start = tell(LOG); 4660 } 4661 4662 doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; 4663 4664 # Always show which build directory and output directory is being used 4665 doprint "BUILD_DIR=$builddir\n"; 4666 doprint "OUTPUT_DIR=$outputdir\n\n"; 4667 4668 if (defined($pre_test)) { 4669 my $ret = run_command $pre_test; 4670 if (!$ret && defined($pre_test_die) && 4671 $pre_test_die) { 4672 dodie "failed to pre_test\n"; 4673 } 4674 } 4675 4676 unlink $dmesg; 4677 unlink $buildlog; 4678 unlink $testlog; 4679 4680 if (defined($addconfig)) { 4681 my $min = $minconfig; 4682 if (!defined($minconfig)) { 4683 $min = ""; 4684 } 4685 run_command "cat $addconfig $min > $tmpdir/add_config" or 4686 dodie "Failed to create temp config"; 4687 $minconfig = "$tmpdir/add_config"; 4688 } 4689 4690 if (defined($checkout)) { 4691 run_command "git checkout $checkout" or 4692 dodie "failed to checkout $checkout"; 4693 } 4694 4695 $no_reboot = 0; 4696 4697 # A test may opt to not reboot the box 4698 if ($reboot_on_success) { 4699 $reboot_success = 1; 4700 } 4701 4702 if ($test_type eq "bisect") { 4703 bisect $i; 4704 next; 4705 } elsif ($test_type eq "config_bisect") { 4706 config_bisect $i; 4707 next; 4708 } elsif ($test_type eq "patchcheck") { 4709 patchcheck $i; 4710 next; 4711 } elsif ($test_type eq "make_min_config") { 4712 make_min_config $i; 4713 next; 4714 } elsif ($test_type eq "make_warnings_file") { 4715 $no_reboot = 1; 4716 make_warnings_file $i; 4717 next; 4718 } 4719 4720 if ($build_type ne "nobuild") { 4721 build $build_type or next; 4722 check_buildlog or next; 4723 } 4724 4725 if ($test_type eq "install") { 4726 get_version; 4727 install; 4728 success $i; 4729 next; 4730 } 4731 4732 if ($test_type ne "build") { 4733 my $failed = 0; 4734 start_monitor_and_install or $failed = 1; 4735 4736 if (!$failed && $test_type ne "boot" && defined($run_test)) { 4737 do_run_test or $failed = 1; 4738 } 4739 end_monitor; 4740 if ($failed) { 4741 print_times; 4742 next; 4743 } 4744 } 4745 4746 print_times; 4747 4748 success $i; 4749} 4750 4751run_post_ktest; 4752 4753if ($opt{"POWEROFF_ON_SUCCESS"}) { 4754 halt; 4755} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) { 4756 reboot_to_good; 4757} elsif (defined($switch_to_good)) { 4758 # still need to get to the good kernel 4759 run_command $switch_to_good; 4760} 4761 4762doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 4763 4764if ($email_when_finished) { 4765 send_email("KTEST: Your test has finished!", 4766 "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!"); 4767} 4768 4769if (defined($opt{"LOG_FILE"})) { 4770 print "\n See $opt{LOG_FILE} for the record of results.\n\n"; 4771 close LOG; 4772} 4773 4774exit 0; 4775 4776## 4777# The following are here to standardize tabs/spaces/etc across the most likely editors 4778### 4779 4780# Local Variables: 4781# mode: perl 4782# End: 4783# vim: softtabstop=4 4784