aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-07-15 21:25:24 -0400
committerSteven Rostedt <rostedt@goodmis.org>2011-07-15 21:29:09 -0400
commitb9066f6c0e215386d4b888eaedd739397b987421 (patch)
treeb8b319812e7d70150de827720d71a9e776b53e71 /tools
parent4c4ab1204fe4e201ece94c3062aa6b5eed670457 (diff)
ktest: Use Kconfig dependencies to shorten time to make min_config
To save time, the test does not just grab any option and test it. The Kconfig files are examined to determine the dependencies of the configs. If a config is chosen that depends on another config, that config will be checked first. By checking the parents first, we can eliminate whole groups of configs that may have been enabled. For example, if a USB device config is chosen and depends on CONFIG_USB, the CONFIG_USB will be tested before the device. If CONFIG_USB is found not to be needed, it, as well as all configs that depend on it, will be disabled and removed from the current min_config. Note, the code from streamline_config (make localmodconfig) was copied and used to find the dependencies in the Kconfig file. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'tools')
-rwxr-xr-xtools/testing/ktest/ktest.pl283
-rw-r--r--tools/testing/ktest/sample.conf12
2 files changed, 273 insertions, 22 deletions
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index 5323c6f9bf9b..a9f2e10fc16f 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -2162,6 +2162,159 @@ sub patchcheck {
2162 return 1; 2162 return 1;
2163} 2163}
2164 2164
2165my %depends;
2166my $iflevel = 0;
2167my @ifdeps;
2168
2169# prevent recursion
2170my %read_kconfigs;
2171
2172# taken from streamline_config.pl
2173sub read_kconfig {
2174 my ($kconfig) = @_;
2175
2176 my $state = "NONE";
2177 my $config;
2178 my @kconfigs;
2179
2180 my $cont = 0;
2181 my $line;
2182
2183
2184 if (! -f $kconfig) {
2185 doprint "file $kconfig does not exist, skipping\n";
2186 return;
2187 }
2188
2189 open(KIN, "$kconfig")
2190 or die "Can't open $kconfig";
2191 while (<KIN>) {
2192 chomp;
2193
2194 # Make sure that lines ending with \ continue
2195 if ($cont) {
2196 $_ = $line . " " . $_;
2197 }
2198
2199 if (s/\\$//) {
2200 $cont = 1;
2201 $line = $_;
2202 next;
2203 }
2204
2205 $cont = 0;
2206
2207 # collect any Kconfig sources
2208 if (/^source\s*"(.*)"/) {
2209 $kconfigs[$#kconfigs+1] = $1;
2210 }
2211
2212 # configs found
2213 if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2214 $state = "NEW";
2215 $config = $2;
2216
2217 for (my $i = 0; $i < $iflevel; $i++) {
2218 if ($i) {
2219 $depends{$config} .= " " . $ifdeps[$i];
2220 } else {
2221 $depends{$config} = $ifdeps[$i];
2222 }
2223 $state = "DEP";
2224 }
2225
2226 # collect the depends for the config
2227 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2228
2229 if (defined($depends{$1})) {
2230 $depends{$config} .= " " . $1;
2231 } else {
2232 $depends{$config} = $1;
2233 }
2234
2235 # Get the configs that select this config
2236 } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
2237 if (defined($depends{$1})) {
2238 $depends{$1} .= " " . $config;
2239 } else {
2240 $depends{$1} = $config;
2241 }
2242
2243 # Check for if statements
2244 } elsif (/^if\s+(.*\S)\s*$/) {
2245 my $deps = $1;
2246 # remove beginning and ending non text
2247 $deps =~ s/^[^a-zA-Z0-9_]*//;
2248 $deps =~ s/[^a-zA-Z0-9_]*$//;
2249
2250 my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2251
2252 $ifdeps[$iflevel++] = join ':', @deps;
2253
2254 } elsif (/^endif/) {
2255
2256 $iflevel-- if ($iflevel);
2257
2258 # stop on "help"
2259 } elsif (/^\s*help\s*$/) {
2260 $state = "NONE";
2261 }
2262 }
2263 close(KIN);
2264
2265 # read in any configs that were found.
2266 foreach $kconfig (@kconfigs) {
2267 if (!defined($read_kconfigs{$kconfig})) {
2268 $read_kconfigs{$kconfig} = 1;
2269 read_kconfig("$builddir/$kconfig");
2270 }
2271 }
2272}
2273
2274sub read_depends {
2275 # find out which arch this is by the kconfig file
2276 open (IN, $output_config)
2277 or dodie "Failed to read $output_config";
2278 my $arch;
2279 while (<IN>) {
2280 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2281 $arch = $1;
2282 last;
2283 }
2284 }
2285 close IN;
2286
2287 if (!defined($arch)) {
2288 doprint "Could not find arch from config file\n";
2289 doprint "no dependencies used\n";
2290 return;
2291 }
2292
2293 # arch is really the subarch, we need to know
2294 # what directory to look at.
2295 if ($arch eq "i386" || $arch eq "x86_64") {
2296 $arch = "x86";
2297 } elsif ($arch =~ /^tile/) {
2298 $arch = "tile";
2299 }
2300
2301 my $kconfig = "$builddir/arch/$arch/Kconfig";
2302
2303 if (! -f $kconfig && $arch =~ /\d$/) {
2304 my $orig = $arch;
2305 # some subarchs have numbers, truncate them
2306 $arch =~ s/\d*$//;
2307 $kconfig = "$builddir/arch/$arch/Kconfig";
2308 if (! -f $kconfig) {
2309 doprint "No idea what arch dir $orig is for\n";
2310 doprint "no dependencies used\n";
2311 return;
2312 }
2313 }
2314
2315 read_kconfig($kconfig);
2316}
2317
2165sub read_config_list { 2318sub read_config_list {
2166 my ($config) = @_; 2319 my ($config) = @_;
2167 2320
@@ -2197,6 +2350,95 @@ sub make_new_config {
2197 close OUT; 2350 close OUT;
2198} 2351}
2199 2352
2353sub get_depends {
2354 my ($dep) = @_;
2355
2356 my $kconfig = $dep;
2357 $kconfig =~ s/CONFIG_//;
2358
2359 $dep = $depends{"$kconfig"};
2360
2361 # the dep string we have saves the dependencies as they
2362 # were found, including expressions like ! && ||. We
2363 # want to split this out into just an array of configs.
2364
2365 my $valid = "A-Za-z_0-9";
2366
2367 my @configs;
2368
2369 while ($dep =~ /[$valid]/) {
2370
2371 if ($dep =~ /^[^$valid]*([$valid]+)/) {
2372 my $conf = "CONFIG_" . $1;
2373
2374 $configs[$#configs + 1] = $conf;
2375
2376 $dep =~ s/^[^$valid]*[$valid]+//;
2377 } else {
2378 die "this should never happen";
2379 }
2380 }
2381
2382 return @configs;
2383}
2384
2385my %min_configs;
2386my %keep_configs;
2387my %processed_configs;
2388my %nochange_config;
2389
2390sub test_this_config {
2391 my ($config) = @_;
2392
2393 my $found;
2394
2395 # if we already processed this config, skip it
2396 if (defined($processed_configs{$config})) {
2397 return undef;
2398 }
2399 $processed_configs{$config} = 1;
2400
2401 # if this config failed during this round, skip it
2402 if (defined($nochange_config{$config})) {
2403 return undef;
2404 }
2405
2406 my $kconfig = $config;
2407 $kconfig =~ s/CONFIG_//;
2408
2409 # Test dependencies first
2410 if (defined($depends{"$kconfig"})) {
2411 my @parents = get_depends $config;
2412 foreach my $parent (@parents) {
2413 # if the parent is in the min config, check it first
2414 next if (!defined($min_configs{$parent}));
2415 $found = test_this_config($parent);
2416 if (defined($found)) {
2417 return $found;
2418 }
2419 }
2420 }
2421
2422 # Remove this config from the list of configs
2423 # do a make oldnoconfig and then read the resulting
2424 # .config to make sure it is missing the config that
2425 # we had before
2426 my %configs = %min_configs;
2427 delete $configs{$config};
2428 make_new_config ((values %configs), (values %keep_configs));
2429 make_oldconfig;
2430 undef %configs;
2431 assign_configs \%configs, $output_config;
2432
2433 return $config if (!defined($configs{$config}));
2434
2435 doprint "disabling config $config did not change .config\n";
2436
2437 $nochange_config{$config} = 1;
2438
2439 return undef;
2440}
2441
2200sub make_min_config { 2442sub make_min_config {
2201 my ($i) = @_; 2443 my ($i) = @_;
2202 2444
@@ -2216,8 +2458,12 @@ sub make_min_config {
2216 2458
2217 run_command "$make allnoconfig" or return 0; 2459 run_command "$make allnoconfig" or return 0;
2218 2460
2461 read_depends;
2462
2219 process_config_ignore $output_config; 2463 process_config_ignore $output_config;
2220 my %keep_configs; 2464
2465 undef %keep_configs;
2466 undef %min_configs;
2221 2467
2222 if (defined($ignore_config)) { 2468 if (defined($ignore_config)) {
2223 # make sure the file exists 2469 # make sure the file exists
@@ -2229,7 +2475,6 @@ sub make_min_config {
2229 2475
2230 # Look at the current min configs, and save off all the 2476 # Look at the current min configs, and save off all the
2231 # ones that were set via the allnoconfig 2477 # ones that were set via the allnoconfig
2232 my %min_configs;
2233 assign_configs \%min_configs, $start_minconfig; 2478 assign_configs \%min_configs, $start_minconfig;
2234 2479
2235 my @config_keys = keys %min_configs; 2480 my @config_keys = keys %min_configs;
@@ -2261,9 +2506,8 @@ sub make_min_config {
2261 } 2506 }
2262 } 2507 }
2263 2508
2264 my %nochange_config;
2265
2266 my $done = 0; 2509 my $done = 0;
2510 my $take_two = 0;
2267 2511
2268 while (!$done) { 2512 while (!$done) {
2269 2513
@@ -2293,35 +2537,30 @@ sub make_min_config {
2293 undef %nochange_config; 2537 undef %nochange_config;
2294 } 2538 }
2295 2539
2296 foreach my $config (@test_configs) { 2540 undef %processed_configs;
2297 2541
2298 # Remove this config from the list of configs 2542 foreach my $config (@test_configs) {
2299 # do a make oldnoconfig and then read the resulting
2300 # .config to make sure it is missing the config that
2301 # we had before
2302 my %configs = %min_configs;
2303 delete $configs{$config};
2304 make_new_config ((values %configs), (values %keep_configs));
2305 make_oldconfig;
2306 undef %configs;
2307 assign_configs \%configs, $output_config;
2308 2543
2309 if (!defined($configs{$config})) { 2544 $found = test_this_config $config;
2310 $found = $config;
2311 last;
2312 }
2313 2545
2314 doprint "disabling config $config did not change .config\n"; 2546 last if (defined($found));
2315 2547
2316 # oh well, try another config 2548 # oh well, try another config
2317 $nochange_config{$config} = 1;
2318 } 2549 }
2319 2550
2320 if (!defined($found)) { 2551 if (!defined($found)) {
2552 # we could have failed due to the nochange_config hash
2553 # reset and try again
2554 if (!$take_two) {
2555 undef %nochange_config;
2556 $take_two = 1;
2557 next;
2558 }
2321 doprint "No more configs found that we can disable\n"; 2559 doprint "No more configs found that we can disable\n";
2322 $done = 1; 2560 $done = 1;
2323 last; 2561 last;
2324 } 2562 }
2563 $take_two = 0;
2325 2564
2326 $config = $found; 2565 $config = $found;
2327 2566
@@ -2338,7 +2577,7 @@ sub make_min_config {
2338 $in_bisect = 0; 2577 $in_bisect = 0;
2339 2578
2340 if ($failed) { 2579 if ($failed) {
2341 doprint "$config is needed to boot the box... keeping\n"; 2580 doprint "$min_configs{$config} is needed to boot the box... keeping\n";
2342 # this config is needed, add it to the ignore list. 2581 # this config is needed, add it to the ignore list.
2343 $keep_configs{$config} = $min_configs{$config}; 2582 $keep_configs{$config} = $min_configs{$config};
2344 delete $min_configs{$config}; 2583 delete $min_configs{$config};
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index a83846d829bd..d096a0c80401 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -837,6 +837,18 @@
837# TODO: add a test version that makes the config do more than just 837# TODO: add a test version that makes the config do more than just
838# boot, like having network access. 838# boot, like having network access.
839# 839#
840# To save time, the test does not just grab any option and test
841# it. The Kconfig files are examined to determine the dependencies
842# of the configs. If a config is chosen that depends on another
843# config, that config will be checked first. By checking the
844# parents first, we can eliminate whole groups of configs that
845# may have been enabled.
846#
847# For example, if a USB device config is chosen and depends on CONFIG_USB,
848# the CONFIG_USB will be tested before the device. If CONFIG_USB is
849# found not to be needed, it, as well as all configs that depend on
850# it, will be disabled and removed from the current min_config.
851#
840# OUTPUT_MIN_CONFIG is the path and filename of the file that will 852# OUTPUT_MIN_CONFIG is the path and filename of the file that will
841# be created from the MIN_CONFIG. If you interrupt the test, set 853# be created from the MIN_CONFIG. If you interrupt the test, set
842# this file as your new min config, and use it to continue the test. 854# this file as your new min config, and use it to continue the test.