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