在开发过程中,偶然发现了spinand驱动的一个bug,满怀欣喜地往社区提补丁。这是怎么样的一个bug呢?
Copy
staticintspinand_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; }
代码逻辑如下:
遍历读取每一个page
如果读出错则直接返回
如果出现坏块,则置位ecc_failed,在函数最后会检查此标志
如果出现位翻转,则暂存最大位翻转的bit位数量
全部读取完后,如果有置位ecc_failed,则返回坏块错误码;如果出现位翻转,则返回最大位翻转;否则返回0,表示正常
问题出在于,如果刚好最后一次读取出现位翻转,此时ret != 0 就直接退出循环,此时会导致坏块标识无效,且返回最后的位翻转量而非历史位翻转最大值。这是代码不严谨的地方。
第一次提交#
修改补丁如下,补丁逻辑不再解释。
Copy ---------------------------------------------------------------------------------------------------------------------- 我们尊重原创,也注重分享,文章来源于微信公众号:中圣智彩HR,建议关注公众号查看原文。如若侵权请联系qter@qter.org。 ----------------------------------------------------------------------------------------------------------------------
|