前言

内核模块的更新一般需要卸载模块再加载,但是很多时候使用场景决定了无法做卸载的操作,而linux支持了热更新内核模块的功能,这个已经支持了有一段时间了,一直没有拿ceph的相关模块进行验证

准备工作

先检查当前的版本支持不

[root@lab101 kpatch]# cat /boot/config-3.10.0-1062.el7.x86_64 |grep PATCH
CONFIG_HAVE_LIVEPATCH=y
CONFIG_LIVEPATCH=y
CONFIG_DVB_BUDGET_PATCH=m
CONFIG_SND_HDA_PATCH_LOADER=y

可以看到默认内核是支持的,这个是红帽维护的一个体系,自己的内核,肯定会很快集成进去的

安装依赖包

[root@lab102 ~]# yum install  elfutils-devel  rpm-build
[root@lab102 ~]# rpm -ivh kernel-debuginfo-common-x86_64-3.10.0-1062.el7.x86_64.rpm kernel-debuginfo-3.10.0-1062.el7.x86_64.rpm

下载软件

git clone https://github.com/dynup/kpatch.git
make
make install

上面的软件提供两个命令

一个是kpatch

一个是kpatch-build

后面会用到

我的机器是这个版本

[root@lab102 ~]# uname  -a
Linux lab102 3.10.0-1062.el7.x86_64 #1 SMP Wed Aug 7 18:08:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

那么提前下载好

kernel-3.10.0-1062.el7.src.rpm

生成差异热更新模块

因为这个打补丁是基于差异打的补丁,所以需要知道之前的源码和现在的源码的差异,然后再进行后面的处理,所以我们要准备两份源码,一份未修改的,一份修改了的

[root@lab102 kernel]# rpm2cpio kernel-3.10.0-1062.el7.src.rpm |cpio -div
[root@lab102 kernel]# xz -d linux-3.10.0-1062.el7.tar.xz
[root@lab102 kernel]# tar -xvf linux-3.10.0-1062.el7.tar
[root@lab102 kernel]# cp -ra linux-3.10.0-1062.el7/ linux-3.10.0-1062.el7-patch

我们现在就有两份源码了

我们默认使用的是前面那套内核里面的代码,后面的是准备修改的代码

修改代码

[root@lab102 kernel]# vim linux-3.10.0-1062.el7-patch/drivers/block/rbd.c

为了方便查看我们修改rbd map的函数

        pr_info("%s: capacity %llu features 0x%llx\n", rbd_dev->disk->disk_name,
(unsigned long long)get_capacity(rbd_dev->disk) << SECTOR_SHIFT,
rbd_dev->header.features);
rc = count;

改成

       pr_info("%s: capacity 我改这里的显示了  %llu features 0x%llx\n", rbd_dev->disk->disk_name,
(unsigned long long)get_capacity(rbd_dev->disk) << SECTOR_SHIFT,
rbd_dev->header.features);
rc = count;

获取差异文件

[root@lab102 kernel]#  diff -u linux-3.10.0-1062.el7/drivers/block/rbd.c linux-3.10.0-1062.el7-patch/drivers/block/rbd.c > rbd.patch

得到的文件如下

