0%

How do Linux kernel maintainers of stable tree backport patches?

Quilt : manage patches

Sample code repo : https://github.com/Ganliber/linux-kernel-backporting

diff + patch

Demo structure

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
origin-project
├── new-project
│ ├── build
│ │ └── Makefile
│ ├── inc
│ │ ├── def1.h
│ │ └── def2.h
│ └── src
│ ├── drivers
│ │ ├── drv1.c
│ │ ├── drv1.h
│ │ ├── drv2.c
│ │ └── drv2.h
│ ├── lib
│ │ ├── lib1.c
│ │ ├── lib1.h
│ │ ├── lib2.c
│ │ └── lib2.h
│ └── sys
│ ├── sys1.c
│ └── sys1.h
└── old-project
├── build
│ └── Makefile
├── inc
│ ├── def1.h
│ └── def2.h
└── src
├── drivers
│ ├── drv1.c
│ ├── drv1.h
│ ├── drv2.c
│ └── drv2.h
├── lib
│ ├── lib1.c
│ ├── lib1.h
│ ├── lib2.c
│ └── lib2.h
└── sys
├── sys1.c
└── sys1.h

Usage 1 : file patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ diff 
[1]
diff -u [old-file] [new-file] > [patch-file]
[---] -> old file
[+++] -> new file
[@@ -a,b +c,d @@] between '@@' is the different partition, the other lines is "context".
-> in old file, beginning from line-a, there are b lines that have been changed.
-> in new file, beginning from line-c, there are d lines that differentiate from old one.
[2]
diff -Nur [old-dir] [new-dir] > [patch-file]
diff -Naur [old-dir] [new-dir] > [patch-file]
[-u] unified style
[-N] treat non-existent file as empty files, without [-N], patch will not include the file that new-proj includes but old-proj dose not include.
[-r] compare sub-dir
[-a] treat all files as text files
$ patch
patch -pn < [patch-file]
  • make patch drv1-h.diff

    1
    diff -u old-project/src/drivers/drv1.h new-project/src/drivers/drv1.h > ../drv1-h.diff
  • make copy of old-file

    1
    cp -r old-project ../old-project-cp
  • apply patch in old-project-cp

    About -pn : n means removing the n-level of '/', for example, -p1 means that the file to be patched is src/drivers/drv1.h without old-project/, -p2 means that the file is drivers/drv1.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
      $ cat -n ../drv1-h.diff
    1 --- old-project/src/drivers/drv1.h 2022-09-09 16:29:55.524191836 +0800
    2 +++ new-project/src/drivers/drv1.h 2022-09-09 16:31:28.137213185 +0800
    3 @@ -7,9 +7,8 @@
    4 typedef struct
    5 {
    6 /* data */
    7 - int p1;
    8 - int p2;
    9 - int p3;
    10 + int p_new1;
    11 + int p_new2;
    12 } lib1;
    13
    14 void func_lib1(void);
    $ patch -p1 < ../drv1-h.diff
    patching file src/drivers/drv1.h



    ### Usage 2 : dir patch

    ```bash
    diff -Nur old-project new-project > ../prj-dir.diff

View patch content

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
$ cat -n ../prj-dir.diff 
1 diff --color -Nur old-project/src/drivers/drv1.h new-project/src/drivers/drv1.h
2 --- old-project/src/drivers/drv1.h 2022-09-09 16:29:55.524191836 +0800
3 +++ new-project/src/drivers/drv1.h 2022-09-09 16:31:28.137213185 +0800
4 @@ -7,9 +7,8 @@
5 typedef struct
6 {
7 /* data */
8 - int p1;
9 - int p2;
10 - int p3;
11 + int p_new1;
12 + int p_new2;
13 } lib1;
14
15 void func_lib1(void);
16 diff --color -Nur old-project/src/usr/usr.c new-project/src/usr/usr.c
17 --- old-project/src/usr/usr.c 1970-01-01 08:00:00.000000000 +0800
18 +++ new-project/src/usr/usr.c 2022-09-09 17:11:23.733029333 +0800
19 @@ -0,0 +1 @@
20 +#include "usr.h"
21 diff --color -Nur old-project/src/usr/usr.h new-project/src/usr/usr.h
22 --- old-project/src/usr/usr.h 1970-01-01 08:00:00.000000000 +0800
23 +++ new-project/src/usr/usr.h 2022-09-09 17:10:52.065591264 +0800
24 @@ -0,0 +1,4 @@
25 +#ifndef USR1_H
26 +#define USR1_H
27 +#include "def.h"
28 +#endif

Apply patch

1
2
3
4
$ patch -p1 < ../prj-dir.diff
patching file src/drivers/drv1.h
patching file src/usr/usr.c
patching file src/usr/usr.h

quilt

  • quilt manages patches by using stack.

  • structure

    1
    2
    patches
    .pc
  • instruction set

    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
    /* 对于一个patch其实在quilt中不只是一个补丁文件, 而是一个补丁环境, 具有与其关联的文件(修改&未修改) */
    quilt import [patch-file] //导入补丁(not applied)
    quilt applied //查看已经应用的补丁
    quilt unapplied //查看还没有应用的补丁
    quilt top //查询栈顶补丁(已应用的最新补丁)
    quilt previous //查询上一个补丁
    quilt push //应用补丁
    quilt push -a //应用所有补丁
    quilt pop //回退刚刚文件的改动
    quilt add [-P 'patch-name'] [file-name]
    //为指定补丁保存了指定文件的当前快照
    //将文件的当前状态和补丁联系起来
    //如果没有指定补丁名,就与栈顶补丁联系起来
    quilt remove [-P 'patch-name'] [file-name]
    //取消关联文件
    quilt new [new-patch-name] //不想修改原补丁, 新建patch
    quilt diff //查看对比修改的内容
    quilt diff -z [-P 'patch-name'] [file-name] //查看指定补丁指定文件当前改动
    quilt diff -z
    quilt files [patch-name] //查看与补丁相关联的文件
    quilt files -val //查看所有补丁联系的所有文件
    // -v : 更友好的显示
    // -a : 所有补丁
    // -l : 显示补丁名
    quilt refresh
    //修改完成后将该记录更新至补丁之中
    //刷新指定的补丁,或默认刷新最上面的补丁。补丁文件中实际补丁之前的文件将被保留。

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
proj
├── build
│ └── Makefile
├── inc
│ ├── def1.h
│ └── def2.h
└── src
├── drivers
│ ├── drv1.c
│ ├── drv1.h
│ ├── drv2.c
│ └── drv2.h
├── lib
│ ├── lib1.c
│ ├── lib1.h
│ ├── lib2.c
│ └── lib2.h
└── sys
├── sys1.c
└── sys1.h
  • Import patch through quilt

    1
    2
    $ quilt import ../prj.diff
    Importing patch ../prj.diff (stored as patches/prj.diff)
  • After quilt import, a dir named patches will be generated under the current dir.

    series will play as a patch-queue list recording the deployed patches in order.

    1
    2
    3
    4
    5
    6
    $ ls
    build inc patches src
    $ ls patches
    prj.diff series
    $ cat -n series
    1 prj.diff
  • Add new patch, bind several files with a patch.

    1
    2
    quilt new drv_p1.diff
    quilt add drv2.h // 与栈顶补丁联系起来, 即drv_p1.diff

Backporting in stable-queue

Overview on process of backporting in stable-queue

scripts list

Scripts used for backporting patches to stable-queue up to now

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* added-to-stable
bad_stable
* c2p
convert_to_utf8
dorelease
dropped_commits
guess-charset
makemail
make_message_id
mbox2send
quilt-mail
smtpsend
splitmbox.py
tag_stable

procedure

  • Select patch.

    ( Manually ) select suitable patch from mail-queue-stable, get the commit id of that patch.

  • Grab the patch.

    c2p ( written in perl ) : commit id -> patch ( grab this patch from linus’tree ( upstream ) )

    1
    ./scripts/c2p [commit-id]
    • Grabs the patch by commit id
    • Formats the patch into proper layout needed for a stable tree.
    • Enter a editor where maintainer( Greg or Levin ) can edit it.
    • After editing, this script will copy it into stable-tree directory
  • Check before applying it.

    1
    2
    3
    4
    5
    6
    * [example]
    patch -p1 --dry-run < ../patch-name.patch
    * Greg make a alias for it like:
    alias p1='patch -p1 --dry-run'
    * About parameter '--dry-run':
    The --dry-run option tells patch to do everything apart from actually modifying the files. patch will perform all of its pre-flight checks on the files and if it encounters any problems, it reports them. Either way, no files are modified.
  • Apply that patch.

    1
    2
    3
    4
    5
    6
    quilt import ../patch-name.patch
    * import this patch to the quilt-series-patch-queue
    q push
    * Apply this patch, 'q' is the alias of 'quilt'
    q refresh
    * Refreshes the specified patch, or the topmost patch by default.Documentation that comes before the actual patch in the patch file is retained.
  • Git commit in stable-tree.

    1
    2
    3
    4
    git add queue-[version]/
    git commit -a
    // edit the note message
    git push
  • Notify the author his patch has been merged in the stable-[version] tree.

    In the file added-to-stable, there are one line which means that the msmtp will send the email to the author according to commit-id:~/bin/msmtp-enqueue.sh -a coco "$to"

    1
    ./scripts/added-to-stable [patch-file]
  • Build the patch into the stable-kernel image.

  • Testing it.

Reference