一、问题背景
linux开发工作种往往会碰到一种情况,那就是低版本kernel有问题,高版本kernel无问题,而解决问题的patch就在这其中的某一次提交中,自己没有明确的排查想法,最后只能尝试用最笨的二分实验来查找。
二、具体的二分查找patch
1.kernel源码包级别
初始采用从网站(如https://mirrors.aliyun.com/centos/)下载特定的tar包,编译kernel后逐次实验,最终定位到问题修复版本区间为4.18.20----4.19.0.
但由于kernel开发布局影响,两个版本分属不同的开发分支:
kernel-4.18 --- v4.19-rc1 --- v4.19-rc2 ………… v4.19-rc8 --- v4.19.0 (主开发分支)
\
\ ----- v4.18.1 --- v4.18.2 …………v4.18.20 (维护分支)
于是退回到 v4.18---v4.19 开始重新二分,由于没有现成的tar包,所以采用从git中按tag二分。

首先下载linux的git仓库,然后从linux-4.19.y分支中依次抽取v4.19分支,v4.19-rcX分支,最终实验出 4.19.0-rc1可以。
2.git log页级别
由于4.18到4.19.0-rc1属于补丁合入窗口,期间有五千多补丁,所以初期按照git log 中以页为单位划分,最终将区间缩小到git提交中的一页,于是范围缩小到page3--page4.
4.18不可以---4.18-p3不可以-----------------4.18-p4可以--- 4.18-p10可以-- 4.19.0-rc1可以

然后针对page3--page4中的各个提交继续二分,以此为主线的测试结果为
4.18不可以--4.18-p2不可以--4.18-acpi不行-p3不行---ACPICA不行--ib不行---mail不行---plat不行---
------4.18-harden可以---4.18-p4可以--- 4.18-p10可以-- 4.19.0-rc1可以
但此时存在问题(其实是个人对git log的误解),比如v4.18-ACPICA分支,明明在p3--p4之间,但针对该分支查看log,发现其仅处在p2之前,还没有p3的标记,出现错乱。

其实这些错乱源自于git 的merge属性,由于存在大量merge tag,有些很早就提交的patch经过merge后反而被git log --oneline显示在前面,这样针对这个被merge过来的提交创建新分支,其代码不知道老旧到什么地步了。
正确的做法应该是把merge提交全部打开,或者说是按merge顺序反方向去revert,这样就能避免log 错乱问题。其实更简单的,在git log 时加上--graph参数,就能窥见全貌不再错乱。
有以下几个git命令组合比较有帮助:
//隐去细节,宏观查看所有提交,不管是merge还是commit平等对待
git log --oneline --first-parent <tag1>^1..<tag2>
git log --oneline --first-parent v6.6..v6.7
//打开一个merge,查看该merge中的所有补丁
git log --oneline --decorate <merge_commit>^1..<merge_commit>
git log --oneline --decorate ba70ffa7d20d^1..ba70ffa7d20d
//宏观查看该branch的整个历史演进,merge及其提交均通过支流显示
git log --oneline --decorate --graph <commit>^1..<commit>
git log --oneline --decorate --graph v4.18-x86^1..v4.18-au
3.git中自行创建的branch级别
所以,先根据之前测试【成功-失败】的区间,找一个最近范围的如【v4.18-harden到v4.18-acpi】总体看一下区间中的merge记录,(--first-parent)
然后再详细看一下merge打开的记录(--graph)

记住只针对graph显示中首行为*的提交创建新分支(其实也就是--first-parent的显示)。因为那是主流汇集点,也就是merge过来形成的节点,属于大河交汇处,是第一级目录,所以针对这个二分就不会顺序错乱。
然后进行二分,即针对节点是*的提交拉去新分支去编译kernel,然后安装去二分实验,最终将范围缩小到两个一级标签之间【v4.18-au到v4.18-x86】

可以发现他们之间已经没有任何一级提交点了,最终的patch就在这俩tag之间,而且基本都是以patch的形式存在,就算有merge记录打开查看也是很小的提交记录。

4.git提交级别(单个patch)
以此开始,可以有两种方法继续排查。
1.可以在好的节点v4.18-au开始一个个反方向回退(二分打多个),也就是git revert 打上退回的补丁,逐一实验。
2.也可在坏的节点v4.18-x86处开始按真实的历史一个个正向打补丁(二分打多个),逐一实验。
由于这两个tag之间的patch不多只有90多个,所以我选择第2种正向打补丁测试。
首先用 git format-patch一次性获取这两个tag之间的所有补丁。

获得补丁后,以v4.18-x86为基准(每次切换到这个分支后进行copy)通过脚本的方式一次性对kernel源码打一半补丁-->实验后二分-->继续打一半补丁,直到最终找到那一个补丁或一个补丁集。
#cat dopa.sh
----------------------------------
for p in $(ls -v *.patch); do
echo "应用: $p"
if ! patch -p1 < "$p"; then
echo "失败于: $p"
break
fi
done

二分之前稍微看下补丁内容,结合所遇问题基本就能断出几个位置,最终的二分实验结果如下:
x86不行---p22不行---p29不可以---p33不可以-------p34可以---p49可以---au可以


于是最终锁定了那个patch34:https://patchwork.kernel.org/project/linux-arm-kernel/patch/20180625130552.5636-1-lorenzo.pieralisi@arm.com/
三、过程中其他记录
1.给一个配置静态IP的方法,其实就是3行配置(ip三元素) + 2行改动(bootproto=static及onboot=yes)

[root@localhost ~]# cd /etc/sysconfig/network-scripts/
[root@localhost network-scripts]# cat ifcfg-enP11s111f0
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
IPADDR=10.5.102.189
PREFIX=24
GATEWAY=10.5.102.254
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=enP11s111f0
UUID=31e25947-93cf-4c7c-9dd1-91b85792fc73
DEVICE=enP11s111f0
ONBOOT=yes
静态配置网卡IP,记得要重启机器,只重启NetworkManager服务没用。

2.给一个进入grub后,重新找到kernel并启动的方法,其实就是手动设置kernel+initrd


4133

被折叠的 条评论
为什么被折叠?



