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