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