Scripts, patches and fun with them

These two weeks have been great fun, working with some Coccinelle scripts and sending in patches.

So lets look at a few scripts. These may look a bit too structured for a blog but wanted to keep it understandable thats why its so :P.

Aim : This script removes null test on values that cannot be null as they are assigned the value that has the form &a->b (add the offset of b to the address of a where a is a valid pointer) or are assigned using get_drvdata functions.
Purpose : This helped in removal of good amount of code within the NULL test block in some instances and also reduces unnecessary checks.
Coccinelle script :
@r@
expression e,f;
identifier g,y;
statement S1,S2;
position p1,p2;
identifier accessor =~ “get_drvdata”;
@@

e =@p1 &f->g
<+… \(f->y\|accessor(f)\)
…+>
if (e@p2 != NULL || …)
S1 else S2

@bad@
expression e,e2;
position r.p1,r.p2;
@@

… when != e =@p1 e2
e@p2

@depends on !bad@
expression e,e1,e2;
position r.p1,r.p2;
@@

* e =@p1 e2
… when != e = e1
when != &e
* e@p2

Aim: This patch removes magicnumbers and replaces them by existing constants:
Purpose: This will encourage use of the defined constants and help in better readability of the code for developers.
Coccinelle script:
@r@
type T;
T E;
identifier fld;
identifier c;
@@

E->fld & c

@s@
constant C;
identifier r.c;
@@

#define c C

@@
r.T E;
identifier r.fld;
identifier r.c;
constant s.C;
@@

E->fld &
– C
+ c

Aim: This patch eliminates NULL test after alloc_bootmem functions as they never return a NULL.
Purpose: Unnecessary code within NULL test is done away with as NULL values or ERR is never returned by alloc_bootmem functions. Also, useless checks are no longer performed.
Coccinelle Script:
@@
expression E;
statement S;
@@

E = \(alloc_bootmem\|alloc_bootmem_low\|alloc_bootmem_pages\|alloc_bootmem_low_pages\)(…)
… when != E
(
– BUG_ON (E == NULL);
|
– if (E == NULL) S
)

@@
expression E,E1;
@@

E = \(alloc_bootmem\|alloc_bootmem_low\|alloc_bootmem_pages\|alloc_bootmem_low_pages\)(…)
… when != E
– memset(E,0,E1);

Aim: Free memory allocated using kmem_cache_zalloc using kmem_cache_free rather than kfree.
Purpose: This will ensure proper deallocation of the cached content by calling cache_from_obj to get the kmem_cache and then free it.
Coccinelle Script:
@@
expression x,E,c;
@@

x = \(kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\)(c,…)
… when != x = E
when != &x
?-kfree(x)
+kmem_cache_free(c,x)

An important point, as no mistake is a small mistake!

I encountered an interesting case in Coccinelle due to a change in language semantics. Earlier, if a specified string was used with “declarer” it used to match only that declaration but now it declares a metavariable that can match any declarer. So, we should use “declarer name” instead.

This is matching any declarer (thing like DEFINE_MUTEX, etc) and hence I ended up with 435 cases and was perplexed that how can so many instances endup using spin_lock instead of a mutex_lock.
initial::
@def@
declarer DEFINE_MUTEX;
identifier m;
@@

DEFINE_MUTEX(m);

@@
identifier def.m;
@@

(
– spin_lock(&m)
+ mutex_lock(&m)
|
– spin_unlock(&m)
+ mutex_unlock(&m)
)

But, then I realized the problem and found the right cases where a lock is defined as a mutex lock but is used with spin_lock 🙂 .
final::
@def@
declarer name DEFINE_MUTEX;
identifier m;
@@

DEFINE_MUTEX(m);

@@
identifier def.m;
@@

(
– spin_lock(&m)
+ mutex_lock(&m)
|
– spin_unlock(&m)
+ mutex_unlock(&m)
)

I have added the managed interfaces for kasprintf and kvasprintf that help in allocating resource managed space and copying an existing formatted string into it. Here is the patch and yeah its accepted. My first two official managed interfaces 😀

Woof!! It was interesting to work with these patches and tackle the issues 🙂 But, there are many more to go. 😛
Will keep you posted about more…Bye

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s