summaryrefslogtreecommitdiffstats
path: root/doc/README
blob: 1175f01da4d04c8fff7e6cbea80181d9c4b8a64a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
1 Overview
~~~~~~~~~~

This is a set of scripts and tools for verifying Linux kernel patches.
Most of the scripts accept "-h" or "--help" options, which you can use
to get an idea what different scripts do.

It is important to know that all the scripts are written so that:
 * all the debugging and verbose (-v) cruft is printed to stderr
 * all the user-friendly output is printed to stdout

Thus, if you for example run "./aiaiai-test-patchset -v .... 2>log", then the
"log" file will contain all the unreadable debugging cruft and the nice
output will be visible on the console.

Also it is useful to know that the scripts never modify the repositories
you specify and the scripts remove all the temporary files upon exit,
Ctrl-C interruption, or error (unless -p option is specified).

Do not forget to compile the 'remap-log' and 'aiaiai-locker' tools before using
Aiaiai by just typing "make".

The layout of the repository.

* aiaiai/email/
    All the scripts related to emails handling. If you use Aiaiai locally
    you do not need these scripts.
* aiaiai/external/
    Some external tools and files which we use are stored here.
* aiaiai/doc
    Some documentation.
* aiaiai/tests/
    Unit-tests.
* aiaiai/
    The root repository directory contains the scripts which do all the
    patch checking work. The central script is 'aiaiai-test-patchset' which
    uses all the other scripts as helpers.

Let's briefly review the contents of the repository.


1.1 E-mail-related scripts
~~~~~~~~~~~~~~~~~~~~~~~~~~

* email/aiaiai-email-lda
    This is Aiaiai's local delivery agent script which receives the incoming
    emails from the mail server (via a pipe), procesess them (drops all e-mails
    which do not start with [PATCH*], detects and collects patch-sets), and
    puts them to the "queue" sub-directory of the work directory. This
    should, in turn, wake up the "aiaiai-email-dispatcher" script which will
    take further care of the patch or patch-set.

* email/aiaiai-email-dispatcher
    This script waits for the incoming patch-sets in the "queue" directory and
    runs a user-defined command for every incoming patch-set. The role of this
    script is to limit the amount of patch-sets we can run at a time. You
    can configure this via command line options.

    As it was already said, in our setup 'aiaiai-email-dispatcher' runs
    'aiaiai-email-test-patchset'.

* email/aiaiai-email-dispatcher-helper
    This is a private helper script for 'aiaiai-email-dispatcher'.

* email/aiaiai-email-test-patchset
    This script parses the incoming e-mail (in mbox format), finds out which
    kernel tree has to be used, sends a notification to the sender, runs
    the 'aiaiai-test-patchset' script with the right command-line arguments, and
    sends the results of 'aiaiai-test-patchset' back to the patch submitter.

* email/aiaiai.cfg
    This is an example of 'aiaiai-email-test-patchset' configuration file. It
    describes the projects Aiaiai supports and their parameters. Take a
    look inside - the file is self-descriptive.

Here is how all these scripts work together.  When you send an e-mail to the
server which runs Aiaiai, the MTA pipes it to 'aiaiai-email-lda'. We used the
postfix MTA, and the 'aiaiai' Linux user had the following file in its home
directory:

$ cat $HOME/.forward
|/home/aiaiai/bin/my-aiaiai-lda

Which made sure that all e-mails coming to aiaiai@our-domain.ququ were piped
to the my-aiaiai-lda script. The script simply ran aiaiai-email-lda with
tje options we needed:

$ cat /home/aiaiai/bin/my-aiaiai-lda
$HOME/git/email/aiaiai-email-lda -v --reap-archive=43200 --reap-incomplete=10 -- $HOME/aiaiai-workdir >> $HOME/aiaiai-logs/email-lda.log" 2>&1


So, aiaiai-email-lda collects patches belonging to the patch-sets, and when it
has all of them, it squashes them into one mbox file and moves them to the
queue directory. This will wake up the 'aiaiai-email-dispatcher' script, which
will execute 'aiaiai-email-test-patchset' for this mbox (unless there are
already too many jobs, in which case it will wait).

The 'aiaiai-email-test-patchset' will parse the patch-set, find out which
kernel it has to be tested against using the configuration file, send a
notification e-mail to the patch sender, and execute the 'aiaiai-test-patchset'
script.

The 'aiaiai-test-patchset' script does all the testing work and outputs the
test results to stdout. 'aiaiai-email-test-patchset' captures the output and
sends it back to the patch submitter.


1.2 Non-e-mail scripts
~~~~~~~~~~~~~~~~~~~~~~

* aiaiai-test-patchset
    The central script which tests a patch-set is 'aiaiai-test-patchset'. You
    should use it if you want to test your patches locally. It accepts patches
    in the mbox format. You should specify various input parameters like the
    path to the kernel to test against, the commit id to test against, which
    tests to run, etc.

