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