我们都知道linux内核中的代码非常精妙,但是有些代码由于历史原因,一个函数为了兼容处理各种情况,到最后可能变得非常糟糕,到处都是goto 和if,看的想跳楼(宋老师口头禅^_^)

如果在系统中读一个文件时会调用

generic_file_buffered_read

这个函数的功能是把磁盘中的数据读到page之后,或者直接获取cache中的page,然后调用copy_page_to_iter把page拷贝到用户层的buffer中。

一天寂静的下午,得空,打开电脑,准备仔细研究一下这个函数,发现这个函数的注释上面就写明了:

* This is really ugly. But the goto's actually try to clarify some

* of the logic when it comes to error handling etc.

仔细看了一下代码,果然ugly的不像话,到处都是跳转和判断,令人眩晕,而且整个函数达到300行左右(原谅我看了注释才斗胆这样讲:-) ),发现要是把这个函数看下去,今天一整天的心情都不会好了(当时看的是Linux5.10的代码)

ssize_t generic_file_buffered_read(struct kiocb *iocb,

struct iov_iter *iter, ssize_t written)

{

find_page:

if (fatal_signal_pending(current)) {

error = -EINTR;

goto out;

}

error = wait_on_page_locked_killable(page);

if (unlikely(error))

goto readpage_error;

if (PageUptodate(page))

goto page_ok;

if (inode->i_blkbits == PAGE_SHIFT ||

!mapping->a_ops->is_partially_uptodate)

goto page_not_up_to_date;

/* pipes can't handle partially uptodate pages */

if (unlikely(iov_iter_is_pipe(iter)))

goto page_not_up_to_date;

if (!trylock_page(page))

goto page_not_up_to_date;

/* Did it get truncated before we got the lock? */

if (!page->mapping)

goto page_not_up_to_date_locked;

if (!mapping->a_ops->is_partially_uptodate(page,

offset, iter->count))

goto page_not_up_to_date_locked;

unlock_page(page);

}

于是就想内核社区这么多牛人,他们整天盯着这些代码,肯定很多人早已经注意到了,于是想去看看有没有人提交patch重构这个函数:

./scripts/get_maintainer.pl mm/filemap.c

linux-kernel@vger.kernel.org (open list)

然后我就在下面网址中搜索generic_file_buffered_read,果然在10月25号(我看代码那天在11月1号前后),就有人发了相关patch:

https://lore.kernel.org/lkml/

然后迫不及待查看patch,并把整个patch 下载下来:

这里推荐一个工具,使用b4工具

https://git.kernel.org/pub/scm/utils/b4/b4.git

可以直接从

https://lore.kernel.org

获取原始格式的patch,便于自己git am之后测试。

# b4 am https://lore.kernel.org/lkml/20201025212949.602194-1-kent.overstreet@gmail.com

v2_20201025_kent_overstreet_generic_file_buffered_read_improvements.cover

v2_20201025_kent_overstreet_generic_file_buffered_read_improvements.mbx

然后直接 git am ,非常方便,这样就打上了lore.kernel.org上提交的patch.

git am v2_20201025_kent_overstreet_generic_file_buffered_read_improvements.mbx

提示:在git am之前,可以提前git apply --check 一下

# gitlogdate -3

fc5608fc9917 2020-10-25 Kent Overstreet fs: generic_file_buffered_read() now uses find_get_pages_contig

3bcadc3306be 2020-10-25 Kent Overstreet fs: Break generic_file_buffered_read up into multiple functions

3650b228f83a 2020-10-25 Linus Torvalds Linux 5.10-rc1

alias gitlogdate='git log --pretty=format:"%h%x09%ad%x09%an%x09%s" --date=short'

打了这个patch之后,generic_file_buffered_read变成了这个样子:

ssize_t generic_file_buffered_read(struct kiocb *iocb,

struct iov_iter *iter, ssize_t written)

{

..

pg_nr = generic_file_buffered_read_get_pages(iocb, iter,

pages, nr_pages);

...

for (i = 0; i < pg_nr; i++) {

copied = copy_page_to_iter(pages[i], offset, bytes, iter);

}

而且

generic_file_buffered_read_get_pages

也非常之清晰:

static int generic_file_buffered_read_get_pages(struct kiocb *iocb,

struct iov_iter *iter,

struct page **pages,

unsigned int nr)

nr_got = find_get_pages_contig(mapping, index, nr, pages);

if (nr_got)

goto got_pages;

if (iocb->ki_flags & IOCB_NOIO)

return -EAGAIN;

page_cache_sync_readahead(mapping, ra, filp, index, last_index - index);

nr_got = find_get_pages_contig(mapping, index, nr, pages);

if (nr_got)

goto got_pages;

...

}

看完generic_file_buffered_read()之后,整个下午的心情都好多了。

ps: 这个补丁很快就被各种review, 并被相关maintainer收进自己仓库。

获取更多使用patch研究linux内核的方法,可以参考:

