Merge branch 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
Linus Torvalds [Mon, 16 Jan 2012 22:36:07 +0000 (14:36 -0800)]
* 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild:
  scripts/coccinelle: improve the coverage of some semantic patches
  coccinelle: semantic patches related to devm_ functions (part 2)
  coccinelle: semantic patches related to devm_ functions (part 1)
  coccinelle.txt: update documentation to include M= option
  coccicheck: add M= option to control which dir is processed
  ctags: remove struct forward declarations
  scripts/tags.sh: Add Page flag function magic

16 files changed:
Documentation/coccinelle.txt
scripts/coccicheck
scripts/coccinelle/api/devm_request_and_ioremap.cocci [new file with mode: 0644]
scripts/coccinelle/api/kstrdup.cocci
scripts/coccinelle/api/memdup.cocci
scripts/coccinelle/api/memdup_user.cocci
scripts/coccinelle/free/devm_free.cocci [new file with mode: 0644]
scripts/coccinelle/free/kfree.cocci
scripts/coccinelle/iterators/fen.cocci
scripts/coccinelle/iterators/itnull.cocci
scripts/coccinelle/locks/call_kern.cocci
scripts/coccinelle/locks/flags.cocci
scripts/coccinelle/locks/mini_lock.cocci
scripts/coccinelle/misc/doubleinit.cocci
scripts/coccinelle/null/eno.cocci
scripts/tags.sh

index 96b6903..cf44eb6 100644 (file)
@@ -102,9 +102,15 @@ or
        make coccicheck COCCI=<my_SP.cocci> MODE=report
 
 
- Using Coccinelle on (modified) files
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Controlling Which Files are Processed by Coccinelle
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+By default the entire kernel source tree is checked.
+
+To apply Coccinelle to a specific directory, M= can be used.
+For example, to check drivers/net/wireless/ one may write:
 
+    make coccicheck M=drivers/net/wireless/
+    
 To apply Coccinelle on a file basis, instead of a directory basis, the
 following command may be used:
 
index 1bb1a1b..3c27764 100755 (executable)
@@ -9,14 +9,23 @@ if [ "$C" = "1" -o "$C" = "2" ]; then
 #    FLAGS="-ignore_unknown_options -very_quiet"
 #    OPTIONS=$*
 
