1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > linux内核多个补丁 一个令人惊叹的Linux内核补丁

linux内核多个补丁 一个令人惊叹的Linux内核补丁

时间:2023-03-27 04:47:16

相关推荐

linux内核多个补丁 一个令人惊叹的Linux内核补丁

我们都知道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@ (open list)

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

/lkml/

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

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

/pub/scm/utils/b4/b4.git

可以直接从

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

# b4 am /lkml/2025212949.602194-1-kent.overstreet@

v2_2025_kent_overstreet_generic_file_buffered_read_improvements.cover

v2_2025_kent_overstreet_generic_file_buffered_read_improvements.mbx

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

git am v2_2025_kent_overstreet_generic_file_buffered_read_improvements.mbx

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

# gitlogdate -3

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

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

3650b228f83a -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内核

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。