From cbdfd2d86ffe0565cbeccca97b83457e3325bca4 Mon Sep 17 00:00:00 2001 From: James Youngman Date: Sat, 18 Jul 2009 15:15:05 +0100 Subject: [PATCH] Optimise -fstype NOTUSED to -false at -O2. Optimise -fstype NOTUSED to -false at -O2. * find/parser.c: Include mountlist.h. (insert_false): New function, inserts a -false predicate. (parse_false): Use insert_false. (is_used_fs_type): New function, determines if any mounted filesystem is of the named type. (parse_fstype): At optimisation level 2 and above, -fstpe FOO is converted to -false if no mounted filesytem is of type FOO. * find/find.1: Document this optimisation. * doc/find.texi (Optimisation Options): Likewise. * NEWS: Mention this change. --- ChangeLog | 12 ++++++++ NEWS | 7 +++++ doc/find.texi | 6 ++++ find/find.1 | 9 ++++++ find/parser.c | 83 ++++++++++++++++++++++++++++++++++++++++++--------- 5 files changed, 103 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 279eda40..62eb4a9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2010-04-01 James Youngman + Optimise -fstype NOTUSED to -false at -O2. + * find/parser.c: Include mountlist.h. + (insert_false): New function, inserts a -false predicate. + (parse_false): Use insert_false. + (is_used_fs_type): New function, determines if any mounted + filesystem is of the named type. + (parse_fstype): At optimisation level 2 and above, -fstpe FOO + is converted to -false if no mounted filesytem is of type FOO. + * find/find.1: Document this optimisation. + * doc/find.texi (Optimisation Options): Likewise. + * NEWS: Mention this change. + Updated copyright years to add 2010. * find/find.c: Add 2010. * find/fstype.c: Add 2010. diff --git a/NEWS b/NEWS index c9e90743..d2fc8af4 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,13 @@ since it contains Makefiles which are vulnerable to CVE-2009-4029. patch #4848: Patch - Support for SELinux +** Performance changes + +If you use the -fstype FOO predicate and specify a filsystem type FOO +which is not known (e.g. present in /etc/mtab) at the time find +starts, that predicate is now equivalent to -false. This substitution +currently occurs at optimisation level 2 and above. + ** Bug Fixes #29089: SELinux --context and %Z options diff --git a/doc/find.texi b/doc/find.texi index 8ce1f6fe..2e302aa1 100644 --- a/doc/find.texi +++ b/doc/find.texi @@ -3123,6 +3123,12 @@ information from the inode. On many modern versions of Unix, file types are returned by @code{readdir()} and so these predicates are faster to evaluate than predicates which need to stat the file first. +If you use the @samp{-fstype FOO} predicate and specify a filsystem +type @samp{FOO} which is not known (that is, present in +@file{/etc/mtab}) at the time @code{find} starts, that predicate is +equivalent to @samp{-false}. + + @item 3 At this optimisation level, the full cost-based query optimiser is enabled. The order of tests is modified so that cheap (i.e., fast) diff --git a/find/find.1 b/find/find.1 index b8adcc87..94137a94 100644 --- a/find/find.1 +++ b/find/find.1 @@ -253,6 +253,15 @@ modern versions of Unix, file types are returned by .B readdir() and so these predicates are faster to evaluate than predicates which need to stat the file first. +If you use the +.B \-fstype +.I FOO +predicate and specify a filsystem type +.I FOO +which is not known (that is, present in `/etc/mtab') at the time +.B find +starts, that predicate is equivalent to +.BR \-false . .IP 3 At this optimisation level, the full cost-based query optimiser is enabled. The order of tests is modified so that cheap (i.e. fast) diff --git a/find/parser.c b/find/parser.c index 32b1d20d..6083298d 100644 --- a/find/parser.c +++ b/find/parser.c @@ -26,6 +26,7 @@ #include #include #include +#include "mountlist.h" #include "modechange.h" #include "modetype.h" #include "xstrtol.h" @@ -941,20 +942,26 @@ parse_execdir (const struct parser_table* entry, char **argv, int *arg_ptr) } static boolean -parse_false (const struct parser_table* entry, char **argv, int *arg_ptr) +insert_false(void) { struct predicate *our_pred; + const struct parser_table *entry_false; - (void) argv; - (void) arg_ptr; - - our_pred = insert_primary_noarg (entry); + entry_false = find_parser("false"); + our_pred = insert_primary_noarg (entry_false); our_pred->need_stat = our_pred->need_type = false; our_pred->side_effects = our_pred->no_default_print = false; our_pred->est_success_rate = 0.0f; return true; } + +static boolean +parse_false (const struct parser_table* entry, char **argv, int *arg_ptr) +{ + return insert_false (); +} + static boolean insert_fls (const struct parser_table* entry, const char *filename) { @@ -1056,22 +1063,70 @@ static float estimate_fstype_success_rate (const char *fsname) } + +static boolean +is_used_fs_type(const char *name) +{ + if (0 == strcmp("afs", name)) + { + /* I guess AFS may not appear in /etc/mtab (or equivalent) but still be in use, + so assume we always need to check for AFS. */ + return true; + } + else + { + const struct mount_entry *entries = read_file_system_list(false); + if (entries) + { + const struct mount_entry *entry; + for (entry = entries; entry; entry = entry->me_next) + { + if (0 == strcmp(name, entry->me_type)) + return true; + } + } + else + { + return true; + } + } + return false; +} + + static boolean parse_fstype (const struct parser_table* entry, char **argv, int *arg_ptr) { const char *typename; if (collect_arg (argv, arg_ptr, &typename)) { - struct predicate *our_pred = insert_primary (entry, typename); - our_pred->args.str = typename; + if (options.optimisation_level < 2 || is_used_fs_type (typename)) + { + struct predicate *our_pred = insert_primary (entry, typename); + our_pred->args.str = typename; - /* This is an expensive operation, so although there are - * circumstances where it is selective, we ignore this fact - * because we probably don't want to promote this test to the - * front anyway. - */ - our_pred->est_success_rate = estimate_fstype_success_rate (typename); - return true; + /* This is an expensive operation, so although there are + * circumstances where it is selective, we ignore this fact + * because we probably don't want to promote this test to the + * front anyway. + */ + our_pred->est_success_rate = estimate_fstype_success_rate (typename); + return true; + } + else + { + /* This filesystem type is not listed in the mount table. + * Hence this predicate will always return false (with this argument). + * Substitute a predicate with the same effect as -false. + */ + if (options.debug_options & DebugTreeOpt) + { + fprintf (stderr, + "-fstype %s can never succeed, substituting -false\n", + typename); + } + return insert_false (); + } } else {