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