* aiaiai-make-kernel
    Low-level scripts which builds the kernel. It has several switches which
    change its behavior, e.g., you can select whether you want to run
    sparse/smatch/cppcheck/coccinelle tools or not.

    'aiaiai-make-kernel' utilizes the 'aiaiai-locker' utility to make
    sure the build logs of parallel builds are not scrambled and stay readable.

* aiaiai-locker
    This utility was inspired by Eric Melski's blog-post I found in the Internet.
    We use this tool to make Linux kernel build logs saner than parallel build
    produces (e.g., "make -j 20"). Indeed, parallel make scrambles all the
    lines which makes build logs not comparable and not readable.

    The idea is to run all make commands via the 'aiaiai-locker' utility using
    the GNU make 'SHELL' variable re-definition. 'aiaiai-locker' intercepts the
    stdout and stderr output of commands, gathers all the output until the
    command finishes, and locks a common lockfile, and prints the intercepted
    output. So the effect of this is that the in the build log the output of
    one program goes as one big block and it is not mixed with the output of
    another command.

* aiaiai-checker
    A helper script for 'aiaiai-make-kernel' which runs
    sparse/smatch/cppcheck/coccinelle tools. The reason we need it is because
    the kernel build system allows only one checking program at a time, but we
    want to run multiple of them.

* aiaiai-diff-log
    Compares 2 build logs and provides the differences. This script used the
    'external/remap-log' tool to re-map line numbers in the warnings of the
    first build log to correspond to line numbers in the second build-log.

* aiaiai-diff-log-helper
    A helper script for aiaiai-diff-log which sorts 2 build logs and compares
    them.  Written in Python because the shell version was too slow.

* external/remap-log
    This is a small C program originally written by Al Viro which helps
    comparing 2 build logs by remapping line numbers. Roughly speaking,
    'remap-log' takes the build log of the pre-patched kernel and the patch and
    changes line numbers in the build log to match line numbers in the build
    log of the patched kernel. For example, supposed that you have the
    following warning in the pre-patched kernel:

    driver.c:100 Unused variable 'ret'

    and your patch adds a new include to the driver.c file, so the patched
    kernel will produce the following warning:

    driver.c:101 Unused variable 'ret'

    Obviously, you do not want to bug the patch author about this warning
    because it was not his patch which introduced it. And if you used a plain
    diff, it would produce something like:

    -driver.c:100 Unused variable 'ret'
    +driver.c:101 Unused variable 'ret'

    But we pass the build log for the pre-patched kernel via 'remap-log' and it
    transforms that warning into

    driver.c:101 Unused variable 'ret'

    so the build logs of the pre-patched and patched kernels will contain the
    same line and the diff won't show anything.

* aiaiai-test-bisectability
    Accepts a patch-set as the input and checks that the patch-set does not
    break compilation at any step. This is achieved by applying every patch in
    the series one-by-one, compiling the kernel and checking that compilation
    was successful.

* aiaiai-decode-rfc-2047
    A small helper script which decodes unreadable patch subjects encoded with
    RFC-2047 MIME encoding.

* aiaiai-concat-mboxes
    A little helper script which concatenates multiple mbox files into one.

* aiaiai-match-keywords
   A simple script which can be used to match certain unwelcom keywords in
   patches.

To summarize:
 * 'aiaiai-test-patchset' is the central script
   * it runs 'checkpatch.pl'
   * it runs 'aiaiai-test-bisectability'
   * for every configuration specified by the user, it builds the kernel
     before and after the patch using the 'aiaiai-make-kernel' script, then
     compares the build log using the 'aiaiai-diff-log' script.
   * Things are done in parallel.
   * The results of all tests are collected and printed to stdout
   * The "verbose" contents is printed to stderr
   * Many of the jobs above are run in parallel

The 'aiaiai-diff-log' script which compares 2 logs. It uses the 'remap-log'
tool for comparing 2 build logs the smart way.


2 Using Aiaiai locally
~~~~~~~~~~~~~~~~~~~~~~

If you just want to test a patch-set locally, you should use the
'aiaiai-test-patchset' script. Do not forget to build the remap-log.c file in
the 'external' subdirectory.

Here are some examples.

1. Test a patch or a patch-set p.mbox against the linux-vfs kernel tree,
   against the 'origin/next' branch, and use the 'i386_defconfig'
   defconfig, the architecture is i386 (translates to 'make ARCH=i386'). Use
   16 jobs.

   cat p.mbox | ./aiaiai-test-patchset --bisectability --sparse --smatch \
       --cppcheck --coccinelle -j 16 -c origin/next \
       /<path>/linux-vfs i386_defconfig,i386

2. Test a patch or a patch-set p.mbox against the linux-omap kernel tree,
   against the master branch, use the 'omap2plus_defconfig' defconfig,
   'arm' architecture and 'arm-eabi-' cross-compiler prefix (translates to
   'make CROSS_COMPILE=arm-eabi-').

   cat p.mbox | ./aiaiai-test-patchset --bisectability --sparse --smatch \
       --cppcheck --coccinelle -j 16 -c master \
       /<path>/linux-omap omap2plus_defconfig,arm,arm-eabi-

