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