背景

在开发过程中,偶然发现了spinand驱动的一个bug,满怀欣喜地往社区提补丁。这是怎么样的一个bug呢?

static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
......
nanddev_io_for_each_page(nand, from, ops, &iter) {
......
ret = spinand_read_page(spinand, &iter.req, enable_ecc);
if (ret < 0 && ret != -EBADMSG) /* 读取数据出错 */
break; if (ret == -EBADMSG) {
/* -EBADMSG 返回表示坏块 */
ecc_failed = true;
mtd->ecc_stats.failed++;
ret = 0;
} else {
/* 出现位翻转或者读取正常,则记录历史位翻转最大值 */
mtd->ecc_stats.corrected += ret;
max_bitflips = max_t(unsigned int, max_bitflips, ret);
} ops->retlen += iter.req.datalen;
ops->oobretlen += iter.req.ooblen;
} if (ecc_failed && !ret)
ret = -EBADMSG; return ret ? ret : max_bitflips;
}

代码逻辑如下:

  1. 遍历读取每一个page
  2. 如果读出错则直接返回
  3. 如果出现坏块,则置位ecc_failed,在函数最后会检查此标志
  4. 如果出现位翻转,则暂存最大位翻转的bit位数量
  5. 全部读取完后,如果有置位ecc_failed,则返回坏块错误码;如果出现位翻转,则返回最大位翻转;否则返回0,表示正常

问题出在于,如果刚好最后一次读取出现位翻转,此时ret != 0就直接退出循环,此时会导致坏块标识无效,且返回最后的位翻转量而非历史位翻转最大值。这是代码不严谨的地方。

第一次提交

修改补丁如下,补丁逻辑不再解释。

In function spinand_mtd_read, if the last page to read occurs bitflip,
this function will return error value because veriable ret not equal to 0. Signed-off-by: liaoweixiong <liaoweixiong@allwinnertech.com>
---
drivers/mtd/nand/spi/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 556bfdb..6b9388d 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -511,12 +511,12 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
if (ret == -EBADMSG) {
ecc_failed = true;
mtd->ecc_stats.failed++;
- ret = 0;
} else {
mtd->ecc_stats.corrected += ret;
max_bitflips = max_t(unsigned int, max_bitflips, ret);
} + ret = 0;
ops->retlen += iter.req.datalen;
ops->oobretlen += iter.req.ooblen;
}

21:13分发出的邮件,21:45分陆续收到两个回复:

<maintainer A>:

Actually, that's exactly what the MTD core expects (see [1]), so you're
the one introducing a regression here.
<maintainer B>:

To me it looks like the patch description is somewhat incorrect, but the
fix itself looks okay, unless I'm getting it wrong. In case of the last page containing bitflips (ret > 0),
spinand_mtd_read() will return that number of bitflips for the last
page. But to me it looks like it should instead return max_bitflips like
it does when the last page read returns with 0.

以及隔天回复

<maintainer A>:

Oh, you're right. liaoweixiong, can you adjust the commit message
accordingly?

好吧,问题出在与我没把问题描述清楚,改改再提交

第二次提交

只改了comment和补丁标题:

Subject: [PATCH v2] mtd: spinand: read return badly if the last page has bitflips

In case of the last page containing bitflips (ret > 0),
spinand_mtd_read() will return that number of bitflips for the last
page. But to me it looks like it should instead return max_bitflips like
it does when the last page read returns with 0.

然后哗啦啦收到两个Reviewed-by,附带一个建议:

Reviewed-by: <maintainer B>

This should probably be resent with the following tags:

Cc: stable@vger.kernel.org
Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI
NANDs")

得,再提交一次吧

第三次提交

此时的我提交补丁到社区经验并不多,Maintainer让我resend,我就忐忑开始胡思乱想了:

版本号需要累加么?该怎么标记是重新发送?有两个maintainer已经"认可"了我的补丁(reviewed-by),我改怎么体现到新的邮件中?

仔细想想内容并没改,因此不需要累加版本号;查询前人提交,在邮件标题可以加上RESEND字样;搜索含RESEND字样的前人邮件,刚好找到一个在maintainer reviewed后resend为acked,写在signed-off-by区。

OK,确定下来就重新发吧

Subject: [RESEND PATCH v2] mtd: spinand: read return badly if the last page has bitflips

