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