分享以原始patch开始深究Linux内核

linux内核多个补丁,一个令人惊叹的Linux内核补丁相关推荐

  1. 免费创建一个令人惊叹的网站的7个技巧

    这里有一些好消息.你不需要花钱来创建一个令人惊叹的网站.你甚至不需要设计或编程经验.你所需要的只是一个互联网连接和一台电脑.就这么简单.看看这个,创建你自己的免费网站吧 1. 从环境中获得灵感 你的竞 ...

  2. 神经辐射场(NERF)模型:一个令人惊叹的三维场景重建方法

    在计算机图形学.计算机视觉和增强现实等领域,三维场景重建一直是一个热门话题.近年来,神经网络模型的出现已经彻底改变了这个领域,而其中最引人注目的就是 NERF(神经辐射场)模型.在这篇文章中,我们将深 ...

  3. 2038年问题 linux内核5.6,又一个“千年虫”问题!Linux Kernel 5.6已着手应对

    原标题:又一个"千年虫"问题!Linux Kernel 5.6已着手应对 新十年伊始,Linux Kernel 5.6 的开发者已经准备好着手解决将在下一个十年到来的 2038 年 ...

  4. Linux内核分析:完成一个简单的时间片轮转多道程序内核代码

    PS.贺邦   原创作品转载请注明出处  <Linux内核分析>MOOC课程    http://mooc.study.163.com/course/USTC-1000029000 1.m ...

  5. Linux内核分析2:一个简单的时间片轮转多道程序内核代码分析

    Lab2:一个简单的时间片轮转多道程序内核代码 席金玉   <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-100002900 ...

  6. 身份证扫描器web开发_如何以Web开发人员的身份建立一个令人惊叹的投资组合网站

    身份证扫描器web开发 This sponsored article was created by our content partner, BAW Media. Thank you for supp ...

  7. linux软件实现看门狗,一个软件实现的Linux看门狗—soft_wdt

    soft_wdt(下面简称本软件)是一个软件实现的Linux看门狗. 本软件是一款开源.免费软件. 下载地址: 本软件和/drivers/watchdog/softdog.c实现的软件看门狗差点儿一样 ...

  8. linux内核实验一:一个简单的时间片轮转多道程序内核代码

    学号517原创作品,转载请注明出处. 本实验资源来源: https://github.com/mengning/linuxkernel/ 一.mykernel 本次实验是在孟宁老师所建立的一个供用户开 ...

  9. Linux云计算学习教程,一个全新的世界—Linux

    1990 年代中期,因特网因出现 World Wide Web, HTML 这种新型态的应用, 而开始迅速的延烧全世界.一夕间,架设因特网主机的需求激增.这时有一套可 以免费取得,并且能让 x86 计 ...

  10. linux补丁rt ck pf zen,Linux 内核社区补丁对比

    Linux 内核主线总体而言兼具了性能.稳定和安全于一身,不过总有些 Geek 不满足主线中的种种限制,使用各自社区的补丁为它添砖加瓦. 概述 pf内核,这算是一个非常为人熟知的内核.包含了ck补丁( ...

最新文章

  1. python基础-------迭代器,生成器,协程函数
  2. python算法与数据结构-二分查找算法
  3. [python] 基于k-means和tfidf的文本聚类代码简单实现
  4. STL中sort算法简析
  5. [js] 使用ajax请求真的不安全吗?为什么?
  6. 自动化测试工具selenium python_Selenium自动化测试工具使用方法汇总
  7. 编码规范二 缩进与注释
  8. Quartz调度源码分析
  9. spring this.logger.isDebugEnabled()
  10. 【No.1】基于Cookie的单点登录(SSO)
  11. MySql数据库导出完整版(导出数据库,导出表,导出数据库结构)
  12. python实现按照给定范围随机生成小数,偶数,奇数,整数,正态分布,均匀分布数据以及图片
  13. TechTool Pro 11 Mac(硬件检测和系统维护工具)附序列号中文版
  14. 大数据平台建设方案(项目需求与技术方案)
  15. JavaWeb之servlet详解(转帖)
  16. 通过jacob实现office在线预览
  17. SpringCloud分布式开发理解
  18. 解决Ubuntu系统上网速度慢的问题
  19. java-php-python-ssm企业员工考勤系统的设计与实现计算机毕业设计
  20. Lambda将搬砖变成艺术

热门文章

  1. Android实现全屏显示的方法
  2. 使用C#代码实现增加用户帐号
  3. 微信小程序onReachBottom不触发
  4. android 按键上报流程,input子系统详解,按键如何上报
  5. 基于XMLHttpRequest封装Ajax请求
  6. Bootstrap图片中加播放按钮
  7. Python百度语音合成
  8. PCA相关 PCL库和Matlab对比
  9. 用了几个开源项目,都无法运行,推广柳氏风格
  10. WINDOWS对文件签名,算法如何由sha1改为sha256/sha512