......
Signed-off-by: liaoweixiong <liaoweixiong@allwinnertech.com>
Acked-by: <maintainer A>
Acked-by: <maintainer B>
Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI NANDs")

很快,就挨批了...

第四次提交

晚上10点多,收到回复:

<maintainer B>

Why did you change our Reviewed-by tags to Acked-by tags?

额...我也是看别人这么做我才这么做的,大佬生气了!赶紧补救

......
Reviewed-by: <maintainer A>
Reviewed-by: <maintainer B>
Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI NANDs")

第五次提交

埋下的坑终究是要踩的,很快,再次挨批了

<maintainer C>

This is not the correct way to submit patches for inclusion in the
stable kernel tree. Please read:
https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
for how to do this properly.
<maintainer A>

FYI, you should not send the patch to stable@vger.kernel.org, but
instead, as I said in my other reply, add the tag "Cc:
stable@vger.kernel.org". See "Option 1" in the document Greg referred to.

小白赶紧狠补基础操作规范...

第六次提交

......
Reviewed-by: <maintainer A>
Reviewed-by: <maintainer B>
Cc: stable@vger.kernel.org
Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI NANDs")

总结

哎,我只是挪了一行代码的位置而已啊,Maintainer严审下,我竟然提交了6次!6次!突然感觉心好累。

累归累,问题总结还是需要的

  1. 新手不具备提交代码的一些常识,包括

    a) 提交中各个tag的含义,在什么时候加这些tag,例如Reviewed-by和Acked-by的差别

    b) 提交补丁到stable的注意事项
  2. 对补丁的问题描述不够仔细清楚,导致maintainer B无法理解,幸好maintainer A帮我澄清了

解决方法:

  1. linux提交有规范文档的,抽时间撸一遍,并翻译发博客
  2. 在发补丁之前,让身边的人帮忙看一下补丁说明是否足够清晰

希望我的经历能帮助到正在或者准备向Linux内核开源社区的小伙伴

续:第七次提交

竟然还要第七次提交,你敢相信? 距离上一次提交过了2天,无声无息,然后一声惊雷,一个新的maintainer回复了

<maintainer D>

......
Please write your entire official first/last name(s)
......
Finally, when we ask you to resend a patch, it means sending a new
version of the patch. So in the subject, you should not use the
[RESEND] keyword (which means you are sending something again exactly
as it was before, you just got ignored, for example) but instead you
should increment the version number (v3) and also write a nice
changelog after the three dashes '---' (will be ignored by Git when
applying). I would like to queue this for the next release so if you can do it
ASAP, that would be great.
.....

这邮件让我明白了4点:

  1. 名字都要特定划分first/last name么?对署名都有要求...大佬要求,改!
  2. Manintainer要求Resend,原来要累加版本号的,soga~
  3. 在叠加版本时,需要在---的字段后添加版本迭代说明,跟之前发的系列补丁,在cover中说明还不一样
  4. RESEND 的关键字,表示之前的邮件被意外忽略了所以重发,明白了!

干起来!

Subject: [PATCH v3] mtd: spinand: read return badly if the last page has bitflips

......
Signed-off-by: Weixiong Liao <liaoweixiong@allwinnertech.com>
Reviewed-by: <maintainer A>
Reviewed-by: <maintainer B>
Cc: stable@vger.kernel.org
Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI NANDs")
---
Changes since v2:
- Resend this patch with Cc and Fixes tags. Changes since v1:
- More accurate description for this patch
---
......

