x86/vdso: Fix vdso_install
[deliverable/linux.git] / scripts / checkpatch.pl
index 464dcef79b353be5426115fb3fb8ba1f746546df..010b18ef4ea0cb9e1575b9e54f3922c7bd7f9888 100755 (executable)
@@ -24,6 +24,7 @@ my $emacs = 0;
 my $terse = 0;
 my $file = 0;
 my $check = 0;
+my $check_orig = 0;
 my $summary = 1;
 my $mailback = 0;
 my $summary_file = 0;
@@ -146,6 +147,7 @@ GetOptions(
 help(0) if ($help);
 
 $fix = 1 if ($fix_inplace);
+$check_orig = $check;
 
 my $exit = 0;
 
@@ -281,7 +283,7 @@ our $Attribute      = qr{
                        __weak
                  }x;
 our $Modifier;
-our $Inline    = qr{inline|__always_inline|noinline};
+our $Inline    = qr{inline|__always_inline|noinline|__inline|__inline__};
 our $Member    = qr{->$Ident|\.$Ident|\[[^]]*\]};
 our $Lval      = qr{$Ident(?:$Member)*};
 
@@ -289,13 +291,14 @@ our $Int_type     = qr{(?i)llu|ull|ll|lu|ul|l|u};
 our $Binary    = qr{(?i)0b[01]+$Int_type?};
 our $Hex       = qr{(?i)0x[0-9a-f]+$Int_type?};
 our $Int       = qr{[0-9]+$Int_type?};
+our $Octal     = qr{0[0-7]+$Int_type?};
 our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
 our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
 our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?};
 our $Float     = qr{$Float_hex|$Float_dec|$Float_int};
-our $Constant  = qr{$Float|$Binary|$Hex|$Int};
+our $Constant  = qr{$Float|$Binary|$Octal|$Hex|$Int};
 our $Assignment        = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
-our $Compare    = qr{<=|>=|==|!=|<|>};
+our $Compare    = qr{<=|>=|==|!=|<|(?<!-)>};
 our $Arithmetic = qr{\+|-|\*|\/|%};
 our $Operators = qr{
                        <=|>=|==|!=|
@@ -303,6 +306,8 @@ our $Operators      = qr{
                        &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
                  }x;
 
+our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
+
 our $NonptrType;
 our $NonptrTypeWithAttr;
 our $Type;
@@ -378,6 +383,27 @@ our @modifierList = (
        qr{fastcall},
 );
 
+our @mode_permission_funcs = (
+       ["module_param", 3],
+       ["module_param_(?:array|named|string)", 4],
+       ["module_param_array_named", 5],
+       ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2],
+       ["proc_create(?:_data|)", 2],
+       ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2],
+);
+
+#Create a search pattern for all these functions to speed up a loop below
+our $mode_perms_search = "";
+foreach my $entry (@mode_permission_funcs) {
+       $mode_perms_search .= '|' if ($mode_perms_search ne "");
+       $mode_perms_search .= $entry->[0];
+}
+
+our $declaration_macros = qr{(?x:
+       (?:$Storage\s+)?(?:DECLARE|DEFINE)_[A-Z]+\s*\(|
+       (?:$Storage\s+)?LIST_HEAD\s*\(
+)};
+
 our $allowed_asm_includes = qr{(?x:
        irq|
        memory
@@ -412,7 +438,7 @@ sub build_types {
                        (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)?
                        (?:\s+$Inline|\s+$Modifier)*
                  }x;
-       $Declare        = qr{(?:$Storage\s+)?$Type};
+       $Declare        = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
 }
 build_types();
 
@@ -423,15 +449,20 @@ our $Typecast     = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*};
 # Any use must be runtime checked with $^V
 
 our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;
-our $LvalOrFunc        = qr{($Lval)\s*($balanced_parens{0,1})\s*};
+our $LvalOrFunc        = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
 our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)};
 
 sub deparenthesize {
        my ($string) = @_;
        return "" if (!defined($string));
-       $string =~ s@^\s*\(\s*@@g;
-       $string =~ s@\s*\)\s*$@@g;
+
+       while ($string =~ /^\s*\(.*\)\s*$/) {
+               $string =~ s@^\s*\(\s*@@;
+               $string =~ s@\s*\)\s*$@@;
+       }
+
        $string =~ s@\s+@ @g;
+
        return $string;
 }
 
