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