|
@@ -27,7 +27,7 @@ $default{"TEST_TYPE"} = "test";
|
|
$default{"BUILD_TYPE"} = "randconfig";
|
|
$default{"BUILD_TYPE"} = "randconfig";
|
|
$default{"MAKE_CMD"} = "make";
|
|
$default{"MAKE_CMD"} = "make";
|
|
$default{"TIMEOUT"} = 120;
|
|
$default{"TIMEOUT"} = 120;
|
|
-$default{"TMP_DIR"} = "/tmp/ktest";
|
|
|
|
|
|
+$default{"TMP_DIR"} = "/tmp/ktest/\${MACHINE}";
|
|
$default{"SLEEP_TIME"} = 60; # sleep time between tests
|
|
$default{"SLEEP_TIME"} = 60; # sleep time between tests
|
|
$default{"BUILD_NOCLEAN"} = 0;
|
|
$default{"BUILD_NOCLEAN"} = 0;
|
|
$default{"REBOOT_ON_ERROR"} = 0;
|
|
$default{"REBOOT_ON_ERROR"} = 0;
|
|
@@ -41,6 +41,7 @@ $default{"CLEAR_LOG"} = 0;
|
|
$default{"BISECT_MANUAL"} = 0;
|
|
$default{"BISECT_MANUAL"} = 0;
|
|
$default{"BISECT_SKIP"} = 1;
|
|
$default{"BISECT_SKIP"} = 1;
|
|
$default{"SUCCESS_LINE"} = "login:";
|
|
$default{"SUCCESS_LINE"} = "login:";
|
|
|
|
+$default{"DETECT_TRIPLE_FAULT"} = 1;
|
|
$default{"BOOTED_TIMEOUT"} = 1;
|
|
$default{"BOOTED_TIMEOUT"} = 1;
|
|
$default{"DIE_ON_FAILURE"} = 1;
|
|
$default{"DIE_ON_FAILURE"} = 1;
|
|
$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
|
|
$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
|
|
@@ -62,6 +63,10 @@ my $output_config;
|
|
my $test_type;
|
|
my $test_type;
|
|
my $build_type;
|
|
my $build_type;
|
|
my $build_options;
|
|
my $build_options;
|
|
|
|
+my $pre_build;
|
|
|
|
+my $post_build;
|
|
|
|
+my $pre_build_die;
|
|
|
|
+my $post_build_die;
|
|
my $reboot_type;
|
|
my $reboot_type;
|
|
my $reboot_script;
|
|
my $reboot_script;
|
|
my $power_cycle;
|
|
my $power_cycle;
|
|
@@ -81,12 +86,17 @@ my $make;
|
|
my $post_install;
|
|
my $post_install;
|
|
my $noclean;
|
|
my $noclean;
|
|
my $minconfig;
|
|
my $minconfig;
|
|
|
|
+my $start_minconfig;
|
|
|
|
+my $start_minconfig_defined;
|
|
|
|
+my $output_minconfig;
|
|
|
|
+my $ignore_config;
|
|
my $addconfig;
|
|
my $addconfig;
|
|
my $in_bisect = 0;
|
|
my $in_bisect = 0;
|
|
my $bisect_bad = "";
|
|
my $bisect_bad = "";
|
|
my $reverse_bisect;
|
|
my $reverse_bisect;
|
|
my $bisect_manual;
|
|
my $bisect_manual;
|
|
my $bisect_skip;
|
|
my $bisect_skip;
|
|
|
|
+my $config_bisect_good;
|
|
my $in_patchcheck = 0;
|
|
my $in_patchcheck = 0;
|
|
my $run_test;
|
|
my $run_test;
|
|
my $redirect;
|
|
my $redirect;
|
|
@@ -98,9 +108,12 @@ my $monitor_cnt = 0;
|
|
my $sleep_time;
|
|
my $sleep_time;
|
|
my $bisect_sleep_time;
|
|
my $bisect_sleep_time;
|
|
my $patchcheck_sleep_time;
|
|
my $patchcheck_sleep_time;
|
|
|
|
+my $ignore_warnings;
|
|
my $store_failures;
|
|
my $store_failures;
|
|
|
|
+my $test_name;
|
|
my $timeout;
|
|
my $timeout;
|
|
my $booted_timeout;
|
|
my $booted_timeout;
|
|
|
|
+my $detect_triplefault;
|
|
my $console;
|
|
my $console;
|
|
my $success_line;
|
|
my $success_line;
|
|
my $stop_after_success;
|
|
my $stop_after_success;
|
|
@@ -115,6 +128,7 @@ my $successes = 0;
|
|
my %entered_configs;
|
|
my %entered_configs;
|
|
my %config_help;
|
|
my %config_help;
|
|
my %variable;
|
|
my %variable;
|
|
|
|
+my %force_config;
|
|
|
|
|
|
$config_help{"MACHINE"} = << "EOF"
|
|
$config_help{"MACHINE"} = << "EOF"
|
|
The machine hostname that you will test.
|
|
The machine hostname that you will test.
|
|
@@ -204,6 +218,26 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
|
|
EOF
|
|
EOF
|
|
;
|
|
;
|
|
|
|
|
|
|
|
+sub read_yn {
|
|
|
|
+ my ($prompt) = @_;
|
|
|
|
+
|
|
|
|
+ my $ans;
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ print "$prompt [Y/n] ";
|
|
|
|
+ $ans = <STDIN>;
|
|
|
|
+ chomp $ans;
|
|
|
|
+ if ($ans =~ /^\s*$/) {
|
|
|
|
+ $ans = "y";
|
|
|
|
+ }
|
|
|
|
+ last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
|
|
|
|
+ print "Please answer either 'y' or 'n'.\n";
|
|
|
|
+ }
|
|
|
|
+ if ($ans !~ /^y$/i) {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
|
|
sub get_ktest_config {
|
|
sub get_ktest_config {
|
|
my ($config) = @_;
|
|
my ($config) = @_;
|
|
@@ -335,6 +369,7 @@ sub read_config {
|
|
my $num_tests_set = 0;
|
|
my $num_tests_set = 0;
|
|
my $skip = 0;
|
|
my $skip = 0;
|
|
my $rest;
|
|
my $rest;
|
|
|
|
+ my $test_case = 0;
|
|
|
|
|
|
while (<IN>) {
|
|
while (<IN>) {
|
|
|
|
|
|
@@ -360,6 +395,7 @@ sub read_config {
|
|
$rest = $1;
|
|
$rest = $1;
|
|
$skip = 1;
|
|
$skip = 1;
|
|
} else {
|
|
} else {
|
|
|
|
+ $test_case = 1;
|
|
$skip = 0;
|
|
$skip = 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -464,6 +500,15 @@ sub read_config {
|
|
# make sure we have all mandatory configs
|
|
# make sure we have all mandatory configs
|
|
get_ktest_configs;
|
|
get_ktest_configs;
|
|
|
|
|
|
|
|
+ # was a test specified?
|
|
|
|
+ if (!$test_case) {
|
|
|
|
+ print "No test case specified.\n";
|
|
|
|
+ print "What test case would you like to run?\n";
|
|
|
|
+ my $ans = <STDIN>;
|
|
|
|
+ chomp $ans;
|
|
|
|
+ $default{"TEST_TYPE"} = $ans;
|
|
|
|
+ }
|
|
|
|
+
|
|
# set any defaults
|
|
# set any defaults
|
|
|
|
|
|
foreach my $default (keys %default) {
|
|
foreach my $default (keys %default) {
|
|
@@ -473,6 +518,69 @@ sub read_config {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+sub __eval_option {
|
|
|
|
+ my ($option, $i) = @_;
|
|
|
|
+
|
|
|
|
+ # Add space to evaluate the character before $
|
|
|
|
+ $option = " $option";
|
|
|
|
+ my $retval = "";
|
|
|
|
+
|
|
|
|
+ while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
|
|
|
|
+ my $start = $1;
|
|
|
|
+ my $var = $2;
|
|
|
|
+ my $end = $3;
|
|
|
|
+
|
|
|
|
+ # Append beginning of line
|
|
|
|
+ $retval = "$retval$start";
|
|
|
|
+
|
|
|
|
+ # If the iteration option OPT[$i] exists, then use that.
|
|
|
|
+ # otherwise see if the default OPT (without [$i]) exists.
|
|
|
|
+
|
|
|
|
+ my $o = "$var\[$i\]";
|
|
|
|
+
|
|
|
|
+ if (defined($opt{$o})) {
|
|
|
|
+ $o = $opt{$o};
|
|
|
|
+ $retval = "$retval$o";
|
|
|
|
+ } elsif (defined($opt{$var})) {
|
|
|
|
+ $o = $opt{$var};
|
|
|
|
+ $retval = "$retval$o";
|
|
|
|
+ } else {
|
|
|
|
+ $retval = "$retval\$\{$var\}";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $option = $end;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $retval = "$retval$option";
|
|
|
|
+
|
|
|
|
+ $retval =~ s/^ //;
|
|
|
|
+
|
|
|
|
+ return $retval;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sub eval_option {
|
|
|
|
+ my ($option, $i) = @_;
|
|
|
|
+
|
|
|
|
+ my $prev = "";
|
|
|
|
+
|
|
|
|
+ # Since an option can evaluate to another option,
|
|
|
|
+ # keep iterating until we do not evaluate any more
|
|
|
|
+ # options.
|
|
|
|
+ my $r = 0;
|
|
|
|
+ while ($prev ne $option) {
|
|
|
|
+ # Check for recursive evaluations.
|
|
|
|
+ # 100 deep should be more than enough.
|
|
|
|
+ if ($r++ > 100) {
|
|
|
|
+ die "Over 100 evaluations accurred with $option\n" .
|
|
|
|
+ "Check for recursive variables\n";
|
|
|
|
+ }
|
|
|
|
+ $prev = $option;
|
|
|
|
+ $option = __eval_option($option, $i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return $option;
|
|
|
|
+}
|
|
|
|
+
|
|
sub _logit {
|
|
sub _logit {
|
|
if (defined($opt{"LOG_FILE"})) {
|
|
if (defined($opt{"LOG_FILE"})) {
|
|
open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
|
|
open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
|
|
@@ -617,9 +725,15 @@ sub fail {
|
|
end_monitor;
|
|
end_monitor;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ my $name = "";
|
|
|
|
+
|
|
|
|
+ if (defined($test_name)) {
|
|
|
|
+ $name = " ($test_name)";
|
|
|
|
+ }
|
|
|
|
+
|
|
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
|
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
|
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
|
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
|
- doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n";
|
|
|
|
|
|
+ doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
|
|
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
|
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
|
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
|
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
|
|
|
|
|
@@ -836,17 +950,35 @@ sub monitor {
|
|
my $failure_start;
|
|
my $failure_start;
|
|
my $monitor_start = time;
|
|
my $monitor_start = time;
|
|
my $done = 0;
|
|
my $done = 0;
|
|
|
|
+ my $version_found = 0;
|
|
|
|
|
|
while (!$done) {
|
|
while (!$done) {
|
|
|
|
|
|
- if ($booted) {
|
|
|
|
|
|
+ if ($bug && defined($stop_after_failure) &&
|
|
|
|
+ $stop_after_failure >= 0) {
|
|
|
|
+ my $time = $stop_after_failure - (time - $failure_start);
|
|
|
|
+ $line = wait_for_input($monitor_fp, $time);
|
|
|
|
+ if (!defined($line)) {
|
|
|
|
+ doprint "bug timed out after $booted_timeout seconds\n";
|
|
|
|
+ doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
|
|
|
|
+ last;
|
|
|
|
+ }
|
|
|
|
+ } elsif ($booted) {
|
|
$line = wait_for_input($monitor_fp, $booted_timeout);
|
|
$line = wait_for_input($monitor_fp, $booted_timeout);
|
|
|
|
+ if (!defined($line)) {
|
|
|
|
+ my $s = $booted_timeout == 1 ? "" : "s";
|
|
|
|
+ doprint "Successful boot found: break after $booted_timeout second$s\n";
|
|
|
|
+ last;
|
|
|
|
+ }
|
|
} else {
|
|
} else {
|
|
$line = wait_for_input($monitor_fp);
|
|
$line = wait_for_input($monitor_fp);
|
|
|
|
+ if (!defined($line)) {
|
|
|
|
+ my $s = $timeout == 1 ? "" : "s";
|
|
|
|
+ doprint "Timed out after $timeout second$s\n";
|
|
|
|
+ last;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- last if (!defined($line));
|
|
|
|
-
|
|
|
|
doprint $line;
|
|
doprint $line;
|
|
print DMESG $line;
|
|
print DMESG $line;
|
|
|
|
|
|
@@ -896,6 +1028,22 @@ sub monitor {
|
|
$bug = 1;
|
|
$bug = 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ # Detect triple faults by testing the banner
|
|
|
|
+ if ($full_line =~ /\bLinux version (\S+).*\n/) {
|
|
|
|
+ if ($1 eq $version) {
|
|
|
|
+ $version_found = 1;
|
|
|
|
+ } elsif ($version_found && $detect_triplefault) {
|
|
|
|
+ # We already booted into the kernel we are testing,
|
|
|
|
+ # but now we booted into another kernel?
|
|
|
|
+ # Consider this a triple fault.
|
|
|
|
+ doprint "Aleady booted in Linux kernel $version, but now\n";
|
|
|
|
+ doprint "we booted into Linux kernel $1.\n";
|
|
|
|
+ doprint "Assuming that this is a triple fault.\n";
|
|
|
|
+ doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
|
|
|
|
+ last;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if ($line =~ /\n/) {
|
|
if ($line =~ /\n/) {
|
|
$full_line = "";
|
|
$full_line = "";
|
|
}
|
|
}
|
|
@@ -923,6 +1071,16 @@ sub monitor {
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+sub do_post_install {
|
|
|
|
+
|
|
|
|
+ return if (!defined($post_install));
|
|
|
|
+
|
|
|
|
+ my $cp_post_install = $post_install;
|
|
|
|
+ $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
|
|
|
|
+ run_command "$cp_post_install" or
|
|
|
|
+ dodie "Failed to run post install";
|
|
|
|
+}
|
|
|
|
+
|
|
sub install {
|
|
sub install {
|
|
|
|
|
|
run_scp "$outputdir/$build_target", "$target_image" or
|
|
run_scp "$outputdir/$build_target", "$target_image" or
|
|
@@ -942,6 +1100,7 @@ sub install {
|
|
close(IN);
|
|
close(IN);
|
|
|
|
|
|
if (!$install_mods) {
|
|
if (!$install_mods) {
|
|
|
|
+ do_post_install;
|
|
doprint "No modules needed\n";
|
|
doprint "No modules needed\n";
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -964,17 +1123,29 @@ sub install {
|
|
|
|
|
|
unlink "$tmpdir/$modtar";
|
|
unlink "$tmpdir/$modtar";
|
|
|
|
|
|
- run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
|
|
|
|
|
|
+ run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
|
|
dodie "failed to tar modules";
|
|
dodie "failed to tar modules";
|
|
|
|
|
|
run_ssh "rm -f /tmp/$modtar";
|
|
run_ssh "rm -f /tmp/$modtar";
|
|
|
|
|
|
- return if (!defined($post_install));
|
|
|
|
|
|
+ do_post_install;
|
|
|
|
+}
|
|
|
|
|
|
- my $cp_post_install = $post_install;
|
|
|
|
- $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
|
|
|
|
- run_command "$cp_post_install" or
|
|
|
|
- dodie "Failed to run post install";
|
|
|
|
|
|
+sub get_version {
|
|
|
|
+ # get the release name
|
|
|
|
+ doprint "$make kernelrelease ... ";
|
|
|
|
+ $version = `$make kernelrelease | tail -1`;
|
|
|
|
+ chomp($version);
|
|
|
|
+ doprint "$version\n";
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sub start_monitor_and_boot {
|
|
|
|
+ get_grub_index;
|
|
|
|
+ get_version;
|
|
|
|
+ install;
|
|
|
|
+
|
|
|
|
+ start_monitor;
|
|
|
|
+ return monitor;
|
|
}
|
|
}
|
|
|
|
|
|
sub check_buildlog {
|
|
sub check_buildlog {
|
|
@@ -1009,24 +1180,84 @@ sub check_buildlog {
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+sub apply_min_config {
|
|
|
|
+ my $outconfig = "$output_config.new";
|
|
|
|
+
|
|
|
|
+ # Read the config file and remove anything that
|
|
|
|
+ # is in the force_config hash (from minconfig and others)
|
|
|
|
+ # then add the force config back.
|
|
|
|
+
|
|
|
|
+ doprint "Applying minimum configurations into $output_config.new\n";
|
|
|
|
+
|
|
|
|
+ open (OUT, ">$outconfig") or
|
|
|
|
+ dodie "Can't create $outconfig";
|
|
|
|
+
|
|
|
|
+ if (-f $output_config) {
|
|
|
|
+ open (IN, $output_config) or
|
|
|
|
+ dodie "Failed to open $output_config";
|
|
|
|
+ while (<IN>) {
|
|
|
|
+ if (/^(# )?(CONFIG_[^\s=]*)/) {
|
|
|
|
+ next if (defined($force_config{$2}));
|
|
|
|
+ }
|
|
|
|
+ print OUT;
|
|
|
|
+ }
|
|
|
|
+ close IN;
|
|
|
|
+ }
|
|
|
|
+ foreach my $config (keys %force_config) {
|
|
|
|
+ print OUT "$force_config{$config}\n";
|
|
|
|
+ }
|
|
|
|
+ close OUT;
|
|
|
|
+
|
|
|
|
+ run_command "mv $outconfig $output_config";
|
|
|
|
+}
|
|
|
|
+
|
|
sub make_oldconfig {
|
|
sub make_oldconfig {
|
|
- my ($defconfig) = @_;
|
|
|
|
|
|
|
|
- if (!run_command "$defconfig $make oldnoconfig") {
|
|
|
|
|
|
+ my @force_list = keys %force_config;
|
|
|
|
+
|
|
|
|
+ if ($#force_list >= 0) {
|
|
|
|
+ apply_min_config;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!run_command "$make oldnoconfig") {
|
|
# Perhaps oldnoconfig doesn't exist in this version of the kernel
|
|
# Perhaps oldnoconfig doesn't exist in this version of the kernel
|
|
# try a yes '' | oldconfig
|
|
# try a yes '' | oldconfig
|
|
doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
|
|
doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
|
|
- run_command "yes '' | $defconfig $make oldconfig" or
|
|
|
|
|
|
+ run_command "yes '' | $make oldconfig" or
|
|
dodie "failed make config oldconfig";
|
|
dodie "failed make config oldconfig";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+# read a config file and use this to force new configs.
|
|
|
|
+sub load_force_config {
|
|
|
|
+ my ($config) = @_;
|
|
|
|
+
|
|
|
|
+ open(IN, $config) or
|
|
|
|
+ dodie "failed to read $config";
|
|
|
|
+ while (<IN>) {
|
|
|
|
+ chomp;
|
|
|
|
+ if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
|
|
|
|
+ $force_config{$1} = $_;
|
|
|
|
+ } elsif (/^# (CONFIG_\S*) is not set/) {
|
|
|
|
+ $force_config{$1} = $_;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ close IN;
|
|
|
|
+}
|
|
|
|
+
|
|
sub build {
|
|
sub build {
|
|
my ($type) = @_;
|
|
my ($type) = @_;
|
|
- my $defconfig = "";
|
|
|
|
|
|
|
|
unlink $buildlog;
|
|
unlink $buildlog;
|
|
|
|
|
|
|
|
+ if (defined($pre_build)) {
|
|
|
|
+ my $ret = run_command $pre_build;
|
|
|
|
+ if (!$ret && defined($pre_build_die) &&
|
|
|
|
+ $pre_build_die) {
|
|
|
|
+ dodie "failed to pre_build\n";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if ($type =~ /^useconfig:(.*)/) {
|
|
if ($type =~ /^useconfig:(.*)/) {
|
|
run_command "cp $1 $output_config" or
|
|
run_command "cp $1 $output_config" or
|
|
dodie "could not copy $1 to .config";
|
|
dodie "could not copy $1 to .config";
|
|
@@ -1063,24 +1294,33 @@ sub build {
|
|
close(OUT);
|
|
close(OUT);
|
|
|
|
|
|
if (defined($minconfig)) {
|
|
if (defined($minconfig)) {
|
|
- $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
|
|
|
|
|
|
+ load_force_config($minconfig);
|
|
}
|
|
}
|
|
|
|
|
|
- if ($type eq "oldnoconfig") {
|
|
|
|
- make_oldconfig $defconfig;
|
|
|
|
- } else {
|
|
|
|
- run_command "$defconfig $make $type" or
|
|
|
|
|
|
+ if ($type ne "oldnoconfig") {
|
|
|
|
+ run_command "$make $type" or
|
|
dodie "failed make config";
|
|
dodie "failed make config";
|
|
}
|
|
}
|
|
|
|
+ # Run old config regardless, to enforce min configurations
|
|
|
|
+ make_oldconfig;
|
|
|
|
|
|
$redirect = "$buildlog";
|
|
$redirect = "$buildlog";
|
|
- if (!run_command "$make $build_options") {
|
|
|
|
- undef $redirect;
|
|
|
|
|
|
+ my $build_ret = run_command "$make $build_options";
|
|
|
|
+ undef $redirect;
|
|
|
|
+
|
|
|
|
+ if (defined($post_build)) {
|
|
|
|
+ my $ret = run_command $post_build;
|
|
|
|
+ if (!$ret && defined($post_build_die) &&
|
|
|
|
+ $post_build_die) {
|
|
|
|
+ dodie "failed to post_build\n";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!$build_ret) {
|
|
# bisect may need this to pass
|
|
# bisect may need this to pass
|
|
return 0 if ($in_bisect);
|
|
return 0 if ($in_bisect);
|
|
fail "failed build" and return 0;
|
|
fail "failed build" and return 0;
|
|
}
|
|
}
|
|
- undef $redirect;
|
|
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -1102,9 +1342,15 @@ sub success {
|
|
|
|
|
|
$successes++;
|
|
$successes++;
|
|
|
|
|
|
|
|
+ my $name = "";
|
|
|
|
+
|
|
|
|
+ if (defined($test_name)) {
|
|
|
|
+ $name = " ($test_name)";
|
|
|
|
+ }
|
|
|
|
+
|
|
doprint "\n\n*******************************************\n";
|
|
doprint "\n\n*******************************************\n";
|
|
doprint "*******************************************\n";
|
|
doprint "*******************************************\n";
|
|
- doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n";
|
|
|
|
|
|
+ doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n";
|
|
doprint "*******************************************\n";
|
|
doprint "*******************************************\n";
|
|
doprint "*******************************************\n";
|
|
doprint "*******************************************\n";
|
|
|
|
|
|
@@ -1117,14 +1363,6 @@ sub success {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-sub get_version {
|
|
|
|
- # get the release name
|
|
|
|
- doprint "$make kernelrelease ... ";
|
|
|
|
- $version = `$make kernelrelease | tail -1`;
|
|
|
|
- chomp($version);
|
|
|
|
- doprint "$version\n";
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
sub answer_bisect {
|
|
sub answer_bisect {
|
|
for (;;) {
|
|
for (;;) {
|
|
doprint "Pass or fail? [p/f]";
|
|
doprint "Pass or fail? [p/f]";
|
|
@@ -1289,12 +1527,7 @@ sub run_bisect_test {
|
|
dodie "Failed on build" if $failed;
|
|
dodie "Failed on build" if $failed;
|
|
|
|
|
|
# Now boot the box
|
|
# Now boot the box
|
|
- get_grub_index;
|
|
|
|
- get_version;
|
|
|
|
- install;
|
|
|
|
-
|
|
|
|
- start_monitor;
|
|
|
|
- monitor or $failed = 1;
|
|
|
|
|
|
+ start_monitor_and_boot or $failed = 1;
|
|
|
|
|
|
if ($type ne "boot") {
|
|
if ($type ne "boot") {
|
|
if ($failed && $bisect_skip) {
|
|
if ($failed && $bisect_skip) {
|
|
@@ -1473,21 +1706,27 @@ my %null_config;
|
|
|
|
|
|
my %dependency;
|
|
my %dependency;
|
|
|
|
|
|
-sub process_config_ignore {
|
|
|
|
- my ($config) = @_;
|
|
|
|
|
|
+sub assign_configs {
|
|
|
|
+ my ($hash, $config) = @_;
|
|
|
|
|
|
open (IN, $config)
|
|
open (IN, $config)
|
|
or dodie "Failed to read $config";
|
|
or dodie "Failed to read $config";
|
|
|
|
|
|
while (<IN>) {
|
|
while (<IN>) {
|
|
if (/^((CONFIG\S*)=.*)/) {
|
|
if (/^((CONFIG\S*)=.*)/) {
|
|
- $config_ignore{$2} = $1;
|
|
|
|
|
|
+ ${$hash}{$2} = $1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
close(IN);
|
|
close(IN);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+sub process_config_ignore {
|
|
|
|
+ my ($config) = @_;
|
|
|
|
+
|
|
|
|
+ assign_configs \%config_ignore, $config;
|
|
|
|
+}
|
|
|
|
+
|
|
sub read_current_config {
|
|
sub read_current_config {
|
|
my ($config_ref) = @_;
|
|
my ($config_ref) = @_;
|
|
|
|
|
|
@@ -1546,7 +1785,7 @@ sub create_config {
|
|
close(OUT);
|
|
close(OUT);
|
|
|
|
|
|
# exit;
|
|
# exit;
|
|
- make_oldconfig "";
|
|
|
|
|
|
+ make_oldconfig;
|
|
}
|
|
}
|
|
|
|
|
|
sub compare_configs {
|
|
sub compare_configs {
|
|
@@ -1718,6 +1957,10 @@ sub config_bisect {
|
|
|
|
|
|
my $tmpconfig = "$tmpdir/use_config";
|
|
my $tmpconfig = "$tmpdir/use_config";
|
|
|
|
|
|
|
|
+ if (defined($config_bisect_good)) {
|
|
|
|
+ process_config_ignore $config_bisect_good;
|
|
|
|
+ }
|
|
|
|
+
|
|
# Make the file with the bad config and the min config
|
|
# Make the file with the bad config and the min config
|
|
if (defined($minconfig)) {
|
|
if (defined($minconfig)) {
|
|
# read the min config for things to ignore
|
|
# read the min config for things to ignore
|
|
@@ -1727,15 +1970,8 @@ sub config_bisect {
|
|
unlink $tmpconfig;
|
|
unlink $tmpconfig;
|
|
}
|
|
}
|
|
|
|
|
|
- # Add other configs
|
|
|
|
- if (defined($addconfig)) {
|
|
|
|
- run_command "cat $addconfig >> $tmpconfig" or
|
|
|
|
- dodie "failed to append $addconfig";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- my $defconfig = "";
|
|
|
|
if (-f $tmpconfig) {
|
|
if (-f $tmpconfig) {
|
|
- $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig";
|
|
|
|
|
|
+ load_force_config($tmpconfig);
|
|
process_config_ignore $tmpconfig;
|
|
process_config_ignore $tmpconfig;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1755,8 +1991,8 @@ sub config_bisect {
|
|
}
|
|
}
|
|
close(IN);
|
|
close(IN);
|
|
|
|
|
|
- # Now run oldconfig with the minconfig (and addconfigs)
|
|
|
|
- make_oldconfig $defconfig;
|
|
|
|
|
|
+ # Now run oldconfig with the minconfig
|
|
|
|
+ make_oldconfig;
|
|
|
|
|
|
# check to see what we lost (or gained)
|
|
# check to see what we lost (or gained)
|
|
open (IN, $output_config)
|
|
open (IN, $output_config)
|
|
@@ -1882,6 +2118,13 @@ sub patchcheck {
|
|
@list = reverse @list;
|
|
@list = reverse @list;
|
|
|
|
|
|
my $save_clean = $noclean;
|
|
my $save_clean = $noclean;
|
|
|
|
+ my %ignored_warnings;
|
|
|
|
+
|
|
|
|
+ if (defined($ignore_warnings)) {
|
|
|
|
+ foreach my $sha1 (split /\s+/, $ignore_warnings) {
|
|
|
|
+ $ignored_warnings{$sha1} = 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
$in_patchcheck = 1;
|
|
$in_patchcheck = 1;
|
|
foreach my $item (@list) {
|
|
foreach my $item (@list) {
|
|
@@ -1908,18 +2151,16 @@ sub patchcheck {
|
|
build "oldconfig" or return 0;
|
|
build "oldconfig" or return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- check_buildlog $sha1 or return 0;
|
|
|
|
|
|
|
|
- next if ($type eq "build");
|
|
|
|
|
|
+ if (!defined($ignored_warnings{$sha1})) {
|
|
|
|
+ check_buildlog $sha1 or return 0;
|
|
|
|
+ }
|
|
|
|
|
|
- get_grub_index;
|
|
|
|
- get_version;
|
|
|
|
- install;
|
|
|
|
|
|
+ next if ($type eq "build");
|
|
|
|
|
|
my $failed = 0;
|
|
my $failed = 0;
|
|
|
|
|
|
- start_monitor;
|
|
|
|
- monitor or $failed = 1;
|
|
|
|
|
|
+ start_monitor_and_boot or $failed = 1;
|
|
|
|
|
|
if (!$failed && $type ne "boot"){
|
|
if (!$failed && $type ne "boot"){
|
|
do_run_test or $failed = 1;
|
|
do_run_test or $failed = 1;
|
|
@@ -1936,24 +2177,505 @@ sub patchcheck {
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+my %depends;
|
|
|
|
+my $iflevel = 0;
|
|
|
|
+my @ifdeps;
|
|
|
|
+
|
|
|
|
+# prevent recursion
|
|
|
|
+my %read_kconfigs;
|
|
|
|
+
|
|
|
|
+# taken from streamline_config.pl
|
|
|
|
+sub read_kconfig {
|
|
|
|
+ my ($kconfig) = @_;
|
|
|
|
+
|
|
|
|
+ my $state = "NONE";
|
|
|
|
+ my $config;
|
|
|
|
+ my @kconfigs;
|
|
|
|
+
|
|
|
|
+ my $cont = 0;
|
|
|
|
+ my $line;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (! -f $kconfig) {
|
|
|
|
+ doprint "file $kconfig does not exist, skipping\n";
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ open(KIN, "$kconfig")
|
|
|
|
+ or die "Can't open $kconfig";
|
|
|
|
+ while (<KIN>) {
|
|
|
|
+ chomp;
|
|
|
|
+
|
|
|
|
+ # Make sure that lines ending with \ continue
|
|
|
|
+ if ($cont) {
|
|
|
|
+ $_ = $line . " " . $_;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (s/\\$//) {
|
|
|
|
+ $cont = 1;
|
|
|
|
+ $line = $_;
|
|
|
|
+ next;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $cont = 0;
|
|
|
|
+
|
|
|
|
+ # collect any Kconfig sources
|
|
|
|
+ if (/^source\s*"(.*)"/) {
|
|
|
|
+ $kconfigs[$#kconfigs+1] = $1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # configs found
|
|
|
|
+ if (/^\s*(menu)?config\s+(\S+)\s*$/) {
|
|
|
|
+ $state = "NEW";
|
|
|
|
+ $config = $2;
|
|
|
|
+
|
|
|
|
+ for (my $i = 0; $i < $iflevel; $i++) {
|
|
|
|
+ if ($i) {
|
|
|
|
+ $depends{$config} .= " " . $ifdeps[$i];
|
|
|
|
+ } else {
|
|
|
|
+ $depends{$config} = $ifdeps[$i];
|
|
|
|
+ }
|
|
|
|
+ $state = "DEP";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # collect the depends for the config
|
|
|
|
+ } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
|
|
|
|
+
|
|
|
|
+ if (defined($depends{$1})) {
|
|
|
|
+ $depends{$config} .= " " . $1;
|
|
|
|
+ } else {
|
|
|
|
+ $depends{$config} = $1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # Get the configs that select this config
|
|
|
|
+ } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
|
|
|
|
+ if (defined($depends{$1})) {
|
|
|
|
+ $depends{$1} .= " " . $config;
|
|
|
|
+ } else {
|
|
|
|
+ $depends{$1} = $config;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # Check for if statements
|
|
|
|
+ } elsif (/^if\s+(.*\S)\s*$/) {
|
|
|
|
+ my $deps = $1;
|
|
|
|
+ # remove beginning and ending non text
|
|
|
|
+ $deps =~ s/^[^a-zA-Z0-9_]*//;
|
|
|
|
+ $deps =~ s/[^a-zA-Z0-9_]*$//;
|
|
|
|
+
|
|
|
|
+ my @deps = split /[^a-zA-Z0-9_]+/, $deps;
|
|
|
|
+
|
|
|
|
+ $ifdeps[$iflevel++] = join ':', @deps;
|
|
|
|
+
|
|
|
|
+ } elsif (/^endif/) {
|
|
|
|
+
|
|
|
|
+ $iflevel-- if ($iflevel);
|
|
|
|
+
|
|
|
|
+ # stop on "help"
|
|
|
|
+ } elsif (/^\s*help\s*$/) {
|
|
|
|
+ $state = "NONE";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ close(KIN);
|
|
|
|
+
|
|
|
|
+ # read in any configs that were found.
|
|
|
|
+ foreach $kconfig (@kconfigs) {
|
|
|
|
+ if (!defined($read_kconfigs{$kconfig})) {
|
|
|
|
+ $read_kconfigs{$kconfig} = 1;
|
|
|
|
+ read_kconfig("$builddir/$kconfig");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sub read_depends {
|
|
|
|
+ # find out which arch this is by the kconfig file
|
|
|
|
+ open (IN, $output_config)
|
|
|
|
+ or dodie "Failed to read $output_config";
|
|
|
|
+ my $arch;
|
|
|
|
+ while (<IN>) {
|
|
|
|
+ if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
|
|
|
|
+ $arch = $1;
|
|
|
|
+ last;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ close IN;
|
|
|
|
+
|
|
|
|
+ if (!defined($arch)) {
|
|
|
|
+ doprint "Could not find arch from config file\n";
|
|
|
|
+ doprint "no dependencies used\n";
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # arch is really the subarch, we need to know
|
|
|
|
+ # what directory to look at.
|
|
|
|
+ if ($arch eq "i386" || $arch eq "x86_64") {
|
|
|
|
+ $arch = "x86";
|
|
|
|
+ } elsif ($arch =~ /^tile/) {
|
|
|
|
+ $arch = "tile";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ my $kconfig = "$builddir/arch/$arch/Kconfig";
|
|
|
|
+
|
|
|
|
+ if (! -f $kconfig && $arch =~ /\d$/) {
|
|
|
|
+ my $orig = $arch;
|
|
|
|
+ # some subarchs have numbers, truncate them
|
|
|
|
+ $arch =~ s/\d*$//;
|
|
|
|
+ $kconfig = "$builddir/arch/$arch/Kconfig";
|
|
|
|
+ if (! -f $kconfig) {
|
|
|
|
+ doprint "No idea what arch dir $orig is for\n";
|
|
|
|
+ doprint "no dependencies used\n";
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ read_kconfig($kconfig);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sub read_config_list {
|
|
|
|
+ my ($config) = @_;
|
|
|
|
+
|
|
|
|
+ open (IN, $config)
|
|
|
|
+ or dodie "Failed to read $config";
|
|
|
|
+
|
|
|
|
+ while (<IN>) {
|
|
|
|
+ if (/^((CONFIG\S*)=.*)/) {
|
|
|
|
+ if (!defined($config_ignore{$2})) {
|
|
|
|
+ $config_list{$2} = $1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ close(IN);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sub read_output_config {
|
|
|
|
+ my ($config) = @_;
|
|
|
|
+
|
|
|
|
+ assign_configs \%config_ignore, $config;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sub make_new_config {
|
|
|
|
+ my @configs = @_;
|
|
|
|
+
|
|
|
|
+ open (OUT, ">$output_config")
|
|
|
|
+ or dodie "Failed to write $output_config";
|
|
|
|
+
|
|
|
|
+ foreach my $config (@configs) {
|
|
|
|
+ print OUT "$config\n";
|
|
|
|
+ }
|
|
|
|
+ close OUT;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sub get_depends {
|
|
|
|
+ my ($dep) = @_;
|
|
|
|
+
|
|
|
|
+ my $kconfig = $dep;
|
|
|
|
+ $kconfig =~ s/CONFIG_//;
|
|
|
|
+
|
|
|
|
+ $dep = $depends{"$kconfig"};
|
|
|
|
+
|
|
|
|
+ # the dep string we have saves the dependencies as they
|
|
|
|
+ # were found, including expressions like ! && ||. We
|
|
|
|
+ # want to split this out into just an array of configs.
|
|
|
|
+
|
|
|
|
+ my $valid = "A-Za-z_0-9";
|
|
|
|
+
|
|
|
|
+ my @configs;
|
|
|
|
+
|
|
|
|
+ while ($dep =~ /[$valid]/) {
|
|
|
|
+
|
|
|
|
+ if ($dep =~ /^[^$valid]*([$valid]+)/) {
|
|
|
|
+ my $conf = "CONFIG_" . $1;
|
|
|
|
+
|
|
|
|
+ $configs[$#configs + 1] = $conf;
|
|
|
|
+
|
|
|
|
+ $dep =~ s/^[^$valid]*[$valid]+//;
|
|
|
|
+ } else {
|
|
|
|
+ die "this should never happen";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return @configs;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+my %min_configs;
|
|
|
|
+my %keep_configs;
|
|
|
|
+my %save_configs;
|
|
|
|
+my %processed_configs;
|
|
|
|
+my %nochange_config;
|
|
|
|
+
|
|
|
|
+sub test_this_config {
|
|
|
|
+ my ($config) = @_;
|
|
|
|
+
|
|
|
|
+ my $found;
|
|
|
|
+
|
|
|
|
+ # if we already processed this config, skip it
|
|
|
|
+ if (defined($processed_configs{$config})) {
|
|
|
|
+ return undef;
|
|
|
|
+ }
|
|
|
|
+ $processed_configs{$config} = 1;
|
|
|
|
+
|
|
|
|
+ # if this config failed during this round, skip it
|
|
|
|
+ if (defined($nochange_config{$config})) {
|
|
|
|
+ return undef;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ my $kconfig = $config;
|
|
|
|
+ $kconfig =~ s/CONFIG_//;
|
|
|
|
+
|
|
|
|
+ # Test dependencies first
|
|
|
|
+ if (defined($depends{"$kconfig"})) {
|
|
|
|
+ my @parents = get_depends $config;
|
|
|
|
+ foreach my $parent (@parents) {
|
|
|
|
+ # if the parent is in the min config, check it first
|
|
|
|
+ next if (!defined($min_configs{$parent}));
|
|
|
|
+ $found = test_this_config($parent);
|
|
|
|
+ if (defined($found)) {
|
|
|
|
+ return $found;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # Remove this config from the list of configs
|
|
|
|
+ # do a make oldnoconfig and then read the resulting
|
|
|
|
+ # .config to make sure it is missing the config that
|
|
|
|
+ # we had before
|
|
|
|
+ my %configs = %min_configs;
|
|
|
|
+ delete $configs{$config};
|
|
|
|
+ make_new_config ((values %configs), (values %keep_configs));
|
|
|
|
+ make_oldconfig;
|
|
|
|
+ undef %configs;
|
|
|
|
+ assign_configs \%configs, $output_config;
|
|
|
|
+
|
|
|
|
+ return $config if (!defined($configs{$config}));
|
|
|
|
+
|
|
|
|
+ doprint "disabling config $config did not change .config\n";
|
|
|
|
+
|
|
|
|
+ $nochange_config{$config} = 1;
|
|
|
|
+
|
|
|
|
+ return undef;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sub make_min_config {
|
|
|
|
+ my ($i) = @_;
|
|
|
|
+
|
|
|
|
+ if (!defined($output_minconfig)) {
|
|
|
|
+ fail "OUTPUT_MIN_CONFIG not defined" and return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # If output_minconfig exists, and the start_minconfig
|
|
|
|
+ # came from min_config, than ask if we should use
|
|
|
|
+ # that instead.
|
|
|
|
+ if (-f $output_minconfig && !$start_minconfig_defined) {
|
|
|
|
+ print "$output_minconfig exists\n";
|
|
|
|
+ if (read_yn " Use it as minconfig?") {
|
|
|
|
+ $start_minconfig = $output_minconfig;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!defined($start_minconfig)) {
|
|
|
|
+ fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ my $temp_config = "$tmpdir/temp_config";
|
|
|
|
+
|
|
|
|
+ # First things first. We build an allnoconfig to find
|
|
|
|
+ # out what the defaults are that we can't touch.
|
|
|
|
+ # Some are selections, but we really can't handle selections.
|
|
|
|
+
|
|
|
|
+ my $save_minconfig = $minconfig;
|
|
|
|
+ undef $minconfig;
|
|
|
|
+
|
|
|
|
+ run_command "$make allnoconfig" or return 0;
|
|
|
|
+
|
|
|
|
+ read_depends;
|
|
|
|
+
|
|
|
|
+ process_config_ignore $output_config;
|
|
|
|
+
|
|
|
|
+ undef %save_configs;
|
|
|
|
+ undef %min_configs;
|
|
|
|
+
|
|
|
|
+ if (defined($ignore_config)) {
|
|
|
|
+ # make sure the file exists
|
|
|
|
+ `touch $ignore_config`;
|
|
|
|
+ assign_configs \%save_configs, $ignore_config;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ %keep_configs = %save_configs;
|
|
|
|
+
|
|
|
|
+ doprint "Load initial configs from $start_minconfig\n";
|
|
|
|
+
|
|
|
|
+ # Look at the current min configs, and save off all the
|
|
|
|
+ # ones that were set via the allnoconfig
|
|
|
|
+ assign_configs \%min_configs, $start_minconfig;
|
|
|
|
+
|
|
|
|
+ my @config_keys = keys %min_configs;
|
|
|
|
+
|
|
|
|
+ # Remove anything that was set by the make allnoconfig
|
|
|
|
+ # we shouldn't need them as they get set for us anyway.
|
|
|
|
+ foreach my $config (@config_keys) {
|
|
|
|
+ # Remove anything in the ignore_config
|
|
|
|
+ if (defined($keep_configs{$config})) {
|
|
|
|
+ my $file = $ignore_config;
|
|
|
|
+ $file =~ s,.*/(.*?)$,$1,;
|
|
|
|
+ doprint "$config set by $file ... ignored\n";
|
|
|
|
+ delete $min_configs{$config};
|
|
|
|
+ next;
|
|
|
|
+ }
|
|
|
|
+ # But make sure the settings are the same. If a min config
|
|
|
|
+ # sets a selection, we do not want to get rid of it if
|
|
|
|
+ # it is not the same as what we have. Just move it into
|
|
|
|
+ # the keep configs.
|
|
|
|
+ if (defined($config_ignore{$config})) {
|
|
|
|
+ if ($config_ignore{$config} ne $min_configs{$config}) {
|
|
|
|
+ doprint "$config is in allnoconfig as '$config_ignore{$config}'";
|
|
|
|
+ doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
|
|
|
|
+ $keep_configs{$config} = $min_configs{$config};
|
|
|
|
+ } else {
|
|
|
|
+ doprint "$config set by allnoconfig ... ignored\n";
|
|
|
|
+ }
|
|
|
|
+ delete $min_configs{$config};
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ my $done = 0;
|
|
|
|
+ my $take_two = 0;
|
|
|
|
+
|
|
|
|
+ while (!$done) {
|
|
|
|
+
|
|
|
|
+ my $config;
|
|
|
|
+ my $found;
|
|
|
|
+
|
|
|
|
+ # Now disable each config one by one and do a make oldconfig
|
|
|
|
+ # till we find a config that changes our list.
|
|
|
|
+
|
|
|
|
+ # Put configs that did not modify the config at the end.
|
|
|
|
+ my @test_configs = keys %min_configs;
|
|
|
|
+ my $reset = 1;
|
|
|
|
+ for (my $i = 0; $i < $#test_configs; $i++) {
|
|
|
|
+ if (!defined($nochange_config{$test_configs[0]})) {
|
|
|
|
+ $reset = 0;
|
|
|
|
+ last;
|
|
|
|
+ }
|
|
|
|
+ # This config didn't change the .config last time.
|
|
|
|
+ # Place it at the end
|
|
|
|
+ my $config = shift @test_configs;
|
|
|
|
+ push @test_configs, $config;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # if every test config has failed to modify the .config file
|
|
|
|
+ # in the past, then reset and start over.
|
|
|
|
+ if ($reset) {
|
|
|
|
+ undef %nochange_config;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undef %processed_configs;
|
|
|
|
+
|
|
|
|
+ foreach my $config (@test_configs) {
|
|
|
|
+
|
|
|
|
+ $found = test_this_config $config;
|
|
|
|
+
|
|
|
|
+ last if (defined($found));
|
|
|
|
+
|
|
|
|
+ # oh well, try another config
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!defined($found)) {
|
|
|
|
+ # we could have failed due to the nochange_config hash
|
|
|
|
+ # reset and try again
|
|
|
|
+ if (!$take_two) {
|
|
|
|
+ undef %nochange_config;
|
|
|
|
+ $take_two = 1;
|
|
|
|
+ next;
|
|
|
|
+ }
|
|
|
|
+ doprint "No more configs found that we can disable\n";
|
|
|
|
+ $done = 1;
|
|
|
|
+ last;
|
|
|
|
+ }
|
|
|
|
+ $take_two = 0;
|
|
|
|
+
|
|
|
|
+ $config = $found;
|
|
|
|
+
|
|
|
|
+ doprint "Test with $config disabled\n";
|
|
|
|
+
|
|
|
|
+ # set in_bisect to keep build and monitor from dieing
|
|
|
|
+ $in_bisect = 1;
|
|
|
|
+
|
|
|
|
+ my $failed = 0;
|
|
|
|
+ build "oldconfig";
|
|
|
|
+ start_monitor_and_boot or $failed = 1;
|
|
|
|
+ end_monitor;
|
|
|
|
+
|
|
|
|
+ $in_bisect = 0;
|
|
|
|
+
|
|
|
|
+ if ($failed) {
|
|
|
|
+ doprint "$min_configs{$config} is needed to boot the box... keeping\n";
|
|
|
|
+ # this config is needed, add it to the ignore list.
|
|
|
|
+ $keep_configs{$config} = $min_configs{$config};
|
|
|
|
+ $save_configs{$config} = $min_configs{$config};
|
|
|
|
+ delete $min_configs{$config};
|
|
|
|
+
|
|
|
|
+ # update new ignore configs
|
|
|
|
+ if (defined($ignore_config)) {
|
|
|
|
+ open (OUT, ">$temp_config")
|
|
|
|
+ or die "Can't write to $temp_config";
|
|
|
|
+ foreach my $config (keys %save_configs) {
|
|
|
|
+ print OUT "$save_configs{$config}\n";
|
|
|
|
+ }
|
|
|
|
+ close OUT;
|
|
|
|
+ run_command "mv $temp_config $ignore_config" or
|
|
|
|
+ dodie "failed to copy update to $ignore_config";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ # We booted without this config, remove it from the minconfigs.
|
|
|
|
+ doprint "$config is not needed, disabling\n";
|
|
|
|
+
|
|
|
|
+ delete $min_configs{$config};
|
|
|
|
+
|
|
|
|
+ # Also disable anything that is not enabled in this config
|
|
|
|
+ my %configs;
|
|
|
|
+ assign_configs \%configs, $output_config;
|
|
|
|
+ my @config_keys = keys %min_configs;
|
|
|
|
+ foreach my $config (@config_keys) {
|
|
|
|
+ if (!defined($configs{$config})) {
|
|
|
|
+ doprint "$config is not set, disabling\n";
|
|
|
|
+ delete $min_configs{$config};
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # Save off all the current mandidory configs
|
|
|
|
+ open (OUT, ">$temp_config")
|
|
|
|
+ or die "Can't write to $temp_config";
|
|
|
|
+ foreach my $config (keys %keep_configs) {
|
|
|
|
+ print OUT "$keep_configs{$config}\n";
|
|
|
|
+ }
|
|
|
|
+ foreach my $config (keys %min_configs) {
|
|
|
|
+ print OUT "$min_configs{$config}\n";
|
|
|
|
+ }
|
|
|
|
+ close OUT;
|
|
|
|
+
|
|
|
|
+ run_command "mv $temp_config $output_minconfig" or
|
|
|
|
+ dodie "failed to copy update to $output_minconfig";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ doprint "Reboot and wait $sleep_time seconds\n";
|
|
|
|
+ reboot;
|
|
|
|
+ start_monitor;
|
|
|
|
+ wait_for_monitor $sleep_time;
|
|
|
|
+ end_monitor;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ success $i;
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n";
|
|
$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n";
|
|
|
|
|
|
if ($#ARGV == 0) {
|
|
if ($#ARGV == 0) {
|
|
$ktest_config = $ARGV[0];
|
|
$ktest_config = $ARGV[0];
|
|
if (! -f $ktest_config) {
|
|
if (! -f $ktest_config) {
|
|
print "$ktest_config does not exist.\n";
|
|
print "$ktest_config does not exist.\n";
|
|
- my $ans;
|
|
|
|
- for (;;) {
|
|
|
|
- print "Create it? [Y/n] ";
|
|
|
|
- $ans = <STDIN>;
|
|
|
|
- chomp $ans;
|
|
|
|
- if ($ans =~ /^\s*$/) {
|
|
|
|
- $ans = "y";
|
|
|
|
- }
|
|
|
|
- last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
|
|
|
|
- print "Please answer either 'y' or 'n'.\n";
|
|
|
|
- }
|
|
|
|
- if ($ans !~ /^y$/i) {
|
|
|
|
|
|
+ if (!read_yn "Create it?") {
|
|
exit 0;
|
|
exit 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1977,6 +2699,10 @@ EOF
|
|
}
|
|
}
|
|
read_config $ktest_config;
|
|
read_config $ktest_config;
|
|
|
|
|
|
|
|
+if (defined($opt{"LOG_FILE"})) {
|
|
|
|
+ $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
|
|
|
|
+}
|
|
|
|
+
|
|
# Append any configs entered in manually to the config file.
|
|
# Append any configs entered in manually to the config file.
|
|
my @new_configs = keys %entered_configs;
|
|
my @new_configs = keys %entered_configs;
|
|
if ($#new_configs >= 0) {
|
|
if ($#new_configs >= 0) {
|
|
@@ -2045,70 +2771,13 @@ sub __set_test_option {
|
|
return undef;
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
|
|
-sub eval_option {
|
|
|
|
- my ($option, $i) = @_;
|
|
|
|
-
|
|
|
|
- # Add space to evaluate the character before $
|
|
|
|
- $option = " $option";
|
|
|
|
- my $retval = "";
|
|
|
|
-
|
|
|
|
- while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
|
|
|
|
- my $start = $1;
|
|
|
|
- my $var = $2;
|
|
|
|
- my $end = $3;
|
|
|
|
-
|
|
|
|
- # Append beginning of line
|
|
|
|
- $retval = "$retval$start";
|
|
|
|
-
|
|
|
|
- # If the iteration option OPT[$i] exists, then use that.
|
|
|
|
- # otherwise see if the default OPT (without [$i]) exists.
|
|
|
|
-
|
|
|
|
- my $o = "$var\[$i\]";
|
|
|
|
-
|
|
|
|
- if (defined($opt{$o})) {
|
|
|
|
- $o = $opt{$o};
|
|
|
|
- $retval = "$retval$o";
|
|
|
|
- } elsif (defined($opt{$var})) {
|
|
|
|
- $o = $opt{$var};
|
|
|
|
- $retval = "$retval$o";
|
|
|
|
- } else {
|
|
|
|
- $retval = "$retval\$\{$var\}";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $option = $end;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $retval = "$retval$option";
|
|
|
|
-
|
|
|
|
- $retval =~ s/^ //;
|
|
|
|
-
|
|
|
|
- return $retval;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
sub set_test_option {
|
|
sub set_test_option {
|
|
my ($name, $i) = @_;
|
|
my ($name, $i) = @_;
|
|
|
|
|
|
my $option = __set_test_option($name, $i);
|
|
my $option = __set_test_option($name, $i);
|
|
return $option if (!defined($option));
|
|
return $option if (!defined($option));
|
|
|
|
|
|
- my $prev = "";
|
|
|
|
-
|
|
|
|
- # Since an option can evaluate to another option,
|
|
|
|
- # keep iterating until we do not evaluate any more
|
|
|
|
- # options.
|
|
|
|
- my $r = 0;
|
|
|
|
- while ($prev ne $option) {
|
|
|
|
- # Check for recursive evaluations.
|
|
|
|
- # 100 deep should be more than enough.
|
|
|
|
- if ($r++ > 100) {
|
|
|
|
- die "Over 100 evaluations accurred with $name\n" .
|
|
|
|
- "Check for recursive variables\n";
|
|
|
|
- }
|
|
|
|
- $prev = $option;
|
|
|
|
- $option = eval_option($option, $i);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return $option;
|
|
|
|
|
|
+ return eval_option($option, $i);
|
|
}
|
|
}
|
|
|
|
|
|
# First we need to do is the builds
|
|
# First we need to do is the builds
|
|
@@ -2126,10 +2795,17 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
|
|
$test_type = set_test_option("TEST_TYPE", $i);
|
|
$test_type = set_test_option("TEST_TYPE", $i);
|
|
$build_type = set_test_option("BUILD_TYPE", $i);
|
|
$build_type = set_test_option("BUILD_TYPE", $i);
|
|
$build_options = set_test_option("BUILD_OPTIONS", $i);
|
|
$build_options = set_test_option("BUILD_OPTIONS", $i);
|
|
|
|
+ $pre_build = set_test_option("PRE_BUILD", $i);
|
|
|
|
+ $post_build = set_test_option("POST_BUILD", $i);
|
|
|
|
+ $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
|
|
|
|
+ $post_build_die = set_test_option("POST_BUILD_DIE", $i);
|
|
$power_cycle = set_test_option("POWER_CYCLE", $i);
|
|
$power_cycle = set_test_option("POWER_CYCLE", $i);
|
|
$reboot = set_test_option("REBOOT", $i);
|
|
$reboot = set_test_option("REBOOT", $i);
|
|
$noclean = set_test_option("BUILD_NOCLEAN", $i);
|
|
$noclean = set_test_option("BUILD_NOCLEAN", $i);
|
|
$minconfig = set_test_option("MIN_CONFIG", $i);
|
|
$minconfig = set_test_option("MIN_CONFIG", $i);
|
|
|
|
+ $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
|
|
|
|
+ $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
|
|
|
|
+ $ignore_config = set_test_option("IGNORE_CONFIG", $i);
|
|
$run_test = set_test_option("TEST", $i);
|
|
$run_test = set_test_option("TEST", $i);
|
|
$addconfig = set_test_option("ADD_CONFIG", $i);
|
|
$addconfig = set_test_option("ADD_CONFIG", $i);
|
|
$reboot_type = set_test_option("REBOOT_TYPE", $i);
|
|
$reboot_type = set_test_option("REBOOT_TYPE", $i);
|
|
@@ -2145,12 +2821,16 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
|
|
$sleep_time = set_test_option("SLEEP_TIME", $i);
|
|
$sleep_time = set_test_option("SLEEP_TIME", $i);
|
|
$bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
|
|
$bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
|
|
$patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
|
|
$patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
|
|
|
|
+ $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
|
|
$bisect_manual = set_test_option("BISECT_MANUAL", $i);
|
|
$bisect_manual = set_test_option("BISECT_MANUAL", $i);
|
|
$bisect_skip = set_test_option("BISECT_SKIP", $i);
|
|
$bisect_skip = set_test_option("BISECT_SKIP", $i);
|
|
|
|
+ $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
|
|
$store_failures = set_test_option("STORE_FAILURES", $i);
|
|
$store_failures = set_test_option("STORE_FAILURES", $i);
|
|
|
|
+ $test_name = set_test_option("TEST_NAME", $i);
|
|
$timeout = set_test_option("TIMEOUT", $i);
|
|
$timeout = set_test_option("TIMEOUT", $i);
|
|
$booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
|
|
$booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
|
|
$console = set_test_option("CONSOLE", $i);
|
|
$console = set_test_option("CONSOLE", $i);
|
|
|
|
+ $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
|
|
$success_line = set_test_option("SUCCESS_LINE", $i);
|
|
$success_line = set_test_option("SUCCESS_LINE", $i);
|
|
$stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
|
|
$stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
|
|
$stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
|
|
$stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
|
|
@@ -2161,6 +2841,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
|
|
$target_image = set_test_option("TARGET_IMAGE", $i);
|
|
$target_image = set_test_option("TARGET_IMAGE", $i);
|
|
$localversion = set_test_option("LOCALVERSION", $i);
|
|
$localversion = set_test_option("LOCALVERSION", $i);
|
|
|
|
|
|
|
|
+ $start_minconfig_defined = 1;
|
|
|
|
+
|
|
|
|
+ if (!defined($start_minconfig)) {
|
|
|
|
+ $start_minconfig_defined = 0;
|
|
|
|
+ $start_minconfig = $minconfig;
|
|
|
|
+ }
|
|
|
|
+
|
|
chdir $builddir || die "can't change directory to $builddir";
|
|
chdir $builddir || die "can't change directory to $builddir";
|
|
|
|
|
|
if (!-d $tmpdir) {
|
|
if (!-d $tmpdir) {
|
|
@@ -2193,6 +2880,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
|
|
$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
|
|
$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if ($test_type eq "make_min_config") {
|
|
|
|
+ $run_type = "";
|
|
|
|
+ }
|
|
|
|
+
|
|
# mistake in config file?
|
|
# mistake in config file?
|
|
if (!defined($run_type)) {
|
|
if (!defined($run_type)) {
|
|
$run_type = "ERROR";
|
|
$run_type = "ERROR";
|
|
@@ -2204,11 +2895,12 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
|
|
unlink $dmesg;
|
|
unlink $dmesg;
|
|
unlink $buildlog;
|
|
unlink $buildlog;
|
|
|
|
|
|
- if (!defined($minconfig)) {
|
|
|
|
- $minconfig = $addconfig;
|
|
|
|
-
|
|
|
|
- } elsif (defined($addconfig)) {
|
|
|
|
- run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
|
|
|
|
|
|
+ if (defined($addconfig)) {
|
|
|
|
+ my $min = $minconfig;
|
|
|
|
+ if (!defined($minconfig)) {
|
|
|
|
+ $min = "";
|
|
|
|
+ }
|
|
|
|
+ run_command "cat $addconfig $min > $tmpdir/add_config" or
|
|
dodie "Failed to create temp config";
|
|
dodie "Failed to create temp config";
|
|
$minconfig = "$tmpdir/add_config";
|
|
$minconfig = "$tmpdir/add_config";
|
|
}
|
|
}
|
|
@@ -2228,6 +2920,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
|
|
} elsif ($test_type eq "patchcheck") {
|
|
} elsif ($test_type eq "patchcheck") {
|
|
patchcheck $i;
|
|
patchcheck $i;
|
|
next;
|
|
next;
|
|
|
|
+ } elsif ($test_type eq "make_min_config") {
|
|
|
|
+ make_min_config $i;
|
|
|
|
+ next;
|
|
}
|
|
}
|
|
|
|
|
|
if ($build_type ne "nobuild") {
|
|
if ($build_type ne "nobuild") {
|
|
@@ -2235,13 +2930,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
|
|
}
|
|
}
|
|
|
|
|
|
if ($test_type ne "build") {
|
|
if ($test_type ne "build") {
|
|
- get_grub_index;
|
|
|
|
- get_version;
|
|
|
|
- install;
|
|
|
|
-
|
|
|
|
my $failed = 0;
|
|
my $failed = 0;
|
|
- start_monitor;
|
|
|
|
- monitor or $failed = 1;;
|
|
|
|
|
|
+ start_monitor_and_boot or $failed = 1;
|
|
|
|
|
|
if (!$failed && $test_type ne "boot" && defined($run_test)) {
|
|
if (!$failed && $test_type ne "boot" && defined($run_test)) {
|
|
do_run_test or $failed = 1;
|
|
do_run_test or $failed = 1;
|