@@ -1421,21 +1452,25 @@ sub possible {
 my $prefix = '';
 
 sub show_type {
-       return defined $use_type{$_[0]} if (scalar keys %use_type > 0);
+       my ($type) = @_;
+
+       return defined $use_type{$type} if (scalar keys %use_type > 0);
 
-       return !defined $ignore_type{$_[0]};
+       return !defined $ignore_type{$type};
 }
 
 sub report {
-       if (!show_type($_[1]) ||
-           (defined $tst_only && $_[2] !~ /\Q$tst_only\E/)) {
+       my ($level, $type, $msg) = @_;
+
+       if (!show_type($type) ||
+           (defined $tst_only && $msg !~ /\Q$tst_only\E/)) {
                return 0;
        }
        my $line;
        if ($show_types) {
-               $line = "$prefix$_[0]:$_[1]: $_[2]\n";
+               $line = "$prefix$level:$type: $msg\n";
        } else {
-               $line = "$prefix$_[0]: $_[2]\n";
+               $line = "$prefix$level: $msg\n";
        }
        $line = (split('\n', $line))[0] . "\n" if ($terse);
 
@@ -1443,12 +1478,15 @@ sub report {
 
        return 1;
 }
+
 sub report_dump {
        our @report;
 }
 
 sub ERROR {
-       if (report("ERROR", $_[0], $_[1])) {
+       my ($type, $msg) = @_;
+
+       if (report("ERROR", $type, $msg)) {
                our $clean = 0;
                our $cnt_error++;
                return 1;
@@ -1456,7 +1494,9 @@ sub ERROR {
        return 0;
 }
 sub WARN {
-       if (report("WARNING", $_[0], $_[1])) {
+       my ($type, $msg) = @_;
+
+       if (report("WARNING", $type, $msg)) {
                our $clean = 0;
                our $cnt_warn++;
                return 1;
@@ -1464,7 +1504,9 @@ sub WARN {
        return 0;
 }
 sub CHK {
-       if ($check && report("CHECK", $_[0], $_[1])) {
+       my ($type, $msg) = @_;
+
+       if ($check && report("CHECK", $type, $msg)) {
                our $clean = 0;
                our $cnt_chk++;
                return 1;
@@ -1574,7 +1616,7 @@ sub pos_last_openparen {
                }
        }
 
-       return $last_openparen + 1;
+       return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
 }
 
 sub process {
@@ -1773,11 +1815,13 @@ sub process {
                $here = "#$linenr: " if (!$file);
                $here = "#$realline: " if ($file);
 
+               my $found_file = 0;
                # extract the filename as it passes
                if ($line =~ /^diff --git.*?(\S+)$/) {
                        $realfile = $1;
                        $realfile =~ s@^([^/]*)/@@ if (!$file);
                        $in_commit_log = 0;
+                       $found_file = 1;
                } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
                        $realfile = $1;
                        $realfile =~ s@^([^/]*)/@@ if (!$file);
@@ -1794,6 +1838,15 @@ sub process {
                                ERROR("MODIFIED_INCLUDE_ASM",
                                      "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
                        }
+                       $found_file = 1;
+               }
+
+               if ($found_file) {
+                       if ($realfile =~ m@^(drivers/net/|net/)@) {
+                               $check = 1;
+                       } else {
+                               $check = $check_orig;
+                       }
                        next;
                }
 
@@ -1891,6 +1944,18 @@ sub process {
                        }
                }
 
+# Check for old stable address
+               if ($line =~ /^\s*cc:\s*.*<?\bstable\@kernel\.org\b>?.*$/i) {
+                       ERROR("STABLE_ADDRESS",
+                             "The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr);
+               }
+
+# Check for unwanted Gerrit info
+               if ($in_commit_log && $line =~ /^\s*change-id:/i) {
+                       ERROR("GERRIT_CHANGE_ID",
+                             "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
+               }
+
 # Check for wrappage within a valid hunk of the file
                if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
                        ERROR("CORRUPTED_PATCH",
@@ -2041,28 +2106,32 @@ sub process {
                }
 
 # check for DT compatible documentation
-               if (defined $root && $realfile =~ /\.dts/ &&
-                   $rawline =~ /^\+\s*compatible\s*=/) {
+               if (defined $root &&
+                       (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
+                        ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) {
+
                        my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
 
+                       my $dt_path = $root . "/Documentation/devicetree/bindings/";
+                       my $vp_file = $dt_path . "vendor-prefixes.txt";
+
                        foreach my $compat (@compats) {
                                my $compat2 = $compat;
-                               my $dt_path =  $root . "/Documentation/devicetree/bindings/";
-                               $compat2 =~ s/\,[a-z]*\-/\,<\.\*>\-/;
-                               `grep -Erq "$compat|$compat2" $dt_path`;
+                               $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/;
+                               my $compat3 = $compat;
+                               $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/;
+                               `grep -Erq "$compat|$compat2|$compat3" $dt_path`;
                                if ( $? >> 8 ) {
                                        WARN("UNDOCUMENTED_DT_STRING",
                                             "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr);
                                }
 
-                               my $vendor = $compat;
-                               my $vendor_path = $dt_path . "vendor-prefixes.txt";
-                               next if (! -f $vendor_path);
-                               $vendor =~ s/^([a-zA-Z0-9]+)\,.*/$1/;
-                               `grep -Eq "$vendor" $vendor_path`;
+                               next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
+                               my $vendor = $1;
+                               `grep -Eq "^$vendor\\b" $vp_file`;
                                if ( $? >> 8 ) {
                                        WARN("UNDOCUMENTED_DT_STRING",
-                                            "DT compatible string vendor \"$vendor\" appears un-documented -- check $vendor_path\n" . $herecurr);
+                                            "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
                                }
                        }
                }
@@ -2159,7 +2228,7 @@ sub process {
 
 # check multi-line statement indentation matches previous line
                if ($^V && $^V ge 5.10.0 &&
-                   $prevline =~ /^\+(\t*)(if \(|$Ident\().*(\&\&|\|\||,)\s*$/) {
+                   $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
                        $prevline =~ /^\+(\t*)(.*)$/;
                        my $oldindent = $1;
                        my $rest = $2;
@@ -2198,7 +2267,8 @@ sub process {
 
                if ($realfile =~ m@^(drivers/net/|net/)@ &&
                    $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
-                   $rawline =~ /^\+[ \t]*\*/) {
+                   $rawline =~ /^\+[ \t]*\*/ &&
+                   $realline > 2) {
                        WARN("NETWORKING_BLOCK_COMMENT_STYLE",
                             "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
                }
@@ -2221,6 +2291,40 @@ sub process {
                             "networking block comments put the trailing */ on a separate line\n" . $herecurr);
                }
 
+# check for missing blank lines after declarations
+               if ($sline =~ /^\+\s+\S/ &&                     #Not at char 1
+                       # actual declarations
+                   ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
+                       # foo bar; where foo is some local typedef or #define
+                    $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
+                       # known declaration macros
+                    $prevline =~ /^\+\s+$declaration_macros/) &&
+                       # for "else if" which can look like "$Ident $Ident"
+                   !($prevline =~ /^\+\s+$c90_Keywords\b/ ||
+                       # other possible extensions of declaration lines
+                     $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
+                       # not starting a section or a macro "\" extended line
+                     $prevline =~ /(?:\{\s*|\\)$/) &&
+                       # looks like a declaration
+                   !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
+                       # foo bar; where foo is some local typedef or #define
+                     $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
+                       # known declaration macros
+                     $sline =~ /^\+\s+$declaration_macros/ ||
+                       # start of struct or union or enum
+                     $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ ||
+                       # start or end of block or continuation of declaration
+                     $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
+                       # bitfield continuation
+                     $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ ||
+                       # other possible extensions of declaration lines
+                     $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) &&
+                       # indentation of previous and current line are the same
+                   (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) {
+                       WARN("SPACING",
+                            "Missing a blank line after declarations\n" . $hereprev);
+               }
+
 # check for spaces at the beginning of a line.
 # Exceptions:
 #  1) within comments
@@ -2665,6 +2769,13 @@ sub process {
                                $herecurr);
                }
 
+# check for non-global char *foo[] = {"bar", ...} declarations.
+               if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
+                       WARN("STATIC_CONST_CHAR_ARRAY",
+                            "char * array declaration might be better as static const\n" .
+                               $herecurr);
+               }
+
 # check for function declarations without arguments like "int foo()"
                if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
                        if (ERROR("FUNCTION_WITHOUT_ARGS",
@@ -2799,7 +2910,7 @@ sub process {
                        my $level2 = $level;
                        $level2 = "dbg" if ($level eq "debug");
                        WARN("PREFER_PR_LEVEL",
-                            "Prefer netdev_$level2(netdev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
+                            "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
                }
 
                if ($line =~ /\bpr_warning\s*\(/) {
@@ -2848,10 +2959,7 @@ sub process {
 # Function pointer declarations
 # check spacing between type, funcptr, and args
 # canonical declaration is "type (*funcptr)(args...)"
-#
-# the $Declare variable will capture all spaces after the type
-# so check it for trailing missing spaces or multiple spaces
-               if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)$Ident(\s*)\)(\s*)\(/) {
+               if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) {
                        my $declare = $1;
                        my $pre_pointer_space = $2;
                        my $post_pointer_space = $3;
@@ -2859,16 +2967,30 @@ sub process {
                        my $post_funcname_space = $5;
                        my $pre_args_space = $6;
 
-                       if ($declare !~ /\s$/) {
+# the $Declare variable will capture all spaces after the type
+# so check it for a missing trailing missing space but pointer return types
+# don't need a space so don't warn for those.
+                       my $post_declare_space = "";
+                       if ($declare =~ /(\s+)$/) {
+                               $post_declare_space = $1;
+                               $declare = rtrim($declare);
+                       }
+                       if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) {
                                WARN("SPACING",
                                     "missing space after return type\n" . $herecurr);
+                               $post_declare_space = " ";
                        }
 
 # unnecessary space "type  (*funcptr)(args...)"
-                       elsif ($declare =~ /\s{2,}$/) {
-                               WARN("SPACING",
-                                    "Multiple spaces after return type\n" . $herecurr);
-                       }
+# This test is not currently implemented because these declarations are
+# equivalent to
+#      int  foo(int bar, ...)
+# and this is form shouldn't/doesn't generate a checkpatch warning.
+#
+#                      elsif ($declare =~ /\s{2,}$/) {
+#                              WARN("SPACING",
+#                                   "Multiple spaces after return type\n" . $herecurr);
+#                      }
 
 # unnecessary space "type ( *funcptr)(args...)"
                        if (defined $pre_pointer_space &&
@@ -2900,7 +3022,7 @@ sub process {
 
                        if (show_type("SPACING") && $fix) {
                                $fixed[$linenr - 1] =~
-                                   s/^(.\s*$Declare)\(\s*\*\s*($Ident)\s*\)\s*\(/rtrim($1) . " " . "\(\*$2\)\("/ex;
+                                   s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex;
                        }
                }
 
@@ -3061,10 +3183,13 @@ sub process {
                                # // is a comment
                                } elsif ($op eq '//') {
 
+                               #   :   when part of a bitfield
+                               } elsif ($opv eq ':B') {
+                                       # skip the bitfield test for now
+
                                # No spaces for:
                                #   ->
-                               #   :   when part of a bitfield
-                               } elsif ($op eq '->' || $opv eq ':B') {
+                               } elsif ($op eq '->') {
                                        if ($ctx =~ /Wx.|.xW/) {
                                                if (ERROR("SPACING",
                                                          "spaces prohibited around that '$op' $at\n" . $hereptr)) {
@@ -3334,20 +3459,30 @@ sub process {
                        }
                }
 
-# Return is not a function.
+# return is not a function
                if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
                        my $spacing = $1;
                        if ($^V && $^V ge 5.10.0 &&
-                           $stat =~ /^.\s*return\s*$balanced_parens\s*;\s*$/) {
-                               ERROR("RETURN_PARENTHESES",
-                                     "return is not a function, parentheses are not required\n" . $herecurr);
-
+                           $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
+                               my $value = $1;
+                               $value = deparenthesize($value);
+                               if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) {
+                                       ERROR("RETURN_PARENTHESES",
+                                             "return is not a function, parentheses are not required\n" . $herecurr);
+                               }
                        } elsif ($spacing !~ /\s+/) {
                                ERROR("SPACING",
                                      "space required before the open parenthesis '('\n" . $herecurr);
                        }
                }
 
+# unnecessary return in a void function? (a single leading tab, then return;)
+               if ($sline =~ /^\+\treturn\s*;\s*$/ &&
+                   $prevline =~ /^\+/) {
+                       WARN("RETURN_VOID",
+                            "void function return statements are not generally useful\n" . $herecurr);
+               }
+
 # if statements using unnecessary parentheses - ie: if ((foo == bar))
                if ($^V && $^V ge 5.10.0 &&
                    $line =~ /\bif\s*((?:\(\s*){2,})/) {
@@ -3699,6 +3834,17 @@ sub process {
                                        WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON",
                                             "do {} while (0) macros should not be semicolon terminated\n" . "$herectx");
                                }
+                       } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {
+                               $ctx =~ s/\n*$//;
+                               my $cnt = statement_rawlines($ctx);
+                               my $herectx = $here . "\n";
+
+                               for (my $n = 0; $n < $cnt; $n++) {
+                                       $herectx .= raw_line($linenr, $n) . "\n";
+                               }
+
+                               WARN("TRAILING_SEMICOLON",
+                                    "macros should not use a trailing semicolon\n" . "$herectx");
                        }
                }
 
@@ -3910,12 +4056,30 @@ sub process {
                        }
                }
 
+# don't use __constant_<foo> functions outside of include/uapi/
+               if ($realfile !~ m@^include/uapi/@ &&
+                   $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) {
+                       my $constant_func = $1;
+                       my $func = $constant_func;
+                       $func =~ s/^__constant_//;
+                       if (WARN("CONSTANT_CONVERSION",
+                                "$constant_func should be $func\n" . $herecurr) &&
+                           $fix) {
+                               $fixed[$linenr - 1] =~ s/\b$constant_func\b/$func/g;
+                       }
+               }
+
 # prefer usleep_range over udelay
                if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
+                       my $delay = $1;
                        # ignore udelay's < 10, however
-                       if (! ($1 < 10) ) {
+                       if (! ($delay < 10) ) {
                                CHK("USLEEP_RANGE",
-                                   "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line);
+                                   "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr);
+                       }
+                       if ($delay > 2000) {
+                               WARN("LONG_UDELAY",
+                                    "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
                        }
                }
 
@@ -3923,7 +4087,7 @@ sub process {
                if ($line =~ /\bmsleep\s*\((\d+)\);/) {
                        if ($1 < 20) {
                                WARN("MSLEEP",
-                                    "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line);
+                                    "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr);
                        }
                }
 
@@ -4149,7 +4313,7 @@ sub process {
 # check for naked sscanf
                if ($^V && $^V ge 5.10.0 &&
                    defined $stat &&
-                   $stat =~ /\bsscanf\b/ &&
+                   $line =~ /\bsscanf\b/ &&
                    ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
                     $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ &&
                     $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
@@ -4163,6 +4327,27 @@ sub process {
                             "unchecked sscanf return value\n" . "$here\n$stat_real\n");
                }
 
+# check for simple sscanf that should be kstrto<foo>
+               if ($^V && $^V ge 5.10.0 &&
+                   defined $stat &&
+                   $line =~ /\bsscanf\b/) {
+                       my $lc = $stat =~ tr@\n@@;
+                       $lc = $lc + $linenr;
+                       my $stat_real = raw_line($linenr, 0);
+                       for (my $count = $linenr + 1; $count <= $lc; $count++) {
+                               $stat_real = $stat_real . "\n" . raw_line($count, 0);
+                       }
+                       if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) {
+                               my $format = $6;
+                               my $count = $format =~ tr@%@%@;
+                               if ($count == 1 &&
+                                   $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) {
+                                       WARN("SSCANF_TO_KSTRTO",
+                                            "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n");
+                               }
+                       }
+               }
+
 # check for new externs in .h files.
                if ($realfile =~ /\.h$/ &&
                    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
@@ -4227,6 +4412,30 @@ sub process {
                            "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
                }
 
+# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
+               if ($^V && $^V ge 5.10.0 &&
+                   $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/) {
+                       my $oldfunc = $3;
+                       my $a1 = $4;
+                       my $a2 = $10;
+                       my $newfunc = "kmalloc_array";
+                       $newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
+                       if ($a1 =~ /^sizeof\s*\S/ || $a2 =~ /^sizeof\s*\S/) {
+                               if (WARN("ALLOC_WITH_MULTIPLY",
+                                        "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) &&
+                                   $fix) {
+                                       my $r1 = $a1;
+                                       my $r2 = $a2;
+                                       if ($a1 =~ /^sizeof\s*\S/) {
+                                               $r1 = $a2;
+                                               $r2 = $a1;
+                                       }
+                                       $fixed[$linenr - 1] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
+
+                               }
+                       }
+               }
+
 # check for krealloc arg reuse
                if ($^V && $^V ge 5.10.0 &&
                    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) {
@@ -4240,12 +4449,6 @@ sub process {
                             "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
                }
 
-# check for GFP_NOWAIT use
-               if ($line =~ /\b__GFP_NOFAIL\b/) {
-                       WARN("__GFP_NOFAIL",
-                            "Use of __GFP_NOFAIL is deprecated, no new users should be added\n" . $herecurr);
-               }
-
 # check for multiple semicolons
                if ($line =~ /;\s*;\s*$/) {
                        if (WARN("ONE_SEMICOLON",
@@ -4348,10 +4551,10 @@ sub process {
                             "$1 is obsolete, use k$3 instead\n" . $herecurr);
                }
 
-# check for __initcall(), use device_initcall() explicitly please
+# check for __initcall(), use device_initcall() explicitly or more appropriate function please
                if ($line =~ /^.\s*__initcall\s*\(/) {
                        WARN("USE_DEVICE_INITCALL",
-                            "please use device_initcall() instead of __initcall()\n" . $herecurr);
+                            "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
                }
 
 # check for various ops structs, ensure they are const.
@@ -4457,6 +4660,34 @@ sub process {
                        WARN("EXPORTED_WORLD_WRITABLE",
                             "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
                }
+
+# Mode permission misuses where it seems decimal should be octal
+# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
+               if ($^V && $^V ge 5.10.0 &&
+                   $line =~ /$mode_perms_search/) {
+                       foreach my $entry (@mode_permission_funcs) {
+                               my $func = $entry->[0];
+                               my $arg_pos = $entry->[1];
+
+                               my $skip_args = "";
+                               if ($arg_pos > 1) {
+                                       $arg_pos--;
+                                       $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
+                               }
+                               my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]";
+                               if ($line =~ /$test/) {
+                                       my $val = $1;
+                                       $val = $6 if ($skip_args ne "");
+
+                                       if ($val !~ /^0$/ &&
+                                           (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
+                                            length($val) ne 4)) {
+                                               ERROR("NON_OCTAL_PERMISSIONS",
+                                                     "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr);
+                                       }
+                               }
+                       }
+               }
        }
 
        # If we have no input at all, then there is nothing to report on
This page took 0.032624 seconds and 5 git commands to generate.