3. If you are a maintainer you may want to test patches for more than one
   architecture. You can do this - you'll just need to maintain defconfigs.
   E.g., to test p.mbox against both i386_defconfig (Intel i386) and
   omap2plus_defconfig (ARM-based SoC), you can run:

   cat p.mbox | ./aiaiai-test-patchset --bisectability --sparse --smatch \
       --cppcheck --coccinelle -j 16 -c master /<path>/linux-my \
       i386_defconfig,i386 omap2plus_defconfig,arm,arm-eabi-

   IOW, just specify defconfigs, architectures, and cross-compiler prefixes at
   the end.

Note, the 'aiaiai-test-patchset' script accepts one mbox file via stdio or the
'-i' option. If you have several files belonging to one patch-set and you want
to test them all, you need to concatenate them. Use the 'aiaiai-concat-mboxes'
script for this. E.g., if you have '01.mbox' and '02.mbox' comprising a
patch-set, you can test do like this:

$ aiaiai-concat-mboxes 01.mbox 02.mbox | aiaiai-test-patchset ....

Patches generated with 'git format-patch' are also mbox files so you can test
them with 'aiaiai-test-patchset' as well. Just remember to use the '--thread'
option to make 'git format-patch' generate "Message-Id:" and "In-Reply-To:"
headers. For example:

$ git format-patch --thread HEAD~10
$ aiaiai-concat-mboxes 00* | aiaiai-test-patchset ...

I usually run 'aiaiai-test-patchset' with the lowest priority in order to make
sure the machine is still usable for other things:

$ nice -n19 ionice -c3 aiaiai-test-patchset ...

And for the kernel trees I test frequently against, I usually have a helper
script so that I do not have to type the 'aiaiai-test-patchset' options over
and over again.


3 Dependencies
~~~~~~~~~~~~~~

3.1 smatch
~~~~~~~~~~

Project homepage: http://smatch.sourceforge.net

I do not think this tool is a part of Linux distributions. I found it very
useful. To use it, you have to clone it, patch it, and install in your system.

$ git clone git://repo.or.cz/smatch.git
$ cd smatch
$ make PREFIX=$HOME/programs/smatch all install
$ export PATH="$PATH:/home/aiaiai/programs/smatch/bin"

These commands will install smatch to "/home/aiaiai/programs/smatch". Of
course, you should specify your path and make sure smatch is in your "PATH"
environment variable.


3.2 sparse
~~~~~~~~~~

Similarly to smatch, you need to install it manually. This is what I did:

$ git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git
$ cd sparse
$ make
$ cp sparse $HOME/bin
$ export PATH="$HOME/bin:$PATH"


3.3 coccinelle
~~~~~~~~~~~~~~

Coccinelle or "spatch" is a great semantic patch tool, very useful on its own.
The Linux kernel contains a bunch of coccinelle semantic patches which catch
various types of API abuses etc. We store a copy of these scripts in the
"external" subdirectory.

The "spatch" tool is part of distributions like Debian and Fedora, so you most
probably just need to install the corresponding package. The binary program is
called "spatch".

You may find a lot of information about this awesome tool by Googling.


3.4 Dependencies
~~~~~~~~~~~~~~~~

The scripts use many external programs which are usually part of the Linux
distribution. Here are they are, but the list is not complete - if you spot
a missing dependency - please, let me know or send a patch against the README
file.

gcc
make
cppcheck
formail
perl
python
mutt
sed
grep
awk
git
lockfile
diff
patch
inotifywait


3.5 Code conventions
~~~~~~~~~~~~~~~~~~~~

The scripts have been written for the "dash" shell and they do not use
any "bashizm" and should be very portable. Please, keep this in mind
when changing them. The scripts try to follow a uniform coding style
and conventions. Below are some of them.

* Stdout is used only for user-friendly stuff. In many cases it is assumed that
  the higher-level scripts just capture the stdout of lower-level scripts and
  provide that to the user. For example, 'aiaiai-test-patchset' captures stdout
  of the 'aiaiai-test-bisectability' scripts and uses it for reporting to the
  user. In turn, the 'aiaiai-email-test-patchset' script captures stdout of the
  'aiaiai-test-patchset' script and sends it back to the user via e-mail.

* Stderr is use for all the debugging, verbose and additional prints.

* The scripts use the "-e" shell option and in case of any error (non-zero
  return code from any program) we exit immediately. This allows us simplify
  the scripts and avoid handling errors for all the commands which is very
  convenient.

  Well, the automatic exit does not work if the errorred command is in a
  pipeline, and not the last. But this is not a big deal in most cases.

  And sometimes we do not want the whole script to error out if a command
  returns non zero (e.g., grep returns 1 if it did not match the pattern),
  in which case we usually use "||:" after the command.

* We use "-u" shell option to make sure our scripts are of good quality.

* We try to be more secure and use the "-f" shell option whenever we can.

* We make use of the external "libshell" library which is part of the Alt
  Linux project and is extremely useful.

* All the temporary files should be remover upon exit or interruption
  (ctrl-C must be handled gracefully)

* Users' git repository have to be treated as read-only and no modifications
  should be made there. All the work has to be done in a clone of the original
  repository.