-# Workaround for Coccinelle < 0.2.3
-    FLAGS="-I $srctree/include -very_quiet"
-    shift $(( $# - 1 ))
-    OPTIONS=$1
+    if [ "$KBUILD_EXTMOD" = "" ] ; then
+        # Workaround for Coccinelle < 0.2.3
+        FLAGS="-I $srctree/include -very_quiet"
+        shift $(( $# - 1 ))
+        OPTIONS=$1
+    else
+       echo M= is not currently supported when C=1 or C=2
+       exit 1
+    fi
 else
     ONLINE=0
     FLAGS="-very_quiet"
-    OPTIONS="-dir $srctree"
+    if [ "$KBUILD_EXTMOD" = "" ] ; then
+        OPTIONS="-dir $srctree"
+    else
+        OPTIONS="-dir $KBUILD_EXTMOD -patch $srctree -I $srctree/include -I $KBUILD_EXTMOD/include"
+    fi
 fi
 
 if [ ! -x "$SPATCH" ]; then
diff --git a/scripts/coccinelle/api/devm_request_and_ioremap.cocci b/scripts/coccinelle/api/devm_request_and_ioremap.cocci
new file mode 100644 (file)
index 0000000..46beb81
--- /dev/null
@@ -0,0 +1,105 @@
+/// Reimplement a call to devm_request_mem_region followed by a call to ioremap
+/// or ioremap_nocache by a call to devm_request_and_ioremap.
+/// Devm_request_and_ioremap was introduced in
+/// 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0.  It makes the code much more
+/// concise.
+///
+///
+// Confidence: High
+// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+virtual org
+virtual report
+virtual context
+
+@nm@
+expression myname;
+identifier i;
+@@
+
+struct platform_driver i = { .driver = { .name = myname } };
+
+@depends on patch@
+expression dev,res,size;
+@@
+
+-if (!devm_request_mem_region(dev, res->start, size,
+-                              \(res->name\|dev_name(dev)\))) {
+-   ...
+-   return ...;
+-}
+... when != res->start
+(
+-devm_ioremap(dev,res->start,size)
++devm_request_and_ioremap(dev,res)
+|
+-devm_ioremap_nocache(dev,res->start,size)
++devm_request_and_ioremap(dev,res)
+)
+... when any
+    when != res->start
+
+// this rule is separate from the previous one, because a single file can
+// have multiple values of myname
+@depends on patch@
+expression dev,res,size;
+expression nm.myname;
+@@
+
+-if (!devm_request_mem_region(dev, res->start, size,myname)) {
+-   ...
+-   return ...;
+-}
+... when != res->start
+(
+-devm_ioremap(dev,res->start,size)
++devm_request_and_ioremap(dev,res)
+|
+-devm_ioremap_nocache(dev,res->start,size)
++devm_request_and_ioremap(dev,res)
+)
+... when any
+    when != res->start
+
+
+@pb depends on org || report || context@
+expression dev,res,size;
+expression nm.myname;
+position p1,p2;
+@@
+
+*if
+  (!devm_request_mem_region@p1(dev, res->start, size,
+                              \(res->name\|dev_name(dev)\|myname\))) {
+   ...
+   return ...;
+}
+... when != res->start
+(
+*devm_ioremap@p2(dev,res->start,size)
+|
+*devm_ioremap_nocache@p2(dev,res->start,size)
+)
+... when any
+    when != res->start
+
+@script:python depends on org@
+p1 << pb.p1;
+p2 << pb.p2;
+@@
+
+cocci.print_main("INFO: replace by devm_request_and_ioremap",p1)
+cocci.print_secs("",p2)
+
+@script:python depends on report@
+p1 << pb.p1;
+p2 << pb.p2;
+@@
+
+msg = "INFO: devm_request_mem_region followed by ioremap on line %s can be replaced by devm_request_and_ioremap" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
index e0805ad..07a74b2 100644 (file)
@@ -1,16 +1,19 @@
 /// Use kstrdup rather than duplicating its implementation
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 expression from,to;
 expression flag,E1,E2;
 statement S;
@@ -23,7 +26,7 @@ statement S;
    ... when != \(from = E2 \| to = E2 \)
 -  strcpy(to, from);
 
-@@
+@depends on patch@
 expression x,from,to;
 expression flag,E1,E2,E3;
 statement S;
@@ -37,3 +40,65 @@ statement S;
     if (to==NULL || ...) S
     ... when != \(x = E3 \| from = E3 \| to = E3 \)
 -   memcpy(to, from, x);
+
+// ---------------------------------------------------------------------
+
+@r1 depends on !patch exists@
+expression from,to;
+expression flag,E1,E2;
+statement S;
+position p1,p2;
+@@
+
+*  to = kmalloc@p1(strlen(from) + 1,flag);
+   ... when != \(from = E1 \| to = E1 \)
+   if (to==NULL || ...) S
+   ... when != \(from = E2 \| to = E2 \)
+*  strcpy@p2(to, from);
+
+@r2 depends on !patch exists@
+expression x,from,to;
+expression flag,E1,E2,E3;
+statement S;
+position p1,p2;
+@@
+
+*   x = strlen(from) + 1;
+    ... when != \( x = E1 \| from = E1 \)
+*   to = \(kmalloc@p1\|kzalloc@p2\)(x,flag);
+    ... when != \(x = E2 \| from = E2 \| to = E2 \)
+    if (to==NULL || ...) S
+    ... when != \(x = E3 \| from = E3 \| to = E3 \)
+*   memcpy@p2(to, from, x);
+
+@script:python depends on org@
+p1 << r1.p1;
+p2 << r1.p2;
+@@
+
+cocci.print_main("WARNING opportunity for kstrdep",p1)
+cocci.print_secs("strcpy",p2)
+
+@script:python depends on org@
+p1 << r2.p1;
+p2 << r2.p2;
+@@
+
+cocci.print_main("WARNING opportunity for kstrdep",p1)
+cocci.print_secs("memcpy",p2)
+
+@script:python depends on report@
+p1 << r1.p1;
+p2 << r1.p2;
+@@
+
+msg = "WARNING opportunity for kstrdep (strcpy on line %s)" % (p2[0].line)
+coccilib.report.print_report(p1[0], msg)
+
+@script:python depends on report@
+p1 << r2.p1;
+p2 << r2.p2;
+@@
+
+msg = "WARNING opportunity for kstrdep (memcpy on line %s)" % (p2[0].line)
+coccilib.report.print_report(p1[0], msg)
index b5d7220..4dceab6 100644 (file)
@@ -1,14 +1,17 @@
 /// Use kmemdup rather than duplicating its implementation
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
 @r1@
 expression from,to;
@@ -28,7 +31,7 @@ position p;
     ... when != \( x = E1 \| from = E1 \)
     to = \(kmalloc@p\|kzalloc@p\)(x,flag);
 
-@@
+@depends on patch@
 expression from,to,size,flag;
 position p != {r1.p,r2.p};
 statement S;
@@ -38,3 +41,26 @@ statement S;
 +  to = kmemdup(from,size,flag);
    if (to==NULL || ...) S
 -  memcpy(to, from, size);
+
+@r depends on !patch@
+expression from,to,size,flag;
+position p != {r1.p,r2.p};
+statement S;
+@@
+
+*  to = \(kmalloc@p\|kzalloc@p\)(size,flag);
+   to = kmemdup(from,size,flag);
+   if (to==NULL || ...) S
+*  memcpy(to, from, size);
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING opportunity for kmemdep")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0], "WARNING opportunity for kmemdep")
index 72ce012..2efac28 100644 (file)
@@ -1,23 +1,25 @@
-/// Use kmemdup_user rather than duplicating its implementation
+/// Use memdup_user rather than duplicating its implementation
 /// This is a little bit restricted to reduce false positives
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 expression from,to,size,flag;
-position p;
 identifier l1,l2;
 @@
 
--  to = \(kmalloc@p\|kzalloc@p\)(size,flag);
+-  to = \(kmalloc\|kzalloc\)(size,flag);
 +  to = memdup_user(from,size);
    if (
 -      to==NULL
@@ -33,3 +35,26 @@ identifier l1,l2;
 -    -EFAULT
 -    ...+>
 -  }
+
+@r depends on !patch@
+expression from,to,size,flag;
+position p;
+statement S1,S2;
+@@
+
+*  to = \(kmalloc@p\|kzalloc@p\)(size,flag);
+   if (to==NULL || ...) S1
+   if (copy_from_user(to, from, size) != 0)
+   S2
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING opportunity for memdep_user")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0], "WARNING opportunity for memdep_user")
diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci
new file mode 100644 (file)
index 0000000..0a1e361
--- /dev/null
@@ -0,0 +1,71 @@
+/// Find uses of standard freeing functons on values allocated using devm_
+/// functions.  Values allocated using the devm_functions are freed when
+/// the device is detached, and thus the use of the standard freeing
+/// function would cause a double free.
+/// See Documentation/driver-model/devres.txt for more information.
+///
+/// A difficulty of detecting this problem is that the standard freeing
+/// function might be called from a different function than the one
+/// containing the allocation function.  It is thus necessary to make the
+/// connection between the allocation function and the freeing function.
+/// Here this is done using the specific argument text, which is prone to
+/// false positives.  There is no rule for the request_region and
+/// request_mem_region variants because this heuristic seems to be a bit
+/// less reliable in these cases.
+///
+// Confidence: Moderate
+// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual org
+virtual report
+virtual context
+
+@r depends on context || org || report@
+expression x;
+@@
+
+(
+ x = devm_kzalloc(...)
+|
+ x = devm_request_irq(...)
+|
+ x = devm_ioremap(...)
+|
+ x = devm_ioremap_nocache(...)
+|
+ x = devm_ioport_map(...)
+)
+
+@pb@
+expression r.x;
+position p;
+@@
+
+(
+* kfree@p(x)
+|
+* free_irq@p(x)
+|
+* iounmap@p(x)
+|
+* ioport_unmap@p(x)
+)
+
+@script:python depends on org@
+p << pb.p;
+@@
+
+msg="WARNING: invalid free of devm_ allocated data"
+coccilib.org.print_todo(p[0], msg)
+
+@script:python depends on report@
+p << pb.p;
+@@
+
+msg="WARNING: invalid free of devm_ allocated data"
+coccilib.report.print_report(p[0], msg)
+
index f9f79d9..d9ae6d8 100644 (file)
@@ -5,9 +5,9 @@
 //# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
 ///
 // Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
@@ -23,7 +23,7 @@ position p1;
 kfree@p1(E)
 
 @print expression@
-constant char *c;
+constant char [] c;
 expression free.E,E2;
 type T;
 position p;
@@ -37,6 +37,10 @@ identifier f;
 |
  E@p != E2
 |
+ E2 == E@p
+|
+ E2 != E@p
+|
  !E@p
 |
  E@p || ...
@@ -113,5 +117,5 @@ p1 << free.p1;
 p2 << r.p2;
 @@
 
-msg = "reference preceded by free on line %s" % (p1[0].line)
+msg = "ERROR: reference preceded by free on line %s" % (p1[0].line)
 coccilib.report.print_report(p2[0],msg)
index 77bc108..0a40af8 100644 (file)
@@ -2,16 +2,19 @@
 /// is no point to call of_node_put on the final value.
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 iterator name for_each_node_by_name;
 expression np,E;
 identifier l;
@@ -24,7 +27,7 @@ for_each_node_by_name(np,...) {
 ... when != np = E
 - of_node_put(np);
 
-@@
+@depends on patch@
 iterator name for_each_node_by_type;
 expression np,E;
 identifier l;
@@ -37,7 +40,7 @@ for_each_node_by_type(np,...) {
 ... when != np = E
 - of_node_put(np);
 
-@@
+@depends on patch@
 iterator name for_each_compatible_node;
 expression np,E;
 identifier l;
@@ -50,7 +53,7 @@ for_each_compatible_node(np,...) {
 ... when != np = E
 - of_node_put(np);
 
-@@
+@depends on patch@
 iterator name for_each_matching_node;
 expression np,E;
 identifier l;
@@ -62,3 +65,59 @@ for_each_matching_node(np,...) {
 }
 ... when != np = E
 - of_node_put(np);
+
+// ----------------------------------------------------------------------
+
+@r depends on !patch forall@
+//iterator name for_each_node_by_name;
+//iterator name for_each_node_by_type;
+//iterator name for_each_compatible_node;
+//iterator name for_each_matching_node;
+expression np,E;
+identifier l;
+position p1,p2;
+@@
+
+(
+*for_each_node_by_name@p1(np,...)
+{
+  ... when != break;
+      when != goto l;
+}
+|
+*for_each_node_by_type@p1(np,...)
+{
+  ... when != break;
+      when != goto l;
+}
+|
+*for_each_compatible_node@p1(np,...)
+{
+  ... when != break;
+      when != goto l;
+}
+|
+*for_each_matching_node@p1(np,...)
+{
+  ... when != break;
+      when != goto l;
+}
+)
+... when != np = E
+* of_node_put@p2(np);
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("unneeded of_node_put",p2)
+cocci.print_secs("iterator",p1)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: of_node_put not needed after iterator on line %s" % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
index baa4297..259899f 100644 (file)
@@ -1,20 +1,24 @@
 /// Many iterators have the property that the first argument is always bound
-/// to a real list element, never NULL.  False positives arise for some
-/// iterators that do not have this property, or in cases when the loop
-/// cursor is reassigned.  The latter should only happen when the matched
-/// code is on the way to a loop exit (break, goto, or return).
+/// to a real list element, never NULL.
+//# False positives arise for some iterators that do not have this property,
+//# or in cases when the loop cursor is reassigned.  The latter should only
+//# happen when the matched code is on the way to a loop exit (break, goto,
+//# or return).
 ///
 // Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 iterator I;
 expression x,E,E1,E2;
 statement S,S1,S2;
@@ -55,4 +59,36 @@ I(x,...) { <...
   x != NULL
 + )
 )
-  ...> }
\ No newline at end of file
+  ...> }
+
+@r depends on !patch exists@
+iterator I;
+expression x,E;
+position p1,p2;
+@@
+
+*I@p1(x,...)
+{ ... when != x = E
+(
+*  x@p2 == NULL
+|
+*  x@p2 != NULL
+)
+  ... when any
+}
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("iterator-bound variable",p1)
+cocci.print_secs("useless NULL test",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
index 00af534..8f10b49 100644 (file)
@@ -1,17 +1,20 @@
 /// Find functions that refer to GFP_KERNEL but are called with locks held.
-/// The proposed change of converting the GFP_KERNEL is not necessarily the
-/// correct one.  It may be desired to unlock the lock, or to not call the
-/// function under the lock in the first place.
+//# The proposed change of converting the GFP_KERNEL is not necessarily the
+//# correct one.  It may be desired to unlock the lock, or to not call the
+//# function under the lock in the first place.
 ///
 // Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
 @gfp exists@
 identifier fn;
@@ -32,28 +35,29 @@ fn(...) {
  ... when any
 }
 
-@locked@
+@locked exists@
 identifier gfp.fn;
+position p1,p2;
 @@
 
 (
-read_lock_irq
+read_lock_irq@p1
 |
-write_lock_irq
+write_lock_irq@p1
 |
-read_lock_irqsave
+read_lock_irqsave@p1
 |
-write_lock_irqsave
+write_lock_irqsave@p1
 |
-spin_lock
+spin_lock@p1
 |
-spin_trylock
+spin_trylock@p1
 |
-spin_lock_irq
+spin_lock_irq@p1
 |
-spin_lock_irqsave
+spin_lock_irqsave@p1
 |
-local_irq_disable
+local_irq_disable@p1
 )
  (...)
 ...  when != read_unlock_irq(...)
@@ -64,11 +68,38 @@ local_irq_disable
      when != spin_unlock_irq(...)
      when != spin_unlock_irqrestore(...)
      when != local_irq_enable(...)
-fn(...)
+fn@p2(...)
 
-@depends on locked@
+@depends on locked && patch@
 position gfp.p;
 @@
 
 - GFP_KERNEL@p
 + GFP_ATOMIC
+
+@depends on locked && !patch@
+position gfp.p;
+@@
+
+* GFP_KERNEL@p
+
+@script:python depends on !patch && org@
+p << gfp.p;
+fn << gfp.fn;
+p1 << locked.p1;
+p2 << locked.p2;
+@@
+
+cocci.print_main("lock",p1)
+cocci.print_secs("call",p2)
+cocci.print_secs("GFP_KERNEL",p)
+
+@script:python depends on !patch && report@
+p << gfp.p;
+fn << gfp.fn;
+p1 << locked.p1;
+p2 << locked.p2;
+@@
+
+msg = "ERROR: function %s called on line %s inside lock on line %s but uses GFP_KERNEL" % (fn,p2[0].line,p1[0].line)
+coccilib.report.print_report(p[0], msg)
index b4344d8..1c4ffe6 100644 (file)
@@ -1,9 +1,9 @@
 /// Find nested lock+irqsave functions that use the same flags variables
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
@@ -12,7 +12,7 @@ virtual context
 virtual org
 virtual report
 
-@r@
+@r exists@
 expression lock1,lock2,flags;
 position p1,p2;
 @@
@@ -39,7 +39,7 @@ read_lock_irqsave@p2(lock2,flags)
 write_lock_irqsave@p2(lock2,flags)
 )
 
-@d@
+@d exists@
 expression f <= r.flags;
 expression lock1,lock2,flags;
 position r.p1, r.p2;
@@ -76,5 +76,5 @@ p1 << r.p1;
 p2 << r.p2;
 @@
 
-msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line)
+msg="ERROR: nested lock+irqsave that reuses flags from line %s." % (p1[0].line)
 coccilib.report.print_report(p2[0], msg)
index 7641a29..3267d74 100644 (file)
@@ -6,13 +6,14 @@
 /// function call that releases the lock.
 ///
 // Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
+virtual context
 virtual org
 virtual report
 
@@ -57,7 +58,7 @@ position r;
 
 for(...;...;...) { <+... return@r ...; ...+> }
 
-@err@
+@err exists@
 expression E1;
 position prelocked.p;
 position up != prelocked.p1;
@@ -65,14 +66,14 @@ position r!=looped.r;
 identifier lock,unlock;
 @@
 
-lock(E1@p,...);
+*lock(E1@p,...);
 <+... when != E1
 if (...) {
   ... when != E1
-  return@r ...;
+*  return@r ...;
 }
 ...+>
-unlock@up(E1,...);
+*unlock@up(E1,...);
 
 @script:python depends on org@
 p << prelocked.p1;
index 156b20a..cf74a00 100644 (file)
@@ -3,9 +3,9 @@
 /// initialization.
 ///
 // Confidence: Low
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
 // Options: -no_includes -include_headers
@@ -49,5 +49,5 @@ pr << r.p;
 @@
 
 if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
-  msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line)
+  msg = "%s: first occurrence line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line)
   coccilib.report.print_report(p0[0],msg)
index 4c9c52b..ed961a1 100644 (file)
@@ -1,16 +1,19 @@
 /// The various basic memory allocation functions don't return ERR_PTR
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 expression x,E;
 @@
 
@@ -18,3 +21,28 @@ x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache
 ... when != x = E
 - IS_ERR(x)
 + !x
+
+@r depends on !patch exists@
+expression x,E;
+position p1,p2;
+@@
+
+*x = \(kmalloc@p1\|kzalloc@p1\|kcalloc@p1\|kmem_cache_alloc@p1\|kmem_cache_zalloc@p1\|kmem_cache_alloc_node@p1\|kmalloc_node@p1\|kzalloc_node@p1\)(...)
+... when != x = E
+* IS_ERR@p2(x)
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("alloc call",p1)
+cocci.print_secs("IS_ERR that should be NULL tests",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: allocation function on line %s returns NULL not ERR_PTR on failure" % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
index 38f6617..833813a 100755 (executable)
@@ -132,7 +132,28 @@ exuberant()
        --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/'        \
        --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
        --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/'               \
-       --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/'
+       --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/'     \
+       --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/'                     \
+       --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/'                  \
+       --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/'                \
+       --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/'           \
+       --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/'                 \
+       --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/'               \
+       --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/'           \
+       --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/'       \
+       --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/'     \
+       --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/'           \
+       --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/'       \
+       --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/'              \
+       --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/'            \
+       --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/'               \
+       --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/'            \
+       --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/'          \
+       --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/'          \
+       --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/'      \
+       --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/'  \
+       --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
+       --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --langdef=kconfig --language-force=kconfig              \
@@ -146,6 +167,8 @@ exuberant()
        --langdef=dotconfig --language-force=dotconfig          \
        --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'
 
+       # Remove structure forward declarations.
+       LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' tags
 }
 
 emacs()
@@ -154,7 +177,28 @@ emacs()
        --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/'            \
        --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/'   \
        --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/'          \
-       --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/'
+       --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \
+       --regex='/PAGEFLAG\(([^,)]*).*/Page\1/'                 \
+       --regex='/PAGEFLAG\(([^,)]*).*/SetPage\1/'              \
+       --regex='/PAGEFLAG\(([^,)]*).*/ClearPage\1/'            \
+       --regex='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/'       \
+       --regex='/TESTPAGEFLAG\(([^,)]*).*/Page\1/'             \
+       --regex='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/'           \
+       --regex='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/'       \
+       --regex='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/'   \
+       --regex='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
+       --regex='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/'       \
+       --regex='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/'   \
+       --regex='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/'          \
+       --regex='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/'        \
+       --regex='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/'           \
+       --regex='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/'        \
+       --regex='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/'      \
+       --regex='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/'      \
+       --regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/'  \
+       --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
+       --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
+       --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'