[root@lab102 kernel]# cat rbd.patch
--- linux-3.10.0-1062.el7/drivers/block/rbd.c 2019-07-19 03:58:03.000000000 +0800
+++ linux-3.10.0-1062.el7-patch/drivers/block/rbd.c 2020-11-19 15:22:21.653239816 +0800
@@ -6299,7 +6299,7 @@
list_add_tail(&rbd_dev->node, &rbd_dev_list);
spin_unlock(&rbd_dev_list_lock); - pr_info("%s: capacity %llu features 0x%llx\n", rbd_dev->disk->disk_name,
+ pr_info("%s: capacity 我改这里的显示了 %llu features 0x%llx\n", rbd_dev->disk->disk_name,
(unsigned long long)get_capacity(rbd_dev->disk) << SECTOR_SHIFT,
rbd_dev->header.features);
rc = count;

我们需要根据这个

[root@lab102 kernel]# /usr/local/bin/kpatch-build rbd.patch  --skip-gcc-check --skip-cleanup  -r kernel-3.10.0-1062.el7.src.rpm
WARNING: Skipping gcc version matching check (not recommended)
Skipping cleanup
Fedora/Red Hat distribution detected
Downloading kernel source for 3.10.0-1062.el7.x86_64
Unpacking kernel source
Testing patch file(s)
Reading special section data
Building original source
Building patched source
Extracting new and modified ELF sections
rbd.o: changed function: do_rbd_add.isra.45
Patched objects: drivers/block/rbd.ko
Building patch module: livepatch-rbd.ko
SUCCESS

可以从提示上面看到一些信息

修改是drivers/block/rbd.ko模块,改了do_rbd_add这个函数,生成得是livepatch-rbd.ko这个ko文件

我们把这个ko文件拷贝到相同内核的,需要更新的机器

先做map的操作,检查打补丁前的输出

[root@lab101 patch]# rbd map testrbd
/dev/rbd0
[root@lab101 patch]# dmesg
[3303179.423310] libceph: mon0 192.168.19.101:6789 session established
[3303179.423726] libceph: client20564 fsid beeb1bd5-54ed-40b6-897f-f31f43a517e6
[3303179.429378] rbd: rbd0: capacity 53687091200 features 0x1 [root@lab101 patch]# kpatch list
Loaded patch modules:
Installed patch modules:

可以看到没有打过补丁

加载补丁

[root@lab101 patch]# kpatch load livepatch-rbd.ko
loading patch module: livepatch-rbd.ko
waiting (up to 15 seconds) for patch transition to complete...
transition complete (3 seconds)

尝试map

[root@lab101 patch]# rbd map testrbda
/dev/rbd1
[root@lab101 patch]# dmesg
[3303179.423310] libceph: mon0 192.168.19.101:6789 session established
[3303179.423726] libceph: client20564 fsid beeb1bd5-54ed-40b6-897f-f31f43a517e6
[3303179.429378] rbd: rbd0: capacity 53687091200 features 0x1
[3303262.296794] livepatch: enabling patch 'livepatch_rbd'
[3303262.307782] livepatch: 'livepatch_rbd': starting patching transition
[3303264.938241] livepatch: 'livepatch_rbd': patching complete
[3303291.798301] rbd: rbd1: capacity 我改这里的显示了 53687091200 features 0x1
[root@lab101 patch]# kpatch list
Loaded patch modules:
livepatch_rbd [enabled] Installed patch modules:

可以看到上面的操作过程中我并没有去rmmod rbd 或者重新modprobe rbd,内核模块就已经更新了

上面的是加载了补丁,如果需要安装补丁是需要执行

[root@lab101 patch]# kpatch install livepatch-rbd.ko
installing livepatch-rbd.ko (3.10.0-1062.el7.x86_64)
Created symlink from /etc/systemd/system/multi-user.target.wants/kpatch.service to /usr/local/lib/systemd/system/kpatch.service.

实际上上面的操作是把patch的ko拷贝到了路径

/var/lib/kpatch/3.10.0-1062.el7.x86_64/livepatch-rbd.ko

install的操作就是启动的时候把这个加载进去

如果觉得不满意,补丁是支持回退的

[root@lab101 patch]# kpatch unload livepatch-rbd
disabling patch module: livepatch_rbd
waiting (up to 15 seconds) for patch transition to complete...
transition complete (3 seconds)
unloading patch module: livepatch_rbd

基于以上就完成了rbd的一次热更新的过程了,通常来说模块的更新并不需要重启机器,但是如果模块提供的服务上面加载了其它服务,服务又被客户端连接的话,这个更新步骤就比较麻烦了,如果能够热更新,能够省很多事情,当然内核模块的更新要测试验证没有问题再去动,否则很容易把机器搞死机了

自有内核模块的热更新

如果内核模块是自己改过的,或者并不是内核树里面的,需要打补丁,可以用下面的命令处理

/usr/local/bin/kpatch-build -s ./block/ -t all -e ./block/rbd.ko block-rbd.patch  --skip-gcc-check

上面的block为源码的目录,需要准备好Makefile的,后面的-e后面接的是之前版本编译出来的内核模块,block-rbd.patch 就是源码的差异,然后编译出来的就是patch模块

这个地方内核的版本就再block的里面的Makefile里面去控制了

[root@lab102 kernel]# /usr/local/bin/kpatch-build -s ./block/ -t all -e ./block/rbd.ko block-rbd.patch  --skip-gcc-check
WARNING: Skipping gcc version matching check (not recommended)
Using source directory at /root/kernel/block
Testing patch file(s)
Reading special section data
Building original source
Building patched source
Extracting new and modified ELF sections
rbd.o: changed function: do_rbd_add.isra.45
Patched objects: rbd.ko
Building patch module: livepatch-block-rbd.ko
SUCCESS

这个方式的编译就快很多了,如果是更新内核自带的模块,用上面的整个编译的,如果是自己改过的,就可以用后面的方式去实现了

内核补丁热更新ceph内核模块的更多相关文章

  1. 另类Unity热更新大法:代码注入式补丁热更新

    对老项目进行热更新 项目用纯C#开发的? 眼看Unity引擎热火朝天,无数程序猿加入到了Unity开发的大本营. 一些老项目,在当时ulua/slua还不如今天那样的成熟,因此他们选择了全c#开发:也 ...

  2. Unity3D 热更新方案总结

    如何评价腾讯在Unity下的xLua(开源)热更方案? Unity 游戏用XLua的HotFix实现热更原理揭秘 腾讯开源手游热更新方案,Unity3D下的Lua编程 [Unity]基于IL代码注入的 ...

  3. 热更新应用--热补丁Hotfix学习笔记

    一.热补丁简介 热补丁主要是用于将纯C#工程在不重做的情况下通过打补丁的形式改造成具备lua热更新功能工程,主要是让原来脚本中Start函数和Update函数等函数代码块重定向到lua代码. 二.第一 ...

  4. 移动端热更新方案(iOS+Android)

    PPT资源包含iOS+Android 各种方案分析:https://github.com/qiyer/Share/blob/master/%E7%83%AD%E6%9B%B4%E6%96%B0%E5% ...

  5. 手写热更新阐述tinker实现原理

    关于热更新如今面试也是基本上都会提及到的,我上一家公司用的是tinker,而这里准备研究的也是它的原理,而关于tinker的原理网上也是一大堆文章进行介绍,为了对它有个更加进一步的认识,所以自己动手来 ...

  6. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  7. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  8. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  9. IOS热更新-JSPatch实现原理+Patch现场恢复

    关于HotfixPatch 在IOS开发领域,由于Apple严格的审核标准和低效率,IOS应用的发版速度极慢,稍微大型的app发版基本上都在一个月以上,所以代码热更新(HotfixPatch)对于IO ...

随机推荐

  1. 还不会ida*算法?看完这篇或许能理解点。

    IDA* 算法分析 IDA* 本质上就是带有估价函数和迭代加深优化的dfs与,A * 相似A *的本质便是带 有估价函数的bfs,估价函数是什么呢?估价函数顾名思义,就是估计由目前状态达 到目标状态的 ...

  2. monolog封装

    做一下基本关于Monolog的基本介绍: Monolog是基于PHP的日志类库. 介绍就到这,言归正传 安装 安装最新版本:(composer 还没安装的~:https://www.phpcompos ...

  3. nginx安全:配置allow/deny控制ip访问(ngx_http_access_module)

    一,nginx中allow/deny指令的用途 1, Nginx的deny和allow指令是由ngx_http_access_module模块提供, Nginx安装默认内置了该模块 2, nginx访 ...

  4. Web调优之IBM JDK+liberty(一): Jmeter pod里压力,50个线程并发测试,调整 -Xms -Xms, Log原来是大问题

    1.运行环境 k8s Web服务器: Liberty(IBM J9 JDK),base image : FROM websphere-liberty:20.0.0.3-kernel-java8-ibm ...

  5. Linux机器之间SSH免密钥登录设置

    SSH免密钥登录 私钥:密钥留在本机 公钥:密钥发给其他机 hadoop01 生成密钥: ssh-keygen -t rsa (密钥存放路径:/root/.ssh) id_rsa:私钥 id_rsa. ...

  6. vue-cli中使用全局less变量

    1.执行 vue add style-resources-loader 命令,选择less 2.在 vue.config.js中添加配置,注意将路径更改为自己存放less变量文件的地址 // 全局使用 ...

  7. confluence 4.2 升级至 6.10.x 记录

    confluence 4.2 升级至 6.10.x 记录 首先将线上环境中的 confluence 安装目录.数据目录以及数据库进行备份,相关信息如下: 安装目录:/opt/atlassian/con ...

  8. Linux下的django项目02

    3.创建user模型 3.1 创建用户模型user 第一步 django-admin startproject syl 第二 在syl下创建apps文件包并标记根源 cd 到apps下并进行以下步骤 ...

  9. codeforces 1442 A. Extreme Subtraction(贪心,构造)

    传送门 样例(x): 8 15 16 17 19 27 36 29 33 结果(t1) 15 15 16 18 26 35 28 32 思路:我们可以把最左端和最右端当做两个水龙头,每个水龙头流量的上 ...

  10. MIPS汇编及模拟器下载

    1. 简述汇编语言发展 在计算机发展初期,人们用0-1序列来表示每一条语言,亦即二进制的机器指令 由于机器指令过于繁琐,程序员们开发出了一种新的语言,这种用符号表示的计算机语言被称为汇编语言 计算机继 ...