一次向linux开源社区提交补丁的经历的更多相关文章

  1. 算法工程师想进一步提高竞争力?向TensorFlow开源社区贡献你的代码吧

    算法工程师为什么也要向社区贡献代码? [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] “做算法的人要熟悉算法框架源码吗?算法工程师难 ...

  2. Linux已经全然统治了这个世界:反对开源社区愚不可及

    原文来自:http://readwrite.jp/archives/9977 不管一个企业多强大,它都不存在和开源社区抗衡的实力 十年前.Unix占有最快的计算机世界排名前10位的五席,以及超级计算机 ...

  3. 做一名开源社区的扫地僧——从Bug report到Google Summer of Code(GSoC):从200个bug到5000美金

    今年的软件自由日(SFD),我在广州Linux用户组的线下活动上做了一个分享,主题叫做<做一名开源社区的扫地僧(上)>.我把演讲的内容重新整理扩充, 写出了文字版, 希望可以跟更多朋友分享 ...

  4. MySQL 创始人:写代码比打游戏爽,程序员应多泡开源社区

     王练 发布于2017年09月04日 收藏 43   开源中国全球专享福利,云栖大会购票大返现!>>>   根据StackOverflow的最新调查,MySQL仍然是全世界最流行的数 ...

  5. Linux开源系统对比Windows闭源系统的优势解析

    当我们听到linux的时候是不是觉得高大上的感觉呢?在我刚上大学的时候,听着学长们给我讲他们的大学的学习经历,先学习C语言.单片机.然后做一些项目,现在正学习linux操作系统,当我听到linux操作 ...

  6. 如何向Openstack社区提交一个新项目

    前几天有个朋友问我:自己有一个idea不错的项目,也把基本的框架写好了,想贡献到Openstack社区,却不知道应该怎么做.正好之前我有过类似的经历,那么来分享一下我是如何向Openstack社区提交 ...

  7. 500G !!史上最全的JAVA全套教学视频网盘分享 (JEECG开源社区)

    500 G JAVA视频网盘分享(JEECG开源社区) [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有] JEECG开源社区 ...

  8. 500 G JAVA视频网盘分享(JEECG开源社区)

    500 G JAVA视频网盘分享(JEECG开源社区)   [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有]   [转载:h ...

  9. 500G JAVA视频网盘分享 (JEECG开源社区)

    500 G JAVA视频网盘分享(JEECG开源社区)   [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有]       J ...

随机推荐

  1. vue-awesome-swiper插件爬坑

    最近自己在做一个基于vue的知乎的移动端单页面,遇到很多坑,先说一下遇到最大的坑,其实并不推荐使用 vue-awesome-swiper,如果项目应用轮播,切换少的话.言归正传,现在来介绍vue-aw ...

  2. 初涉网络流[EK&dinic]

    主要还是板子 Edmonds-Karp 从S开始bfs,直到找到一条到达T的路径后将该路径增广,并重复这一过程. 在处理过程中,为了应对“找到的一条路径把其他路径堵塞”的情况,采用了建反向弧的方式来实 ...

  3. sql_autoload_register()函数

    复习__autoload的时候,看到了spl_autoload_register()这个函数.但是一下子没有弄明白,通过查资料我算是弄明白了. 1.__autoload()    ——    自动加载 ...

  4. STM32CUBEMX入门学习笔记1:软件的简单介绍

    STM32CUBEMX是ST公司设计的一款免费软件,软件可以通过其官网下载.现在已经下载到.通过STM32CUBEMX可以完成从单片机选型,程序初始化,中断配置……工作.并生成对应的"HAL ...

  5. Linux异常体系之vector_stub宏解析

    ARM-Linux汇编的宏定义语法说明如下: 使用注意: 1.宏定义以.macro开始,以.endm结束 2.可带参数,参数可有默认值 3.直接使用参数的名字\arg vector_stub宏的功能: ...

  6. The 2018 ACM-ICPC Chinese Collegiate Programming Contest Fight Against Monsters

    #include <iostream> #include <cstdio> #include <cstring> #include <string> # ...

  7. Linux学习-备份的种类、频率与工具的选择

    完整备份之累积备份 (Incremental backup) 还原的考虑 如果是完整备份的话.若硬件出问题导致系统损毁时,只要将完整备份拿出来,整个给他倾倒回去硬盘, 所有事情就搞定了!有些时候 (例 ...

  8. HBase0.94.2-cdh4.2.0需求评估测试报告1.0之一

    hbase是bigtable的开源山寨版本.是建立的hdfs之上,提供高可靠性.高性能.列存储.可伸缩.实时读写的数据库系统.它介于nosql和RDBMS之间,仅能通过主键(row key)和主键的r ...

  9. ROM,PROM,EPROM,EEPROM及FLASH存储器的区别

    在微机的发展初期,BIOS都存放在ROM(Read Only Memory,只读存储器)中.ROM内部的资料是在ROM的制造工序中,在工厂里用特殊的方法被烧录进去的,其中的内容只能读不能改,一旦烧录进 ...

  10. 详解Python中的相对导入和绝对导入

    Python 相对导入与绝对导入,这两个概念是相对于包内导入而言的.包内导入即是包内的模块导入包内部的模块. Python import 的搜索路径 在当前目录下搜索该模块 在环境变量 PYTHONP ...